From 0cda1a8f8b4e3d79c30291685456c7cb62fd7e8e Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 24 Apr 2023 13:39:14 -0400
Subject: add folder for physics box

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 494 +++++++++++++++++++++
 1 file changed, 494 insertions(+)
 create mode 100644 src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
new file mode 100644
index 000000000..d0e854263
--- /dev/null
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -0,0 +1,494 @@
+import "./PhysicsSimulationBox.scss";
+import { FieldView, FieldViewProps } from './FieldView';
+import React = require('react');
+import { ViewBoxAnnotatableComponent } from '../DocComponent';
+import { observer } from 'mobx-react';
+import "./PhysicsSimulationBox.scss";
+import Weight from "./PhysicsSimulationWeight";
+import Wall  from "./PhysicsSimulationWall"
+import Wedge from "./PhysicsSimulationWedge"
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { CheckBox } from "../search/CheckBox";
+export interface IForce {
+  description: string;
+  magnitude: number;
+  directionInDegrees: number;
+}
+export interface IWallProps {
+  length: number;
+  xPos: number;
+  yPos: number;
+  angleInDegrees: number;
+}
+
+interface PhysicsVectorTemplate {
+  top: number;
+  left: number;
+  width: number;
+  height: number;
+  x1: number;
+  y1: number;
+  x2: number;
+  y2: number;
+  weightX: number;
+  weightY: number;
+}
+
+@observer
+export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
+
+  public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PhysicsSimulationBox, fieldKey); }
+
+  // Constants
+  gravityMagnitude = 9.81;
+  forceOfGravity: IForce = {
+    description: "Gravity",
+    magnitude: this.gravityMagnitude,
+    directionInDegrees: 270,
+  };
+  xMin = 0;
+  yMin = 0;
+  xMax = 300;
+  yMax = 300;
+  color = `rgba(0,0,0,0.5)`;
+  radius = 0.1*this.yMax
+  update = true
+  menuIsOpen = false
+
+  constructor(props: any) {
+    super(props);
+  }
+
+  // Add one weight to the simulation
+  addWeight () {
+    this.dataDoc.weight = true;
+    this.dataDoc.wedge = false;
+    this.dataDoc.pendulum = false;
+    this.addWalls();
+  };
+
+  // Set weight defaults
+  setToWeightDefault () {
+    this.dataDoc.startPosY = this.yMin+this.radius;
+    this.dataDoc.startPosX = (this.xMax+this.xMin-this.radius)/2;
+    this.dataDoc.updatedForces = [this.forceOfGravity];
+    this.dataDoc.startForces = [this.forceOfGravity];
+  }
+
+  // Add a wedge with a One Weight to the simulation
+  addWedge () {
+    this.dataDoc.weight = true;
+    this.dataDoc.wedge = true;
+    this.dataDoc.pendulum = false;
+    this.addWalls();
+  };
+
+  // Set wedge defaults
+  setToWedgeDefault () {
+    this.changeWedgeBasedOnNewAngle(26);
+    this.updateForcesWithFriction(this.dataDoc.coefficientOfStaticFriction);
+  }
+
+  // Add a simple pendulum to the simulation
+  addPendulum = () => {
+    this.dataDoc.weight = true;
+    this.dataDoc.wedge = false;
+    this.dataDoc.pendulum = true;
+    this.removeWalls();
+    let angle = this.dataDoc.pendulumAngle;
+    let mag = 9.81 * Math.cos((angle * Math.PI) / 180);
+    let forceOfTension: IForce = {
+      description: "Tension",
+      magnitude: mag,
+      directionInDegrees: 90 - angle,
+    };
+    this.dataDoc.updatedForces = [this.forceOfGravity, forceOfTension];
+    this.dataDoc.startForces = [this.forceOfGravity, forceOfTension];
+  };
+
+  // Set pendulum defaults
+  setToPendulumDefault () {
+    let length = this.xMax*0.7;
+    let angle = 35;
+    let x = length * Math.cos(((90 - angle) * Math.PI) / 180);
+    let y = length * Math.sin(((90 - angle) * Math.PI) / 180);
+    let xPos = this.xMax / 2 - x - this.radius;
+    let yPos = y - this.radius;
+    this.dataDoc.startPosX = xPos;
+    this.dataDoc.startPosY = yPos;
+    let mag = 9.81 * Math.cos((angle * Math.PI) / 180);
+    this.dataDoc.pendulumAngle = angle;
+    this.dataDoc.pendulumLength = length;
+    this.dataDoc.startPendulumAngle = angle;
+    this.dataDoc.adjustPendulumAngle = !this.dataDoc.adjustPendulumAngle;
+  }
+
+  // Update forces when coefficient of static friction changes in freeform mode
+  updateForcesWithFriction (
+    coefficient: number,
+    width: number = this.dataDoc.wedgeWidth,
+    height: number = this.dataDoc.wedgeHeight
+  ) {
+    let normalForce = {
+      description: "Normal Force",
+      magnitude: this.forceOfGravity.magnitude * Math.cos(Math.atan(height / width)),
+      directionInDegrees:
+        180 - 90 - (Math.atan(height / width) * 180) / Math.PI,
+    };
+    let frictionForce: IForce = {
+      description: "Static Friction Force",
+      magnitude:
+        coefficient *
+        this.forceOfGravity.magnitude *
+        Math.cos(Math.atan(height / width)),
+      directionInDegrees: 180 - (Math.atan(height / width) * 180) / Math.PI,
+    };
+    // reduce magnitude of friction force if necessary such that block cannot slide up plane
+    let yForce = -this.forceOfGravity.magnitude;
+    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) +
+          this.forceOfGravity.magnitude) /
+        Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
+    }
+    if (coefficient != 0) {
+      this.dataDoc.startForces = [this.forceOfGravity, normalForce, frictionForce];
+      this.dataDoc.updatedForces = [this.forceOfGravity, normalForce, frictionForce];
+    } else {
+      this.dataDoc.startForces = [this.forceOfGravity, normalForce];
+      this.dataDoc.updatedForces = [this.forceOfGravity, normalForce];
+    }
+  };
+
+  // Change wedge height and width and weight position to match new wedge angle
+  changeWedgeBasedOnNewAngle = (angle: number) => {
+    let width = 0;
+    let height = 0;
+    if (angle < 50) {
+      width = this.xMax*0.6;
+      height = Math.tan((angle * Math.PI) / 180) * width;
+      this.dataDoc.wedgeWidth = width;
+      this.dataDoc.wedgeHeight = height;
+    } else if (angle < 70) {
+      width = this.xMax*0.3;
+      height = Math.tan((angle * Math.PI) / 180) * width;
+      this.dataDoc.wedgeWidth = width;
+      this.dataDoc.wedgeHeight = height;
+    } else {
+      width = this.xMax*0.15;
+      height = Math.tan((angle * Math.PI) / 180) * width;
+      this.dataDoc.wedgeWidth =  width;
+      this.dataDoc.wedgeHeight = height;
+    }
+
+    // update weight position based on updated wedge width/height
+    let xPos = (this.xMax * 0.2)-this.radius;
+    let yPos = width * Math.tan((angle * Math.PI) / 180) - this.radius;
+
+    this.dataDoc.startPosX = xPos;
+    this.dataDoc.startPosY = this.getDisplayYPos(yPos);
+    this.updateForcesWithFriction(
+      Number(this.dataDoc.coefficientOfStaticFriction),
+      width,
+      height
+    );
+    this.dataDoc['updateDisplay'] = !this.dataDoc['updateDisplay']
+  };
+
+  // Helper function to go between display and real values
+  getDisplayYPos = (yPos: number) => {
+    return this.yMax - yPos - 2 * 50 + 5;
+  };
+
+  // In review mode, edit force arrow sketch on mouse movement
+  editForce = (element: PhysicsVectorTemplate) => {
+    if (!this.dataDoc.sketching) {
+      let sketches = this.dataDoc.forceSketches.filter((sketch: PhysicsVectorTemplate) => sketch != element);
+      this.dataDoc.forceSketches = sketches;
+      this.dataDoc.currentForceSketch = element;
+      this.dataDoc.sketching = true;
+    }
+  };
+
+  // In review mode, used to delete force arrow sketch on SHIFT+click
+  deleteForce = (element: PhysicsVectorTemplate) => {
+    if (!this.dataDoc.sketching) {
+      let sketches = this.dataDoc.forceSketches.filter((sketch: PhysicsVectorTemplate) => sketch != element);
+      this.dataDoc.forceSketches = sketches;
+    }
+  };
+
+  // Remove floor and walls from simulation
+  removeWalls = () => {
+    this.dataDoc.wallPositions = []
+  };
+
+  // Add floor and walls to simulation
+  addWalls = () => {
+    let walls = [];
+    walls.push({ length: 100, xPos: 0, yPos: 97, angleInDegrees: 0 });
+    walls.push({ length: 100, xPos: 0, yPos: 0, angleInDegrees: 90 });
+    walls.push({ length: 100, xPos: 97, yPos: 0, angleInDegrees: 90 });
+    this.dataDoc.wallPositions = walls
+  };
+
+
+  componentDidMount() {
+    this.xMax = this.layoutDoc._width;
+    this.yMax = this.layoutDoc._height;
+    this.radius = 0.1*this.layoutDoc._height;
+
+    // Add weight
+    if (this.dataDoc.simulationType == "Inclined Plane") {
+      this.addWedge()
+    } else if (this.dataDoc.simulationType == "Pendulum") {
+      this.addPendulum()
+    } else {
+      this.dataDoc.simulationType = "Free Weight"
+      this.addWeight()
+    }
+    this.dataDoc.accelerationXDisplay = this.dataDoc.accelerationXDisplay ?? 0;
+    this.dataDoc.accelerationYDisplay = this.dataDoc.accelerationYDisplay ?? 0;
+    this.dataDoc.coefficientOfKineticFriction = this.dataDoc.coefficientOfKineticFriction ?? 0;
+    this.dataDoc.coefficientOfStaticFriction = this.dataDoc.coefficientOfStaticFriction ?? 0;
+    this.dataDoc.currentForceSketch = this.dataDoc.currentForceSketch ?? [];
+    this.dataDoc.elasticCollisions = this.dataDoc.elasticCollisions ?? false;
+    this.dataDoc.forceSketches = this.dataDoc.forceSketches ?? [];
+    this.dataDoc.pendulumAngle = this.dataDoc.pendulumAngle ?? 26;
+    this.dataDoc.pendulumLength = this.dataDoc.pendulumLength ?? 300;
+    this.dataDoc.positionXDisplay = this.dataDoc.positionXDisplay ?? 0;
+    this.dataDoc.positionYDisplay = this.dataDoc.positionYDisplay ?? 0;
+    this.dataDoc.showAcceleration = this.dataDoc.showAcceleration ?? false;
+    this.dataDoc.showForceMagnitudes = this.dataDoc.showForceMagnitudes ?? false;
+    this.dataDoc.showForces = this.dataDoc.showForces ?? false;
+    this.dataDoc.showVelocity = this.dataDoc.showVelocity ?? false;
+    this.dataDoc.startForces = this.dataDoc.startForces ?? [this.forceOfGravity];
+    this.dataDoc.startPendulumAngle = this.dataDoc.startPendulumAngle ?? 0;
+    this.dataDoc.startPosX = this.dataDoc.startPosX ?? 50;
+    this.dataDoc.startPosY = this.dataDoc.startPosY ?? 50;
+    this.dataDoc.stepNumber = this.dataDoc.stepNumber ?? 0;
+    this.dataDoc.updateDisplay = this.dataDoc.updateDisplay ?? false;
+    this.dataDoc.updatedForces = this.dataDoc.updatedForces ?? [this.forceOfGravity];
+    this.dataDoc.velocityXDisplay = this.dataDoc.velocityXDisplay ?? 0;
+    this.dataDoc.velocityYDisplay = this.dataDoc.velocityYDisplay ?? 0;
+    this.dataDoc.wallPositions = this.dataDoc.wallPositions ?? [];
+    this.dataDoc.wedgeAngle = this.dataDoc.wedgeAngle ?? 26;
+    this.dataDoc.wedgeHeight = this.dataDoc.wedgeHeight ?? Math.tan((26 * Math.PI) / 180) * this.xMax*0.6;
+    this.dataDoc.wedgeWidth = this.dataDoc.wedgeWidth ?? this.xMax*0.6;
+
+    this.dataDoc.adjustPendulumAngle = true;
+    this.dataDoc.simulationPaused = true;
+    this.dataDoc.simulationReset = false;
+
+    // Add listener for SHIFT key, which determines if sketch force arrow will be edited or deleted on click
+    document.addEventListener("keydown", (e) => {
+      if (e.shiftKey) {
+        this.dataDoc.deleteMode = true;
+      }
+    });
+    document.addEventListener("keyup", (e) => {
+      if (e.shiftKey) {
+        this.dataDoc.deleteMode = false;
+      }
+    });
+  }
+
+  componentDidUpdate() {
+    this.xMax = this.layoutDoc._width;
+    this.yMax = this.layoutDoc._height;
+    this.radius = 0.1*this.layoutDoc._height;
+  }
+
+  render () { 
+    return (
+      <div>
+        <div className="mechanicsSimulationContainer">
+          <div className="mechanicsSimulationContentContainer">
+            <div className="mechanicsSimulationButtonsAndElements">
+              <div className="mechanicsSimulationElements">
+                {this.dataDoc.weight && (
+                  <Weight
+                    adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
+                    color={"red"}
+                    dataDoc={this.dataDoc}
+                    mass={1}
+                    radius={this.radius}
+                    simulationReset={this.dataDoc.simulationReset}
+                    startPosX={this.dataDoc.startPosX}
+                    startPosY={this.dataDoc.startPosY}
+                    timestepSize={0.002}
+                    updateDisplay={this.dataDoc.updateDisplay}
+                    walls={this.dataDoc.wallPositions}
+                    wedge={this.dataDoc.wedge}
+                    wedgeWidth={this.dataDoc.wedgeWidth}
+                    wedgeHeight={this.dataDoc.wedgeHeight}
+                    xMax={this.xMax}
+                    xMin={this.xMin}
+                    yMax={this.yMax}
+                    yMin={this.yMin}
+                  />
+                )}
+                {this.dataDoc.wedge && (
+                  <Wedge
+                    startWidth={this.dataDoc.wedgeWidth}
+                    startHeight={this.dataDoc.wedgeHeight}
+                    startLeft={this.xMax * 0.2}
+                    xMax={this.xMax}
+                    yMax={this.yMax}
+                  />
+                )}
+              </div>
+              <div>
+                {(this.dataDoc.wallPositions ?? []).map((element: { length: number; xPos: number; yPos: number; angleInDegrees: number; }, index: React.Key | null | undefined) => {
+                    return (
+                      <div key={index}>
+                        <Wall
+                          length={element.length}
+                          xPos={element.xPos}
+                          yPos={element.yPos}
+                          angleInDegrees={element.angleInDegrees}
+                        />
+                      </div>
+                    );
+                  })}
+              </div>
+            </div>
+          </div>
+          <div style = {{width: this.layoutDoc._width+'px', height: this.layoutDoc._height+'px'}}>
+            {this.menuIsOpen && (
+              <div className="mechanicsSimulationSettingsMenu">
+                <div className="close-button" onClick={() => {this.menuIsOpen = false; this.dataDoc.simulationReset = !this.dataDoc.simulationReset;}}>
+                    <FontAwesomeIcon icon={'times'} color="black" size={'lg'} />
+                </div>
+                <h4>Simulation Settings</h4>
+                <div className="mechanicsSimulationSettingsMenuRow">
+                   <div className="mechanicsSimulationSettingsMenuRowDescription"><p>Show forces</p></div>
+                   <div><input type="checkbox" checked={this.dataDoc.showForces} onClick={() => {this.dataDoc.showForces = !this.dataDoc.showForces}}/></div>
+                </div>
+                <div className="mechanicsSimulationSettingsMenuRow">
+                  <div className="mechanicsSimulationSettingsMenuRowDescription"><p>Show acceleration</p></div>
+                  <div><input type="checkbox" checked={this.dataDoc.showAcceleration}  onClick={() => {this.dataDoc.showAcceleration = !this.dataDoc.showAcceleration}}/></div>
+                </div>
+                <div className="mechanicsSimulationSettingsMenuRow">
+                <div className="mechanicsSimulationSettingsMenuRowDescription">
+                  <p>Show velocity</p></div>
+                  <div><input type="checkbox" checked={this.dataDoc.showVelocity} onClick={() => {this.dataDoc.showVelocity = !this.dataDoc.showVelocity}}/></div>
+                </div>
+                <hr/>
+                {this.dataDoc.simulationType == "Free Weight" && <div className="mechanicsSimulationSettingsMenuRow">
+                  <div className="mechanicsSimulationSettingsMenuRowDescription"><p>Elastic collisions </p></div>
+                  <div><input type="checkbox" checked={this.dataDoc.elasticCollisions} onClick={() => {this.dataDoc.elasticCollisions = !this.dataDoc.elasticCollisions}}/></div>
+                </div>}
+                {this.dataDoc.simulationType == "Pendulum" && <div className="mechanicsSimulationSettingsMenuRow">
+                  <div className="mechanicsSimulationSettingsMenuRowDescription"><p>Pendulum start angle</p></div>
+                  <div>
+                    <input 
+                      type="number" 
+                      value={this.dataDoc.startPendulumAngle} 
+                      max={35} 
+                      min={0} 
+                      step={1} 
+                      onInput={(e) => {
+                        let angle = e.target.value;
+                        if (angle > 35) {
+                          angle = 35
+                        }
+                        if (angle < 0) {
+                          angle = 0
+                        }
+                        let length = this.xMax*0.7;
+                        let x = length * Math.cos(((90 - angle) * Math.PI) / 180);
+                        let y = length * Math.sin(((90 - angle) * Math.PI) / 180);
+                        let xPos = this.xMax / 2 - x - this.radius;
+                        let yPos = y - this.radius;
+                        this.dataDoc.startPosX = xPos;
+                        this.dataDoc.startPosY = yPos;
+                        let mag = 9.81 * Math.cos((angle * Math.PI) / 180);
+                        this.dataDoc.pendulumAngle = angle;
+                        this.dataDoc.pendulumLength = length;
+                        this.dataDoc.startPendulumAngle = angle;
+                        this.dataDoc.adjustPendulumAngle = !this.dataDoc.adjustPendulumAngle;
+                      }}
+                    />
+                  </div>
+                </div>}
+                {this.dataDoc.simulationType == "Inclined Plane" && <div className="mechanicsSimulationSettingsMenuRow">
+                  <div className="mechanicsSimulationSettingsMenuRowDescription"><p>Inclined plane angle</p></div>
+                  <div>
+                    <input 
+                      type="number" 
+                      value={this.dataDoc.wedgeAngle} 
+                      max={70} 
+                      min={0} 
+                      step={1} 
+                      onInput={(e) => {
+                        let angle = e.target.value ?? 0
+                        if (angle > 70) {
+                          angle = 70
+                        } 
+                        if (angle < 0) {
+                          angle = 0
+                        }
+                        this.dataDoc.wedgeAngle = angle
+                        this.changeWedgeBasedOnNewAngle(angle)
+                      }}
+                    />
+                  </div>
+                </div>}
+              </div>
+            )}
+          </div>
+          <div className="mechanicsSimulationEquationContainer">
+            <div className="mechanicsSimulationControls">
+            <div>
+                {this.dataDoc.simulationPaused && (
+                <button onClick={() => {
+                  this.dataDoc.simulationPaused = false}
+                } >START</button>
+                )}
+                {!this.dataDoc.simulationPaused && (
+                <button onClick={() => {
+                  this.dataDoc.simulationPaused = true}
+                } >PAUSE</button>
+                )}
+                {this.dataDoc.simulationPaused && (
+                <button onClick={() => {
+                  this.dataDoc.simulationReset = !this.dataDoc.simulationReset}
+                } >RESET</button>
+                )}
+                {this.dataDoc.simulationPaused && ( <button onClick={() => {
+                  if (!this.dataDoc.pendulum && !this.dataDoc.wedge) {
+                    this.addWedge()
+                    this.setToWedgeDefault()
+                    this.dataDoc.simulationType = "Inclined Plane"
+                    this.dataDoc.elasticCollisions = false
+                  }
+                  else if (!this.dataDoc.pendulum && this.dataDoc.wedge) {
+                    this.setToPendulumDefault()
+                    this.addPendulum()
+                    this.dataDoc.simulationType = "Pendulum"
+                    this.dataDoc.elasticCollisions = false
+                  }
+                  else {
+                    this.setToWeightDefault()
+                    this.addWeight()
+                    this.dataDoc.simulationType = "Free Weight"
+                  }
+                  this.dataDoc.simulationReset = !this.dataDoc.simulationReset
+                }} >TYPE</button>)}
+                <button onClick={() => {this.menuIsOpen=true; this.dataDoc.simulationReset = !this.dataDoc.simulationReset;}}>MENU</button>
+                </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      );
+    }
+  }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From f327a27d664f45c10a90a4464cd0fa5edec59b68 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 1 May 2023 12:51:12 -0400
Subject: start adding box code

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 745 ++++++++++-----------
 .../nodes/PhysicsBox/PhysicsSimulationWedge.tsx    |  83 ---
 2 files changed, 346 insertions(+), 482 deletions(-)
 delete mode 100644 src/client/views/nodes/PhysicsBox/PhysicsSimulationWedge.tsx

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index d0e854263..f27843ab0 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -6,22 +6,41 @@ import { observer } from 'mobx-react';
 import "./PhysicsSimulationBox.scss";
 import Weight from "./PhysicsSimulationWeight";
 import Wall  from "./PhysicsSimulationWall"
-import Wedge from "./PhysicsSimulationWedge"
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { CheckBox } from "../search/CheckBox";
-export interface IForce {
-  description: string;
-  magnitude: number;
-  directionInDegrees: number;
-}
-export interface IWallProps {
-  length: number;
-  xPos: number;
-  yPos: number;
-  angleInDegrees: number;
-}
-
-interface PhysicsVectorTemplate {
+import PauseIcon from "@mui/icons-material/Pause";
+import PlayArrowIcon from "@mui/icons-material/PlayArrow";
+import ReplayIcon from "@mui/icons-material/Replay";
+import QuestionMarkIcon from "@mui/icons-material/QuestionMark";
+import ArrowLeftIcon from "@mui/icons-material/ArrowLeft";
+import ArrowRightIcon from "@mui/icons-material/ArrowRight";
+import EditIcon from "@mui/icons-material/Edit";
+import EditOffIcon from "@mui/icons-material/EditOff";
+import {
+  Box,
+  Button,
+  Checkbox,
+  Dialog,
+  DialogTitle,
+  DialogContent,
+  DialogContentText,
+  DialogActions,
+  FormControl,
+  FormControlLabel,
+  FormGroup,
+  IconButton,
+  LinearProgress,
+  Stack,
+} from "@mui/material";
+import Typography from "@mui/material/Typography";
+import React, { useEffect, useState } from "react";
+import "./App.scss";
+import { InputField } from "./InputField";
+import questions from "./PhysicsSimulationQuestions.json";
+import tutorials from "./PhysicsSimulationTutorial.json";
+import { IWallProps, Wall } from "./Wall";
+import { IForce, Weight } from "./Weight";
+interface VectorTemplate {
   top: number;
   left: number;
   width: number;
@@ -33,118 +52,191 @@ interface PhysicsVectorTemplate {
   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;
+    }[];
+    showMagnitude: boolean;
+  }[];
+}
 
 @observer
 export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
 
   public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PhysicsSimulationBox, fieldKey); }
 
-  // Constants
-  gravityMagnitude = 9.81;
-  forceOfGravity: IForce = {
-    description: "Gravity",
-    magnitude: this.gravityMagnitude,
-    directionInDegrees: 270,
-  };
-  xMin = 0;
-  yMin = 0;
-  xMax = 300;
-  yMax = 300;
-  color = `rgba(0,0,0,0.5)`;
-  radius = 0.1*this.yMax
-  update = true
-  menuIsOpen = false
-
   constructor(props: any) {
     super(props);
   }
 
-  // Add one weight to the simulation
-  addWeight () {
-    this.dataDoc.weight = true;
-    this.dataDoc.wedge = false;
-    this.dataDoc.pendulum = false;
-    this.addWalls();
-  };
+  // Constants
+  const xMin = 0;
+  const yMin = 0;
+  const xMax = window.innerWidth * 0.7;
+  const yMax = window.innerHeight * 0.8;
+  const color = `rgba(0,0,0,0.5)`;
+  const radius = 50;
+  const wallPositions: IWallProps[] = [];
 
-  // Set weight defaults
-  setToWeightDefault () {
-    this.dataDoc.startPosY = this.yMin+this.radius;
-    this.dataDoc.startPosX = (this.xMax+this.xMin-this.radius)/2;
-    this.dataDoc.updatedForces = [this.forceOfGravity];
-    this.dataDoc.startForces = [this.forceOfGravity];
-  }
 
-  // Add a wedge with a One Weight to the simulation
-  addWedge () {
-    this.dataDoc.weight = true;
-    this.dataDoc.wedge = true;
-    this.dataDoc.pendulum = false;
-    this.addWalls();
-  };
+  componentDidMount() {
+    this.wallPositions.push({ length: 70, xPos: 0, yPos: 0, angleInDegrees: 0 });
+    this.wallPositions.push({ length: 70, xPos: 0, yPos: 80, angleInDegrees: 0 });
+    this.wallPositions.push({ length: 80, xPos: 0, yPos: 0, angleInDegrees: 90 });
+    this.wallPositions.push({ length: 80, xPos: 69.5, yPos: 0, angleInDegrees: 90 });
 
-  // Set wedge defaults
-  setToWedgeDefault () {
-    this.changeWedgeBasedOnNewAngle(26);
-    this.updateForcesWithFriction(this.dataDoc.coefficientOfStaticFriction);
-  }
+    // Used throughout sims
+    this.xMax = this.layoutDoc._width;
+    this.yMax = this.layoutDoc._height;
+    this.radius = 0.1*this.layoutDoc._height;
+    this.dataDoc.reviewCoefficient = this.dataDoc.reviewCoefficient ?? 0;
+    this.dataDoc.questionVariables = this.dataDoc.questionVariables ?? [];
+    this.dataDoc.accelerationXDisplay = this.dataDoc.accelerationXDisplay ?? 0;
+    this.dataDoc.accelerationYDisplay = this.dataDoc.accelerationYDisplay ?? 0;
+    this.dataDoc.componentForces = this.dataDoc.componentForces ?? [];
+    this.dataDoc.displayChange = this.dataDoc.displayChange ?? { xDisplay: 0, yDisplay: 0 };
+    this.dataDoc.elasticCollisions = this.dataDoc.elasticCollisions ?? false;
+    this.dataDoc.gravity = this.dataDoc.gravity ?? -9.81;
+    this.dataDoc.mass = this.dataDoc.mass ?? 1;
+    this.dataDoc.mode = this.dataDoc.mode ?? "Freeform";
+    this.dataDoc.positionXDisplay = this.dataDoc.positionXDisplay ?? 0;
+    this.dataDoc.positionYDisplay = this.dataDoc.positionYDisplay ?? 0;
+    this.dataDoc.resetAll = this.dataDoc.resetAll ?? true;
+    this.dataDoc.showAcceleration = this.dataDoc.showAcceleration ?? false;
+    this.dataDoc.showComponentForces = this.dataDoc.showComponentForces ?? false;
+    this.dataDoc.showForces = this.dataDoc.showForces ?? true;
+    this.dataDoc.showForceMagnitudes = this.dataDoc.showForceMagnitudes ?? true;
+    this.dataDoc.showVelocity = this.dataDoc.showVelocity ?? false;
+    this.dataDoc.simulationPaused = this.dataDoc.simulationPaused ?? true;
+    this.dataDoc.simulationReset = this.dataDoc.simulationReset ?? false;
+    this.dataDoc.simulationSpeed = this.dataDoc.simulationSpeed ?? 2;
+    this.dataDoc.simulationType = this.dataDoc.simulationType ?? "Inclined Plane";
+    this.dataDoc.startForces = this.dataDoc.startForces ?? [];
+    this.dataDoc.startPosX = this.dataDoc.startPosX ?? 0;
+    this.dataDoc.startPosY = this.dataDoc.startPosY ?? 0;
+    this.dataDoc.startVelX = this.dataDoc.startVelX ?? 0;
+    this.dataDoc.startVelY = this.dataDoc.startVelY ?? 0;
+    this.dataDoc.stepNumber = this.dataDoc.stepNumber ?? 0;
+    this.dataDoc.timer = this.dataDoc.timer ?? 0;
+    this.dataDoc.updatedForces = this.dataDoc.updatedForces ?? [];
+    this.dataDoc.velocityXDisplay = this.dataDoc.velocityXDisplay ?? 0;
+    this.dataDoc.velocityYDisplay = this.dataDoc.velocityYDisplay ?? 0;
 
-  // Add a simple pendulum to the simulation
-  addPendulum = () => {
-    this.dataDoc.weight = true;
-    this.dataDoc.wedge = false;
-    this.dataDoc.pendulum = true;
-    this.removeWalls();
-    let angle = this.dataDoc.pendulumAngle;
-    let mag = 9.81 * Math.cos((angle * Math.PI) / 180);
-    let forceOfTension: IForce = {
-      description: "Tension",
-      magnitude: mag,
-      directionInDegrees: 90 - angle,
-    };
-    this.dataDoc.updatedForces = [this.forceOfGravity, forceOfTension];
-    this.dataDoc.startForces = [this.forceOfGravity, forceOfTension];
-  };
+    // Used for review mode
+    this.dataDoc.answerInputFields = this.dataDoc.answerInputFields ?? <div></div>;
+    this.dataDoc.currentForceSketch = this.dataDoc.currentForceSketch ?? null;
+    this.dataDoc.deleteMode = this.dataDoc.deleteMode ?? false;
+    this.dataDoc.forceSketches = this.dataDoc.forceSketches ?? [];
+    this.dataDoc.hintDialogueOpen = this.dataDoc.hintDialogueOpen ?? false;
+    this.dataDoc.noMovement = this.dataDoc.noMovement ?? false;
+    this.dataDoc.questionNumber = this.dataDoc.questionNumber ?? 0;
+    this.dataDoc.questionPartOne = this.dataDoc.questionPartOne ?? "";
+    this.dataDoc.questionPartTwo = this.dataDoc.questionPartTwo ?? "";
+    this.dataDoc.reviewGravityAngle = this.dataDoc.reviewGravityAngle ?? 0;
+    this.dataDoc.reviewGravityMagnitude = this.dataDoc.reviewGravityMagnitude ?? 0;
+    this.dataDoc.reviewNormalAngle = this.dataDoc.reviewNormalAngle ?? 0;
+    this.dataDoc.reviewNormalMagnitude = this.dataDoc.reviewNormalMagnitude ?? 0;
+    this.dataDoc.reviewStaticAngle = this.dataDoc.reviewStaticAngle ?? 0;
+    this.dataDoc.reviewStaticMagnitude = this.dataDoc.reviewStaticMagnitude ?? 0;
+    this.dataDoc.selectedSolutions = 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;
 
-  // Set pendulum defaults
-  setToPendulumDefault () {
-    let length = this.xMax*0.7;
-    let angle = 35;
-    let x = length * Math.cos(((90 - angle) * Math.PI) / 180);
-    let y = length * Math.sin(((90 - angle) * Math.PI) / 180);
-    let xPos = this.xMax / 2 - x - this.radius;
-    let yPos = y - this.radius;
-    this.dataDoc.startPosX = xPos;
-    this.dataDoc.startPosY = yPos;
-    let mag = 9.81 * Math.cos((angle * Math.PI) / 180);
-    this.dataDoc.pendulumAngle = angle;
-    this.dataDoc.pendulumLength = length;
-    this.dataDoc.startPendulumAngle = angle;
-    this.dataDoc.adjustPendulumAngle = !this.dataDoc.adjustPendulumAngle;
+    // Used for uniform circular motion
+    this.dataDoc.circularMotionRadius = this.dataDoc.circularMotionRadius ?? 150;
+
+    // Used for spring simulation
+    this.dataDoc.springConstant = this.dataDoc.springConstant ?? 0.5;
+    this.dataDoc.springRestLength = this.dataDoc.springRestLength ?? 200;
+    this.dataDoc.springStartLength = this.dataDoc.springStartLength ?? 200;
+
+    // Used for pendulum simulation
+    this.dataDoc.adjustPendulumAngle = this.dataDoc.adjustPendulumAngle ?? { angle: 0, length: 0 };
+    this.dataDoc.pendulumAngle = this.dataDoc.pendulumAngle ?? 0;
+    this.dataDoc.pendulumLength = this.dataDoc.pendulumLength ?? 300;
+    this.dataDoc.startPendulumAngle = this.dataDoc.startPendulumAngle ?? 0;
+
+    // Used for wedge simulation
+    this.dataDoc.coefficientOfKineticFriction = this.dataDoc.coefficientOfKineticFriction ?? 0;
+    this.dataDoc.coefficientOfStaticFriction = this.dataDoc.coefficientOfStaticFriction ?? 0;
+    this.dataDoc.wedgeAngle = this.dataDoc.wedgeAngle ?? 26;
+    this.dataDoc.wedgeHeight = this.dataDoc.wedgeHeight ?? Math.tan((26 * Math.PI) / 180) * 400;
+    this.dataDoc.wedgeWidth = this.dataDoc.wedgeWidth ?? 400;
+
+    // Used for pulley simulation
+    this.dataDoc.positionXDisplay2 = this.dataDoc.positionXDisplay2 ?? 0;
+    this.dataDoc.velocityXDisplay2 = this.dataDoc.velocityXDisplay2 ?? 0;
+    this.dataDoc.accelerationXDisplay2 = this.dataDoc.accelerationXDisplay2 ?? 0;
+    this.dataDoc.positionYDisplay2 = this.dataDoc.positionYDisplay2 ?? 0;
+    this.dataDoc.velocityYDisplay2 = this.dataDoc.velocityYDisplay2 ?? 0;
+    this.dataDoc.accelerationYDisplay2 = this.dataDoc.accelerationYDisplay2 ?? 0;
+    this.dataDoc.startPosX2 = this.dataDoc.startPosX2 ?? 0;
+    this.dataDoc.startPosY2 = this.dataDoc.startPosY2 ?? 0;
+    this.dataDoc.displayChange2 = this.dataDoc.displayChange2 ?? { xDisplay: 0, yDisplay: 0 };
+    this.dataDoc.startForces2 = this.dataDoc.startForces2 ?? [];
+    this.dataDoc.updatedForces2 = this.dataDoc.updatedForces2 ?? [];
+    this.dataDoc.mass2 = this.dataDoc.mass2 ?? 1;
+  }
+
+  componentDidUpdate() {
+    this.xMax = this.layoutDoc._width;
+    this.yMax = this.layoutDoc._height;
+    this.radius = 0.1*this.layoutDoc._height;
   }
 
+  // Helper function to go between display and real values
+  getDisplayYPos = (yPos: number) => {
+    return this.yMax - this.dataDoc.yPos - 2 * this.radius + 5;
+  };
+  getYPosFromDisplay = (yDisplay: number) => {
+    return this.yMax - this.dataDoc.yDisplay - 2 * this.radius + 5;
+  };
+
   // Update forces when coefficient of static friction changes in freeform mode
-  updateForcesWithFriction (
+  updateForcesWithFriction = (
     coefficient: number,
-    width: number = this.dataDoc.wedgeWidth,
-    height: number = this.dataDoc.wedgeHeight
-  ) {
-    let normalForce = {
+    width: number = this.wedgeWidth,
+    height: number = this.wedgeHeight
+  ) => {
+    const normalForce: IForce = {
       description: "Normal Force",
-      magnitude: this.forceOfGravity.magnitude * Math.cos(Math.atan(height / width)),
+      magnitude: Math.abs(this.gravity) * Math.cos(Math.atan(height / width)) * this.mass,
       directionInDegrees:
         180 - 90 - (Math.atan(height / width) * 180) / Math.PI,
+      component: false,
     };
     let frictionForce: IForce = {
       description: "Static Friction Force",
       magnitude:
         coefficient *
-        this.forceOfGravity.magnitude *
-        Math.cos(Math.atan(height / width)),
+        Math.abs(this.gravity) *
+        Math.cos(Math.atan(height / width)) *
+        this.mass,
       directionInDegrees: 180 - (Math.atan(height / width) * 180) / Math.PI,
+      component: false,
     };
-    // reduce magnitude of friction force if necessary such that block cannot slide up plane
-    let yForce = -this.forceOfGravity.magnitude;
+    // reduce magnitude or friction force if necessary such that block cannot slide up plane
+    let yForce = -Math.abs(this.gravity) * this.mass;
     yForce +=
       normalForce.magnitude *
       Math.sin((normalForce.directionInDegrees * Math.PI) / 180);
@@ -155,15 +247,65 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       frictionForce.magnitude =
         (-normalForce.magnitude *
           Math.sin((normalForce.directionInDegrees * Math.PI) / 180) +
-          this.forceOfGravity.magnitude) /
+          Math.abs(this.gravity) * this.mass) /
         Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
     }
+    const frictionForceComponent: IForce = {
+      description: "Static Friction Force",
+      magnitude:
+        coefficient * Math.abs(this.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(this.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:
+      this.mass *
+        Math.abs(this.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:
+      this.mass *
+        Math.abs(this.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: this.mass * Math.abs(this.gravity),
+      directionInDegrees: 270,
+      component: false,
+    };
     if (coefficient != 0) {
-      this.dataDoc.startForces = [this.forceOfGravity, normalForce, frictionForce];
-      this.dataDoc.updatedForces = [this.forceOfGravity, normalForce, frictionForce];
+      this.dataDoc.startForces = [gravityForce, normalForce, frictionForce];
+      this.dataDoc.updatedForces = [gravityForce, normalForce, frictionForce];
+      this.dataDoc.componentForces = [
+        frictionForceComponent,
+        normalForceComponent,
+        gravityParallel,
+        gravityPerpendicular,
+      ];
     } else {
-      this.dataDoc.startForces = [this.forceOfGravity, normalForce];
-      this.dataDoc.updatedForces = [this.forceOfGravity, normalForce];
+      this.dataDoc.startForces = [gravityForce, normalForce];
+      this.dataDoc.updatedForces = [gravityForce, normalForce];
+      this.dataDoc.componentForces = [
+        normalForceComponent,
+        gravityParallel,
+        gravityPerpendicular,
+      ];
     }
   };
 
@@ -172,323 +314,128 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     let width = 0;
     let height = 0;
     if (angle < 50) {
-      width = this.xMax*0.6;
-      height = Math.tan((angle * Math.PI) / 180) * width;
+      width = 400;
+      height = Math.tan((angle * Math.PI) / 180) * 400;
       this.dataDoc.wedgeWidth = width;
       this.dataDoc.wedgeHeight = height;
     } else if (angle < 70) {
-      width = this.xMax*0.3;
-      height = Math.tan((angle * Math.PI) / 180) * width;
+      width = 200;
+      height = Math.tan((angle * Math.PI) / 180) * 200;
       this.dataDoc.wedgeWidth = width;
       this.dataDoc.wedgeHeight = height;
     } else {
-      width = this.xMax*0.15;
-      height = Math.tan((angle * Math.PI) / 180) * width;
-      this.dataDoc.wedgeWidth =  width;
+      width = 100;
+      height = Math.tan((angle * Math.PI) / 180) * 100;
+      this.dataDoc.wedgeWidth = width;
       this.dataDoc.wedgeHeight = height;
     }
 
     // update weight position based on updated wedge width/height
-    let xPos = (this.xMax * 0.2)-this.radius;
-    let yPos = width * Math.tan((angle * Math.PI) / 180) - this.radius;
+    let yPos = (width - this.radius) * Math.tan((angle * Math.PI) / 180);
+    if (angle < 40) {
+      yPos += Math.sqrt(angle);
+    } else if (angle < 58) {
+      yPos += angle / 2;
+    } else if (angle < 68) {
+      yPos += angle;
+    } else if (angle < 70) {
+      yPos += angle * 1.3;
+    } else if (angle < 75) {
+      yPos += angle * 1.5;
+    } else if (angle < 78) {
+      yPos += angle * 2;
+    } else if (angle < 79) {
+      yPos += angle * 2.25;
+    } else if (angle < 80) {
+      yPos += angle * 2.6;
+    } else {
+      yPos += angle * 3;
+    }
 
-    this.dataDoc.startPosX = xPos;
+    this.dataDoc.startPosX = Math.round((this.xMax * 0.5 - 200) * 10) / 10;
     this.dataDoc.startPosY = this.getDisplayYPos(yPos);
-    this.updateForcesWithFriction(
-      Number(this.dataDoc.coefficientOfStaticFriction),
-      width,
-      height
-    );
-    this.dataDoc['updateDisplay'] = !this.dataDoc['updateDisplay']
-  };
-
-  // Helper function to go between display and real values
-  getDisplayYPos = (yPos: number) => {
-    return this.yMax - yPos - 2 * 50 + 5;
-  };
-
-  // In review mode, edit force arrow sketch on mouse movement
-  editForce = (element: PhysicsVectorTemplate) => {
-    if (!this.dataDoc.sketching) {
-      let sketches = this.dataDoc.forceSketches.filter((sketch: PhysicsVectorTemplate) => sketch != element);
-      this.dataDoc.forceSketches = sketches;
-      this.dataDoc.currentForceSketch = element;
-      this.dataDoc.sketching = true;
+    if (this.dataDoc.mode == "Freeform") {
+      this.updateForcesWithFriction(
+        Number(this.dataDoc.coefficientOfStaticFriction),
+        width,
+        height
+      );
     }
   };
 
-  // In review mode, used to delete force arrow sketch on SHIFT+click
-  deleteForce = (element: PhysicsVectorTemplate) => {
-    if (!this.dataDoc.sketching) {
-      let sketches = this.dataDoc.forceSketches.filter((sketch: PhysicsVectorTemplate) => sketch != element);
-      this.dataDoc.forceSketches = sketches;
+  // In review mode, update forces when coefficient of static friction changed
+  updateReviewForcesBasedOnCoefficient = (coefficient: number) => {
+    let theta: number = Number(this.dataDoc.wedgeAngle);
+    let index =
+      this.dataDoc.selectedQuestion.variablesForQuestionSetup.indexOf("theta - max 45");
+    if (index >= 0) {
+      theta = this.dataDoc.questionVariables[index];
     }
+    if (isNaN(theta)) {
+      return;
+    }
+    this.dataDoc.reviewGravityMagnitude = (Math.abs(this.dataDoc.gravity));
+    this.dataDoc.reviewGravityAngle = (270);
+    this.dataDoc.reviewNormalMagnitude = (
+      Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180)
+    );
+    this.dataDoc.reviewNormalAngle = (90 - theta);
+    let yForce = -Math.abs(this.dataDoc.gravity);
+    yForce +=
+      Math.abs(this.dataDoc.gravity) *
+      Math.cos((theta * Math.PI) / 180) *
+      Math.sin(((90 - theta) * Math.PI) / 180);
+    yForce +=
+      coefficient *
+      Math.abs(this.dataDoc.gravity) *
+      Math.cos((theta * Math.PI) / 180) *
+      Math.sin(((180 - theta) * Math.PI) / 180);
+    let friction =
+      coefficient * Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180);
+    if (yForce > 0) {
+      friction =
+        (-(Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180)) *
+          Math.sin(((90 - theta) * Math.PI) / 180) +
+          Math.abs(this.dataDoc.gravity)) /
+        Math.sin(((180 - theta) * Math.PI) / 180);
+    }
+    this.dataDoc.reviewStaticMagnitude = (friction);
+    this.dataDoc.reviewStaticAngle = (180 - theta);
   };
 
-  // Remove floor and walls from simulation
-  removeWalls = () => {
-    this.dataDoc.wallPositions = []
-  };
-
-  // Add floor and walls to simulation
-  addWalls = () => {
-    let walls = [];
-    walls.push({ length: 100, xPos: 0, yPos: 97, angleInDegrees: 0 });
-    walls.push({ length: 100, xPos: 0, yPos: 0, angleInDegrees: 90 });
-    walls.push({ length: 100, xPos: 97, yPos: 0, angleInDegrees: 90 });
-    this.dataDoc.wallPositions = walls
-  };
-
-
-  componentDidMount() {
-    this.xMax = this.layoutDoc._width;
-    this.yMax = this.layoutDoc._height;
-    this.radius = 0.1*this.layoutDoc._height;
-
-    // Add weight
-    if (this.dataDoc.simulationType == "Inclined Plane") {
-      this.addWedge()
-    } else if (this.dataDoc.simulationType == "Pendulum") {
-      this.addPendulum()
-    } else {
-      this.dataDoc.simulationType = "Free Weight"
-      this.addWeight()
+  // In review mode, update forces when wedge angle changed
+  updateReviewForcesBasedOnAngle = (angle: number) => {
+    this.dataDoc.reviewGravityMagnitude = (Math.abs(this.dataDoc.gravity));
+    this.dataDoc.reviewGravityAngle = (270);
+    this.dataDoc.reviewNormalMagnitude = (
+      Math.abs(this.dataDoc.gravity) * Math.cos((Number(angle) * Math.PI) / 180)
+    );
+    this.dataDoc.reviewNormalAngle = (90 - angle);
+    let yForce = -Math.abs(this.dataDoc.gravity);
+    yForce +=
+      Math.abs(this.dataDoc.gravity) *
+      Math.cos((Number(angle) * Math.PI) / 180) *
+      Math.sin(((90 - Number(angle)) * Math.PI) / 180);
+    yForce +=
+      this.dataDoc.reviewCoefficient *
+      Math.abs(this.dataDoc.gravity) *
+      Math.cos((Number(angle) * Math.PI) / 180) *
+      Math.sin(((180 - Number(angle)) * Math.PI) / 180);
+    let friction =
+      this.dataDoc.reviewCoefficient *
+      Math.abs(this.dataDoc.gravity) *
+      Math.cos((Number(angle) * Math.PI) / 180);
+    if (yForce > 0) {
+      friction =
+        (-(Math.abs(this.dataDoc.gravity) * Math.cos((Number(angle) * Math.PI) / 180)) *
+          Math.sin(((90 - Number(angle)) * Math.PI) / 180) +
+          Math.abs(this.dataDoc.gravity)) /
+        Math.sin(((180 - Number(angle)) * Math.PI) / 180);
     }
-    this.dataDoc.accelerationXDisplay = this.dataDoc.accelerationXDisplay ?? 0;
-    this.dataDoc.accelerationYDisplay = this.dataDoc.accelerationYDisplay ?? 0;
-    this.dataDoc.coefficientOfKineticFriction = this.dataDoc.coefficientOfKineticFriction ?? 0;
-    this.dataDoc.coefficientOfStaticFriction = this.dataDoc.coefficientOfStaticFriction ?? 0;
-    this.dataDoc.currentForceSketch = this.dataDoc.currentForceSketch ?? [];
-    this.dataDoc.elasticCollisions = this.dataDoc.elasticCollisions ?? false;
-    this.dataDoc.forceSketches = this.dataDoc.forceSketches ?? [];
-    this.dataDoc.pendulumAngle = this.dataDoc.pendulumAngle ?? 26;
-    this.dataDoc.pendulumLength = this.dataDoc.pendulumLength ?? 300;
-    this.dataDoc.positionXDisplay = this.dataDoc.positionXDisplay ?? 0;
-    this.dataDoc.positionYDisplay = this.dataDoc.positionYDisplay ?? 0;
-    this.dataDoc.showAcceleration = this.dataDoc.showAcceleration ?? false;
-    this.dataDoc.showForceMagnitudes = this.dataDoc.showForceMagnitudes ?? false;
-    this.dataDoc.showForces = this.dataDoc.showForces ?? false;
-    this.dataDoc.showVelocity = this.dataDoc.showVelocity ?? false;
-    this.dataDoc.startForces = this.dataDoc.startForces ?? [this.forceOfGravity];
-    this.dataDoc.startPendulumAngle = this.dataDoc.startPendulumAngle ?? 0;
-    this.dataDoc.startPosX = this.dataDoc.startPosX ?? 50;
-    this.dataDoc.startPosY = this.dataDoc.startPosY ?? 50;
-    this.dataDoc.stepNumber = this.dataDoc.stepNumber ?? 0;
-    this.dataDoc.updateDisplay = this.dataDoc.updateDisplay ?? false;
-    this.dataDoc.updatedForces = this.dataDoc.updatedForces ?? [this.forceOfGravity];
-    this.dataDoc.velocityXDisplay = this.dataDoc.velocityXDisplay ?? 0;
-    this.dataDoc.velocityYDisplay = this.dataDoc.velocityYDisplay ?? 0;
-    this.dataDoc.wallPositions = this.dataDoc.wallPositions ?? [];
-    this.dataDoc.wedgeAngle = this.dataDoc.wedgeAngle ?? 26;
-    this.dataDoc.wedgeHeight = this.dataDoc.wedgeHeight ?? Math.tan((26 * Math.PI) / 180) * this.xMax*0.6;
-    this.dataDoc.wedgeWidth = this.dataDoc.wedgeWidth ?? this.xMax*0.6;
-
-    this.dataDoc.adjustPendulumAngle = true;
-    this.dataDoc.simulationPaused = true;
-    this.dataDoc.simulationReset = false;
+    this.dataDoc.reviewStaticMagnitude = (friction);
+    this.dataDoc.reviewStaticAngle = (180 - angle);
+  };
 
-    // Add listener for SHIFT key, which determines if sketch force arrow will be edited or deleted on click
-    document.addEventListener("keydown", (e) => {
-      if (e.shiftKey) {
-        this.dataDoc.deleteMode = true;
-      }
-    });
-    document.addEventListener("keyup", (e) => {
-      if (e.shiftKey) {
-        this.dataDoc.deleteMode = false;
-      }
-    });
-  }
-
-  componentDidUpdate() {
-    this.xMax = this.layoutDoc._width;
-    this.yMax = this.layoutDoc._height;
-    this.radius = 0.1*this.layoutDoc._height;
-  }
 
   render () { 
-    return (
-      <div>
-        <div className="mechanicsSimulationContainer">
-          <div className="mechanicsSimulationContentContainer">
-            <div className="mechanicsSimulationButtonsAndElements">
-              <div className="mechanicsSimulationElements">
-                {this.dataDoc.weight && (
-                  <Weight
-                    adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
-                    color={"red"}
-                    dataDoc={this.dataDoc}
-                    mass={1}
-                    radius={this.radius}
-                    simulationReset={this.dataDoc.simulationReset}
-                    startPosX={this.dataDoc.startPosX}
-                    startPosY={this.dataDoc.startPosY}
-                    timestepSize={0.002}
-                    updateDisplay={this.dataDoc.updateDisplay}
-                    walls={this.dataDoc.wallPositions}
-                    wedge={this.dataDoc.wedge}
-                    wedgeWidth={this.dataDoc.wedgeWidth}
-                    wedgeHeight={this.dataDoc.wedgeHeight}
-                    xMax={this.xMax}
-                    xMin={this.xMin}
-                    yMax={this.yMax}
-                    yMin={this.yMin}
-                  />
-                )}
-                {this.dataDoc.wedge && (
-                  <Wedge
-                    startWidth={this.dataDoc.wedgeWidth}
-                    startHeight={this.dataDoc.wedgeHeight}
-                    startLeft={this.xMax * 0.2}
-                    xMax={this.xMax}
-                    yMax={this.yMax}
-                  />
-                )}
-              </div>
-              <div>
-                {(this.dataDoc.wallPositions ?? []).map((element: { length: number; xPos: number; yPos: number; angleInDegrees: number; }, index: React.Key | null | undefined) => {
-                    return (
-                      <div key={index}>
-                        <Wall
-                          length={element.length}
-                          xPos={element.xPos}
-                          yPos={element.yPos}
-                          angleInDegrees={element.angleInDegrees}
-                        />
-                      </div>
-                    );
-                  })}
-              </div>
-            </div>
-          </div>
-          <div style = {{width: this.layoutDoc._width+'px', height: this.layoutDoc._height+'px'}}>
-            {this.menuIsOpen && (
-              <div className="mechanicsSimulationSettingsMenu">
-                <div className="close-button" onClick={() => {this.menuIsOpen = false; this.dataDoc.simulationReset = !this.dataDoc.simulationReset;}}>
-                    <FontAwesomeIcon icon={'times'} color="black" size={'lg'} />
-                </div>
-                <h4>Simulation Settings</h4>
-                <div className="mechanicsSimulationSettingsMenuRow">
-                   <div className="mechanicsSimulationSettingsMenuRowDescription"><p>Show forces</p></div>
-                   <div><input type="checkbox" checked={this.dataDoc.showForces} onClick={() => {this.dataDoc.showForces = !this.dataDoc.showForces}}/></div>
-                </div>
-                <div className="mechanicsSimulationSettingsMenuRow">
-                  <div className="mechanicsSimulationSettingsMenuRowDescription"><p>Show acceleration</p></div>
-                  <div><input type="checkbox" checked={this.dataDoc.showAcceleration}  onClick={() => {this.dataDoc.showAcceleration = !this.dataDoc.showAcceleration}}/></div>
-                </div>
-                <div className="mechanicsSimulationSettingsMenuRow">
-                <div className="mechanicsSimulationSettingsMenuRowDescription">
-                  <p>Show velocity</p></div>
-                  <div><input type="checkbox" checked={this.dataDoc.showVelocity} onClick={() => {this.dataDoc.showVelocity = !this.dataDoc.showVelocity}}/></div>
-                </div>
-                <hr/>
-                {this.dataDoc.simulationType == "Free Weight" && <div className="mechanicsSimulationSettingsMenuRow">
-                  <div className="mechanicsSimulationSettingsMenuRowDescription"><p>Elastic collisions </p></div>
-                  <div><input type="checkbox" checked={this.dataDoc.elasticCollisions} onClick={() => {this.dataDoc.elasticCollisions = !this.dataDoc.elasticCollisions}}/></div>
-                </div>}
-                {this.dataDoc.simulationType == "Pendulum" && <div className="mechanicsSimulationSettingsMenuRow">
-                  <div className="mechanicsSimulationSettingsMenuRowDescription"><p>Pendulum start angle</p></div>
-                  <div>
-                    <input 
-                      type="number" 
-                      value={this.dataDoc.startPendulumAngle} 
-                      max={35} 
-                      min={0} 
-                      step={1} 
-                      onInput={(e) => {
-                        let angle = e.target.value;
-                        if (angle > 35) {
-                          angle = 35
-                        }
-                        if (angle < 0) {
-                          angle = 0
-                        }
-                        let length = this.xMax*0.7;
-                        let x = length * Math.cos(((90 - angle) * Math.PI) / 180);
-                        let y = length * Math.sin(((90 - angle) * Math.PI) / 180);
-                        let xPos = this.xMax / 2 - x - this.radius;
-                        let yPos = y - this.radius;
-                        this.dataDoc.startPosX = xPos;
-                        this.dataDoc.startPosY = yPos;
-                        let mag = 9.81 * Math.cos((angle * Math.PI) / 180);
-                        this.dataDoc.pendulumAngle = angle;
-                        this.dataDoc.pendulumLength = length;
-                        this.dataDoc.startPendulumAngle = angle;
-                        this.dataDoc.adjustPendulumAngle = !this.dataDoc.adjustPendulumAngle;
-                      }}
-                    />
-                  </div>
-                </div>}
-                {this.dataDoc.simulationType == "Inclined Plane" && <div className="mechanicsSimulationSettingsMenuRow">
-                  <div className="mechanicsSimulationSettingsMenuRowDescription"><p>Inclined plane angle</p></div>
-                  <div>
-                    <input 
-                      type="number" 
-                      value={this.dataDoc.wedgeAngle} 
-                      max={70} 
-                      min={0} 
-                      step={1} 
-                      onInput={(e) => {
-                        let angle = e.target.value ?? 0
-                        if (angle > 70) {
-                          angle = 70
-                        } 
-                        if (angle < 0) {
-                          angle = 0
-                        }
-                        this.dataDoc.wedgeAngle = angle
-                        this.changeWedgeBasedOnNewAngle(angle)
-                      }}
-                    />
-                  </div>
-                </div>}
-              </div>
-            )}
-          </div>
-          <div className="mechanicsSimulationEquationContainer">
-            <div className="mechanicsSimulationControls">
-            <div>
-                {this.dataDoc.simulationPaused && (
-                <button onClick={() => {
-                  this.dataDoc.simulationPaused = false}
-                } >START</button>
-                )}
-                {!this.dataDoc.simulationPaused && (
-                <button onClick={() => {
-                  this.dataDoc.simulationPaused = true}
-                } >PAUSE</button>
-                )}
-                {this.dataDoc.simulationPaused && (
-                <button onClick={() => {
-                  this.dataDoc.simulationReset = !this.dataDoc.simulationReset}
-                } >RESET</button>
-                )}
-                {this.dataDoc.simulationPaused && ( <button onClick={() => {
-                  if (!this.dataDoc.pendulum && !this.dataDoc.wedge) {
-                    this.addWedge()
-                    this.setToWedgeDefault()
-                    this.dataDoc.simulationType = "Inclined Plane"
-                    this.dataDoc.elasticCollisions = false
-                  }
-                  else if (!this.dataDoc.pendulum && this.dataDoc.wedge) {
-                    this.setToPendulumDefault()
-                    this.addPendulum()
-                    this.dataDoc.simulationType = "Pendulum"
-                    this.dataDoc.elasticCollisions = false
-                  }
-                  else {
-                    this.setToWeightDefault()
-                    this.addWeight()
-                    this.dataDoc.simulationType = "Free Weight"
-                  }
-                  this.dataDoc.simulationReset = !this.dataDoc.simulationReset
-                }} >TYPE</button>)}
-                <button onClick={() => {this.menuIsOpen=true; this.dataDoc.simulationReset = !this.dataDoc.simulationReset;}}>MENU</button>
-                </div>
-            </div>
-          </div>
-        </div>
-      </div>
-      );
-    }
   }
\ No newline at end of file
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWedge.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWedge.tsx
deleted file mode 100644
index 6134a6bc0..000000000
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWedge.tsx
+++ /dev/null
@@ -1,83 +0,0 @@
-import React = require('react');
-import "./PhysicsSimulationBox.scss";
-
-export interface IWedgeProps {
-  startHeight: number;
-  startWidth: number;
-  startLeft: number;
-  xMax: number;
-  yMax: number;
-}
-
-interface IState {
-  angleInRadians: number, 
-  left: number,
-  coordinates: string,
-}
-
-export default class Wedge extends React.Component<IWedgeProps, IState> {
-
-  constructor(props: any) {
-    super(props)
-    this.state = {
-      angleInRadians: Math.atan(this.props.startHeight / this.props.startWidth),
-      left: this.props.startLeft,
-      coordinates: "",
-    }
-  }
-
-  color = "#deb887";
-
-  updateCoordinates() {
-    const coordinatePair1 =
-      Math.round(this.state.left) + "," + Math.round(this.props.yMax) + " ";
-    const coordinatePair2 =
-      Math.round(this.state.left + this.props.startWidth) +
-      "," +
-      Math.round(this.props.yMax) +
-      " ";
-    const coordinatePair3 =
-      Math.round(this.state.left) +
-      "," +
-      Math.round(this.props.yMax - this.props.startHeight);
-    const coord = coordinatePair1 + coordinatePair2 + coordinatePair3;
-    this.setState({coordinates: coord}); 
-  }
-
-  componentDidMount() {
-    this.updateCoordinates()
-  }
-
-  componentDidUpdate(prevProps: Readonly<IWedgeProps>, prevState: Readonly<IState>, snapshot?: any): void {
-    if (prevProps.startHeight != this.props.startHeight || prevProps.startWidth != this.props.startWidth) {
-      this.setState({angleInRadians: Math.atan(this.props.startHeight / this.props.startWidth)});
-      this.updateCoordinates();
-    } 
-  }
-  
-  render() {
-    return (
-      <div>
-        <div style={{ position: "absolute", left: "0", top: "0" }}>
-          <svg
-            width={this.props.xMax + "px"}
-            height={this.props.yMax + "px"}
-          >
-            <polygon points={this.state.coordinates} style={{ fill: "burlywood" }} />
-          </svg>
-        </div>
-
-        <p
-          style={{
-            position: "absolute",
-            zIndex: 500,
-            left: Math.round(this.state.left + this.props.startWidth - 80) + "px",
-            top: Math.round(this.props.yMax - 40) + "px",
-          }}
-        >
-          {Math.round(((this.state.angleInRadians * 180) / Math.PI) * 100) / 100}°
-        </p>
-      </div>
-    );
-  }
-};
-- 
cgit v1.2.3-70-g09d2


From 1eb8bee423564970c15ea0fbe9898d9e8c6b0491 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 1 May 2023 13:02:18 -0400
Subject: start adding box code

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 406 ++++++++++++++++++++-
 1 file changed, 405 insertions(+), 1 deletion(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index f27843ab0..3ae281177 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -198,7 +198,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.mass2 = this.dataDoc.mass2 ?? 1;
   }
 
-  componentDidUpdate() {
+  componentDidUpdate(prevProps, prevState) {
     this.xMax = this.layoutDoc._width;
     this.yMax = this.layoutDoc._height;
     this.radius = 0.1*this.layoutDoc._height;
@@ -436,6 +436,410 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.reviewStaticAngle = (180 - angle);
   };
 
+  // Solve for the correct answers to the generated problem
+  getAnswersToQuestion = (
+    question: QuestionTemplate,
+    questionVars: number[]
+  ) => {
+    const solutions: number[] = [];
+
+    let theta: number = Number(this.dataDoc.wedgeAngle);
+    let index = question.variablesForQuestionSetup.indexOf("theta - max 45");
+    if (index >= 0) {
+      theta = questionVars[index];
+    }
+    let muS: number = Number(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(Number(description))) {
+        solutions.push(Number(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(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(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(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(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(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(this.dataDoc.reviewGravityMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon
+          ) {
+            error = true;
+          }
+        } else if (this.dataDoc.selectedQuestion.answerParts[i] == "angle of gravity") {
+          if (Math.abs(this.dataDoc.reviewGravityAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
+            error = true;
+          }
+        } else if (this.dataDoc.selectedQuestion.answerParts[i] == "normal force") {
+          if (
+            Math.abs(this.dataDoc.reviewNormalMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon
+          ) {
+            error = true;
+          }
+        } else if (this.dataDoc.selectedQuestion.answerParts[i] == "angle of normal force") {
+          if (Math.abs(this.dataDoc.reviewNormalAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
+            error = true;
+          }
+        } else if (
+          this.dataDoc.selectedQuestion.answerParts[i] == "force of static friction"
+        ) {
+          if (
+            Math.abs(this.dataDoc.reviewStaticMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon
+          ) {
+            error = true;
+          }
+        } else if (
+          this.dataDoc.selectedQuestion.answerParts[i] == "angle of static friction"
+        ) {
+          if (Math.abs(this.dataDoc.reviewStaticAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
+            error = true;
+          }
+        } else if (
+          this.dataDoc.selectedQuestion.answerParts[i] == "coefficient of static friction"
+        ) {
+          if (
+            Math.abs(
+              Number(this.dataDoc.coefficientOfStaticFriction) - this.dataDoc.selectedSolutions[i]
+            ) > epsilon
+          ) {
+            error = true;
+          }
+        } else if (this.dataDoc.selectedQuestion.answerParts[i] == "wedge angle") {
+          if (Math.abs(Number(this.dataDoc.wedgeAngle) - this.dataDoc.selectedSolutions[i]) > epsilon) {
+            error = true;
+          }
+        }
+      }
+    }
+    if (showAlert) {
+      if (!error) {
+        this.dataDoc.simulationPaused = (false);
+        setTimeout(() => {
+          this.dataDoc.simulationPaused = (true);
+        }, 3000);
+      } else {
+        this.dataDoc.simulationPaused = (false);
+        setTimeout(() => {
+          this.dataDoc.simulationPaused = (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.reviewGravityMagnitude = (0);
+    this.dataDoc.reviewGravityAngle = (0);
+    this.dataDoc.reviewNormalMagnitude = (0);
+    this.dataDoc.reviewNormalAngle = (0);
+    this.dataDoc.reviewStaticMagnitude = (0);
+    this.dataDoc.reviewStaticAngle = (0);
+    this.dataDoc.coefficientOfKineticFriction = (0);
+    this.dataDoc.simulationPaused = (true);
+    this.dataDoc.answerInputFields = (<div></div>);
+  };
+
+  // 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.simulationType == "Inclined Plane") {
+      if (this.dataDoc.questionNumber == questions.inclinePlane.length - 1) {
+        this.dataDoc.questionNumber = (0);
+      } else {
+        this.dataDoc.questionNumber =(questionNumber + 1);
+      }
+      question = questions.inclinePlane[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.reviewCoefficient = 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 = vars;
+    this.dataDoc.selectedQuestion = (question);
+    this.dataDoc.questionPartOne = (q);
+    this.dataDoc.questionPartTwo = (question.question);
+    const answers = this.getAnswersToQuestion(question, vars);
+    this.generateInputFieldsForQuestion(false, question, answers);
+    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+  };
+
+  // Generate answerInputFields for new review question
+  generateInputFieldsForQuestion = (
+    showIcon: boolean = false,
+    question: QuestionTemplate = this.dataDoc.selectedQuestion,
+    answers: number[] = this.dataDoc.selectedSolutions
+  ) => {
+    let answerInput = [];
+    const d = new Date();
+    for (let i = 0; i < question.answerParts.length; i++) {
+      if (question.answerParts[i] == "force of gravity") {
+        this.dataDoc.reviewGravityMagnitude = (0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={<p>Gravity magnitude</p>}
+              lowerBound={0}
+              changeValue={this.dataDoc.reviewGravityMagnitude}
+              step={0.1}
+              unit={"N"}
+              upperBound={50}
+              value={this.dataDoc.reviewGravityMagnitude}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+              labelWidth={"7em"}
+            />
+          </div>
+        );
+      } else if (question.answerParts[i] == "angle of gravity") {
+        this.dataDoc.reviewGravityAngle = (0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={<p>Gravity angle</p>}
+              lowerBound={0}
+              changeValue={this.dataDoc.reviewGravityAngle}
+              step={1}
+              unit={"°"}
+              upperBound={360}
+              value={this.dataDoc.reviewGravityAngle}
+              radianEquivalent={true}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+              labelWidth={"7em"}
+            />
+          </div>
+        );
+      } else if (question.answerParts[i] == "normal force") {
+        this.dataDoc.reviewNormalMagnitude = (0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={<p>Normal force magnitude</p>}
+              lowerBound={0}
+              changeValue={this.dataDoc.reviewNormalMagnitude}
+              step={0.1}
+              unit={"N"}
+              upperBound={50}
+              value={this.dataDoc.reviewNormalMagnitude}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+              labelWidth={"7em"}
+            />
+          </div>
+        );
+      } else if (question.answerParts[i] == "angle of normal force") {
+        this.dataDoc.reviewNormalAngle = (0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={<p>Normal force angle</p>}
+              lowerBound={0}
+              changeValue={this.dataDoc.reviewNormalAngle}
+              step={1}
+              unit={"°"}
+              upperBound={360}
+              value={this.dataDoc.reviewNormalAngle}
+              radianEquivalent={true}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+              labelWidth={"7em"}
+            />
+          </div>
+        );
+      } else if (question.answerParts[i] == "force of static friction") {
+        this.dataDoc.reviewStaticMagnitude = (0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={<p>Static friction magnitude</p>}
+              lowerBound={0}
+              changeValue={this.dataDoc.reviewStaticMagnitude}
+              step={0.1}
+              unit={"N"}
+              upperBound={50}
+              value={this.dataDoc.reviewStaticMagnitude}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+              labelWidth={"7em"}
+            />
+          </div>
+        );
+      } else if (question.answerParts[i] == "angle of static friction") {
+        this.dataDoc.reviewStaticAngle = (0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={<p>Static friction angle</p>}
+              lowerBound={0}
+              changeValue={this.dataDoc.reviewStaticAngle}
+              step={1}
+              unit={"°"}
+              upperBound={360}
+              value={this.dataDoc.reviewStaticAngle}
+              radianEquivalent={true}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+              labelWidth={"7em"}
+            />
+          </div>
+        );
+      } else if (question.answerParts[i] == "coefficient of static friction") {
+        this.updateReviewForcesBasedOnCoefficient(0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={
+                <Box>
+                  &mu;<sub>s</sub>
+                </Box>
+              }
+              lowerBound={0}
+              changeValue={this.dataDoc.coefficientOfStaticFriction}
+              step={0.1}
+              unit={""}
+              upperBound={1}
+              value={this.dataDoc.coefficientOfStaticFriction}
+              effect={this.updateReviewForcesBasedOnCoefficient}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+            />
+          </div>
+        );
+      } else if (question.answerParts[i] == "wedge angle") {
+        this.updateReviewForcesBasedOnAngle(0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={<Box>&theta;</Box>}
+              lowerBound={0}
+              changeValue={this.dataDoc.qedgeAngle}
+              step={1}
+              unit={"°"}
+              upperBound={49}
+              value={this.dataDoc.wedgeAngle}
+              effect={(val: number) => {
+                this.changeWedgeBasedOnNewAngle(val);
+                this.updateReviewForcesBasedOnAngle(val);
+              }}
+              radianEquivalent={true}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+            />
+          </div>
+        );
+      }
+    }
+
+    this.dataDoc.answerInputFields = (
+      <div
+        style={{ display: "flex", flexDirection: "column", alignItems: "left" }}
+      >
+        {answerInput}
+      </div>
+    );
+  };
+  
+
+
 
   render () { 
   }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From a936f7c60c56e4a92aed99cae8e4194fa7fdeda5 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 1 May 2023 14:19:49 -0400
Subject: add to box

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 343 ++++++++++++++++++++-
 1 file changed, 341 insertions(+), 2 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 3ae281177..88338d9b8 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -95,7 +95,6 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   const radius = 50;
   const wallPositions: IWallProps[] = [];
 
-
   componentDidMount() {
     this.wallPositions.push({ length: 70, xPos: 0, yPos: 0, angleInDegrees: 0 });
     this.wallPositions.push({ length: 70, xPos: 0, yPos: 80, angleInDegrees: 0 });
@@ -196,9 +195,167 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.startForces2 = this.dataDoc.startForces2 ?? [];
     this.dataDoc.updatedForces2 = this.dataDoc.updatedForces2 ?? [];
     this.dataDoc.mass2 = this.dataDoc.mass2 ?? 1;
+
+    // Setup simulation
+    if (this.dataDoc.simulationType != "Circular Motion") {
+      this.dataDoc.startVelX = 0;
+      this.dataDoc.setStartVelY = 0;
+      this.dataDoc.velocityXDisplay = (0);
+      this.dataDoc.velocityYDisplay = (0);
+    }
+    if (this.dataDoc.mode == "Freeform") {
+      this.dataDoc.showForceMagnitudes = (true);
+      if (this.dataDoc.simulationType == "One Weight") {
+        this.dataDoc.showComponentForces = false;
+        this.dataDoc.startPosY = (this.yMin + this.radius);
+        this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
+        this.dataDoc.positionYDisplay = (this.getDisplayYPos(this.yMin + this.radius));
+        this.dataDoc.positionXDisplay((this.xMax + this.xMin) / 2 - this.radius);
+        this.dataDoc.updatedForces = ([
+          {
+            description: "Gravity",
+            magnitude: Math.abs(this.dataDoc.gravity) * this.dataDoc.mass,
+            directionInDegrees: 270,
+            component: false,
+          },
+        ]);
+        this.dataDoc.startForces = ([
+          {
+            description: "Gravity",
+            magnitude: Math.abs(this.dataDoc.gravity) * this.dataDoc.mass,
+            directionInDegrees: 270,
+            component: false,
+          },
+        ]);
+        this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+      } else if (this.dataDoc.simulationType == "Inclined Plane") {
+        this.changeWedgeBasedOnNewAngle(26);
+        this.dataDoc.startForces = ([
+          {
+            description: "Gravity",
+            magnitude: Math.abs(this.dataDoc.gravity) * this.dataDoc.mass,
+            directionInDegrees: 270,
+            component: false,
+          },
+        ]);
+        this.updateForcesWithFriction(Number(this.dataDoc.coefficientOfStaticFriction));
+      } else if (this.dataDoc.simulationType == "Pendulum") {
+        this.setupPendulum();
+      } else if (this.dataDoc.simulationType == "Spring") {
+        this.setupSpring();
+      } else if (this.dataDoc.simulationType == "Circular Motion") {
+        this.setupCircular(0);
+      } else if (this.dataDoc.simulationType == "Pulley") {
+        this.setupPulley();
+      } else if (this.dataDoc.simulationType == "Suspension") {
+        this.setupSuspension();
+      }
+    } else if (this.dataDoc.mode == "Review") {
+      this.dataDoc.showComponentForces = (false);
+      this.dataDoc.showForceMagnitudes = (true);
+      this.dataDoc.showAcceleration = (false);
+      this.dataDoc.showVelocity = (false);
+      this.dataDoc.showForces= (true);
+      this.generateNewQuestion();
+      if (this.dataDoc.simulationType == "One Weight") {
+        // TODO - one weight review problems
+      } else if (this.dataDoc.simulationType == "Spring") {
+        this.setupSpring();
+        // TODO - spring review problems
+      } else if (this.dataDoc.simulationType == "Inclined Plane") {
+        this.dataDoc.updatedForces = ([]);
+        this.dataDoc.startForces = ([]);
+      } else if (this.dataDoc.simulationType == "Pendulum") {
+        this.setupPendulum();
+        // TODO - pendulum review problems
+      } else if (this.dataDoc.simulationType == "Circular Motion") {
+        this.setupCircular(0);
+        // TODO - circular motion review problems
+      } else if (this.dataDoc.simulationType == "Pulley") {
+        this.setupPulley();
+        // TODO - pulley tutorial review problems
+      } else if (this.dataDoc.simulationType == "Suspension") {
+        this.setupSuspension();
+        // TODO - suspension tutorial review problems
+      }
+    } else if (this.dataDoc.mode == "Tutorial") {
+      this.dataDoc.showComponentForces = (false);
+      this.dataDoc.stepNumber = (0);
+      this.dataDoc.showAcceleration = (false);
+      if (this.dataDoc.simulationType != "Circular Motion") {
+        this.dataDoc.velocityXDisplay = (0);
+        setVelocityYDisplay = (0);
+        this.dataDoc.showVelocity = (false);
+      } else {
+        this.dataDoc.velocityXDisplay = (20);
+        this.dataDoc.velocityYDisplay = (0);
+        this.dataDoc.showVelocity = (true);
+      }
+
+      if (this.dataDoc.simulationType == "One Weight") {
+        this.dataDoc.showForces = (true);
+        this.dataDoc.startPosY = (this.yMax - 100);
+        this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
+        this.dataDoc.selectedTutorial = (tutorials.freeWeight);
+        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.freeWeight.steps[0].forces));
+        this.dataDoc.showForceMagnitudes = (tutorials.freeWeight.steps[0].showMagnitude);
+      } else if (this.dataDoc.simulationType == "Spring") {
+        this.dataDoc.showForces = (true);
+        this.setupSpring();
+        this.dataDoc.startPosY = (this.yMin + 200 + 19.62);
+        this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
+        this.dataDoc.selectedTutorial = (tutorials.spring);
+        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.spring.steps[0].forces));
+        this.dataDoc.showForceMagnitudes = (tutorials.spring.steps[0].showMagnitude);
+      } else if (this.dataDoc.simulationType == "Pendulum") {
+        this.dataDoc.showForces = (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 - this.radius;
+        const yPos = y - this.radius - 5;
+        this.dataDoc.startPosX = (xPos);
+        this.dataDoc.startPosY = (yPos);
+        this.dataDoc.selectedTutorial = (tutorials.pendulum);
+        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.pendulum.steps[0].forces));
+        this.dataDoc.showForceMagnitudes = (tutorials.pendulum.steps[0].showMagnitude);
+        this.dataDoc.pendulumAngle = (30);
+        this.dataDoc.pendulumLength = (300);
+        this.dataDoc.adjustPendulumAngle = ({ angle: 30, length: 300 });
+      } else if (this.dataDoc.simulationType == "Inclined Plane") {
+        this.dataDoc.showForces = (true);
+        this.dataDoc.wedgeAngle = (26);
+        this.changeWedgeBasedOnNewAngle(26);
+        this.dataDoc.selectedTutorial = (tutorials.inclinePlane);
+        this.dataDoc.startForces = (
+          this.getForceFromJSON(tutorials.inclinePlane.steps[0].forces)
+        );
+        this.dataDoc.showForceMagnitudes = (tutorials.inclinePlane.steps[0].showMagnitude);
+      } else if (this.dataDoc.simulationType == "Circular Motion") {
+        this.dataDoc.showForces = (true);
+        this.setupCircular(40);
+        this.dataDoc.selectedTutorial = (tutorials.circular);
+        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.circular.steps[0].forces));
+        this.dataDoc.showForceMagnitudes = (tutorials.circular.steps[0].showMagnitude);
+      } else if (simulationType == "Pulley") {
+        this.dataDoc.showForces = (true);
+        this.setupPulley();
+        this.dataDoc.selectedTutorial = (tutorials.pulley);
+        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.pulley.steps[0].forces));
+        this.dataDoc.showForceMagnitudes = (tutorials.pulley.steps[0].showMagnitude);
+      } else if (this.dataDoc.simulationType == "Suspension") {
+        this.dataDoc.showForces = (true);
+        this.setupSuspension();
+        this.dataDoc.selectedTutorial = (tutorials.suspension);
+        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.suspension.steps[0].forces));
+        this.dataDoc.showForceMagnitudes = (tutorials.suspension.steps[0].showMagnitude);
+      }
+      this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+    }
   }
 
-  componentDidUpdate(prevProps, prevState) {
+  componentDidUpdate() {
     this.xMax = this.layoutDoc._width;
     this.yMax = this.layoutDoc._height;
     this.radius = 0.1*this.layoutDoc._height;
@@ -838,6 +995,188 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     );
   };
   
+  // Default setup for uniform circular motion simulation
+  setupCircular = (value: number) => {
+    this.dataDoc.showComponentForces = (false);
+    this.dataDoc.startVelY = (0);
+    this.dataDoc.startVelX = (value);
+    let xPos = (this.xMax + this.xMin) / 2 - this.radius;
+    let yPos = (this.yMax + this.yMin) / 2 + this.dataDoc.circularMotionRadius - this.radius;
+    this.dataDoc.startPosY = (yPos);
+    this.dataDoc.startPosX = (xPos);
+    const tensionForce: IForce = {
+      description: "Centripetal Force",
+      magnitude: (this.dataDoc.startVelX ** 2 * this.dataDoc.mass) / this.dataDoc.circularMotionRadius,
+      directionInDegrees: 90,
+      component: false,
+    };
+    this.dataDoc.updatedForces = ([tensionForce]);
+    this.dataDoc.startForces = ([tensionForce]);
+    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+  };
+
+  // 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 - this.radius;
+    const yPos = y - this.radius - 5;
+    this.dataDoc.startPosX = (xPos);
+    this.dataDoc.startPosY = (yPos);
+    const mag = this.dataDoc.mass * Math.abs(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:
+      this.dataDoc.mass * Math.abs(this.dataDoc.gravity) * Math.sin(((90 - angle) * Math.PI) / 180),
+      directionInDegrees: -angle - 90,
+      component: true,
+    };
+    const gravityPerpendicular: IForce = {
+      description: "Gravity Perpendicular Component",
+      magnitude:
+      this.dataDoc.mass * Math.abs(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: this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
+        directionInDegrees: 270,
+        component: false,
+      },
+      forceOfTension,
+    ]);
+    this.dataDoc.startForces = ([
+      {
+        description: "Gravity",
+        magnitude: this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
+        directionInDegrees: 270,
+        component: false,
+      },
+      forceOfTension,
+    ]);
+    this.dataDoc.startPendulumAngle = (30);
+    this.dataDoc.pendulumAngle = (30);
+    this.dataDoc.pendulumLength = (300);
+    this.dataDoc.adjustPendulumAngle = ({ angle: 30, length: 300 });
+  };
+
+  // Default setup for spring simulation
+  setupSpring = () => {
+    this.dataDoc.showComponentForces = (false);
+    const gravityForce: IForce = {
+      description: "Gravity",
+      magnitude: Math.abs(this.dataDoc.gravity) * this.dataDoc.mass,
+      directionInDegrees: 270,
+      component: false,
+    };
+    this.dataDoc.updatedForces = ([gravityForce]);
+    this.dataDoc.startForces = ([gravityForce]);
+    this.dataDoc.startPosX = (this.xMax / 2 - this.radius);
+    this.dataDoc.startPosY = (200);
+    this.dataDoc.springConstant = (0.5);
+    this.dataDoc.springRestLength = (200);
+    this.dataDoc.springStartLength = (200);
+    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+  };
+
+  // Default setup for suspension simulation
+  setupSuspension = () => {
+    let xPos = (this.xMax + this.xMin) / 2 - this.radius;
+    let yPos = this.yMin + 200;
+    this.dataDoc.startPosY = (yPos);
+    this.dataDoc.startPosX = (xPos);
+    this.dataDoc.positionYDisplay = (getDisplayYPos(yPos));
+    this.dataDoc.positionXDisplay = (xPos);
+    let tensionMag = (this.dataDoc.mass * Math.abs(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: this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
+      directionInDegrees: 270,
+      component: false,
+    };
+    this.dataDoc.updatedForces = ([tensionForce1, tensionForce2, grav]);
+    this.dataDoc.startForces = ([tensionForce1, tensionForce2, grav]);
+    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+  };
+
+  // Default setup for pulley simulation
+  setupPulley = () => {
+    this.dataDoc.showComponentForces = (false);
+    this.dataDoc.startPosY = ((this.yMax + this.yMin) / 2);
+    this.dataDoc.startPosX = ((this.xMin + this.xMax) / 2 - 105);
+    this.dataDoc.positionYDisplay = (getDisplayYPos((this.yMax + this.yMin) / 2));
+    this.dataDoc.positionXDisplay = ((this.xMin + this.xMax) / 2 - 105);
+    let a = (-1 * ((mass - mass2) * Math.abs(gravity))) / (mass + mass2);
+    const gravityForce1: IForce = {
+      description: "Gravity",
+      magnitude: this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
+      directionInDegrees: 270,
+      component: false,
+    };
+    const tensionForce1: IForce = {
+      description: "Tension",
+      magnitude: this.dataDoc.mass * a + this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
+      directionInDegrees: 90,
+      component: false,
+    };
+    a *= -1;
+    const gravityForce2: IForce = {
+      description: "Gravity",
+      magnitude: this.dataDoc.mass2 * Math.abs(this.dataDoc.gravity),
+      directionInDegrees: 270,
+      component: false,
+    };
+    const tensionForce2: IForce = {
+      description: "Tension",
+      magnitude: this.dataDoc.mass2 * a + this.dataDoc.mass2 * Math.abs(this.dataDoc.gravity),
+      directionInDegrees: 90,
+      component: false,
+    };
+    this.dataDoc.updatedForces = ([gravityForce1, tensionForce1]);
+    this.dataDoc.startForces = ([gravityForce1, tensionForce1]);
+    this.dataDoc.startPosY2 = ((yMax + yMin) / 2);
+    this.dataDoc.startPosX2 = ((xMin + xMax) / 2 + 5);
+    this.dataDoc.positionYDisplay2 = (getDisplayYPos((yMax + yMin) / 2));
+    this.dataDoc.positionXDisplay2 = ((xMin + xMax) / 2 + 5);
+    this.dataDoc.updatedForces2 = ([gravityForce2, tensionForce2]);
+    this.dataDoc.startForces2 = ([gravityForce2, tensionForce2]);
+    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+  };
 
 
 
-- 
cgit v1.2.3-70-g09d2


From abeb2b59b46e2c6de224d53b341495c162c75c7a Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 1 May 2023 14:34:04 -0400
Subject: add box

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 1302 ++++++++++++++++++++
 1 file changed, 1302 insertions(+)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 88338d9b8..101cf1d4a 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -1178,7 +1178,1309 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
   };
 
+  // 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: this.dataDoc.reviewGravityMagnitude,
+      directionInDegrees: this.dataDoc.reviewGravityAngle,
+      component: false,
+    };
+    const normalForceReview: IForce = {
+      description: "Normal Force",
+      magnitude: this.dataDoc.reviewNormalMagnitude,
+      directionInDegrees: this.dataDoc.reviewNormalAngle,
+      component: false,
+    };
+    const staticFrictionForceReview: IForce = {
+      description: "Static Friction Force",
+      magnitude: this.dataDoc.reviewStaticMagnitude,
+      directionInDegrees: this.dataDoc.reviewStaticAngle,
+      component: false,
+    };
+    this.dataDoc.startForces = ([
+      forceOfGravityReview,
+      normalForceReview,
+      staticFrictionForceReview,
+    ]);
+    this.dataDoc.updatedForces = ([
+      forceOfGravityReview,
+      normalForceReview,
+      staticFrictionForceReview,
+    ]);
+  }
+
+  // Timer for animating the simulation, update every 0.05 seconds
+  setInterval(() => {
+    setTimer(timer + 1);
+  }, 50);
+
 
 
   render () { 
+    <div className="physicsSimApp">
+    <div className="mechanicsSimulationContainer">
+      <div
+        className="mechanicsSimulationContentContainer"
+      >
+        <div className="mechanicsSimulationButtonsAndElements">
+          <div className="mechanicsSimulationButtons">
+            {!this.dataDoc.simulationPaused && (
+              <div
+                style={{
+                  position: "fixed",
+                  left: "10vw",
+                  top: "95vh",
+                  width: "50vw",
+                }}
+              >
+                <LinearProgress />
+              </div>
+            )}
+            <div
+              style={{
+                position: "fixed",
+                top: 1 + "em",
+                left: xMin + 12 + "px",
+              }}
+            >
+              <div className="dropdownMenu">
+                <select
+                  value={this.dataDoc.simulationType}
+                  onChange={(event) => {
+                    this.dataDoc.simulationType = (event.target.value);
+                    // TODO change simulation type based on mode/type
+                  }}
+                  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>
+          </div>
+          <div className="mechanicsSimulationElements">
+            <Weight
+              dataDoc={this.dataDoc}
+              adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
+              gravity={this.dataDoc.gravity}
+              circularMotionRadius={this.dataDoc.circularMotionRadius}
+              componentForces={this.dataDoc.componentForces}
+              showComponentForces={this.dataDoc.showComponentForces}
+              color={"red"}
+              coefficientOfKineticFriction={Number(
+                this.dataDoc.coefficientOfKineticFriction
+              )}
+              displayXVelocity={this.dataDoc.velocityXDisplay}
+              displayYVelocity={this.dataDoc.velocityYDisplay}
+              elasticCollisions={this.dataDoc.elasticCollisions}
+              incrementTime={this.dataDoc.timer}
+              mass={this.dataDoc.mass}
+              mode={this.dataDoc.mode}
+              noMovement={this.dataDoc.noMovement}
+              paused={this.dataDoc.simulationPaused}
+              pendulumAngle={this.dataDoc.pendulumAngle}
+              pendulumLength={this.dataDoc.pendulumLength}
+              radius={this.radius}
+              reset={this.dataDoc.simulationReset}
+              simulationSpeed={this.dataDoc.simulationSpeed}
+              startPendulumAngle={this.dataDoc.startPendulumAngle}
+              showAcceleration={this.dataDoc.showAcceleration}
+              showForceMagnitudes={this.dataDoc.showForceMagnitudes}
+              showForces={this.dataDoc.showForces}
+              showVelocity={this.dataDoc.showVelocity}
+              simulationType={this.dataDoc.simulationType}
+              springConstant={this.dataDoc.springConstant}
+              springStartLength={this.dataDoc.springStartLength}
+              springRestLength={this.dataDoc.springRestLength}
+              startForces={this.dataDoc.startForces}
+              startPosX={this.dataDoc.startPosX}
+              startPosY={this.dataDoc.startPosY}
+              startVelX={this.dataDoc.startVelX}
+              startVelY={this.dataDoc.startVelY}
+              timestepSize={0.05}
+              updateDisplay={this.dataDoc.displayChange}
+              updatedForces={this.dataDoc.updatedForces}
+              wedgeHeight={this.dataDoc.wedgeHeight}
+              wedgeWidth={this.dataDoc.wedgeWidth}
+              xMax={this.xMax}
+              xMin={this.xMin}
+              yMax={this.yMax}
+              yMin={this.yMin}
+            />
+            {this.dataDoc.simulationType == "Pulley" && (
+              <Weight
+                dataDoc={this.dataDoc}
+                adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
+                circularMotionRadius={this.dataDoc.circularMotionRadius}
+                gravity={this.dataDoc.gravity}
+                componentForces={this.dataDoc.componentForces}
+                showComponentForces={this.dataDoc.showComponentForces}
+                color={"blue"}
+                coefficientOfKineticFriction={Number(
+                  this.dataDoc.coefficientOfKineticFriction
+                )}
+                displayXVelocity={this.dataDoc.velocityXDisplay2}
+                displayYVelocity={this.dataDoc.velocityYDisplay2}
+                elasticCollisions={this.dataDoc.elasticCollisions}
+                incrementTime={this.dataDoc.timer}
+                mass={this.dataDoc.mass2}
+                mode={this.dataDoc.mode}
+                noMovement={this.dataDoc.noMovement}
+                paused={this.dataDoc.simulationPaused}
+                pendulumAngle={this.dataDoc.pendulumAngle}
+                pendulumLength={this.dataDoc.pendulumLength}
+                radius={this.dataDoc.radius}
+                reset={this.dataDoc.simulationReset}
+                simulationSpeed={this.dataDoc.simulationSpeed}
+                startPendulumAngle={this.dataDoc.startPendulumAngle}
+                showAcceleration={this.dataDoc.showAcceleration}
+                showForceMagnitudes={this.dataDoc.showForceMagnitudes}
+                showForces={this.dataDoc.showForces}
+                showVelocity={this.dataDoc.showVelocity}
+                simulationType={this.dataDoc.simulationType}
+                springConstant={this.dataDoc.springConstant}
+                springStartLength={this.dataDoc.springStartLength}
+                springRestLength={this.dataDoc.springRestLength}
+                startForces={this.dataDoc.startForces2}
+                startPosX={this.dataDoc.startPosX2}
+                startPosY={this.dataDoc.startPosY2}
+                startVelX={this.dataDoc.startVelX}
+                startVelY={this.dataDoc.startVelY}
+                timestepSize={0.05}
+                updateDisplay={this.dataDoc.displayChange2}
+                updatedForces={this.dataDoc.updatedForces2}
+                wedgeHeight={this.dataDoc.wedgeHeight}
+                wedgeWidth={this.dataDoc.wedgeWidth}
+                xMax={this.xMax}
+                xMin={this.xMin}
+                yMax={this.yMax}
+                yMin={this.yMin}
+              />
+            )}
+          </div>
+          <div>
+            {(this.dataDoc.simulationType == "One Weight" ||
+              this.dataDoc.simulationType == "Inclined Plane") &&
+              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.simulationPaused && this.dataDoc.mode != "Tutorial" && (
+              <IconButton
+                onClick={() => {
+                  this.dataDoc.simulationPaused = (false);
+                }}
+              >
+                <PlayArrowIcon />
+              </IconButton>
+            )}
+            {!this.dataDoc.simulationPaused && this.dataDoc.mode != "Tutorial" && (
+              <IconButton
+                onClick={() => {
+                  this.dataDoc.simulationPaused = (true);
+                }}
+              >
+                <PauseIcon />
+              </IconButton>
+            )}
+            {this.dataDoc.simulationPaused && this.dataDoc.mode != "Tutorial" && (
+              <IconButton
+                onClick={() => {
+                  this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+                }}
+              >
+                <ReplayIcon />
+              </IconButton>
+            )}
+          </Stack>
+          <div className="dropdownMenu">
+            <select
+              value={mode}
+              onChange={(event) => {
+                this.dataDoc.mode = (event.target.value);
+
+                // TODO setup simulation based on type and mode
+              }}
+              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.simulationType != "Inclined Plane" && (
+          <div className="wordProblemBox">
+            <p>{this.dataDoc.simulationType} review problems in progress!</p>
+          </div>
+        )}
+        {this.dataDoc.mode == "Review" && this.dataDoc.simulationType == "Inclined Plane" && (
+          <div>
+            {!this.dataDoc.hintDialogueOpen && (
+              <IconButton
+                onClick={() => {
+                  this.dataDoc.hintDialogueOpen = (true);
+                }}
+                sx={{
+                  position: "fixed",
+                  left: xMax - 50 + "px",
+                  top: yMin + 14 + "px",
+                }}
+              >
+                <QuestionMarkIcon />
+              </IconButton>
+            )}
+            <Dialog
+              maxWidth={"sm"}
+              fullWidth={true}
+              open={this.dataDoc.hintDialogueOpen}
+              onClose={() => this.dataDoc.hintDialogueOpen = (false)}
+            >
+              <DialogTitle>Hints</DialogTitle>
+              <DialogContent>
+                {this.dataDoc.selectedQuestion.hints.map((hint, index) => {
+                  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>{this.dataDoc.questionPartOne}</p>
+                <p>{this.dataDoc.questionPartTwo}</p>
+              </div>
+              <div className="answer">{this.dataDoc.answerInputFields}</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 = 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.startForces = (
+                    this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces)
+                  );
+                  this.dataDoc.updatedForces = (
+                    this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces)
+                  );
+                  this.dataDoc.showForceMagnitudes = (
+                    this.dataDoc.selectedTutorial.steps[step].showMagnitude
+                  );
+                }}
+                disabled={stepNumber == 0}
+              >
+                <ArrowLeftIcon />
+              </IconButton>
+              <div>
+                <h3>
+                  Step {this.dataDoc.stepNumber + 1}:{" "}
+                  {this.dataDoc.selectedTutorial.steps[stepNumber].description}
+                </h3>
+                <p>{this.dataDoc.selectedTutorial.steps[stepNumber].content}</p>
+              </div>
+              <IconButton
+                onClick={() => {
+                  let step = 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.startForces = (
+                    this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces)
+                  );
+                  this.dataDoc.updatedForces = (
+                    this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces)
+                  );
+                  this.dataDoc.showForceMagnitudes = (
+                    this.dataDoc.selectedTutorial.steps[step].showMagnitude
+                  );
+                }}
+                disabled={this.dataDoc.stepNumber == this.dataDoc.selectedTutorial.steps.length - 1}
+              >
+                <ArrowRightIcon />
+              </IconButton>
+            </div>
+            <div>
+              {(this.dataDoc.simulationType == "One Weight" ||
+                this.dataDoc.simulationType == "Inclined Plane" ||
+                this.dataDoc.simulationType == "Pendulum") && <p>Resources</p>}
+              {this.dataDoc.simulationType == "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.simulationType == "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.simulationType == "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.simulationType == "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.simulationReset= (!this.dataDoc.simulationReset);
+                  this.checkAnswers();
+                  this.generateInputFieldsForQuestion(true);
+                }}
+                variant="outlined"
+              >
+                <p>Submit</p>
+              </Button>
+              <Button
+                onClick={() => this.generateNewQuestion()}
+                variant="outlined"
+              >
+                <p>New question</p>
+              </Button>
+            </div>
+          </div>
+        )}
+        {this.dataDoc.mode == "Freeform" && (
+          <div className="vars">
+            <FormControl component="fieldset">
+              <FormGroup>
+                {this.dataDoc.simulationType == "One Weight" && (
+                  <FormControlLabel
+                    control={
+                      <Checkbox
+                        checked={this.dataDoc.elasticCollisions}
+                        onChange={() =>
+                          this.dataDoc.elasticCollisions= (!this.dataDoc.elasticCollisions)
+                        }
+                      />
+                    }
+                    label="Make collisions elastic"
+                    labelPlacement="start"
+                  />
+                )}
+                <FormControlLabel
+                  control={
+                    <Checkbox
+                      checked={this.dataDoc.showForces}
+                      onChange={() => this.dataDoc.showForces = (!this.dataDoc.showForces)}
+                    />
+                  }
+                  label="Show force vectors"
+                  labelPlacement="start"
+                />
+                {(this.dataDoc.simulationType == "Inclined Plane" ||
+                  this.dataDoc.simulationType == "Pendulum") && (
+                  <FormControlLabel
+                    control={
+                      <Checkbox
+                        checked={this.dataDoc.showForces}
+                        onChange={() =>
+                          this.dataDoc.showComponentForces = (!this.dataDoc.showComponentForces)
+                        }
+                      />
+                    }
+                    label="Show component force vectors"
+                    labelPlacement="start"
+                  />
+                )}
+                <FormControlLabel
+                  control={
+                    <Checkbox
+                      checked={this.dataDoc.showAcceleration}
+                      onChange={() => this.dataDoc.showAcceleration = (!this.dataDoc.showAcceleration)}
+                    />
+                  }
+                  label="Show acceleration vector"
+                  labelPlacement="start"
+                />
+                <FormControlLabel
+                  control={
+                    <Checkbox
+                      checked={this.dataDoc.showVelocity}
+                      onChange={() => this.dataDoc.showVelocity = (!this.dataDoc.showVelocity)}
+                    />
+                  }
+                  label="Show velocity vector"
+                  labelPlacement="start"
+                />
+
+                <InputField
+                  label={<Box>Speed</Box>}
+                  lowerBound={1}
+                  changeValue={setSimulationSpeed}
+                  step={1}
+                  unit={"x"}
+                  upperBound={10}
+                  value={simulationSpeed}
+                  labelWidth={"5em"}
+                />
+                {simulationPaused && simulationType != "Circular Motion" && (
+                  <InputField
+                    label={<Box>Gravity</Box>}
+                    lowerBound={-30}
+                    changeValue={setGravity}
+                    step={0.01}
+                    unit={"m/s2"}
+                    upperBound={0}
+                    value={gravity}
+                    effect={(val: number) => {
+                      setResetAll(!resetAll);
+                    }}
+                    labelWidth={"5em"}
+                  />
+                )}
+                {simulationPaused && simulationType != "Pulley" && (
+                  <InputField
+                    label={<Box>Mass</Box>}
+                    lowerBound={1}
+                    changeValue={setMass}
+                    step={0.1}
+                    unit={"kg"}
+                    upperBound={5}
+                    value={mass}
+                    effect={(val: number) => {
+                      setResetAll(!resetAll);
+                    }}
+                    labelWidth={"5em"}
+                  />
+                )}
+                {simulationPaused && simulationType == "Pulley" && (
+                  <InputField
+                    label={<Box>Red mass</Box>}
+                    lowerBound={1}
+                    changeValue={setMass}
+                    step={0.1}
+                    unit={"kg"}
+                    upperBound={5}
+                    value={mass}
+                    effect={(val: number) => {
+                      setResetAll(!resetAll);
+                    }}
+                    labelWidth={"5em"}
+                  />
+                )}
+                {simulationPaused && simulationType == "Pulley" && (
+                  <InputField
+                    label={<Box>Blue mass</Box>}
+                    lowerBound={1}
+                    changeValue={setMass2}
+                    step={0.1}
+                    unit={"kg"}
+                    upperBound={5}
+                    value={mass2}
+                    effect={(val: number) => {
+                      setResetAll(!resetAll);
+                    }}
+                    labelWidth={"5em"}
+                  />
+                )}
+                {simulationPaused && simulationType == "Circular Motion" && (
+                  <InputField
+                    label={<Box>Rod length</Box>}
+                    lowerBound={100}
+                    changeValue={setCircularMotionRadius}
+                    step={5}
+                    unit={"kg"}
+                    upperBound={250}
+                    value={circularMotionRadius}
+                    effect={(val: number) => {
+                      setResetAll(!resetAll);
+                    }}
+                    labelWidth={"5em"}
+                  />
+                )}
+              </FormGroup>
+            </FormControl>
+            {simulationType == "Spring" && simulationPaused && (
+              <div>
+                <InputField
+                  label={
+                    <Typography color="inherit">Spring stiffness</Typography>
+                  }
+                  lowerBound={0.1}
+                  changeValue={setSpringConstant}
+                  step={1}
+                  unit={"N/m"}
+                  upperBound={500}
+                  value={springConstant}
+                  effect={(val: number) => {
+                    setSimulationReset(!simulationReset);
+                  }}
+                  radianEquivalent={false}
+                  mode={"Freeform"}
+                  labelWidth={"7em"}
+                />
+                <InputField
+                  label={<Typography color="inherit">Rest length</Typography>}
+                  lowerBound={10}
+                  changeValue={setSpringRestLength}
+                  step={100}
+                  unit={""}
+                  upperBound={500}
+                  value={springRestLength}
+                  effect={(val: number) => {
+                    setSimulationReset(!simulationReset);
+                  }}
+                  radianEquivalent={false}
+                  mode={"Freeform"}
+                  labelWidth={"7em"}
+                />
+                <InputField
+                  label={
+                    <Typography color="inherit">
+                      Starting displacement
+                    </Typography>
+                  }
+                  lowerBound={-(springRestLength - 10)}
+                  changeValue={(val: number) => {}}
+                  step={10}
+                  unit={""}
+                  upperBound={springRestLength}
+                  value={springStartLength - springRestLength}
+                  effect={(val: number) => {
+                    setStartPosY(springRestLength + val);
+                    setSpringStartLength(springRestLength + val);
+                    setSimulationReset(!simulationReset);
+                  }}
+                  radianEquivalent={false}
+                  mode={"Freeform"}
+                  labelWidth={"7em"}
+                />
+              </div>
+            )}
+            {simulationType == "Inclined Plane" && simulationPaused && (
+              <div>
+                <InputField
+                  label={<Box>&theta;</Box>}
+                  lowerBound={0}
+                  changeValue={setWedgeAngle}
+                  step={1}
+                  unit={"°"}
+                  upperBound={49}
+                  value={wedgeAngle}
+                  effect={(val: number) => {
+                    changeWedgeBasedOnNewAngle(val);
+                    setSimulationReset(!simulationReset);
+                  }}
+                  radianEquivalent={true}
+                  mode={"Freeform"}
+                  labelWidth={"2em"}
+                />
+                <InputField
+                  label={
+                    <Box>
+                      &mu;<sub>s</sub>
+                    </Box>
+                  }
+                  lowerBound={0}
+                  changeValue={setCoefficientOfStaticFriction}
+                  step={0.1}
+                  unit={""}
+                  upperBound={1}
+                  value={coefficientOfStaticFriction}
+                  effect={(val: number) => {
+                    updateForcesWithFriction(val);
+                    if (val < Number(coefficientOfKineticFriction)) {
+                      setCoefficientOfKineticFriction(val);
+                    }
+                    setSimulationReset(!simulationReset);
+                  }}
+                  mode={"Freeform"}
+                  labelWidth={"2em"}
+                />
+                <InputField
+                  label={
+                    <Box>
+                      &mu;<sub>k</sub>
+                    </Box>
+                  }
+                  lowerBound={0}
+                  changeValue={setCoefficientOfKineticFriction}
+                  step={0.1}
+                  unit={""}
+                  upperBound={Number(coefficientOfStaticFriction)}
+                  value={coefficientOfKineticFriction}
+                  effect={(val: number) => {
+                    setSimulationReset(!simulationReset);
+                  }}
+                  mode={"Freeform"}
+                  labelWidth={"2em"}
+                />
+              </div>
+            )}
+            {simulationType == "Inclined Plane" && !simulationPaused && (
+              <Typography>
+                &theta;: {Math.round(Number(wedgeAngle) * 100) / 100}° ≈{" "}
+                {Math.round(((Number(wedgeAngle) * Math.PI) / 180) * 100) /
+                  100}{" "}
+                rad
+                <br />
+                &mu; <sub>s</sub>: {coefficientOfStaticFriction}
+                <br />
+                &mu; <sub>k</sub>: {coefficientOfKineticFriction}
+              </Typography>
+            )}
+            {simulationType == "Pendulum" && !simulationPaused && (
+              <Typography>
+                &theta;: {Math.round(pendulumAngle * 100) / 100}° ≈{" "}
+                {Math.round(((pendulumAngle * Math.PI) / 180) * 100) / 100}{" "}
+                rad
+              </Typography>
+            )}
+            {simulationType == "Pendulum" && simulationPaused && (
+              <div>
+                <InputField
+                  label={<Box>Angle</Box>}
+                  lowerBound={0}
+                  changeValue={setPendulumAngle}
+                  step={1}
+                  unit={"°"}
+                  upperBound={59}
+                  value={pendulumAngle}
+                  effect={(value) => {
+                    setStartPendulumAngle(value);
+                    if (simulationType == "Pendulum") {
+                      const mag =
+                        mass *
+                        Math.abs(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(gravity) *
+                          Math.cos((value * Math.PI) / 180),
+                        directionInDegrees: 270 - value,
+                        component: true,
+                      };
+                      const gravityPerpendicular: IForce = {
+                        description: "Gravity Perpendicular Component",
+                        magnitude:
+                          Math.abs(gravity) *
+                          Math.sin((value * Math.PI) / 180),
+                        directionInDegrees: -value,
+                        component: true,
+                      };
+
+                      const length = pendulumLength;
+                      const x =
+                        length * Math.cos(((90 - value) * Math.PI) / 180);
+                      const y =
+                        length * Math.sin(((90 - value) * Math.PI) / 180);
+                      const xPos = xMax / 2 - x - radius;
+                      const yPos = y - radius - 5;
+                      setStartPosX(xPos);
+                      setStartPosY(yPos);
+
+                      setStartForces([
+                        {
+                          description: "Gravity",
+                          magnitude: Math.abs(gravity) * mass,
+                          directionInDegrees: 270,
+                          component: false,
+                        },
+                        forceOfTension,
+                      ]);
+                      setUpdatedForces([
+                        {
+                          description: "Gravity",
+                          magnitude: Math.abs(gravity) * mass,
+                          directionInDegrees: 270,
+                          component: false,
+                        },
+                        forceOfTension,
+                      ]);
+                      setComponentForces([
+                        tensionComponent,
+                        gravityParallel,
+                        gravityPerpendicular,
+                      ]);
+                      setAdjustPendulumAngle({
+                        angle: value,
+                        length: pendulumLength,
+                      });
+                      setSimulationReset(!simulationReset);
+                    }
+                  }}
+                  radianEquivalent={true}
+                  mode={"Freeform"}
+                  labelWidth={"5em"}
+                />
+                <InputField
+                  label={<Box>Rod length</Box>}
+                  lowerBound={0}
+                  changeValue={setPendulumLength}
+                  step={1}
+                  unit={"m"}
+                  upperBound={400}
+                  value={Math.round(pendulumLength)}
+                  effect={(value) => {
+                    if (simulationType == "Pendulum") {
+                      setAdjustPendulumAngle({
+                        angle: pendulumAngle,
+                        length: value,
+                      });
+                      setSimulationReset(!simulationReset);
+                    }
+                  }}
+                  radianEquivalent={false}
+                  mode={"Freeform"}
+                  labelWidth={"5em"}
+                />
+              </div>
+            )}
+          </div>
+        )}
+        <div className="mechanicsSimulationEquation">
+          {mode == "Freeform" && (
+            <table>
+              <tbody>
+                <tr>
+                  <td>{simulationType == "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>
+                  {(!simulationPaused ||
+                    simulationType == "Inclined Plane" ||
+                    simulationType == "Suspension" ||
+                    simulationType == "Circular Motion" ||
+                    simulationType == "Pulley") && (
+                    <td style={{ cursor: "default" }}>
+                      {positionXDisplay} m
+                    </td>
+                  )}{" "}
+                  {simulationPaused &&
+                    simulationType != "Inclined Plane" &&
+                    simulationType != "Suspension" &&
+                    simulationType != "Circular Motion" &&
+                    simulationType != "Pulley" && (
+                      <td
+                        style={{
+                          cursor: "default",
+                        }}
+                      >
+                        <InputField
+                          lowerBound={0}
+                          changeValue={setPositionXDisplay}
+                          step={1}
+                          unit={"m"}
+                          upperBound={xMax - 110}
+                          value={positionXDisplay}
+                          effect={(value) => {
+                            setDisplayChange({
+                              xDisplay: value,
+                              yDisplay: positionYDisplay,
+                            });
+                          }}
+                          small={true}
+                          mode={"Freeform"}
+                        />
+                      </td>
+                    )}{" "}
+                  {(!simulationPaused ||
+                    simulationType == "Inclined Plane" ||
+                    simulationType == "Suspension" ||
+                    simulationType == "Circular Motion" ||
+                    simulationType == "Pulley") && (
+                    <td style={{ cursor: "default" }}>
+                      {positionYDisplay} m
+                    </td>
+                  )}{" "}
+                  {simulationPaused &&
+                    simulationType != "Inclined Plane" &&
+                    simulationType != "Suspension" &&
+                    simulationType != "Circular Motion" &&
+                    simulationType != "Pulley" && (
+                      <td
+                        style={{
+                          cursor: "default",
+                        }}
+                      >
+                        <InputField
+                          lowerBound={0}
+                          changeValue={setPositionYDisplay}
+                          step={1}
+                          unit={"m"}
+                          upperBound={yMax - 110}
+                          value={positionYDisplay}
+                          effect={(value) => {
+                            setDisplayChange({
+                              xDisplay: positionXDisplay,
+                              yDisplay: value,
+                            });
+                          }}
+                          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>
+                  {(!simulationPaused ||
+                    (simulationType != "One Weight" &&
+                      simulationType != "Circular Motion")) && (
+                    <td style={{ cursor: "default" }}>
+                      {velocityXDisplay} m/s
+                    </td>
+                  )}{" "}
+                  {simulationPaused &&
+                    (simulationType == "One Weight" ||
+                      simulationType == "Circular Motion") && (
+                      <td
+                        style={{
+                          cursor: "default",
+                        }}
+                      >
+                        <InputField
+                          lowerBound={-50}
+                          changeValue={setVelocityXDisplay}
+                          step={1}
+                          unit={"m/s"}
+                          upperBound={50}
+                          value={velocityXDisplay}
+                          effect={(value) => {
+                            setStartVelX(value);
+                            setSimulationReset(!simulationReset);
+                          }}
+                          small={true}
+                          mode={"Freeform"}
+                        />
+                      </td>
+                    )}{" "}
+                  {(!simulationPaused || simulationType != "One Weight") && (
+                    <td style={{ cursor: "default" }}>
+                      {velocityYDisplay} m/s
+                    </td>
+                  )}{" "}
+                  {simulationPaused && simulationType == "One Weight" && (
+                    <td
+                      style={{
+                        cursor: "default",
+                      }}
+                    >
+                      <InputField
+                        lowerBound={-50}
+                        changeValue={setVelocityYDisplay}
+                        step={1}
+                        unit={"m/s"}
+                        upperBound={50}
+                        value={velocityYDisplay}
+                        effect={(value) => {
+                          setStartVelY(-value);
+                          setDisplayChange({
+                            xDisplay: positionXDisplay,
+                            yDisplay: positionYDisplay,
+                          });
+                        }}
+                        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" }}>
+                    {accelerationXDisplay} m/s<sup>2</sup>
+                  </td>
+                  <td style={{ cursor: "default" }}>
+                    {accelerationYDisplay} m/s<sup>2</sup>
+                  </td>
+                </tr>
+                <tr>
+                  <td>
+                    <Box>Momentum</Box>
+                  </td>
+                  <td>
+                    {Math.round(velocityXDisplay * mass * 10) / 10} kg*m/s
+                  </td>
+                  <td>
+                    {Math.round(velocityYDisplay * mass * 10) / 10} kg*m/s
+                  </td>
+                </tr>
+              </tbody>
+            </table>
+          )}
+          {mode == "Freeform" && simulationType == "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" }}>{positionXDisplay2} m</td>
+                  <td style={{ cursor: "default" }}>{positionYDisplay2} m</td>
+                </tr>
+                <tr>
+                  <td>
+                    <Box>Velocity</Box>
+                  </td>
+                  <td style={{ cursor: "default" }}>
+                    {velocityXDisplay2} m/s
+                  </td>
+
+                  <td style={{ cursor: "default" }}>
+                    {velocityYDisplay2} m/s
+                  </td>
+                </tr>
+                <tr>
+                  <td>
+                    <Box>Acceleration</Box>
+                  </td>
+                  <td style={{ cursor: "default" }}>
+                    {accelerationXDisplay2} m/s<sup>2</sup>
+                  </td>
+                  <td style={{ cursor: "default" }}>
+                    {accelerationYDisplay2} m/s<sup>2</sup>
+                  </td>
+                </tr>
+                <tr>
+                  <td>
+                    <Box>Momentum</Box>
+                  </td>
+                  <td>
+                    {Math.round(velocityXDisplay2 * mass * 10) / 10} kg*m/s
+                  </td>
+                  <td>
+                    {Math.round(velocityYDisplay2 * mass * 10) / 10} kg*m/s
+                  </td>
+                </tr>
+              </tbody>
+            </table>
+          )}
+        </div>
+        {simulationType != "Pendulum" && simulationType != "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>
+        )}
+        {simulationType == "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>
+        )}
+        {simulationType == "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: window.innerHeight - 120 + 20 + "px",
+        left: 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: window.innerHeight - 120 + 40 + "px",
+          left: xMin + 90 - 80 + "px",
+        }}
+      >
+        {simulationType == "Circular Motion" ? "Z" : "Y"}
+      </p>
+      <p
+        style={{
+          position: "fixed",
+          top: window.innerHeight - 120 + 80 + "px",
+          left: xMin + 90 - 40 + "px",
+        }}
+      >
+        X
+      </p>
+    </div>
+  </div>
   }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From f6ad7cf21b8763a0dd54275a8e433e473e382afe Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 1 May 2023 14:45:01 -0400
Subject: add box

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 355 ++++++++++-----------
 1 file changed, 177 insertions(+), 178 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 101cf1d4a..446c4933b 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -89,8 +89,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   // Constants
   const xMin = 0;
   const yMin = 0;
-  const xMax = window.innerWidth * 0.7;
-  const yMax = window.innerHeight * 0.8;
+  const xMax = 100;
+  const yMax = 100;
   const color = `rgba(0,0,0,0.5)`;
   const radius = 50;
   const wallPositions: IWallProps[] = [];
@@ -102,8 +102,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.wallPositions.push({ length: 80, xPos: 69.5, yPos: 0, angleInDegrees: 90 });
 
     // Used throughout sims
-    this.xMax = this.layoutDoc._width;
-    this.yMax = this.layoutDoc._height;
+    this.xMax = this.layoutDoc._width*0.08;
+    this.yMax = this.layoutDoc._height*0.08;
     this.radius = 0.1*this.layoutDoc._height;
     this.dataDoc.reviewCoefficient = this.dataDoc.reviewCoefficient ?? 0;
     this.dataDoc.questionVariables = this.dataDoc.questionVariables ?? [];
@@ -356,8 +356,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   }
 
   componentDidUpdate() {
-    this.xMax = this.layoutDoc._width;
-    this.yMax = this.layoutDoc._height;
+    this.xMax = this.layoutDoc._width*0.08;
+    this.yMax = this.layoutDoc._height*0.08;
     this.radius = 0.1*this.layoutDoc._height;
   }
 
@@ -1762,108 +1762,107 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   label="Show velocity vector"
                   labelPlacement="start"
                 />
-
                 <InputField
                   label={<Box>Speed</Box>}
                   lowerBound={1}
-                  changeValue={setSimulationSpeed}
+                  changeValue={this.dataDoc.simulationSpeed} //TODO - deal with input field change value now that datadoc is being used!
                   step={1}
                   unit={"x"}
                   upperBound={10}
-                  value={simulationSpeed}
+                  value={this.dataDoc.simulationSpeed}
                   labelWidth={"5em"}
                 />
-                {simulationPaused && simulationType != "Circular Motion" && (
+                {this.dataDoc.simulationPaused && this.dataDoc.simulationType != "Circular Motion" && (
                   <InputField
                     label={<Box>Gravity</Box>}
                     lowerBound={-30}
-                    changeValue={setGravity}
+                    changeValue={this.dataDoc.gravity}
                     step={0.01}
                     unit={"m/s2"}
                     upperBound={0}
-                    value={gravity}
+                    value={this.dataDoc.gravity}
                     effect={(val: number) => {
-                      setResetAll(!resetAll);
+                      this.dataDoc.resetAll = (!this.dataDoc.resetAll);
                     }}
                     labelWidth={"5em"}
                   />
                 )}
-                {simulationPaused && simulationType != "Pulley" && (
+                {this.dataDoc.simulationPaused && this.dataDoc.simulationType != "Pulley" && (
                   <InputField
                     label={<Box>Mass</Box>}
                     lowerBound={1}
-                    changeValue={setMass}
+                    changeValue={this.dataDoc.mass}
                     step={0.1}
                     unit={"kg"}
                     upperBound={5}
-                    value={mass}
+                    value={this.dataDoc.mass}
                     effect={(val: number) => {
-                      setResetAll(!resetAll);
+                      this.dataDoc.resetAll = (!this.dataDoc.resetAll);
                     }}
                     labelWidth={"5em"}
                   />
                 )}
-                {simulationPaused && simulationType == "Pulley" && (
+                {this.dataDoc.simulationPaused && this.dataDoc.simulationType == "Pulley" && (
                   <InputField
                     label={<Box>Red mass</Box>}
                     lowerBound={1}
-                    changeValue={setMass}
+                    changeValue={this.dataDoc.mass}
                     step={0.1}
                     unit={"kg"}
                     upperBound={5}
-                    value={mass}
+                    value={this.dataDoc.mass}
                     effect={(val: number) => {
-                      setResetAll(!resetAll);
+                      this.dataDoc.resetAll = (!this.dataDoc.resetAll);
                     }}
                     labelWidth={"5em"}
                   />
                 )}
-                {simulationPaused && simulationType == "Pulley" && (
+                {this.dataDoc.simulationPaused && this.dataDoc.simulationType == "Pulley" && (
                   <InputField
                     label={<Box>Blue mass</Box>}
                     lowerBound={1}
-                    changeValue={setMass2}
+                    changeValue={this.dataDoc.mass2}
                     step={0.1}
                     unit={"kg"}
                     upperBound={5}
-                    value={mass2}
+                    value={this.dataDoc.mass2}
                     effect={(val: number) => {
-                      setResetAll(!resetAll);
+                      this.dataDoc.resetAll = (!this.dataDoc.resetAll);
                     }}
                     labelWidth={"5em"}
                   />
                 )}
-                {simulationPaused && simulationType == "Circular Motion" && (
+                {this.dataDoc.simulationPaused && this.dataDoc.simulationType == "Circular Motion" && (
                   <InputField
                     label={<Box>Rod length</Box>}
                     lowerBound={100}
-                    changeValue={setCircularMotionRadius}
+                    changeValue={this.dataDoc.circularMotionRadius}
                     step={5}
                     unit={"kg"}
                     upperBound={250}
-                    value={circularMotionRadius}
+                    value={this.dataDoc.circularMotionRadius}
                     effect={(val: number) => {
-                      setResetAll(!resetAll);
+                      this.dataDoc.resetAll = (!this.dataDoc.resetAll);
                     }}
                     labelWidth={"5em"}
                   />
                 )}
               </FormGroup>
             </FormControl>
-            {simulationType == "Spring" && simulationPaused && (
+            {this.dataDoc.simulationType == "Spring" && this.dataDoc.simulationPaused && (
               <div>
                 <InputField
                   label={
                     <Typography color="inherit">Spring stiffness</Typography>
                   }
                   lowerBound={0.1}
-                  changeValue={setSpringConstant}
+                  changeValue={this.dataDoc.springConstant}
                   step={1}
                   unit={"N/m"}
                   upperBound={500}
                   value={springConstant}
                   effect={(val: number) => {
-                    setSimulationReset(!simulationReset);
+                    this.dataDoc.simulationReset(!this.dataDoc.simulationReset);
                   }}
                   radianEquivalent={false}
                   mode={"Freeform"}
@@ -1872,13 +1871,13 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 <InputField
                   label={<Typography color="inherit">Rest length</Typography>}
                   lowerBound={10}
-                  changeValue={setSpringRestLength}
+                  changeValue={this.dataDoc.springRestLength}
                   step={100}
                   unit={""}
                   upperBound={500}
-                  value={springRestLength}
+                  value={this.dataDoc.springRestLength}
                   effect={(val: number) => {
-                    setSimulationReset(!simulationReset);
+                    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
                   }}
                   radianEquivalent={false}
                   mode={"Freeform"}
@@ -1890,16 +1889,16 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                       Starting displacement
                     </Typography>
                   }
-                  lowerBound={-(springRestLength - 10)}
+                  lowerBound={-(this.dataDoc.springRestLength - 10)}
                   changeValue={(val: number) => {}}
                   step={10}
                   unit={""}
-                  upperBound={springRestLength}
-                  value={springStartLength - springRestLength}
+                  upperBound={this.dataDoc.springRestLength}
+                  value={this.dataDoc.springStartLength - this.dataDoc.springRestLength}
                   effect={(val: number) => {
-                    setStartPosY(springRestLength + val);
-                    setSpringStartLength(springRestLength + val);
-                    setSimulationReset(!simulationReset);
+                    this.dataDoc.startPosY = (this.dataDoc.springRestLength + val);
+                    this.dataDoc.springStartLength = (this.dataDoc.springRestLength + val);
+                    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
                   }}
                   radianEquivalent={false}
                   mode={"Freeform"}
@@ -1907,19 +1906,19 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 />
               </div>
             )}
-            {simulationType == "Inclined Plane" && simulationPaused && (
+            {this.dataDoc.simulationType == "Inclined Plane" && this.dataDoc.simulationPaused && (
               <div>
                 <InputField
                   label={<Box>&theta;</Box>}
                   lowerBound={0}
-                  changeValue={setWedgeAngle}
+                  changeValue={this.dataDoc.wedgeAngle}
                   step={1}
                   unit={"°"}
                   upperBound={49}
-                  value={wedgeAngle}
+                  value={this.dataDoc.wedgeAngle}
                   effect={(val: number) => {
-                    changeWedgeBasedOnNewAngle(val);
-                    setSimulationReset(!simulationReset);
+                    this.changeWedgeBasedOnNewAngle(val);
+                    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
                   }}
                   radianEquivalent={true}
                   mode={"Freeform"}
@@ -1932,17 +1931,17 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     </Box>
                   }
                   lowerBound={0}
-                  changeValue={setCoefficientOfStaticFriction}
+                  changeValue={this.dataDoc.coefficientOfStaticFriction}
                   step={0.1}
                   unit={""}
                   upperBound={1}
-                  value={coefficientOfStaticFriction}
+                  value={this.dataDoc.coefficientOfStaticFriction}
                   effect={(val: number) => {
-                    updateForcesWithFriction(val);
-                    if (val < Number(coefficientOfKineticFriction)) {
-                      setCoefficientOfKineticFriction(val);
+                    this.updateForcesWithFriction(val);
+                    if (val < Number(this.dataDoc.coefficientOfKineticFriction)) {
+                      this.dataDoc.soefficientOfKineticFriction = (val);
                     }
-                    setSimulationReset(!simulationReset);
+                    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
                   }}
                   mode={"Freeform"}
                   labelWidth={"2em"}
@@ -1954,54 +1953,54 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     </Box>
                   }
                   lowerBound={0}
-                  changeValue={setCoefficientOfKineticFriction}
+                  changeValue={this.dataDoc.coefficientOfKineticFriction}
                   step={0.1}
                   unit={""}
-                  upperBound={Number(coefficientOfStaticFriction)}
-                  value={coefficientOfKineticFriction}
+                  upperBound={Number(this.dataDoc.coefficientOfStaticFriction)}
+                  value={this.dataDoc.coefficientOfKineticFriction}
                   effect={(val: number) => {
-                    setSimulationReset(!simulationReset);
+                    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
                   }}
                   mode={"Freeform"}
                   labelWidth={"2em"}
                 />
               </div>
             )}
-            {simulationType == "Inclined Plane" && !simulationPaused && (
+            {this.dataDoc.simulationType == "Inclined Plane" && !this.dataDoc.simulationPaused && (
               <Typography>
-                &theta;: {Math.round(Number(wedgeAngle) * 100) / 100}° ≈{" "}
-                {Math.round(((Number(wedgeAngle) * Math.PI) / 180) * 100) /
+                &theta;: {Math.round(Number(this.dataDoc.wedgeAngle) * 100) / 100}° ≈{" "}
+                {Math.round(((Number(this.dataDoc.wedgeAngle) * Math.PI) / 180) * 100) /
                   100}{" "}
                 rad
                 <br />
-                &mu; <sub>s</sub>: {coefficientOfStaticFriction}
+                &mu; <sub>s</sub>: {this.dataDoc.coefficientOfStaticFriction}
                 <br />
-                &mu; <sub>k</sub>: {coefficientOfKineticFriction}
+                &mu; <sub>k</sub>: {this.dataDoc.coefficientOfKineticFriction}
               </Typography>
             )}
-            {simulationType == "Pendulum" && !simulationPaused && (
+            {this.dataDoc.simulationType == "Pendulum" && !this.dataDoc.simulationPaused && (
               <Typography>
-                &theta;: {Math.round(pendulumAngle * 100) / 100}° ≈{" "}
-                {Math.round(((pendulumAngle * Math.PI) / 180) * 100) / 100}{" "}
+                &theta;: {Math.round(this.dataDoc.pendulumAngle * 100) / 100}° ≈{" "}
+                {Math.round(((this.dataDoc.pendulumAngle * Math.PI) / 180) * 100) / 100}{" "}
                 rad
               </Typography>
             )}
-            {simulationType == "Pendulum" && simulationPaused && (
+            {this.dataDoc.simulationType == "Pendulum" && this.dataDoc.simulationPaused && (
               <div>
                 <InputField
                   label={<Box>Angle</Box>}
                   lowerBound={0}
-                  changeValue={setPendulumAngle}
+                  changeValue={this.dataDoc.pendulumAngle}
                   step={1}
                   unit={"°"}
                   upperBound={59}
-                  value={pendulumAngle}
+                  value={this.dataDoc.pendulumAngle}
                   effect={(value) => {
-                    setStartPendulumAngle(value);
+                    this.dataDoc.startPendulumAngle = (value);
                     if (simulationType == "Pendulum") {
                       const mag =
                         mass *
-                        Math.abs(gravity) *
+                        Math.abs(this.dataDoc.gravity) *
                         Math.cos((value * Math.PI) / 180);
 
                       const forceOfTension: IForce = {
@@ -2020,7 +2019,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                       const gravityParallel: IForce = {
                         description: "Gravity Parallel Component",
                         magnitude:
-                          Math.abs(gravity) *
+                          Math.abs(this.dataDoc.gravity) *
                           Math.cos((value * Math.PI) / 180),
                         directionInDegrees: 270 - value,
                         component: true,
@@ -2028,50 +2027,50 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                       const gravityPerpendicular: IForce = {
                         description: "Gravity Perpendicular Component",
                         magnitude:
-                          Math.abs(gravity) *
+                          Math.abs(this.dataDoc.gravity) *
                           Math.sin((value * Math.PI) / 180),
                         directionInDegrees: -value,
                         component: true,
                       };
 
-                      const length = pendulumLength;
+                      const length = this.dataDoc.pendulumLength;
                       const x =
                         length * Math.cos(((90 - value) * Math.PI) / 180);
                       const y =
                         length * Math.sin(((90 - value) * Math.PI) / 180);
-                      const xPos = xMax / 2 - x - radius;
+                      const xPos = this.xMax / 2 - x - radius;
                       const yPos = y - radius - 5;
-                      setStartPosX(xPos);
-                      setStartPosY(yPos);
+                      this.dataDoc.startPosX = (xPos);
+                      this.dataDoc.startPosY= (yPos);
 
-                      setStartForces([
+                      this.dataDoc.startForces = ([
                         {
                           description: "Gravity",
-                          magnitude: Math.abs(gravity) * mass,
+                          magnitude: Math.abs(this.dataDoc.gravity) * this.dataDoc.mass,
                           directionInDegrees: 270,
                           component: false,
                         },
                         forceOfTension,
                       ]);
-                      setUpdatedForces([
+                      this.dataDoc.updatedForces = ([
                         {
                           description: "Gravity",
-                          magnitude: Math.abs(gravity) * mass,
+                          magnitude: Math.abs(this.dataDoc.gravity) * this.dataDoc.mass,
                           directionInDegrees: 270,
                           component: false,
                         },
                         forceOfTension,
                       ]);
-                      setComponentForces([
+                      this.dataDoc.componentForces = ([
                         tensionComponent,
                         gravityParallel,
                         gravityPerpendicular,
                       ]);
-                      setAdjustPendulumAngle({
+                      this.dataDoc.adjustPendulumAngle = ({
                         angle: value,
                         length: pendulumLength,
                       });
-                      setSimulationReset(!simulationReset);
+                      this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
                     }
                   }}
                   radianEquivalent={true}
@@ -2081,18 +2080,18 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 <InputField
                   label={<Box>Rod length</Box>}
                   lowerBound={0}
-                  changeValue={setPendulumLength}
+                  changeValue={this.dataDoc.pendulumLength}
                   step={1}
                   unit={"m"}
                   upperBound={400}
-                  value={Math.round(pendulumLength)}
+                  value={Math.round(this.dataDoc.pendulumLength)}
                   effect={(value) => {
                     if (simulationType == "Pendulum") {
-                      setAdjustPendulumAngle({
-                        angle: pendulumAngle,
+                      this.dataDoc.adjustPendulumAngle = ({
+                        angle: this.dataDoc.pendulumAngle,
                         length: value,
                       });
-                      setSimulationReset(!simulationReset);
+                      this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
                     }
                   }}
                   radianEquivalent={false}
@@ -2104,39 +2103,39 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
           </div>
         )}
         <div className="mechanicsSimulationEquation">
-          {mode == "Freeform" && (
+          {this.dataDoc.mode == "Freeform" && (
             <table>
               <tbody>
                 <tr>
-                  <td>{simulationType == "Pulley" ? "Red Weight" : ""}</td>
+                  <td>{this.dataDoc.simulationType == "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"
-                      );
-                    }}
+                    // onClick={() => {
+                    //   window.open(
+                    //     "https://www.khanacademy.org/science/physics/two-dimensional-motion"
+                    //   );
+                    // }}
                   >
                     <Box>Position</Box>
                   </td>
-                  {(!simulationPaused ||
-                    simulationType == "Inclined Plane" ||
-                    simulationType == "Suspension" ||
-                    simulationType == "Circular Motion" ||
-                    simulationType == "Pulley") && (
+                  {(!this.dataDoc.simulationPaused ||
+                    this.dataDoc.simulationType == "Inclined Plane" ||
+                    this.dataDoc.simulationType == "Suspension" ||
+                    this.dataDoc.simulationType == "Circular Motion" ||
+                    this.dataDoc.simulationType == "Pulley") && (
                     <td style={{ cursor: "default" }}>
-                      {positionXDisplay} m
+                      {this.dataDoc.positionXDisplay} m
                     </td>
                   )}{" "}
-                  {simulationPaused &&
-                    simulationType != "Inclined Plane" &&
-                    simulationType != "Suspension" &&
-                    simulationType != "Circular Motion" &&
-                    simulationType != "Pulley" && (
+                  {this.dataDoc.simulationPaused &&
+                    this.dataDoc.simulationType != "Inclined Plane" &&
+                    this.dataDoc.simulationType != "Suspension" &&
+                    this.dataDoc.simulationType != "Circular Motion" &&
+                    this.dataDoc.simulationType != "Pulley" && (
                       <td
                         style={{
                           cursor: "default",
@@ -2144,15 +2143,15 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                       >
                         <InputField
                           lowerBound={0}
-                          changeValue={setPositionXDisplay}
+                          changeValue={this.dataDoc.positionXDisplay}
                           step={1}
                           unit={"m"}
-                          upperBound={xMax - 110}
-                          value={positionXDisplay}
+                          upperBound={this.xMax - 110}
+                          value={this.dataDoc.positionXDisplay}
                           effect={(value) => {
-                            setDisplayChange({
+                            this.dataDoc.displayChange = ({
                               xDisplay: value,
-                              yDisplay: positionYDisplay,
+                              yDisplay: this.dataDoc.positionYDisplay,
                             });
                           }}
                           small={true}
@@ -2160,20 +2159,20 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                         />
                       </td>
                     )}{" "}
-                  {(!simulationPaused ||
-                    simulationType == "Inclined Plane" ||
-                    simulationType == "Suspension" ||
-                    simulationType == "Circular Motion" ||
-                    simulationType == "Pulley") && (
+                  {(!this.dataDoc.simulationPaused ||
+                    this.dataDoc.simulationType == "Inclined Plane" ||
+                    this.dataDoc.simulationType == "Suspension" ||
+                    this.dataDoc.simulationType == "Circular Motion" ||
+                    this.dataDoc.simulationType == "Pulley") && (
                     <td style={{ cursor: "default" }}>
-                      {positionYDisplay} m
+                      {this.dataDoc.positionYDisplay} m
                     </td>
                   )}{" "}
-                  {simulationPaused &&
-                    simulationType != "Inclined Plane" &&
-                    simulationType != "Suspension" &&
-                    simulationType != "Circular Motion" &&
-                    simulationType != "Pulley" && (
+                  {this.dataDoc.simulationPaused &&
+                    this.dataDoc.simulationType != "Inclined Plane" &&
+                    this.dataDoc.simulationType != "Suspension" &&
+                    this.dataDoc.simulationType != "Circular Motion" &&
+                    this.dataDoc.simulationType != "Pulley" && (
                       <td
                         style={{
                           cursor: "default",
@@ -2181,14 +2180,14 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                       >
                         <InputField
                           lowerBound={0}
-                          changeValue={setPositionYDisplay}
+                          changeValue={this.dataDoc.positionYDisplay}
                           step={1}
                           unit={"m"}
-                          upperBound={yMax - 110}
-                          value={positionYDisplay}
+                          upperBound={this.yMax - 110}
+                          value={this.dataDoc.positionYDisplay}
                           effect={(value) => {
-                            setDisplayChange({
-                              xDisplay: positionXDisplay,
+                            this.dataDoc.displayChange = ({
+                              xDisplay: this.dataDoc.positionXDisplay,
                               yDisplay: value,
                             });
                           }}
@@ -2201,24 +2200,24 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 <tr>
                   <td
                     style={{ cursor: "help" }}
-                    onClick={() => {
-                      window.open(
-                        "https://www.khanacademy.org/science/physics/two-dimensional-motion"
-                      );
-                    }}
+                    // onClick={() => {
+                    //   window.open(
+                    //     "https://www.khanacademy.org/science/physics/two-dimensional-motion"
+                    //   );
+                    // }}
                   >
                     <Box>Velocity</Box>
                   </td>
-                  {(!simulationPaused ||
-                    (simulationType != "One Weight" &&
-                      simulationType != "Circular Motion")) && (
+                  {(!this.dataDoc.simulationPaused ||
+                    (this.dataDoc.simulationType != "One Weight" &&
+                    this.dataDoc.simulationType != "Circular Motion")) && (
                     <td style={{ cursor: "default" }}>
-                      {velocityXDisplay} m/s
+                      {this.dataDoc.velocityXDisplay} m/s
                     </td>
                   )}{" "}
-                  {simulationPaused &&
-                    (simulationType == "One Weight" ||
-                      simulationType == "Circular Motion") && (
+                  {this.dataDoc.simulationPaused &&
+                    (this.dataDoc.simulationType == "One Weight" ||
+                    this.dataDoc.simulationType == "Circular Motion") && (
                       <td
                         style={{
                           cursor: "default",
@@ -2226,26 +2225,26 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                       >
                         <InputField
                           lowerBound={-50}
-                          changeValue={setVelocityXDisplay}
+                          changeValue={this.dataDoc.velocityXDisplay}
                           step={1}
                           unit={"m/s"}
                           upperBound={50}
-                          value={velocityXDisplay}
+                          value={this.dataDoc.velocityXDisplay}
                           effect={(value) => {
-                            setStartVelX(value);
-                            setSimulationReset(!simulationReset);
+                            this.dataDoc.startVelX = (value);
+                            this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
                           }}
                           small={true}
                           mode={"Freeform"}
                         />
                       </td>
                     )}{" "}
-                  {(!simulationPaused || simulationType != "One Weight") && (
+                  {(!this.dataDoc.simulationPaused || this.dataDoc.simulationType != "One Weight") && (
                     <td style={{ cursor: "default" }}>
-                      {velocityYDisplay} m/s
+                      {this.dataDoc.velocityYDisplay} m/s
                     </td>
                   )}{" "}
-                  {simulationPaused && simulationType == "One Weight" && (
+                  {this.dataDoc.simulationPaused && this.dataDoc.simulationType == "One Weight" && (
                     <td
                       style={{
                         cursor: "default",
@@ -2253,16 +2252,16 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     >
                       <InputField
                         lowerBound={-50}
-                        changeValue={setVelocityYDisplay}
+                        changeValue={this.dataDoc.velocityYDisplay}
                         step={1}
                         unit={"m/s"}
                         upperBound={50}
-                        value={velocityYDisplay}
+                        value={this.dataDoc.velocityYDisplay}
                         effect={(value) => {
-                          setStartVelY(-value);
-                          setDisplayChange({
-                            xDisplay: positionXDisplay,
-                            yDisplay: positionYDisplay,
+                          this.dataDoc.startVelY = (-value);
+                          this.dataDoc.displayChange = ({
+                            xDisplay: this.dataDoc.positionXDisplay,
+                            yDisplay: this.dataDoc.positionYDisplay,
                           });
                         }}
                         small={true}
@@ -2274,19 +2273,19 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 <tr>
                   <td
                     style={{ cursor: "help" }}
-                    onClick={() => {
-                      window.open(
-                        "https://www.khanacademy.org/science/physics/two-dimensional-motion"
-                      );
-                    }}
+                    // onClick={() => {
+                    //   window.open(
+                    //     "https://www.khanacademy.org/science/physics/two-dimensional-motion"
+                    //   );
+                    // }}
                   >
                     <Box>Acceleration</Box>
                   </td>
                   <td style={{ cursor: "default" }}>
-                    {accelerationXDisplay} m/s<sup>2</sup>
+                    {this.dataDoc.accelerationXDisplay} m/s<sup>2</sup>
                   </td>
                   <td style={{ cursor: "default" }}>
-                    {accelerationYDisplay} m/s<sup>2</sup>
+                    {this.dataDoc.accelerationYDisplay} m/s<sup>2</sup>
                   </td>
                 </tr>
                 <tr>
@@ -2294,16 +2293,16 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     <Box>Momentum</Box>
                   </td>
                   <td>
-                    {Math.round(velocityXDisplay * mass * 10) / 10} kg*m/s
+                    {Math.round(this.dataDoc.velocityXDisplay * this.dataDoc.mass * 10) / 10} kg*m/s
                   </td>
                   <td>
-                    {Math.round(velocityYDisplay * mass * 10) / 10} kg*m/s
+                    {Math.round(this.dataDoc.velocityYDisplay * this.dataDoc.mass * 10) / 10} kg*m/s
                   </td>
                 </tr>
               </tbody>
             </table>
           )}
-          {mode == "Freeform" && simulationType == "Pulley" && (
+          {this.dataDoc.mode == "Freeform" && this.dataDoc.simulationType == "Pulley" && (
             <table>
               <tbody>
                 <tr>
@@ -2315,19 +2314,19 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   <td>
                     <Box>Position</Box>
                   </td>
-                  <td style={{ cursor: "default" }}>{positionXDisplay2} m</td>
-                  <td style={{ cursor: "default" }}>{positionYDisplay2} m</td>
+                  <td style={{ cursor: "default" }}>{this.dataDoc.positionXDisplay2} m</td>
+                  <td style={{ cursor: "default" }}>{this.dataDoc.positionYDisplay2} m</td>
                 </tr>
                 <tr>
                   <td>
                     <Box>Velocity</Box>
                   </td>
                   <td style={{ cursor: "default" }}>
-                    {velocityXDisplay2} m/s
+                    {this.dataDoc.velocityXDisplay2} m/s
                   </td>
 
                   <td style={{ cursor: "default" }}>
-                    {velocityYDisplay2} m/s
+                    {this.dataDoc.velocityYDisplay2} m/s
                   </td>
                 </tr>
                 <tr>
@@ -2335,10 +2334,10 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     <Box>Acceleration</Box>
                   </td>
                   <td style={{ cursor: "default" }}>
-                    {accelerationXDisplay2} m/s<sup>2</sup>
+                    {this.dataDoc.accelerationXDisplay2} m/s<sup>2</sup>
                   </td>
                   <td style={{ cursor: "default" }}>
-                    {accelerationYDisplay2} m/s<sup>2</sup>
+                    {this.dataDoc.accelerationYDisplay2} m/s<sup>2</sup>
                   </td>
                 </tr>
                 <tr>
@@ -2346,17 +2345,17 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     <Box>Momentum</Box>
                   </td>
                   <td>
-                    {Math.round(velocityXDisplay2 * mass * 10) / 10} kg*m/s
+                    {Math.round(this.dataDoc.velocityXDisplay2 * this.dataDoc.mass * 10) / 10} kg*m/s
                   </td>
                   <td>
-                    {Math.round(velocityYDisplay2 * mass * 10) / 10} kg*m/s
+                    {Math.round(this.dataDoc.velocityYDisplay2 * this.dataDoc.mass * 10) / 10} kg*m/s
                   </td>
                 </tr>
               </tbody>
             </table>
           )}
         </div>
-        {simulationType != "Pendulum" && simulationType != "Spring" && (
+        {this.dataDoc.simulationType != "Pendulum" && this.dataDoc.simulationType != "Spring" && (
           <div>
             <p>Kinematic Equations</p>
             <ul>
@@ -2373,7 +2372,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             </ul>
           </div>
         )}
-        {simulationType == "Spring" && (
+        {this.dataDoc.simulationType == "Spring" && (
           <div>
             <p>Harmonic Motion Equations: Spring</p>
             <ul>
@@ -2409,7 +2408,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             </ul>
           </div>
         )}
-        {simulationType == "Pendulum" && (
+        {this.dataDoc.simulationType == "Pendulum" && (
           <div>
             <p>Harmonic Motion Equations: Pendulum</p>
             <ul>
@@ -2425,8 +2424,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     <div
       style={{
         position: "fixed",
-        top: window.innerHeight - 120 + 20 + "px",
-        left: xMin + 90 - 80 + "px",
+        top: this.layoutDoc._height - 120 + 20 + "px",
+        left: this.xMin + 90 - 80 + "px",
         zIndex: -10000,
       }}
     >
@@ -2466,8 +2465,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       <p
         style={{
           position: "fixed",
-          top: window.innerHeight - 120 + 40 + "px",
-          left: xMin + 90 - 80 + "px",
+          top: this.layoutDoc._height - 120 + 40 + "px",
+          left: this.xMin + 90 - 80 + "px",
         }}
       >
         {simulationType == "Circular Motion" ? "Z" : "Y"}
@@ -2475,8 +2474,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       <p
         style={{
           position: "fixed",
-          top: window.innerHeight - 120 + 80 + "px",
-          left: xMin + 90 - 40 + "px",
+          top: this.layoutDoc._height - 120 + 80 + "px",
+          left: this.xMin + 90 - 40 + "px",
         }}
       >
         X
-- 
cgit v1.2.3-70-g09d2


From 90baacc3f8104c3e401473cac9a0a3bd574f960d Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 1 May 2023 14:58:32 -0400
Subject: refactor weight

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      |   10 -
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   | 1697 ++++++++++++++------
 2 files changed, 1240 insertions(+), 467 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 446c4933b..bdc76048c 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -133,7 +133,6 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.startVelX = this.dataDoc.startVelX ?? 0;
     this.dataDoc.startVelY = this.dataDoc.startVelY ?? 0;
     this.dataDoc.stepNumber = this.dataDoc.stepNumber ?? 0;
-    this.dataDoc.timer = this.dataDoc.timer ?? 0;
     this.dataDoc.updatedForces = this.dataDoc.updatedForces ?? [];
     this.dataDoc.velocityXDisplay = this.dataDoc.velocityXDisplay ?? 0;
     this.dataDoc.velocityYDisplay = this.dataDoc.velocityYDisplay ?? 0;
@@ -1232,13 +1231,6 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     ]);
   }
 
-  // Timer for animating the simulation, update every 0.05 seconds
-  setInterval(() => {
-    setTimer(timer + 1);
-  }, 50);
-
-
-
   render () { 
     <div className="physicsSimApp">
     <div className="mechanicsSimulationContainer">
@@ -1301,7 +1293,6 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               displayXVelocity={this.dataDoc.velocityXDisplay}
               displayYVelocity={this.dataDoc.velocityYDisplay}
               elasticCollisions={this.dataDoc.elasticCollisions}
-              incrementTime={this.dataDoc.timer}
               mass={this.dataDoc.mass}
               mode={this.dataDoc.mode}
               noMovement={this.dataDoc.noMovement}
@@ -1350,7 +1341,6 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 displayXVelocity={this.dataDoc.velocityXDisplay2}
                 displayYVelocity={this.dataDoc.velocityYDisplay2}
                 elasticCollisions={this.dataDoc.elasticCollisions}
-                incrementTime={this.dataDoc.timer}
                 mass={this.dataDoc.mass2}
                 mode={this.dataDoc.mode}
                 noMovement={this.dataDoc.noMovement}
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 39b3249e8..3bc02cfdd 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -1,27 +1,54 @@
-import React = require('react');
 import { Doc } from '../../../fields/Doc';
-import { IWallProps } from "./PhysicsSimulationWall";
+import React = require('react');
+import { useEffect, useState } from "react";
+import { IWallProps } from "./Wall";
+import "./Weight.scss";
 
 export interface IForce {
   description: string;
   magnitude: number;
   directionInDegrees: number;
+  component: boolean;
 }
 export interface IWeightProps {
-  adjustPendulumAngle: boolean;
+  dataDoc: doc;
+  adjustPendulumAngle: { angle: number; length: number };
+  circularMotionRadius: number;
+  coefficientOfKineticFriction: number;
   color: string;
-  dataDoc: Doc;
+  componentForces: IForce[];
+  displayXVelocity: number;
+  displayYVelocity: number;
+  elasticCollisions: boolean;
+  gravity: number;
+  incrementTime: number;
   mass: number;
+  mode: string;
+  noMovement: boolean;
+  paused: boolean;
+  pendulumAngle: number;
+  pendulumLength: number;
   radius: number;
-  simulationReset: boolean;
+  reset: boolean;
+  showAcceleration: boolean;
+  showComponentForces: boolean;
+  showForceMagnitudes: boolean;
+  showForces: boolean;
+  showVelocity: boolean;
+  simulationSpeed: number;
+  simulationType: string;
+  springConstant: number;
+  springRestLength: number;
+  springStartLength: number;
+  startForces: IForce[];
+  startPendulumAngle: number;
   startPosX: number;
   startPosY: number;
-  startVelX?: number;
-  startVelY?: number;
+  startVelX: number;
+  startVelY: number;
   timestepSize: number;
-  updateDisplay: boolean,
-  walls: IWallProps[];
-  wedge: boolean;
+  updateDisplay: { xDisplay: number; yDisplay: number };
+  updatedForces: IForce[];
   wedgeHeight: number;
   wedgeWidth: number;
   xMax: number;
@@ -34,47 +61,64 @@ interface IState {
   angleLabel: number,
   clickPositionX: number,
   clickPositionY: number,
+  coordinates: string,
   dragging: boolean,
   kineticFriction: boolean,
-  timer: number;
+  maxPosYConservation: number,
+  timer: number,
   update: boolean,
   updatedStartPosX: number,
   updatedStartPosY: number,
+  walls: IWallProps[],
   xPosition: number,
   xVelocity: number,
   yPosition: number,
   yVelocity: number,
+  xAccel: number,
+  yAccel: number,
 }
+
 export default class Weight extends React.Component<IWeightProps, IState> {
 
   constructor(props: any) {
     super(props)
     this.state = {
+      angleLabel: 0,
       clickPositionX: 0,
       clickPositionY: 0,
+      coordinates: "",
       dragging: false,
       kineticFriction: false,
+      maxPosYConservation: 0,
       timer: 0,
-      angleLabel: 0,
       updatedStartPosX: this.props.dataDoc['startPosX'],
       updatedStartPosY: this.props.dataDoc['startPosY'],
+      walls: [],
       xPosition: this.props.dataDoc['startPosX'],
       xVelocity: this.props.startVelX ? this.props.startVelX: 0,
       yPosition: this.props.dataDoc['startPosY'],
       yVelocity: this.props.startVelY ? this.props.startVelY: 0,
+      xAccel: 0,
+      yAccel: 0,
     }
   }
 
+  componentDidMount() {
+    // Timer for animating the simulation
+    setInterval(() => {
+      this.setState({timer: this.state.timer + 1});
+    }, 50);
+  }
+
   // Constants
-  draggable = !this.props.dataDoc['wedge'] ;
-  epsilon = 0.0001;
-  forceOfGravity: IForce = {
-    description: "Gravity",
-    magnitude: this.props.mass * 9.81,
-    directionInDegrees: 270,
-  };
+  const draggable =
+    this.props.dataDoc['simulationType'] != "Inclined Plane" &&
+    this.props.dataDoc['simulationType'] != "Pendulum" &&
+    this.props.dataDoc['mode'] == "Freeform";
+  const epsilon = 0.0001;
+  const labelBackgroundColor = `rgba(255,255,255,0.5)`;
 
-  // Var
+  // Variables
   weightStyle = {
     alignItems: "center",
     backgroundColor: this.props.color,
@@ -115,6 +159,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     this.props.dataDoc['velocityXDisplay'] = Math.round(xVel * 100) / 100;
   };
 
+  // Update display values when simulation updates
   setDisplayValues = (
     xPos: number = this.state.xPosition,
     yPos: number = this.state.yPosition,
@@ -133,208 +178,121 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     ;
   };
 
-  componentDidMount() {
-    // Timer for animating the simulation
-    setInterval(() => {
-      this.setState({timer: this.state.timer + 1});
-    }, 60);
+  componentDidUpdate(prevProps: Readonly<IWeightProps>, prevState: Readonly<IState>, snapshot?: any): void {
   }
 
-  componentDidUpdate(prevProps: Readonly<IWeightProps>, prevState: Readonly<IState>, snapshot?: any): void {
-    
-    // When display values updated by user, update real values
-    if (this.props.updateDisplay != prevProps.updateDisplay) {
-      if (this.props.dataDoc['positionXDisplay'] != this.state.xPosition) {
-        let x = this.props.dataDoc['positionXDisplay'];
-        x = Math.max(0, x);
-        x = Math.min(x, this.props.xMax - 2 * this.props.radius);
-        this.setState({updatedStartPosX: x})
-        this.setState({xPosition: x})
-        this.props.dataDoc['positionXDisplay'] = x;
-      }
-  
-      if (this.props.dataDoc['positionYDisplay'] != this.getDisplayYPos(this.state.yPosition)) {
-        let y = this.props.dataDoc['positionYDisplay'];
-        y = Math.max(0, y);
-        y = Math.min(y, this.props.yMax - 2 * this.props.radius);
-        this.props.dataDoc['positionYDisplay'] = y;
-        let coordinatePosition = this.getYPosFromDisplay(y);
-        this.setState({updatedStartPosY: coordinatePosition})
-        this.setState({yPosition: coordinatePosition})
-      }
-  
-      if (this.props.dataDoc['velocityXDisplay'] != this.state.xVelocity) {
-        let x = this.props.dataDoc['velocityXDisplay'];
-        this.setState({xVelocity: x})
-        this.props.dataDoc['velocityXDisplay'] = x;
-      }
-  
-      if (this.props.dataDoc['velocityYDisplay'] != this.state.yVelocity) {
-        let y = this.props.dataDoc['velocityYDisplay'];
-        this.setState({yVelocity: -y})
-        this.props.dataDoc['velocityYDisplay']
-      }
-    }
-    // Update sim
-    if (this.state.timer != prevState.timer) {
-      if (!this.props.dataDoc['simulationPaused']) {
-        let collisions = false;
-        if (!this.props.dataDoc['pendulum']) {
-          const collisionsWithGround = this.checkForCollisionsWithGround();
-          const collisionsWithWalls = this.checkForCollisionsWithWall();
-          collisions = collisionsWithGround || collisionsWithWalls;
-        }
-        if (!collisions) {
-          this.update();
-        }
-        this.setDisplayValues();
-      }
-    }
 
-    if (this.props.simulationReset != prevProps.simulationReset) {
-      this.resetEverything();
-    }
-    if (this.props.adjustPendulumAngle != prevProps.adjustPendulumAngle) {
-      console.log('update angle')
-      // Change pendulum angle based on input field
-      let length = this.props.dataDoc['pendulumLength'] ?? 0;
-      const x =
-        length * Math.cos(((90 - this.props.dataDoc['pendulumAngle']) * Math.PI) / 180);
-      const y =
-        length * Math.sin(((90 - this.props.dataDoc['pendulumAngle']) * Math.PI) / 180);
-      const xPos = this.props.xMax / 2 - x - this.props.radius;
-      const yPos = y - this.props.radius - 5;
-      this.setState({xPosition: xPos})
-      this.setState({yPosition: yPos})
-      this.setState({updatedStartPosX: xPos})
-      this.setState({updatedStartPosY: yPos})
-      this.setState({angleLabel: Math.round(this.props.dataDoc['pendulumAngle'] * 100) / 100})
-    }
-    // Update x start position
-    if (this.props.startPosX != prevProps.startPosX) {
-      this.setState({updatedStartPosX: this.props.dataDoc['startPosX']})
-      this.setState({xPosition: this.props.dataDoc['startPosX']})
-      this.setXPosDisplay(this.props.dataDoc['startPosX']);
-    }
-    // Update y start position
-    if (this.props.startPosY != prevProps.startPosY) {
-      this.setState({updatedStartPosY: this.props.dataDoc['startPosY']})
-      this.setState({yPosition: this.props.dataDoc['startPosY']})
-      this.setYPosDisplay(this.props.dataDoc['startPosY']);
-    }
-    if (!this.props.dataDoc['simulationPaused']) {
-      if (this.state.xVelocity != prevState.xVelocity) {
-        if (this.props.dataDoc['wedge']  && this.state.xVelocity != 0 && !this.state.kineticFriction) {
-          this.setState({kineticFriction: true});
-          //switch from static to kinetic friction
-          const normalForce: IForce = {
-            description: "Normal Force",
-            magnitude:
-              this.forceOfGravity.magnitude *
-              Math.cos(Math.atan(this.props.dataDoc['wedgeHeight']  / this.props.dataDoc['wedgeWidth'] )),
-            directionInDegrees:
-              180 - 90 - (Math.atan(this.props.dataDoc['wedgeHeight']  / this.props.dataDoc['wedgeWidth'] ) * 180) / Math.PI,
-          };
-          let frictionForce: IForce = {
-            description: "Kinetic Friction Force",
-            magnitude:
-            this.props.dataDoc['coefficientOfKineticFriction'] *
-              this.forceOfGravity.magnitude *
-              Math.cos(Math.atan(this.props.dataDoc['wedgeHeight']  / this.props.dataDoc['wedgeWidth'] )),
-            directionInDegrees:
-              180 - (Math.atan(this.props.dataDoc['wedgeHeight']  / this.props.dataDoc['wedgeWidth'] ) * 180) / Math.PI,
-          };
-          // reduce magnitude of friction force if necessary such that block cannot slide up plane
-          let yForce = -this.forceOfGravity.magnitude;
-          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) +
-                this.forceOfGravity.magnitude) /
-              Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
-          }
-          if (this.props.dataDoc['coefficientOfKineticFriction'] != 0) {
-            this.props.dataDoc['updatedForces'] = [this.forceOfGravity, normalForce, frictionForce];
-          } else {
-            this.props.dataDoc['updatedForces'] = ([this.forceOfGravity, normalForce]);
-          }
-        }
-      }
-    }
 
-    this.weightStyle = {
-      alignItems: "center",
-      backgroundColor: this.props.color,
-      borderColor: this.state.dragging ? "lightblue" : "black",
-      borderRadius: 50 + "%",
-      borderStyle: "solid",
-      display: "flex",
-      height: 2 * this.props.radius + "px",
-      justifyContent: "center",
-      left: this.state.xPosition + "px",
-      position: "absolute" as "absolute",
-      top: this.state.yPosition + "px",
-      touchAction: "none",
-      width: 2 * this.props.radius + "px",
-      zIndex: 5,
-    };
-  }
 
+
+
+
+  // Reset simulation on reset button click
   resetEverything = () => {
     this.setState({kineticFriction: false})
     this.setState({xPosition: this.state.updatedStartPosX})
     this.setState({yPosition: this.state.updatedStartPosY})
     this.setState({xVelocity: this.props.startVelX ?? 0})
     this.setState({yVelocity: this.props.startVelY ?? 0})
+    this.props.dataDoc['pendulumAngle'] = this.props.dataDoc['startPendulumAngle']
     this.props.dataDoc['updatedForces'] = (this.props.dataDoc['startForces'])
+    this.props.dataDoc['accelerationXDisplay'] = 0
+    this.props.dataDoc['accelerationYDisplay'] = 0
+    this.props.dataDoc['positionXDisplay'] = this.state.updatedStartPosX
+    this.props.dataDoc['positionYDisplay'] = this.state.updatedStartPosY
+    this.props.dataDoc['velocityXDisplay'] = this.props.startVelX ?? 0
+    this.props.dataDoc['velocityYDisplay'] = this.props.startVelY ?? 0
     this.setState({angleLabel: Math.round(this.props.dataDoc['pendulumAngle']* 100) / 100})
-    this.setDisplayValues();
   };
 
-  getNewAccelerationX = (forceList: IForce[]) => {
+
+  // Compute x acceleration from forces, F=ma
+  const getNewAccelerationX = (forceList: IForce[]) => {
     let newXAcc = 0;
-    if (forceList) {
-      forceList.forEach((force) => {
+    forceList.forEach((force) => {
+      if (force.component == false) {
         newXAcc +=
           (force.magnitude *
             Math.cos((force.directionInDegrees * Math.PI) / 180)) /
-          this.props.mass;
-      });
-    }
+          mass;
+      }
+    });
     return newXAcc;
   };
 
-  getNewAccelerationY = (forceList: IForce[]) => {
+  // Compute y acceleration from forces, F=ma
+  const getNewAccelerationY = (forceList: IForce[]) => {
     let newYAcc = 0;
-    if (forceList) {
-      forceList.forEach((force) => {
+    forceList.forEach((force) => {
+      if (force.component == false) {
         newYAcc +=
           (-1 *
             (force.magnitude *
               Math.sin((force.directionInDegrees * Math.PI) / 180))) /
-            this.props.mass;
-      });
-    }
+          mass;
+      }
+    });
     return newYAcc;
   };
 
-  getNewForces = (
+  // Compute uniform circular motion forces given x, y positions
+  const getNewCircularMotionForces = (xPos: number, yPos: number) => {
+    let deltaX = (xMin + xMax) / 2 - (xPos + radius);
+    let deltaY = yPos + radius - (yMin + yMax) / 2;
+    let dir = (Math.atan2(deltaY, deltaX) * 180) / Math.PI;
+    const tensionForce: IForce = {
+      description: "Centripetal Force",
+      magnitude: (startVelX ** 2 * mass) / circularMotionRadius,
+      directionInDegrees: dir,
+      component: false,
+    };
+    return [tensionForce];
+  };
+
+  // Compute spring forces given y position
+  const getNewSpringForces = (yPos: number) => {
+    let springForce: IForce = {
+      description: "Spring Force",
+      magnitude: 0,
+      directionInDegrees: 90,
+      component: false,
+    };
+    if (yPos - springRestLength > 0) {
+      springForce = {
+        description: "Spring Force",
+        magnitude: springConstant * (yPos - springRestLength),
+        directionInDegrees: 90,
+        component: false,
+      };
+    } else if (yPos - springRestLength < 0) {
+      springForce = {
+        description: "Spring Force",
+        magnitude: springConstant * (springRestLength - yPos),
+        directionInDegrees: 270,
+        component: false,
+      };
+    }
+
+    return [
+      {
+        description: "Gravity",
+        magnitude: Math.abs(gravity) * mass,
+        directionInDegrees: 270,
+        component: false,
+      },
+      springForce,
+    ];
+  };
+
+  // Compute pendulum forces given position, velocity
+  const getNewPendulumForces = (
     xPos: number,
     yPos: number,
     xVel: number,
     yVel: number
   ) => {
-    if (!this.props.dataDoc['pendulum']) {
-      return this.props.dataDoc['updatedForces'];
-    }
-    const x = this.props.xMax / 2 - xPos - this.props.radius;
-    const y = yPos + this.props.radius + 5;
+    const x = xMax / 2 - xPos - radius;
+    const y = yPos + radius + 5;
     let angle = (Math.atan(y / x) * 180) / Math.PI;
     if (angle < 0) {
       angle += 180;
@@ -345,265 +303,816 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     }
 
     const pendulumLength = Math.sqrt(x * x + y * y);
-    this.props.dataDoc['pendulumAngle'] = oppositeAngle;
-    this.props.dataDoc['pendulumLength'] = Math.sqrt(x * x + y * y);
+    setPendulumAngle(oppositeAngle);
 
     const mag =
-      this.props.mass * 9.81 * Math.cos((oppositeAngle * Math.PI) / 180) +
-      (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength;
+      mass * Math.abs(gravity) * Math.cos((oppositeAngle * Math.PI) / 180) +
+      (mass * (xVel * xVel + yVel * yVel)) / pendulumLength;
 
     const forceOfTension: IForce = {
       description: "Tension",
       magnitude: mag,
       directionInDegrees: angle,
+      component: false,
     };
-    this.setState({angleLabel: Math.round(this.props.dataDoc['pendulumAngle']* 100) / 100})
-
-    return [this.forceOfGravity, forceOfTension];
-  };
 
-  getNewPosition = (pos: number, vel: number) => {
-    return pos + vel * this.props.timestepSize;
+    return [
+      {
+        description: "Gravity",
+        magnitude: Math.abs(gravity) * mass,
+        directionInDegrees: 270,
+        component: false,
+      },
+      forceOfTension,
+    ];
   };
 
-  getNewVelocity = (vel: number, acc: number) => {
-    return vel + acc * this.props.timestepSize;
-  };
-
-  checkForCollisionsWithWall = () => {
+  // Check for collisions in x direction
+  const checkForCollisionsWithWall = () => {
     let collision = false;
-    const minX = this.state.xPosition;
-    const maxX = this.state.xPosition + 2 * this.props.radius;
-    const containerWidth = 300;
-    if (this.state.xVelocity != 0) {
-      if (this.props.dataDoc.wallPositions) {
-      this.props.dataDoc['wallPositions'].forEach((wall) => {
+    const minX = xPosition;
+    const maxX = xPosition + 2 * radius;
+    if (xVelocity != 0) {
+      walls.forEach((wall) => {
         if (wall.angleInDegrees == 90) {
-          const wallX = (wall.xPos / 100) * 300;
+          const wallX = (wall.xPos / 100) * window.innerWidth;
           if (wall.xPos < 0.35) {
             if (minX <= wallX) {
-              if (this.props.dataDoc['elasticCollisions']) {
-                this.setState({xVelocity: -this.state.xVelocity});
+              setXPosition(wallX + 0.01);
+              if (elasticCollisions) {
+                setXVelocity(-xVelocity);
               } else {
-                this.setState({xVelocity: 0});
-                this.setState({xPosition: wallX+5});
+                setXVelocity(0);
               }
               collision = true;
             }
           } else {
             if (maxX >= wallX) {
-              if (this.props.dataDoc['elasticCollisions']) {
-                this.setState({xVelocity: -this.state.xVelocity});
+              setXPosition(wallX - 2 * radius - 0.01);
+              if (elasticCollisions) {
+                setXVelocity(-xVelocity);
               } else {
-                this.setState({xVelocity: 0});
-                this.setState({xPosition: wallX - 2 * this.props.radius + 5});
+                setXVelocity(0);
               }
               collision = true;
             }
           }
         }
       });
-      }
     }
     return collision;
   };
 
-  checkForCollisionsWithGround = () => {
+  // Check for collisions in y direction
+  const checkForCollisionsWithGround = () => {
     let collision = false;
-    const maxY = this.state.yPosition + 2 * this.props.radius;
-    if (this.state.yVelocity > 0) {
-      if (this.props.dataDoc.wallPositions) {
-      this.props.dataDoc['wallPositions'].forEach((wall) => {
-        if (wall.angleInDegrees == 0) {
-          const groundY = (wall.yPos / 100) * this.props.yMax;
-          if (maxY >= groundY) {
-            if (this.props.dataDoc['elasticCollisions']) {
-              this.setState({yVelocity: -this.state.yVelocity})
+    const minY = yPosition;
+    const maxY = yPosition + 2 * radius;
+    if (yVelocity > 0) {
+      walls.forEach((wall) => {
+        if (wall.angleInDegrees == 0 && wall.yPos > 0.4) {
+          const groundY = (wall.yPos / 100) * window.innerHeight;
+          if (maxY > groundY) {
+            setYPosition(groundY - 2 * radius - 0.01);
+            if (elasticCollisions) {
+              setYVelocity(-yVelocity);
             } else {
-              this.setState({yVelocity: 0})
-              this.setState({yPosition: groundY - 2 * this.props.radius + 5})
-              const forceOfGravity: IForce = {
-                description: "Gravity",
-                magnitude: 9.81 * this.props.mass,
-                directionInDegrees: 270,
-              };
-              const normalForce: IForce = {
-                description: "Normal force",
-                magnitude: 9.81 * this.props.mass,
-                directionInDegrees: wall.angleInDegrees + 90,
-              };
-              this.props.dataDoc['updatedForces'] = ([forceOfGravity, normalForce]);
+              setYVelocity(0);
+              if (this.props.dataDoc['simulationType'] != "Two Weights") {
+                const forceOfGravity: IForce = {
+                  description: "Gravity",
+                  magnitude: Math.abs(gravity) * mass,
+                  directionInDegrees: 270,
+                  component: false,
+                };
+                const normalForce: IForce = {
+                  description: "Normal force",
+                  magnitude: Math.abs(gravity) * mass,
+                  directionInDegrees: wall.angleInDegrees + 90,
+                  component: false,
+                };
+                setUpdatedForces([forceOfGravity, normalForce]);
+                if (this.props.dataDoc['simulationType'] == "Inclined Plane") {
+                  const forceOfGravityC: IForce = {
+                    description: "Gravity",
+                    magnitude: Math.abs(gravity) * mass,
+                    directionInDegrees: 270,
+                    component: true,
+                  };
+                  const normalForceC: IForce = {
+                    description: "Normal force",
+                    magnitude: Math.abs(gravity) * mass,
+                    directionInDegrees: wall.angleInDegrees + 90,
+                    component: true,
+                  };
+                  setComponentForces([forceOfGravityC, normalForceC]);
+                }
+              }
+            }
+            collision = true;
+          }
+        }
+      });
+    }
+    if (yVelocity < 0) {
+      walls.forEach((wall) => {
+        if (wall.angleInDegrees == 0 && wall.yPos < 0.4) {
+          const groundY = (wall.yPos / 100) * window.innerHeight;
+          if (minY < groundY) {
+            setYPosition(groundY + 5);
+            if (elasticCollisions) {
+              setYVelocity(-yVelocity);
+            } else {
+              setYVelocity(0);
             }
             collision = true;
           }
         }
       });
-      }
     }
     return collision;
   };
 
-  update = () => {
-    // RK4 update
-    let xPos = this.state.xPosition;
-    let yPos = this.state.yPosition;
-    let xVel = this.state.xVelocity;
-    let yVel = this.state.yVelocity;
-    for (let i = 0; i < 60; i++) {
-      let forces1 = this.getNewForces(xPos, yPos, xVel, yVel);
-      const xAcc1 = this.getNewAccelerationX(forces1);
-      const yAcc1 = this.getNewAccelerationY(forces1);
-      const xVel1 = this.getNewVelocity(xVel, xAcc1);
-      const yVel1 = this.getNewVelocity(yVel, yAcc1);
-
-      let xVel2 = this.getNewVelocity(xVel, xAcc1 / 2);
-      let yVel2 = this.getNewVelocity(yVel, yAcc1 / 2);
-      let xPos2 = this.getNewPosition(xPos, xVel1 / 2);
-      let yPos2 = this.getNewPosition(yPos, yVel1 / 2);
-      const forces2 = this.getNewForces(xPos2, yPos2, xVel2, yVel2);
-      const xAcc2 = this.getNewAccelerationX(forces2);
-      const yAcc2 = this.getNewAccelerationY(forces2);
-      xVel2 = this.getNewVelocity(xVel2, xAcc2);
-      yVel2 = this.getNewVelocity(yVel2, yAcc2);
-      xPos2 = this.getNewPosition(xPos2, xVel2);
-      yPos2 = this.getNewPosition(yPos2, yVel2);
-
-      let xVel3 = this.getNewVelocity(xVel, xAcc2 / 2);
-      let yVel3 = this.getNewVelocity(yVel, yAcc2 / 2);
-      let xPos3 = this.getNewPosition(xPos, xVel2 / 2);
-      let yPos3 = this.getNewPosition(yPos, yVel2 / 2);
-      const forces3 = this.getNewForces(xPos3, yPos3, xVel3, yVel3);
-      const xAcc3 = this.getNewAccelerationX(forces3);
-      const yAcc3 = this.getNewAccelerationY(forces3);
-      xVel3 = this.getNewVelocity(xVel3, xAcc3);
-      yVel3 = this.getNewVelocity(yVel3, yAcc3);
-      xPos3 = this.getNewPosition(xPos3, xVel3);
-      yPos3 = this.getNewPosition(yPos3, yVel3);
-
-      let xVel4 = this.getNewVelocity(xVel, xAcc3);
-      let yVel4 = this.getNewVelocity(yVel, yAcc3);
-      let xPos4 = this.getNewPosition(xPos, xVel3);
-      let yPos4 = this.getNewPosition(yPos, yVel3);
-      const forces4 = this.getNewForces(xPos4, yPos4, xVel4, yVel4);
-      const xAcc4 = this.getNewAccelerationX(forces4);
-      const yAcc4 = this.getNewAccelerationY(forces4);
-      xVel4 = this.getNewVelocity(xVel4, xAcc4);
-      yVel4 = this.getNewVelocity(yVel4, yAcc4);
-      xPos4 = this.getNewPosition(xPos4, xVel4);
-      yPos4 = this.getNewPosition(yPos4, yVel4);
+  // Called at each RK4 step
+  const evaluate = (
+    currentXPos: number,
+    currentYPos: number,
+    currentXVel: number,
+    currentYVel: number,
+    deltaXPos: number,
+    deltaYPos: number,
+    deltaXVel: number,
+    deltaYVel: number,
+    dt: number
+  ) => {
+    const newXPos = currentXPos + deltaXPos * dt;
+    const newYPos = currentYPos + deltaYPos * dt;
+    const newXVel = currentXVel + deltaXVel * dt;
+    const newYVel = currentYVel + deltaYVel * dt;
+    const newDeltaXPos = newXVel;
+    const newDeltaYPos = newYVel;
+    let forces = updatedForces;
+    if (this.props.dataDoc['simulationType'] == "Pendulum") {
+      forces = getNewPendulumForces(newXPos, newYPos, newXVel, newYVel);
+    } else if (this.props.dataDoc['simulationType'] == "Spring") {
+      forces = getNewSpringForces(newYPos);
+    } else if (this.props.dataDoc['simulationType'] == "Circular Motion") {
+      forces = getNewCircularMotionForces(newXPos, newYPos);
+    }
+    const newDeltaXVel = getNewAccelerationX(forces);
+    const newDeltaYVel = getNewAccelerationY(forces);
+    return {
+      xPos: newXPos,
+      yPos: newYPos,
+      xVel: newXVel,
+      yVel: newYVel,
+      deltaXPos: newDeltaXPos,
+      deltaYPos: newDeltaYPos,
+      deltaXVel: newDeltaXVel,
+      deltaYVel: newDeltaYVel,
+    };
+  };
+
+  // Update position, velocity using RK4 method
+  const update = () => {
+    let startXVel = xVelocity;
+    let startYVel = yVelocity;
+    let xPos = xPosition;
+    let yPos = yPosition;
+    let xVel = xVelocity;
+    let yVel = yVelocity;
+    let forces = updatedForces;
+    if (this.props.dataDoc['simulationType'] == "Pendulum") {
+      forces = getNewPendulumForces(xPos, yPos, xVel, yVel);
+    } else if (this.props.dataDoc['simulationType'] == "Spring") {
+      forces = getNewSpringForces(yPos);
+    } else if (this.props.dataDoc['simulationType'] == "Circular Motion") {
+      forces = getNewCircularMotionForces(xPos, yPos);
+    }
+    const xAcc = getNewAccelerationX(forces);
+    const yAcc = getNewAccelerationY(forces);
+    for (let i = 0; i < simulationSpeed; i++) {
+      const k1 = evaluate(xPos, yPos, xVel, yVel, xVel, yVel, xAcc, yAcc, 0);
+      const k2 = evaluate(
+        xPos,
+        yPos,
+        xVel,
+        yVel,
+        k1.deltaXPos,
+        k1.deltaYPos,
+        k1.deltaXVel,
+        k1.deltaYVel,
+        timestepSize * 0.5
+      );
+      const k3 = evaluate(
+        xPos,
+        yPos,
+        xVel,
+        yVel,
+        k2.deltaXPos,
+        k2.deltaYPos,
+        k2.deltaXVel,
+        k2.deltaYVel,
+        timestepSize * 0.5
+      );
+      const k4 = evaluate(
+        xPos,
+        yPos,
+        xVel,
+        yVel,
+        k3.deltaXPos,
+        k3.deltaYPos,
+        k3.deltaXVel,
+        k3.deltaYVel,
+        timestepSize
+      );
 
       xVel +=
-        this.props.timestepSize * (xAcc1 / 6.0 + xAcc2 / 3.0 + xAcc3 / 3.0 + xAcc4 / 6.0);
+        ((timestepSize * 1.0) / 6.0) *
+        (k1.deltaXVel + 2 * (k2.deltaXVel + k3.deltaXVel) + k4.deltaXVel);
       yVel +=
-        this.props.timestepSize * (yAcc1 / 6.0 + yAcc2 / 3.0 + yAcc3 / 3.0 + yAcc4 / 6.0);
+        ((timestepSize * 1.0) / 6.0) *
+        (k1.deltaYVel + 2 * (k2.deltaYVel + k3.deltaYVel) + k4.deltaYVel);
       xPos +=
-        this.props.timestepSize * (xVel1 / 6.0 + xVel2 / 3.0 + xVel3 / 3.0 + xVel4 / 6.0);
+        ((timestepSize * 1.0) / 6.0) *
+        (k1.deltaXPos + 2 * (k2.deltaXPos + k3.deltaXPos) + k4.deltaXPos);
       yPos +=
-        this.props.timestepSize * (yVel1 / 6.0 + yVel2 / 3.0 + yVel3 / 3.0 + yVel4 / 6.0);
+        ((timestepSize * 1.0) / 6.0) *
+        (k1.deltaYPos + 2 * (k2.deltaYPos + k3.deltaYPos) + k4.deltaYPos);
+    }
+    // make sure harmonic motion maintained and errors don't propagate
+    if (this.props.dataDoc['simulationType'] == "Spring") {
+      if (startYVel < 0 && yVel > 0 && yPos < springRestLength) {
+        let equilibriumPos =
+          springRestLength + (mass * Math.abs(gravity)) / springConstant;
+        let amplitude = Math.abs(equilibriumPos - springStartLength);
+        yPos = equilibriumPos - amplitude;
+      } else if (startYVel > 0 && yVel < 0 && yPos > springRestLength) {
+        let equilibriumPos =
+          springRestLength + (mass * Math.abs(gravity)) / springConstant;
+        let amplitude = Math.abs(equilibriumPos - springStartLength);
+        yPos = equilibriumPos + amplitude;
+      }
     }
+    if (this.props.dataDoc['simulationType'] == "Pendulum") {
+      let startX = updatedStartPosX;
+      if (startXVel <= 0 && xVel > 0) {
+        xPos = updatedStartPosX;
+        if (updatedStartPosX > xMax / 2) {
+          xPos = xMax / 2 + (xMax / 2 - startX) - 2 * radius;
+        }
+        yPos = startPosY;
+      } else if (startXVel >= 0 && xVel < 0) {
+        xPos = updatedStartPosX;
+        if (updatedStartPosX < xMax / 2) {
+          xPos = xMax / 2 + (xMax / 2 - startX) - 2 * radius;
+        }
+        yPos = startPosY;
+      }
+    }
+    if (this.props.dataDoc['simulationType'] == "One Weight") {
+      if (yPos < maxPosYConservation) {
+        yPos = maxPosYConservation;
+      }
+    }
+    setXVelocity(xVel);
+    setYVelocity(yVel);
+    setXPosition(xPos);
+    setYPosition(yPos);
+    let forcesn = updatedForces;
+    if (this.props.dataDoc['simulationType'] == "Pendulum") {
+      forcesn = getNewPendulumForces(xPos, yPos, xVel, yVel);
+    } else if (this.props.dataDoc['simulationType'] == "Spring") {
+      forcesn = getNewSpringForces(yPos);
+    } else if (this.props.dataDoc['simulationType'] == "Circular Motion") {
+      forcesn = getNewCircularMotionForces(xPos, yPos);
+    }
+    setUpdatedForces(forcesn);
 
-    this.setState({xVelocity: xVel});
-    this.setState({yVelocity: yVel});
-    this.setState({xPosition: xPos});
-    this.setState({yPosition: yPos});
-    
-    this.props.dataDoc['updatedForces'] = (this.getNewForces(xPos, yPos, xVel, yVel));
+    // set component forces if they change
+    if (this.props.dataDoc['simulationType'] == "Pendulum") {
+      let x = xMax / 2 - xPos - radius;
+      let y = yPos + radius + 5;
+      let angle = (Math.atan(y / x) * 180) / Math.PI;
+      if (angle < 0) {
+        angle += 180;
+      }
+      let oppositeAngle = 90 - angle;
+      if (oppositeAngle < 0) {
+        oppositeAngle = 90 - (180 - angle);
+      }
+
+      const pendulumLength = Math.sqrt(x * x + y * y);
+
+      const mag =
+        mass * Math.abs(gravity) * Math.cos((oppositeAngle * Math.PI) / 180) +
+        (mass * (xVel * xVel + yVel * yVel)) / pendulumLength;
+
+      const tensionComponent: IForce = {
+        description: "Tension",
+        magnitude: mag,
+        directionInDegrees: angle,
+        component: true,
+      };
+      const gravityParallel: IForce = {
+        description: "Gravity Parallel Component",
+        magnitude: Math.abs(gravity) * Math.cos(((90 - angle) * Math.PI) / 180),
+        directionInDegrees: 270 - (90 - angle),
+        component: true,
+      };
+      const gravityPerpendicular: IForce = {
+        description: "Gravity Perpendicular Component",
+        magnitude: Math.abs(gravity) * Math.sin(((90 - angle) * Math.PI) / 180),
+        directionInDegrees: -(90 - angle),
+        component: true,
+      };
+      if (Math.abs(gravity) * Math.sin(((90 - angle) * Math.PI) / 180) < 0) {
+        gravityPerpendicular.magnitude = Math.abs(
+          Math.abs(gravity) * Math.sin(((90 - angle) * Math.PI) / 180)
+        );
+        gravityPerpendicular.directionInDegrees = 180 - (90 - angle);
+      }
+      setComponentForces([
+        tensionComponent,
+        gravityParallel,
+        gravityPerpendicular,
+      ]);
+    }
   };
 
+  // Change pendulum angle based on input field
+  useEffect(() => {
+    let length = adjustPendulumAngle.length;
+    const x =
+      length * Math.cos(((90 - adjustPendulumAngle.angle) * Math.PI) / 180);
+    const y =
+      length * Math.sin(((90 - adjustPendulumAngle.angle) * Math.PI) / 180);
+    const xPos = xMax / 2 - x - radius;
+    const yPos = y - radius - 5;
+    setXPosition(xPos);
+    setYPosition(yPos);
+    setUpdatedStartPosX(xPos);
+    setUpdatedStartPosY(yPos);
+    setPendulumAngle(adjustPendulumAngle.angle);
+    setPendulumLength(adjustPendulumAngle.length);
+  }, [adjustPendulumAngle]);
+
+  // When display values updated by user, update real values
+  useEffect(() => {
+    if (updateDisplay.xDisplay != xPosition) {
+      let x = updateDisplay.xDisplay;
+      x = Math.max(0, x);
+      x = Math.min(x, xMax - 2 * radius);
+      setUpdatedStartPosX(x);
+      setXPosition(x);
+      setDisplayXPosition(x);
+    }
+
+    if (updateDisplay.yDisplay != getDisplayYPos(yPosition)) {
+      let y = updateDisplay.yDisplay;
+      y = Math.max(0, y);
+      y = Math.min(y, yMax - 2 * radius);
+      setDisplayYPosition(y);
+      let coordinatePosition = getYPosFromDisplay(y);
+      setUpdatedStartPosY(coordinatePosition);
+      setYPosition(coordinatePosition);
+    }
+
+    if (displayXVelocity != xVelocity) {
+      let x = displayXVelocity;
+      setXVelocity(x);
+      setDisplayXVelocity(x);
+    }
+
+    if (displayYVelocity != -yVelocity) {
+      let y = displayYVelocity;
+      setYVelocity(-y);
+      setDisplayYVelocity(y);
+    }
+  }, [updateDisplay]);
+
+  // Prevent bug when switching between sims
+  useEffect(() => {
+    setXVelocity(startVelX);
+    setYVelocity(startVelY);
+    setDisplayValues();
+  }, [startForces]);
+
+  // Make sure weight doesn't go above max height
+  useEffect(() => {
+    if (this.props.dataDoc['simulationType'] == "One Weight") {
+      let maxYPos = updatedStartPosY;
+      if (startVelY != 0) {
+        maxYPos -= (startVelY * startVelY) / (2 * Math.abs(gravity));
+      }
+      if (maxYPos < 0) {
+        maxYPos = 0;
+      }
+      setMaxPosYConservation(maxYPos);
+    }
+  }, [updatedStartPosY, startVelY]);
+
+  // Check for collisions and update
+  useEffect(() => {
+    if (!paused && !noMovement) {
+      let collisions = false;
+      if (
+        this.props.dataDoc['simulationType'] == "One Weight" ||
+        this.props.dataDoc['simulationType'] == "Inclined Plane"
+      ) {
+        const collisionsWithGround = checkForCollisionsWithGround();
+        const collisionsWithWalls = checkForCollisionsWithWall();
+        collisions = collisionsWithGround || collisionsWithWalls;
+      }
+      if (this.props.dataDoc['simulationType'] == "Pulley") {
+        if (yPosition <= yMin + 100 || yPosition >= yMax - 100) {
+          collisions = true;
+        }
+      }
+      if (!collisions) {
+        update();
+      }
+      setDisplayValues();
+    }
+  }, [incrementTime]);
+
+  // Reset everything on reset button click
+  useEffect(() => {
+    resetEverything();
+  }, [reset]);
+
+  // Convert from static to kinetic friction if/when weight slips on inclined plane
+  useEffect(() => {
+    if (
+      this.props.dataDoc['simulationType'] == "Inclined Plane" &&
+      Math.abs(xVelocity) > 0.1 &&
+      this.props.dataDoc['mode'] != "Review" &&
+      !kineticFriction
+    ) {
+      setKineticFriction(true);
+      //switch from static to kinetic friction
+      const normalForce: IForce = {
+        description: "Normal Force",
+        magnitude:
+          mass *
+          Math.abs(gravity) *
+          Math.cos(Math.atan(wedgeHeight / wedgeWidth)),
+        directionInDegrees:
+          180 - 90 - (Math.atan(wedgeHeight / wedgeWidth) * 180) / Math.PI,
+        component: false,
+      };
+      let frictionForce: IForce = {
+        description: "Kinetic Friction Force",
+        magnitude:
+          mass *
+          coefficientOfKineticFriction *
+          Math.abs(gravity) *
+          Math.cos(Math.atan(wedgeHeight / wedgeWidth)),
+        directionInDegrees:
+          180 - (Math.atan(wedgeHeight / wedgeWidth) * 180) / Math.PI,
+        component: false,
+      };
+      // reduce magnitude of friction force if necessary such that block cannot slide up plane
+      let yForce = -Math.abs(gravity);
+      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(gravity)) /
+          Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
+      }
+
+      const frictionForceComponent: IForce = {
+        description: "Kinetic Friction Force",
+
+        magnitude:
+          mass *
+          coefficientOfKineticFriction *
+          Math.abs(gravity) *
+          Math.cos(Math.atan(wedgeHeight / wedgeWidth)),
+        directionInDegrees:
+          180 - (Math.atan(wedgeHeight / wedgeWidth) * 180) / Math.PI,
+        component: true,
+      };
+      const normalForceComponent: IForce = {
+        description: "Normal Force",
+        magnitude:
+          mass *
+          Math.abs(gravity) *
+          Math.cos(Math.atan(wedgeHeight / wedgeWidth)),
+        directionInDegrees:
+          180 - 90 - (Math.atan(wedgeHeight / wedgeWidth) * 180) / Math.PI,
+        component: true,
+      };
+      const gravityParallel: IForce = {
+        description: "Gravity Parallel Component",
+        magnitude:
+          mass *
+          Math.abs(gravity) *
+          Math.sin(Math.PI / 2 - Math.atan(wedgeHeight / wedgeWidth)),
+        directionInDegrees:
+          180 -
+          90 -
+          (Math.atan(wedgeHeight / wedgeWidth) * 180) / Math.PI +
+          180,
+        component: true,
+      };
+      const gravityPerpendicular: IForce = {
+        description: "Gravity Perpendicular Component",
+        magnitude:
+          mass *
+          Math.abs(gravity) *
+          Math.cos(Math.PI / 2 - Math.atan(wedgeHeight / wedgeWidth)),
+        directionInDegrees:
+          360 - (Math.atan(wedgeHeight / wedgeWidth) * 180) / Math.PI,
+        component: true,
+      };
+      const gravityForce: IForce = {
+        description: "Gravity",
+        magnitude: mass * Math.abs(gravity),
+        directionInDegrees: 270,
+        component: false,
+      };
+      if (coefficientOfKineticFriction != 0) {
+        setUpdatedForces([gravityForce, normalForce, frictionForce]);
+        setComponentForces([
+          frictionForceComponent,
+          normalForceComponent,
+          gravityParallel,
+          gravityPerpendicular,
+        ]);
+      } else {
+        setUpdatedForces([gravityForce, normalForce]);
+        setComponentForces([
+          normalForceComponent,
+          gravityParallel,
+          gravityPerpendicular,
+        ]);
+      }
+    }
+  }, [xVelocity]);
+
+  // Add/remove walls when simulation type changes
+  useEffect(() => {
+    let w: IWallProps[] = [];
+    if (this.props.dataDoc['simulationType'] == "One Weight" || this.props.dataDoc['simulationType'] == "Inclined Plane") {
+      w.push({ length: 70, xPos: 0, yPos: 0, angleInDegrees: 0 });
+      w.push({ length: 70, xPos: 0, yPos: 80, angleInDegrees: 0 });
+      w.push({ length: 80, xPos: 0, yPos: 0, angleInDegrees: 90 });
+      w.push({ length: 80, xPos: 69.5, yPos: 0, angleInDegrees: 90 });
+    }
+    setWalls(w);
+  }, [this.props.dataDoc['simulationType']]);
+
+  // Update x position when start pos x changes
+  useEffect(() => {
+    if (paused) {
+      setUpdatedStartPosX(startPosX);
+      setXPosition(startPosX);
+      setXPosDisplay(startPosX);
+    }
+  }, [startPosX]);
+
+  // Update y position when start pos y changes
+  useEffect(() => {
+    if (paused) {
+      setUpdatedStartPosY(startPosY);
+      setYPosition(startPosY);
+      setYPosDisplay(startPosY);
+    }
+  }, [startPosY]);
 
-  labelBackgroundColor = `rgba(255,255,255,0.5)`;
+  // Update wedge coordinates
+  useEffect(() => {
+    const left = xMax * 0.5 - 200;
+    const coordinatePair1 = Math.round(left) + "," + yMax + " ";
+    const coordinatePair2 = Math.round(left + wedgeWidth) + "," + yMax + " ";
+    const coordinatePair3 = Math.round(left) + "," + (yMax - wedgeHeight);
+    const coord = coordinatePair1 + coordinatePair2 + coordinatePair3;
+    setCoordinates(coord);
+  }, [wedgeWidth, wedgeHeight]);
 
-  render () {
-    return (
-    <div>
+  // Render weight, spring, rod(s), vectors
+  return (
+    <div style={{ zIndex: -1000 }}>
       <div
         className="weightContainer"
-        // onPointerDown={(e) => {
-        //   if (this.draggable) {
-        //     e.preventDefault();
-        //     this.props.dataDoc['simulationPaused'] = true;
-        //     this.setState({dragging: true});
-        //     this.setState({clickPositionX: e.clientX})
-        //     this.setState({clickPositionY: e.clientY})
-        //   }
-        // }}
-        // onPointerMove={(e) => {
-        //   e.preventDefault();
-        //   if (this.state.dragging) {
-        //     let newY = this.state.yPosition + e.clientY - this.state.clickPositionY;
-        //     if (newY > this.props.yMax - 2 * this.props.radius) {
-        //       newY = this.props.yMax - 2 * this.props.radius;
-        //     }
-
-        //     let newX = this.state.xPosition + e.clientX - this.state.clickPositionX;
-        //     if (newX > this.props.xMax - 2 * this.props.radius) {
-        //       newX = this.props.xMax - 2 * this.props.radius;
-        //     } else if (newX < 0) {
-        //       newX = 0;
-        //     }
-        //     this.setState({xPosition: newX})
-        //     this.setState({yPosition: newY})
-        //     this.setState({updatedStartPosX: newX})
-        //     this.setState({updatedStartPosY: newY})
-        //     this.props.dataDoc['positionYDisplay'] = Math.round((this.props.yMax - 2 * this.props.radius - newY + 5) * 100) / 100;
-        //     this.setState({clickPositionX: e.clientX})
-        //     this.setState({clickPositionY: e.clientY})
-        //     this.setDisplayValues();
-        //   }
-        // }}
-        // onPointerUp={(e) => {
-        //   if (this.state.dragging) {
-        //     e.preventDefault();
-        //     if (!this.props.dataDoc['pendulum']) {
-        //       this.resetEverything();
-        //     }
-        //     this.setState({dragging: false});
-        //     let newY = this.state.yPosition + e.clientY - this.state.clickPositionY;
-        //     if (newY > this.props.yMax - 2 * this.props.radius) {
-        //       newY = this.props.yMax - 2 * this.props.radius;
-        //     }
-
-        //     let newX = this.state.xPosition + e.clientX - this.state.clickPositionX;
-        //     if (newX > this.props.xMax - 2 * this.props.radius) {
-        //       newX = this.props.xMax - 2 * this.props.radius;
-        //     } else if (newX < 0) {
-        //       newX = 0;
-        //     }
-        //     if (this.props.dataDoc['pendulum']) {
-        //       const x = this.props.xMax / 2 - newX - this.props.radius;
-        //       const y = newY + this.props.radius + 5;
-        //       let angle = (Math.atan(y / x) * 180) / Math.PI;
-        //       if (angle < 0) {
-        //         angle += 180;
-        //       }
-        //       let oppositeAngle = 90 - angle;
-        //       if (oppositeAngle < 0) {
-        //         oppositeAngle = 90 - (180 - angle);
-        //       }
-
-        //       const pendulumLength = Math.sqrt(x * x + y * y);
-        //       this.props.dataDoc['pendulumAngle'] = oppositeAngle;
-        //       this.props.dataDoc['pendulumLength'] = Math.sqrt(x * x + y * y);
-        //       const mag = 9.81 * Math.cos((oppositeAngle * Math.PI) / 180);
-        //       const forceOfTension: IForce = {
-        //         description: "Tension",
-        //         magnitude: mag,
-        //         directionInDegrees: angle,
-        //       };
-        //       this.setState({kineticFriction: false})
-        //       this.setState({xVelocity: this.props.startVelX ?? 0})
-        //       this.setState({yVelocity: this.props.startVelY ?? 0})
-        //       this.setDisplayValues();
-        //       this.props.dataDoc['updatedForces'] = ([this.forceOfGravity, forceOfTension]);
-        //     }
-        //   }
-        // }}
+        onPointerDown={(e) => {
+          if (draggable) {
+            e.preventDefault();
+            setPaused(true);
+            setDragging(true);
+            setClickPositionX(e.clientX);
+            setClickPositionY(e.clientY);
+          } else if (this.props.dataDoc['mode'] == "Review") {
+            setSketching(true);
+          }
+        }}
+        onPointerMove={(e) => {
+          e.preventDefault();
+          if (dragging) {
+            let newY = yPosition + e.clientY - clickPositionY;
+            if (newY > yMax - 2 * radius - 10) {
+              newY = yMax - 2 * radius - 10;
+            } else if (newY < 10) {
+              newY = 10;
+            }
+
+            let newX = xPosition + e.clientX - clickPositionX;
+            if (newX > xMax - 2 * radius - 10) {
+              newX = xMax - 2 * radius - 10;
+            } else if (newX < 10) {
+              newX = 10;
+            }
+            if (this.props.dataDoc['simulationType'] == "Suspension") {
+              if (newX < (xMax + xMin) / 4 - radius - 15) {
+                newX = (xMax + xMin) / 4 - radius - 15;
+              } else if (newX > (3 * (xMax + xMin)) / 4 - radius / 2 - 15) {
+                newX = (3 * (xMax + xMin)) / 4 - radius / 2 - 15;
+              }
+            }
+
+            setYPosition(newY);
+            setDisplayYPosition(
+              Math.round((yMax - 2 * radius - newY + 5) * 100) / 100
+            );
+            if (this.props.dataDoc['simulationType'] != "Pulley") {
+              setXPosition(newX);
+              setDisplayXPosition(newX);
+            }
+            if (this.props.dataDoc['simulationType'] != "Suspension") {
+              if (this.props.dataDoc['simulationType'] != "Pulley") {
+                setUpdatedStartPosX(newX);
+              }
+              setUpdatedStartPosY(newY);
+            }
+            setClickPositionX(e.clientX);
+            setClickPositionY(e.clientY);
+            setDisplayValues();
+          }
+        }}
+        onPointerUp={(e) => {
+          if (dragging) {
+            e.preventDefault();
+            if (
+              this.props.dataDoc['simulationType'] != "Pendulum" &&
+              this.props.dataDoc['simulationType'] != "Suspension"
+            ) {
+              resetEverything();
+            }
+            setDragging(false);
+            let newY = yPosition + e.clientY - clickPositionY;
+            if (newY > yMax - 2 * radius - 10) {
+              newY = yMax - 2 * radius - 10;
+            } else if (newY < 10) {
+              newY = 10;
+            }
+
+            let newX = xPosition + e.clientX - clickPositionX;
+            if (newX > xMax - 2 * radius - 10) {
+              newX = xMax - 2 * radius - 10;
+            } else if (newX < 10) {
+              newX = 10;
+            }
+            if (this.props.dataDoc['simulationType'] == "Spring") {
+              setSpringStartLength(newY);
+            }
+            if (this.props.dataDoc['simulationType'] == "Suspension") {
+              let x1rod = (xMax + xMin) / 2 - radius - yMin - 200;
+              let x2rod = (xMax + xMin) / 2 + yMin + 200 + radius;
+              let deltaX1 = xPosition + radius - x1rod;
+              let deltaX2 = x2rod - (xPosition + radius);
+              let deltaY = yPosition + radius;
+              let dir1T = Math.PI - Math.atan(deltaY / deltaX1);
+              let dir2T = Math.atan(deltaY / deltaX2);
+              let tensionMag2 =
+                (mass * Math.abs(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: mass * Math.abs(gravity),
+                directionInDegrees: 270,
+                component: false,
+              };
+              setUpdatedForces([tensionForce1, tensionForce2, grav]);
+            }
+          }
+        }}
       >
-        <div className="weight" style={this.weightStyle}>
-          <p className="weightLabel">{this.props.mass} kg</p>
+        <div className="weight" style={weightStyle}>
+          <p className="weightLabel">{mass} kg</p>
         </div>
       </div>
-      {this.props.dataDoc['pendulum'] && (
+      {this.props.dataDoc['simulationType'] == "Spring" && (
+        <div
+          className="spring"
+          style={{
+            pointerEvents: "none",
+            position: "absolute",
+            left: 0,
+            top: 0,
+            zIndex: -2,
+          }}
+        >
+          <svg width={xMax + "px"} height={window.innerHeight + "px"}>
+            {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map((val) => {
+              const count = 10;
+              let xPos1;
+              let yPos1;
+              let xPos2;
+              let yPos2;
+              if (val % 2 == 0) {
+                xPos1 = xPosition + radius - 20;
+                xPos2 = xPosition + radius + 20;
+              } else {
+                xPos1 = xPosition + radius + 20;
+                xPos2 = xPosition + radius - 20;
+              }
+              yPos1 = (val * yPosition) / count;
+              yPos2 = ((val + 1) * yPosition) / count;
+              return (
+                <line
+                  key={val}
+                  x1={xPos1}
+                  y1={yPos1}
+                  x2={xPos2}
+                  y2={yPos2}
+                  stroke={"#808080"}
+                  strokeWidth="10"
+                />
+              );
+            })}
+          </svg>
+        </div>
+      )}
+      {this.props.dataDoc['simulationType'] == "Pulley" && (
+        <div
+          className="wheel"
+          style={{
+            pointerEvents: "none",
+            position: "absolute",
+            left: 0,
+            top: 0,
+            zIndex: -1,
+          }}
+        >
+          <svg width={xMax + "px"} height={window.innerHeight + "px"}>
+            <circle
+              cx={(xMax + xMin) / 2}
+              cy={radius}
+              r={radius * 1.5}
+              fill={"#808080"}
+            />
+          </svg>
+        </div>
+      )}
+      {this.props.dataDoc['simulationType'] == "Pulley" && (
+        <div
+          className="rod"
+          style={{
+            pointerEvents: "none",
+            position: "absolute",
+            left: 0,
+            top: 0,
+            zIndex: -2,
+          }}
+        >
+          <svg width={xMax + "px"} height={window.innerHeight + "px"}>
+            <line
+              x1={xPosition + radius}
+              y1={yPosition + radius}
+              x2={xPosition + radius}
+              y2={yMin}
+              stroke={"#deb887"}
+              strokeWidth="10"
+            />
+          </svg>
+        </div>
+      )}
+      {this.props.dataDoc['simulationType'] == "Suspension" && (
         <div
           className="rod"
           style={{
@@ -611,45 +1120,200 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             position: "absolute",
             left: 0,
             top: 0,
+            zIndex: -2,
           }}
         >
-          <svg width={this.props.xMax + "px"} height={300 + "px"}>
+          <svg width={xMax + "px"} height={window.innerHeight + "px"}>
             <line
-              x1={this.state.xPosition + this.props.radius}
-              y1={this.state.yPosition + this.props.radius}
-              x2={this.props.xMax / 2}
+              x1={xPosition + radius}
+              y1={yPosition + radius}
+              x2={(xMax + xMin) / 2 - radius - yMin - 200}
+              y2={yMin}
+              stroke={"#deb887"}
+              strokeWidth="10"
+            />
+          </svg>
+          <p
+            style={{
+              position: "absolute",
+              zIndex: 10,
+              left: (xMax + xMin) / 2 - radius - yMin - 200 + 80 + "px",
+              top: 10 + "px",
+              backgroundColor: labelBackgroundColor,
+            }}
+          >
+            {Math.round(
+              ((Math.atan(
+                (yPosition + radius) /
+                  (xPosition +
+                    radius -
+                    ((xMax + xMin) / 2 - radius - yMin - 200))
+              ) *
+                180) /
+                Math.PI) *
+                100
+            ) / 100}
+            °
+          </p>
+        </div>
+      )}
+      {this.props.dataDoc['simulationType'] == "Suspension" && (
+        <div
+          className="rod"
+          style={{
+            pointerEvents: "none",
+            position: "absolute",
+            left: 0,
+            top: 0,
+            zIndex: -2,
+          }}
+        >
+          <svg width={xMax + "px"} height={window.innerHeight + "px"}>
+            <line
+              x1={xPosition + radius}
+              y1={yPosition + radius}
+              x2={(xMax + xMin) / 2 + yMin + 200 + radius}
+              y2={yMin}
+              stroke={"#deb887"}
+              strokeWidth="10"
+            />
+          </svg>
+
+          <p
+            style={{
+              position: "absolute",
+              zIndex: 10,
+              left: (xMax + xMin) / 2 + yMin + 200 + radius - 80 + "px",
+              top: 10 + "px",
+              backgroundColor: labelBackgroundColor,
+            }}
+          >
+            {Math.round(
+              ((Math.atan(
+                (yPosition + radius) /
+                  ((xMax + xMin) / 2 +
+                    yMin +
+                    200 +
+                    radius -
+                    (xPosition + radius))
+              ) *
+                180) /
+                Math.PI) *
+                100
+            ) / 100}
+            °
+          </p>
+        </div>
+      )}
+      {this.props.dataDoc['simulationType'] == "Circular Motion" && (
+        <div
+          className="rod"
+          style={{
+            pointerEvents: "none",
+            position: "absolute",
+            left: 0,
+            top: 0,
+            zIndex: -2,
+          }}
+        >
+          <svg width={xMax + "px"} height={window.innerHeight + "px"}>
+            <line
+              x1={xPosition + radius}
+              y1={yPosition + radius}
+              x2={(xMin + xMax) / 2}
+              y2={(yMin + yMax) / 2}
+              stroke={"#deb887"}
+              strokeWidth="10"
+            />
+          </svg>
+        </div>
+      )}
+      {this.props.dataDoc['simulationType'] == "Pendulum" && (
+        <div
+          className="rod"
+          style={{
+            pointerEvents: "none",
+            position: "absolute",
+            left: 0,
+            top: 0,
+            zIndex: -2,
+          }}
+        >
+          <svg width={xMax + "px"} height={window.innerHeight + "px"}>
+            <line
+              x1={xPosition + radius}
+              y1={yPosition + radius}
+              x2={xMax / 2}
               y2={-5}
               stroke={"#deb887"}
               strokeWidth="10"
             />
           </svg>
-          {!this.state.dragging && (
+          {!dragging && (
             <div>
               <p
                 style={{
                   position: "absolute",
-                  left: this.props.xMax / 2 + "px",
+                  zIndex: 5,
+                  left: xPosition + "px",
+                  top: yPosition - 70 + "px",
+                  backgroundColor: labelBackgroundColor,
+                }}
+              >
+                {Math.round(pendulumLength)} m
+              </p>
+              <p
+                style={{
+                  position: "absolute",
+                  zIndex: -1,
+                  left: xMax / 2 + "px",
                   top: 30 + "px",
-                  backgroundColor: this.labelBackgroundColor,
+                  backgroundColor: labelBackgroundColor,
                 }}
               >
-                {this.state.angleLabel}°
+                {Math.round(pendulumAngle * 100) / 100}°
               </p>
             </div>
           )}
         </div>
       )}
-      {!this.state.dragging && this.props.dataDoc['showAcceleration'] && (
+      {this.props.dataDoc['simulationType'] == "Inclined Plane" && (
+        <div>
+          <div
+            style={{ position: "absolute", left: "0", top: "0", zIndex: -5 }}
+          >
+            <svg width={xMax + "px"} height={yMax + "px"}>
+              <polygon points={coordinates} style={{ fill: "burlywood" }} />
+            </svg>
+          </div>
+
+          <p
+            style={{
+              position: "absolute",
+              zIndex: 500,
+              left: Math.round(xMax * 0.5 - 200 + wedgeWidth - 80) + "px",
+              top: Math.round(window.innerHeight * 0.8 - 40) + "px",
+            }}
+          >
+            {Math.round(
+              ((Math.atan(wedgeHeight / wedgeWidth) * 180) / Math.PI) * 100
+            ) / 100}
+            °
+          </p>
+        </div>
+      )}
+      {!dragging && showAcceleration && (
         <div>
           <div
             style={{
               pointerEvents: "none",
               position: "absolute",
+              zIndex: -1,
               left: 0,
               top: 0,
             }}
           >
-            <svg width={this.props.xMax + "px"} height={300 + "px"}>
+            <svg width={xMax + "px"} height={window.innerHeight + "px"}>
               <defs>
                 <marker
                   id="accArrow"
@@ -664,10 +1328,10 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 </marker>
               </defs>
               <line
-                x1={this.state.xPosition + this.props.radius}
-                y1={this.state.yPosition + this.props.radius}
-                x2={this.state.xPosition + this.props.radius + this.getNewAccelerationX(this.props.dataDoc['updatedForces']) * 5}
-                y2={this.state.yPosition + this.props.radius + this.getNewAccelerationY(this.props.dataDoc['updatedForces']) * 5}
+                x1={xPosition + radius}
+                y1={yPosition + radius}
+                x2={xPosition + radius + getNewAccelerationX(updatedForces) * 7}
+                y2={yPosition + radius + getNewAccelerationY(updatedForces) * 7}
                 stroke={"green"}
                 strokeWidth="5"
                 markerEnd="url(#accArrow)"
@@ -677,46 +1341,35 @@ export default class Weight extends React.Component<IWeightProps, IState> {
               style={{
                 pointerEvents: "none",
                 position: "absolute",
-                left:
-                  this.state.xPosition +
-                  this.props.radius +
-                  this.getNewAccelerationX(this.props.dataDoc['updatedForces']) * 5 +
-                  25 +
-                  "px",
-                top:
-                  this.state.yPosition +
-                  this.props.radius +
-                  this.getNewAccelerationY(this.props.dataDoc['updatedForces']) * 5 +
-                  25 +
-                  "px",
+                left: xPosition + radius + xAccel * 3 + 25 + "px",
+                top: yPosition + radius + yAccel * 3 + 70 + "px",
+                zIndex: -1,
                 lineHeight: 0.5,
               }}
             >
               <p>
                 {Math.round(
-                  100 *
-                    Math.sqrt(
-                      Math.pow(this.getNewAccelerationX(this.props.dataDoc['updatedForces']) * 3, 2) +
-                        Math.pow(this.getNewAccelerationY(this.props.dataDoc['updatedForces']) * 3, 2)
-                    )
+                  100 * Math.sqrt(xAccel * xAccel + yAccel * yAccel)
                 ) / 100}{" "}
-                m/s<sup>2</sup>
+                m/s
+                <sup>2</sup>
               </p>
             </div>
           </div>
         </div>
       )}
-      {!this.state.dragging && this.props.dataDoc['showVelocity'] && (
+      {!dragging && showVelocity && (
         <div>
           <div
             style={{
               pointerEvents: "none",
               position: "absolute",
+              zIndex: -1,
               left: 0,
               top: 0,
             }}
           >
-            <svg width={this.props.xMax + "px"} height={300 + "px"}>
+            <svg width={xMax + "px"} height={window.innerHeight + "px"}>
               <defs>
                 <marker
                   id="velArrow"
@@ -731,10 +1384,10 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 </marker>
               </defs>
               <line
-                x1={this.state.xPosition + this.props.radius}
-                y1={this.state.yPosition + this.props.radius}
-                x2={this.state.xPosition + this.props.radius + this.state.xVelocity * 3}
-                y2={this.state.yPosition + this.props.radius + this.state.yVelocity * 3}
+                x1={xPosition + radius}
+                y1={yPosition + radius}
+                x2={xPosition + radius + xVelocity * 3}
+                y2={yPosition + radius + yVelocity * 3}
                 stroke={"blue"}
                 strokeWidth="5"
                 markerEnd="url(#velArrow)"
@@ -744,14 +1397,19 @@ export default class Weight extends React.Component<IWeightProps, IState> {
               style={{
                 pointerEvents: "none",
                 position: "absolute",
-                left: this.state.xPosition + this.props.radius + this.state.xVelocity * 3 + 25 + "px",
-                top: this.state.yPosition + this.props.radius + this.state.yVelocity * 3 + "px",
+                left: xPosition + radius + xVelocity * 3 + 25 + "px",
+                top: yPosition + radius + yVelocity * 3 + "px",
+                zIndex: -1,
                 lineHeight: 0.5,
               }}
             >
               <p>
                 {Math.round(
-                  100 * Math.sqrt(this.state.xVelocity**2 + this.state.yVelocity**2)
+                  100 *
+                    Math.sqrt(
+                      displayXVelocity * displayXVelocity +
+                        displayYVelocity * displayYVelocity
+                    )
                 ) / 100}{" "}
                 m/s
               </p>
@@ -759,23 +1417,134 @@ export default class Weight extends React.Component<IWeightProps, IState> {
           </div>
         </div>
       )}
-      {!this.state.dragging &&
-        this.props.dataDoc['showForces'] &&
-        this.props.dataDoc['updatedForces'].map((force, index) => {
-          if (force.magnitude < this.epsilon) {
+      {!dragging &&
+        showComponentForces &&
+        componentForces.map((force, index) => {
+          if (force.magnitude < epsilon) {
+            return;
+          }
+          let arrowStartY: number = yPosition + radius;
+          const arrowStartX: number = xPosition + radius;
+          let arrowEndY: number =
+            arrowStartY -
+            Math.abs(force.magnitude) *
+              20 *
+              Math.sin((force.directionInDegrees * Math.PI) / 180);
+          const arrowEndX: number =
+            arrowStartX +
+            Math.abs(force.magnitude) *
+              20 *
+              Math.cos((force.directionInDegrees * Math.PI) / 180);
+
+          let color = "#0d0d0d";
+
+          let labelTop = arrowEndY;
+          let labelLeft = arrowEndX;
+          if (force.directionInDegrees > 90 && force.directionInDegrees < 270) {
+            labelLeft -= 120;
+          } else {
+            labelLeft += 30;
+          }
+          if (force.directionInDegrees >= 0 && force.directionInDegrees < 180) {
+            labelTop += 40;
+          } else {
+            labelTop -= 40;
+          }
+          labelTop = Math.min(labelTop, yMax + 50);
+          labelTop = Math.max(labelTop, yMin);
+          labelLeft = Math.min(labelLeft, xMax - 60);
+          labelLeft = Math.max(labelLeft, xMin);
+
+          return (
+            <div key={index}>
+              <div
+                style={{
+                  pointerEvents: "none",
+                  position: "absolute",
+                  zIndex: -1,
+                  left: xMin,
+                  top: yMin,
+                }}
+              >
+                <svg
+                  width={xMax - xMin + "px"}
+                  height={window.innerHeight + "px"}
+                >
+                  <defs>
+                    <marker
+                      id="forceArrow"
+                      markerWidth="10"
+                      markerHeight="10"
+                      refX="0"
+                      refY="3"
+                      orient="auto"
+                      markerUnits="strokeWidth"
+                    >
+                      <path d="M0,0 L0,6 L9,3 z" fill={color} />
+                    </marker>
+                  </defs>
+                  {force.component == true && (
+                    <line
+                      x1={arrowStartX}
+                      y1={arrowStartY}
+                      x2={arrowEndX}
+                      y2={arrowEndY}
+                      stroke={color}
+                      strokeWidth="5"
+                      strokeDasharray="10,10"
+                      markerEnd="url(#forceArrow)"
+                    />
+                  )}
+                  {force.component == false && (
+                    <line
+                      x1={arrowStartX}
+                      y1={arrowStartY}
+                      x2={arrowEndX}
+                      y2={arrowEndY}
+                      stroke={color}
+                      strokeWidth="5"
+                      markerEnd="url(#forceArrow)"
+                    />
+                  )}
+                </svg>
+              </div>
+              <div
+                style={{
+                  pointerEvents: "none",
+                  position: "absolute",
+                  left: labelLeft + "px",
+                  top: labelTop + "px",
+                  // zIndex: -1,
+                  lineHeight: 0.5,
+                  backgroundColor: labelBackgroundColor,
+                }}
+              >
+                {force.description && <p>{force.description}</p>}
+                {!force.description && <p>Force</p>}
+                {showForceMagnitudes && (
+                  <p>{Math.round(100 * force.magnitude) / 100} N</p>
+                )}
+              </div>
+            </div>
+          );
+        })}
+      {!dragging &&
+        showForces &&
+        updatedForces.map((force, index) => {
+          if (force.magnitude < epsilon) {
             return;
           }
-          let arrowStartY: number = this.state.yPosition + this.props.radius;
-          const arrowStartX: number = this.state.xPosition + this.props.radius;
+          let arrowStartY: number = yPosition + radius;
+          const arrowStartX: number = xPosition + radius;
           let arrowEndY: number =
             arrowStartY -
             Math.abs(force.magnitude) *
-              10 *
+              20 *
               Math.sin((force.directionInDegrees * Math.PI) / 180);
           const arrowEndX: number =
             arrowStartX +
             Math.abs(force.magnitude) *
-              10 *
+              20 *
               Math.cos((force.directionInDegrees * Math.PI) / 180);
 
           let color = "#0d0d0d";
@@ -792,10 +1561,10 @@ export default class Weight extends React.Component<IWeightProps, IState> {
           } else {
             labelTop -= 40;
           }
-          labelTop = Math.min(labelTop, this.props.yMax + 50);
-          labelTop = Math.max(labelTop, this.props.yMin);
-          labelLeft = Math.min(labelLeft, this.props.xMax - 60);
-          labelLeft = Math.max(labelLeft, this.props.xMin);
+          labelTop = Math.min(labelTop, yMax + 50);
+          labelTop = Math.max(labelTop, yMin);
+          labelLeft = Math.min(labelLeft, xMax - 60);
+          labelLeft = Math.max(labelLeft, xMin);
 
           return (
             <div key={index}>
@@ -803,13 +1572,14 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 style={{
                   pointerEvents: "none",
                   position: "absolute",
-                  left: this.props.xMin,
-                  top: this.props.yMin,
+                  zIndex: -1,
+                  left: xMin,
+                  top: yMin,
                 }}
               >
                 <svg
-                  width={this.props.xMax - this.props.xMin + "px"}
-                  height={300 + "px"}
+                  width={xMax - xMin + "px"}
+                  height={window.innerHeight + "px"}
                 >
                   <defs>
                     <marker
@@ -824,15 +1594,29 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                       <path d="M0,0 L0,6 L9,3 z" fill={color} />
                     </marker>
                   </defs>
-                  <line
-                    x1={arrowStartX}
-                    y1={arrowStartY}
-                    x2={arrowEndX}
-                    y2={arrowEndY}
-                    stroke={color}
-                    strokeWidth="5"
-                    markerEnd="url(#forceArrow)"
-                  />
+                  {force.component == true && (
+                    <line
+                      x1={arrowStartX}
+                      y1={arrowStartY}
+                      x2={arrowEndX}
+                      y2={arrowEndY}
+                      stroke={color}
+                      strokeWidth="5"
+                      strokeDasharray="10,10"
+                      markerEnd="url(#forceArrow)"
+                    />
+                  )}
+                  {force.component == false && (
+                    <line
+                      x1={arrowStartX}
+                      y1={arrowStartY}
+                      x2={arrowEndX}
+                      y2={arrowEndY}
+                      stroke={color}
+                      strokeWidth="5"
+                      markerEnd="url(#forceArrow)"
+                    />
+                  )}
                 </svg>
               </div>
               <div
@@ -842,12 +1626,12 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                   left: labelLeft + "px",
                   top: labelTop + "px",
                   lineHeight: 0.5,
-                  backgroundColor: this.labelBackgroundColor,
+                  backgroundColor: labelBackgroundColor,
                 }}
               >
                 {force.description && <p>{force.description}</p>}
                 {!force.description && <p>Force</p>}
-                {this.props.dataDoc['showForceMagnitudes'] && (
+                {showForceMagnitudes && (
                   <p>{Math.round(100 * force.magnitude) / 100} N</p>
                 )}
               </div>
@@ -855,6 +1639,5 @@ export default class Weight extends React.Component<IWeightProps, IState> {
           );
         })}
     </div>
-    );
-  }
+  );
 };
-- 
cgit v1.2.3-70-g09d2


From 993210bb011e326edb93b4654a1f97850e7c9ee8 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 1 May 2023 17:36:33 -0400
Subject: refactorweight

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      |  2 +
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   | 99 +++++++++++-----------
 2 files changed, 52 insertions(+), 49 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index bdc76048c..35a7ee346 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -1281,6 +1281,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
           <div className="mechanicsSimulationElements">
             <Weight
               dataDoc={this.dataDoc}
+              layoutDoc={this.layoutDoc}
               adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
               gravity={this.dataDoc.gravity}
               circularMotionRadius={this.dataDoc.circularMotionRadius}
@@ -1329,6 +1330,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             {this.dataDoc.simulationType == "Pulley" && (
               <Weight
                 dataDoc={this.dataDoc}
+                layoutDoc={this.layoutDoc}
                 adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
                 circularMotionRadius={this.dataDoc.circularMotionRadius}
                 gravity={this.dataDoc.gravity}
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 2ae34374d..c24438e19 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -12,6 +12,7 @@ export interface IForce {
 }
 export interface IWeightProps {
   dataDoc: Doc;
+  layoutDoc: Doc;
   adjustPendulumAngle: { angle: number; length: number };
   circularMotionRadius: number;
   coefficientOfKineticFriction: number;
@@ -584,7 +585,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     if (this.state.xVelocity != 0) {
       this.state.walls.forEach((wall) => {
         if (wall.angleInDegrees == 90) {
-          const wallX = (wall.xPos / 100) * window.innerWidth;
+          const wallX = (wall.xPos / 100) * this.props.layoutDoc._width;
           if (wall.xPos < 0.35) {
             if (minX <= wallX) {
               this.setState({xPosition: wallX+0.01});
@@ -613,14 +614,14 @@ export default class Weight extends React.Component<IWeightProps, IState> {
   };
 
   // Check for collisions in y direction
-  const checkForCollisionsWithGround = () => {
+  checkForCollisionsWithGround = () => {
     let collision = false;
     const minY = this.state.yPosition;
     const maxY = this.state.yPosition + 2 * this.props.radius;
     if (this.state.yVelocity > 0) {
       this.state.walls.forEach((wall) => {
         if (wall.angleInDegrees == 0 && wall.yPos > 0.4) {
-          const groundY = (wall.yPos / 100) * window.innerHeight;
+          const groundY = (wall.yPos / 100) * this.props.layoutDoc._height;
           if (maxY > groundY) {
             this.setState({yPosition: groundY- 2 * this.props.radius-0.01});
             if (this.props.elasticCollisions) {
@@ -666,7 +667,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     if (this.state.yVelocity < 0) {
       this.state.walls.forEach((wall) => {
         if (wall.angleInDegrees == 0 && wall.yPos < 0.4) {
-          const groundY = (wall.yPos / 100) * window.innerHeight;
+          const groundY = (wall.yPos / 100) * this.props.layoutDoc._height;
           if (minY < groundY) {
             this.setState({yPosition: groundY + 0.01});
             if (this.props.elasticCollisions) {
@@ -730,7 +731,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     let yPos = this.state.yPosition;
     let xVel = this.state.xVelocity;
     let yVel = this.state.yVelocity;
-    let forces = this.props.dataDoc['updatedForces'];
+    let forces: IForce[] = this.props.dataDoc['updatedForces'];
     if (this.props.dataDoc['simulationType'] == "Pendulum") {
       forces = this.getNewPendulumForces(xPos, yPos, xVel, yVel);
     } else if (this.props.dataDoc['simulationType'] == "Spring") {
@@ -1025,7 +1026,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             zIndex: -2,
           }}
         >
-          <svg width={this.props.xMax + "px"} height={window.innerHeight + "px"}>
+          <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
             {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map((val) => {
               const count = 10;
               let xPos1;
@@ -1067,7 +1068,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             zIndex: -1,
           }}
         >
-          <svg width={this.props.xMax + "px"} height={window.innerHeight + "px"}>
+          <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
             <circle
               cx={(this.props.xMax + this.props.xMin) / 2}
               cy={this.props.radius}
@@ -1088,7 +1089,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             zIndex: -2,
           }}
         >
-          <svg width={this.props.xMax + "px"} height={window.innerHeight + "px"}>
+          <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
             <line
               x1={this.state.xPosition + this.props.radius}
               y1={this.state.yPosition + this.props.radius}
@@ -1111,7 +1112,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             zIndex: -2,
           }}
         >
-          <svg width={this.props.xMax + "px"} height={window.innerHeight + "px"}>
+          <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
             <line
               x1={this.state.xPosition + this.props.radius}
               y1={this.state.yPosition + this.props.radius}
@@ -1156,7 +1157,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             zIndex: -2,
           }}
         >
-          <svg width={this.props.xMax + "px"} height={window.innerHeight + "px"}>
+          <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
             <line
               x1={this.state.xPosition + this.props.radius}
               y1={this.state.yPosition + this.props.radius}
@@ -1204,7 +1205,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             zIndex: -2,
           }}
         >
-          <svg width={this.props.xMax + "px"} height={window.innerHeight + "px"}>
+          <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
             <line
               x1={this.state.xPosition + this.props.radius}
               y1={this.state.yPosition + this.props.radius}
@@ -1227,7 +1228,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             zIndex: -2,
           }}
         >
-          <svg width={this.props.xMax + "px"} height={window.innerHeight + "px"}>
+          <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
             <line
               x1={this.state.xPosition + this.props.radius}
               y1={this.state.yPosition + this.props.radius}
@@ -1280,7 +1281,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
               position: "absolute",
               zIndex: 500,
               left: Math.round(this.props.xMax * 0.5 - 200 + this.props.wedgeWidth - 80) + "px",
-              top: Math.round(window.innerHeight * 0.8 - 40) + "px",
+              top: Math.round(this.props.layoutDoc._height * 0.8 - 40) + "px",
             }}
           >
             {Math.round(
@@ -1301,7 +1302,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
               top: 0,
             }}
           >
-            <svg width={this.props.xMax + "px"} height={window.innerHeight + "px"}>
+            <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
               <defs>
                 <marker
                   id="accArrow"
@@ -1357,7 +1358,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
               top: 0,
             }}
           >
-            <svg width={this.props.xMax + "px"} height={window.innerHeight + "px"}>
+            <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
               <defs>
                 <marker
                   id="velArrow"
@@ -1395,8 +1396,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 {Math.round(
                   100 *
                     Math.sqrt(
-                      this.props.displayXVelocity *  this.props.displayXVelocity +
-                      this.props.displayYVelocity *  this.props.displayYVelocity
+                      this.props.displayXVelocity * this.props.displayXVelocity +
+                      this.props.displayYVelocity * this.props.displayYVelocity
                     )
                 ) / 100}{" "}
                 m/s
@@ -1405,14 +1406,14 @@ export default class Weight extends React.Component<IWeightProps, IState> {
           </div>
         </div>
       )}
-      {!dragging &&
-        showComponentForces &&
-        componentForces.map((force, index) => {
-          if (force.magnitude < epsilon) {
+      {!this.state.dragging &&
+        this.props.showComponentForces &&
+        this.props.componentForces.map((force, index) => {
+          if (force.magnitude < this.epsilon) {
             return;
           }
-          let arrowStartY: number = yPosition + radius;
-          const arrowStartX: number = xPosition + radius;
+          let arrowStartY: number = this.state.yPosition + this.props.radius;
+          const arrowStartX: number = this.state.xPosition + this.props.radius;
           let arrowEndY: number =
             arrowStartY -
             Math.abs(force.magnitude) *
@@ -1438,10 +1439,10 @@ export default class Weight extends React.Component<IWeightProps, IState> {
           } else {
             labelTop -= 40;
           }
-          labelTop = Math.min(labelTop, yMax + 50);
-          labelTop = Math.max(labelTop, yMin);
-          labelLeft = Math.min(labelLeft, xMax - 60);
-          labelLeft = Math.max(labelLeft, xMin);
+          labelTop = Math.min(labelTop, this.props.yMax + 50);
+          labelTop = Math.max(labelTop, this.props.yMin);
+          labelLeft = Math.min(labelLeft, this.props.xMax - 60);
+          labelLeft = Math.max(labelLeft, this.props.xMin);
 
           return (
             <div key={index}>
@@ -1450,13 +1451,13 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                   pointerEvents: "none",
                   position: "absolute",
                   zIndex: -1,
-                  left: xMin,
-                  top: yMin,
+                  left: this.props.xMin,
+                  top: this.props.yMin,
                 }}
               >
                 <svg
-                  width={xMax - xMin + "px"}
-                  height={window.innerHeight + "px"}
+                  width={this.props.xMax - this.props.xMin + "px"}
+                  height={this.props.layoutDoc._height + "px"}
                 >
                   <defs>
                     <marker
@@ -1504,26 +1505,26 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                   top: labelTop + "px",
                   // zIndex: -1,
                   lineHeight: 0.5,
-                  backgroundColor: labelBackgroundColor,
+                  backgroundColor: this.labelBackgroundColor,
                 }}
               >
                 {force.description && <p>{force.description}</p>}
                 {!force.description && <p>Force</p>}
-                {showForceMagnitudes && (
+                {this.props.showForceMagnitudes && (
                   <p>{Math.round(100 * force.magnitude) / 100} N</p>
                 )}
               </div>
             </div>
           );
         })}
-      {!dragging &&
-        showForces &&
-        updatedForces.map((force, index) => {
-          if (force.magnitude < epsilon) {
+      {!this.state.dragging &&
+        this.props.showForces &&
+        this.props.updatedForces.map((force, index) => {
+          if (force.magnitude < this.epsilon) {
             return;
           }
-          let arrowStartY: number = yPosition + radius;
-          const arrowStartX: number = xPosition + radius;
+          let arrowStartY: number = this.state.yPosition + this.props.radius;
+          const arrowStartX: number = this.state.xPosition + this.props.radius;
           let arrowEndY: number =
             arrowStartY -
             Math.abs(force.magnitude) *
@@ -1549,10 +1550,10 @@ export default class Weight extends React.Component<IWeightProps, IState> {
           } else {
             labelTop -= 40;
           }
-          labelTop = Math.min(labelTop, yMax + 50);
-          labelTop = Math.max(labelTop, yMin);
-          labelLeft = Math.min(labelLeft, xMax - 60);
-          labelLeft = Math.max(labelLeft, xMin);
+          labelTop = Math.min(labelTop, this.props.yMax + 50);
+          labelTop = Math.max(labelTop, this.props.yMin);
+          labelLeft = Math.min(labelLeft, this.props.xMax - 60);
+          labelLeft = Math.max(labelLeft, this.props.xMin);
 
           return (
             <div key={index}>
@@ -1561,13 +1562,13 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                   pointerEvents: "none",
                   position: "absolute",
                   zIndex: -1,
-                  left: xMin,
-                  top: yMin,
+                  left: this.props.xMin,
+                  top: this.props.yMin,
                 }}
               >
                 <svg
-                  width={xMax - xMin + "px"}
-                  height={window.innerHeight + "px"}
+                  width={this.props.xMax - this.props.xMin + "px"}
+                  height={this.props.layoutDoc._height + "px"}
                 >
                   <defs>
                     <marker
@@ -1614,12 +1615,12 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                   left: labelLeft + "px",
                   top: labelTop + "px",
                   lineHeight: 0.5,
-                  backgroundColor: labelBackgroundColor,
+                  backgroundColor: this.labelBackgroundColor,
                 }}
               >
                 {force.description && <p>{force.description}</p>}
                 {!force.description && <p>Force</p>}
-                {showForceMagnitudes && (
+                {this.props.showForceMagnitudes && (
                   <p>{Math.round(100 * force.magnitude) / 100} N</p>
                 )}
               </div>
-- 
cgit v1.2.3-70-g09d2


From 3ca511f885b8cdcd1a3099e2f54179f5513aed92 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 1 May 2023 17:52:05 -0400
Subject: install material ui dependencies

---
 package-lock.json                                  | 31215 +------------------
 package.json                                       |     6 +-
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      |     5 +-
 .../PhysicsBox/PhysicsSimulationInputField.tsx     |   184 +
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   |     3 +-
 5 files changed, 1337 insertions(+), 30076 deletions(-)
 create mode 100644 src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/package-lock.json b/package-lock.json
index bc475d02a..93958b434 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,29432 +1,8 @@
 {
     "name": "dash",
     "version": "1.0.0",
-    "lockfileVersion": 2,
+    "lockfileVersion": 1,
     "requires": true,
-    "packages": {
-        "": {
-            "name": "dash",
-            "version": "1.0.0",
-            "dependencies": {
-                "@ffmpeg/core": "0.10.0",
-                "@ffmpeg/ffmpeg": "0.10.0",
-                "@fortawesome/fontawesome-svg-core": "^1.3.0",
-                "@fortawesome/free-brands-svg-icons": "^5.15.4",
-                "@fortawesome/free-regular-svg-icons": "^5.15.4",
-                "@fortawesome/free-solid-svg-icons": "^5.15.4",
-                "@fortawesome/react-fontawesome": "^0.1.19",
-                "@hig/flyout": "^1.3.1",
-                "@hig/theme-context": "^2.1.3",
-                "@hig/theme-data": "^2.23.1",
-                "@material-ui/core": "^4.12.3",
-                "@octokit/core": "^4.0.4",
-                "@react-google-maps/api": "^2.7.0",
-                "@react-three/fiber": "^6.2.3",
-                "@types/bezier-js": "^4.1.0",
-                "@types/cors": "^2.8.12",
-                "@types/d3-axis": "^2.1.3",
-                "@types/d3-color": "^2.0.3",
-                "@types/d3-scale": "^3.3.2",
-                "@types/d3-selection": "^2.0.1",
-                "@types/dom-speech-recognition": "0.0.1",
-                "@types/formidable": "1.0.31",
-                "@types/google-maps": "^3.2.3",
-                "@types/reveal": "^3.3.33",
-                "@types/supercluster": "^7.1.0",
-                "@types/three": "^0.126.2",
-                "@types/web": "0.0.53",
-                "@webscopeio/react-textarea-autocomplete": "^4.9.1",
-                "adm-zip": "^0.4.16",
-                "archiver": "^3.1.1",
-                "array-batcher": "^1.2.3",
-                "async": "^2.6.2",
-                "axios": "^0.19.2",
-                "babel": "^6.23.0",
-                "bcrypt-nodejs": "0.0.3",
-                "bezier-curve": "^1.0.0",
-                "bezier-js": "^4.1.1",
-                "bluebird": "^3.7.2",
-                "body-parser": "^1.19.2",
-                "bootstrap": "^4.6.1",
-                "browndash-components": "0.0.22",
-                "browser-assert": "^1.2.1",
-                "bson": "^4.6.1",
-                "canvas": "^2.9.3",
-                "child_process": "^1.0.2",
-                "chrome": "^0.1.0",
-                "class-transformer": "^0.2.0",
-                "color": "^3.2.1",
-                "colors": "^1.4.0",
-                "connect-flash": "^0.1.1",
-                "connect-mongo": "^2.0.3",
-                "cookie-parser": "^1.4.6",
-                "cookie-session": "^2.0.0",
-                "cors": "^2.8.5",
-                "D": "^1.0.0",
-                "depcheck": "^0.9.2",
-                "equation-editor-react": "github:bobzel/equation-editor-react#useLocally",
-                "exif": "^0.6.0",
-                "exifr": "^7.1.3",
-                "express": "^4.17.3",
-                "express-flash": "0.0.2",
-                "express-session": "^1.17.2",
-                "express-validator": "^5.3.1",
-                "expressjs": "^1.0.1",
-                "ffmpeg": "0.0.4",
-                "file-saver": "^2.0.5",
-                "find-in-files": "^0.5.0",
-                "fit-curve": "^0.1.7",
-                "flexlayout-react": "^0.3.11",
-                "fluent-ffmpeg": "^2.1.2",
-                "forever-agent": "^0.6.1",
-                "formidable": "1.2.1",
-                "function-plot": "^1.22.8",
-                "golden-layout": "^1.5.9",
-                "google-auth-library": "^4.2.4",
-                "google-maps-react": "^2.0.6",
-                "googleapis": "^40.0.0",
-                "googlephotos": "^0.2.5",
-                "got": "^12.0.1",
-                "howler": "^2.2.3",
-                "html-to-image": "^0.1.3",
-                "html-to-text": "^5.1.1",
-                "html-webpack-plugin": "^5.5.0",
-                "http-browserify": "^1.7.0",
-                "https": "^1.0.0",
-                "https-browserify": "^1.0.0",
-                "i": "^0.3.7",
-                "iink-js": "^1.5.4",
-                "image-data-uri": "^2.0.1",
-                "image-size": "^0.7.5",
-                "image-size-stream": "^1.1.0",
-                "js-datepicker": "^4.6.6",
-                "jsonschema": "^1.4.0",
-                "jszip": "^3.7.1",
-                "lodash": "^4.17.21",
-                "material-ui": "^0.20.2",
-                "md5-file": "^5.0.0",
-                "memorystream": "^0.3.1",
-                "mobile-detect": "^1.4.5",
-                "mobx": "^5.15.7",
-                "mobx-react": "^5.4.4",
-                "mobx-react-devtools": "^6.1.1",
-                "mobx-utils": "^5.6.2",
-                "mongodb": "^3.7.3",
-                "mongoose": "^5.13.14",
-                "node-sass": "^4.14.1",
-                "node-stream-zip": "^1.15.0",
-                "nodemailer": "^5.1.1",
-                "nodemon": "^1.19.4",
-                "normalize.css": "^8.0.1",
-                "npm": "^6.14.18",
-                "p-limit": "^2.2.0",
-                "passport": "^0.4.0",
-                "passport-google-oauth20": "^2.0.0",
-                "passport-local": "^1.0.0",
-                "path-browserify": "^1.0.1",
-                "pdf-parse": "^1.1.1",
-                "pdfjs": "^2.4.7",
-                "pdfjs-dist": "^2.14.305",
-                "probe-image-size": "^4.0.0",
-                "process": "^0.11.10",
-                "prosemirror-commands": "^1.2.1",
-                "prosemirror-dev-tools": "^3.1.0",
-                "prosemirror-find-replace": "^0.9.0",
-                "prosemirror-history": "^1.2.0",
-                "prosemirror-inputrules": "^1.1.3",
-                "prosemirror-keymap": "^1.1.5",
-                "prosemirror-model": "^1.18.1",
-                "prosemirror-schema-list": "^1.1.6",
-                "prosemirror-state": "^1.4.1",
-                "prosemirror-transform": "^1.3.4",
-                "prosemirror-view": "^1.26.5",
-                "pug": "^2.0.4",
-                "puppeteer": "^3.3.0",
-                "query-string": "^6.14.1",
-                "raw-loader": "^1.0.0",
-                "rc-switch": "^1.9.2",
-                "react": "^18.2.0",
-                "react-audio-waveform": "0.0.5",
-                "react-autosuggest": "^9.4.3",
-                "react-beautiful-dnd": "^13.1.0",
-                "react-color": "^2.19.3",
-                "react-compound-slider": "^2.5.0",
-                "react-datepicker": "^3.8.0",
-                "react-dom": "^18.2.0",
-                "react-grid-layout": "^1.3.4",
-                "react-icons": "^4.3.1",
-                "react-jsx-parser": "^1.29.0",
-                "react-loading": "^2.0.3",
-                "react-markdown": "^8.0.3",
-                "react-measure": "^2.5.2",
-                "react-refresh-typescript": "^2.0.7",
-                "react-resizable": "^1.11.1",
-                "react-resizable-rotatable-draggable": "^0.2.0",
-                "react-reveal": "^1.2.2",
-                "react-select": "^3.2.0",
-                "react-table": "^6.11.5",
-                "react-transition-group": "^4.4.2",
-                "readline": "^1.3.0",
-                "rehype-raw": "^6.1.1",
-                "remark-gfm": "^3.0.1",
-                "request": "^2.88.2",
-                "request-promise": "^4.2.6",
-                "reveal.js": "^4.3.0",
-                "rimraf": "^3.0.0",
-                "serializr": "^1.5.4",
-                "sharp": "^0.23.4",
-                "shelljs": "^0.8.5",
-                "socket.io": "^2.5.0",
-                "socket.io-client": "^2.5.0",
-                "solr-node": "^1.2.1",
-                "standard-http-error": "^2.0.1",
-                "stream-browserify": "^3.0.0",
-                "styled-components": "^4.4.1",
-                "supercluster": "^7.1.4",
-                "textarea-caret": "^3.1.0",
-                "three": "^0.127.0",
-                "tough-cookie": "^4.0.0",
-                "translate-google-api": "^1.0.4",
-                "typescript-collections": "^1.3.3",
-                "typescript-language-server": "^0.4.0",
-                "url-loader": "^1.1.2",
-                "util": "^0.12.4",
-                "uuid": "^3.4.0",
-                "valid-url": "^1.0.9",
-                "web-request": "^1.0.7",
-                "webpack-cli": "^4.10.0",
-                "webpack-dev-middleware": "^5.3.1",
-                "webrtc-adapter": "^7.7.1",
-                "wikijs": "^6.3.3",
-                "words-to-numbers": "^1.5.1",
-                "xoauth2": "^1.2.0",
-                "xregexp": "^4.4.1"
-            },
-            "devDependencies": {
-                "@types/adm-zip": "^0.4.34",
-                "@types/animejs": "^2.0.2",
-                "@types/archiver": "^3.1.1",
-                "@types/async": "^2.4.1",
-                "@types/bcrypt-nodejs": "0.0.30",
-                "@types/bluebird": "^3.5.36",
-                "@types/body-parser": "^1.19.2",
-                "@types/chai": "^4.3.0",
-                "@types/color": "^3.0.3",
-                "@types/connect-flash": "0.0.34",
-                "@types/cookie-parser": "^1.4.2",
-                "@types/cookie-session": "^2.0.44",
-                "@types/dotenv": "^6.1.1",
-                "@types/exif": "^0.6.3",
-                "@types/express": "^4.17.13",
-                "@types/express-flash": "0.0.0",
-                "@types/express-session": "^1.17.5",
-                "@types/express-validator": "^3.0.0",
-                "@types/file-saver": "^2.0.5",
-                "@types/google-maps-react": "^2.0.5",
-                "@types/jquery": "^3.5.14",
-                "@types/libxmljs": "^0.18.7",
-                "@types/lodash": "^4.14.179",
-                "@types/mobile-detect": "^1.3.4",
-                "@types/mocha": "^5.2.6",
-                "@types/mongodb": "^3.6.20",
-                "@types/mongoose": "^5.11.97",
-                "@types/node": "^10.17.60",
-                "@types/nodemailer": "^4.6.6",
-                "@types/passport": "^1.0.9",
-                "@types/passport-google-oauth20": "^2.0.11",
-                "@types/passport-local": "^1.0.34",
-                "@types/pdfjs-dist": "^2.10.378",
-                "@types/prosemirror-commands": "^1.0.4",
-                "@types/prosemirror-dev-tools": "^2.1.0",
-                "@types/prosemirror-history": "^1.0.3",
-                "@types/prosemirror-inputrules": "^1.0.4",
-                "@types/prosemirror-keymap": "^1.0.4",
-                "@types/prosemirror-menu": "^1.0.6",
-                "@types/prosemirror-model": "^1.16.1",
-                "@types/prosemirror-schema-list": "^1.0.3",
-                "@types/prosemirror-state": "^1.2.8",
-                "@types/prosemirror-transform": "^1.1.5",
-                "@types/prosemirror-view": "^1.23.1",
-                "@types/rc-switch": "^1.9.2",
-                "@types/react": "^18.0.15",
-                "@types/react-autosuggest": "^9.3.14",
-                "@types/react-color": "^2.17.6",
-                "@types/react-datepicker": "^3.1.8",
-                "@types/react-dom": "^18.0.6",
-                "@types/react-grid-layout": "^1.3.2",
-                "@types/react-icons": "^3.0.0",
-                "@types/react-measure": "^2.0.8",
-                "@types/react-reconciler": "^0.26.4",
-                "@types/react-select": "^3.1.2",
-                "@types/react-table": "^6.8.9",
-                "@types/react-transition-group": "^4.4.5",
-                "@types/request": "^2.48.8",
-                "@types/request-promise": "^4.1.48",
-                "@types/rimraf": "^2.0.5",
-                "@types/sharp": "^0.23.1",
-                "@types/shelljs": "^0.8.11",
-                "@types/socket.io": "^2.1.13",
-                "@types/socket.io-client": "^1.4.36",
-                "@types/socket.io-parser": "^3.0.0",
-                "@types/typescript": "^2.0.0",
-                "@types/uuid": "^3.4.10",
-                "@types/valid-url": "^1.0.3",
-                "@types/webpack": "^4.41.32",
-                "@types/webpack-hot-middleware": "^2.25.6",
-                "@types/xregexp": "^4.4.0",
-                "@types/youtube": "0.0.39",
-                "awesome-typescript-loader": "^5.2.1",
-                "chai": "^4.3.6",
-                "copy-webpack-plugin": "^4.6.0",
-                "cross-env": "^5.2.1",
-                "css-loader": "^2.1.1",
-                "dotenv": "^8.6.0",
-                "eslint": "^8.18.0",
-                "eslint-config-airbnb": "^19.0.4",
-                "eslint-config-node": "^4.1.0",
-                "eslint-config-prettier": "^8.5.0",
-                "eslint-plugin-import": "^2.26.0",
-                "eslint-plugin-jsx-a11y": "^6.6.0",
-                "eslint-plugin-node": "^11.1.0",
-                "eslint-plugin-prettier": "^4.2.1",
-                "eslint-plugin-react": "^7.30.1",
-                "eslint-plugin-react-hooks": "^4.6.0",
-                "file-loader": "^3.0.1",
-                "fork-ts-checker-webpack-plugin": "^1.6.0",
-                "jsdom": "^15.2.1",
-                "mocha": "^5.2.0",
-                "prettier": "^2.7.1",
-                "sass-loader": "^7.3.1",
-                "scss-loader": "0.0.1",
-                "style-loader": "^0.23.1",
-                "ts-loader": "^5.3.3",
-                "ts-node": "^10.9.1",
-                "ts-node-dev": "^2.0.0",
-                "tslint": "^5.20.1",
-                "tslint-loader": "^3.6.0",
-                "typescript": "^4.7.4",
-                "webpack": "^5.69.1",
-                "webpack-dev-server": "^3.11.3",
-                "webpack-hot-middleware": "^2.25.1"
-            }
-        },
-        "node_modules/@babel/code-frame": {
-            "version": "7.16.7",
-            "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
-            "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==",
-            "dependencies": {
-                "@babel/highlight": "^7.16.7"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/generator": {
-            "version": "7.18.2",
-            "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz",
-            "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==",
-            "dependencies": {
-                "@babel/types": "^7.18.2",
-                "@jridgewell/gen-mapping": "^0.3.0",
-                "jsesc": "^2.5.1"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-annotate-as-pure": {
-            "version": "7.16.7",
-            "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz",
-            "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==",
-            "dependencies": {
-                "@babel/types": "^7.16.7"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-environment-visitor": {
-            "version": "7.18.2",
-            "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz",
-            "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==",
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-function-name": {
-            "version": "7.17.9",
-            "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz",
-            "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==",
-            "dependencies": {
-                "@babel/template": "^7.16.7",
-                "@babel/types": "^7.17.0"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-hoist-variables": {
-            "version": "7.16.7",
-            "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz",
-            "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==",
-            "dependencies": {
-                "@babel/types": "^7.16.7"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-module-imports": {
-            "version": "7.16.7",
-            "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz",
-            "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==",
-            "dependencies": {
-                "@babel/types": "^7.16.7"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-plugin-utils": {
-            "version": "7.17.12",
-            "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz",
-            "integrity": "sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==",
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-split-export-declaration": {
-            "version": "7.16.7",
-            "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz",
-            "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==",
-            "dependencies": {
-                "@babel/types": "^7.16.7"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-validator-identifier": {
-            "version": "7.16.7",
-            "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
-            "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==",
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/highlight": {
-            "version": "7.17.12",
-            "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz",
-            "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==",
-            "dependencies": {
-                "@babel/helper-validator-identifier": "^7.16.7",
-                "chalk": "^2.0.0",
-                "js-tokens": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/parser": {
-            "version": "7.18.4",
-            "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.4.tgz",
-            "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==",
-            "bin": {
-                "parser": "bin/babel-parser.js"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/@babel/plugin-syntax-jsx": {
-            "version": "7.17.12",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.17.12.tgz",
-            "integrity": "sha512-spyY3E3AURfxh/RHtjx5j6hs8am5NbUBGfcZ2vB3uShSpZdQyXSf5rR5Mk76vbtlAZOelyVQ71Fg0x9SG4fsog==",
-            "dependencies": {
-                "@babel/helper-plugin-utils": "^7.17.12"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            },
-            "peerDependencies": {
-                "@babel/core": "^7.0.0-0"
-            }
-        },
-        "node_modules/@babel/runtime": {
-            "version": "7.18.3",
-            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.3.tgz",
-            "integrity": "sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==",
-            "dependencies": {
-                "regenerator-runtime": "^0.13.4"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/runtime-corejs3": {
-            "version": "7.18.3",
-            "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.18.3.tgz",
-            "integrity": "sha512-l4ddFwrc9rnR+EJsHsh+TJ4A35YqQz/UqcjtlX2ov53hlJYG5CxtQmNZxyajwDVmCxwy++rtvGU5HazCK4W41Q==",
-            "dependencies": {
-                "core-js-pure": "^3.20.2",
-                "regenerator-runtime": "^0.13.4"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/template": {
-            "version": "7.16.7",
-            "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
-            "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==",
-            "dependencies": {
-                "@babel/code-frame": "^7.16.7",
-                "@babel/parser": "^7.16.7",
-                "@babel/types": "^7.16.7"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/traverse": {
-            "version": "7.18.2",
-            "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.2.tgz",
-            "integrity": "sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==",
-            "dependencies": {
-                "@babel/code-frame": "^7.16.7",
-                "@babel/generator": "^7.18.2",
-                "@babel/helper-environment-visitor": "^7.18.2",
-                "@babel/helper-function-name": "^7.17.9",
-                "@babel/helper-hoist-variables": "^7.16.7",
-                "@babel/helper-split-export-declaration": "^7.16.7",
-                "@babel/parser": "^7.18.0",
-                "@babel/types": "^7.18.2",
-                "debug": "^4.1.0",
-                "globals": "^11.1.0"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/traverse/node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@babel/traverse/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
-        },
-        "node_modules/@babel/types": {
-            "version": "7.18.4",
-            "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz",
-            "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==",
-            "dependencies": {
-                "@babel/helper-validator-identifier": "^7.16.7",
-                "to-fast-properties": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@cspotcode/source-map-support": {
-            "version": "0.8.1",
-            "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
-            "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
-            "dev": true,
-            "dependencies": {
-                "@jridgewell/trace-mapping": "0.3.9"
-            },
-            "engines": {
-                "node": ">=12"
-            }
-        },
-        "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
-            "version": "0.3.9",
-            "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
-            "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
-            "dev": true,
-            "dependencies": {
-                "@jridgewell/resolve-uri": "^3.0.3",
-                "@jridgewell/sourcemap-codec": "^1.4.10"
-            }
-        },
-        "node_modules/@discoveryjs/json-ext": {
-            "version": "0.5.7",
-            "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
-            "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
-            "engines": {
-                "node": ">=10.0.0"
-            }
-        },
-        "node_modules/@emotion/babel-plugin": {
-            "version": "11.9.2",
-            "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.9.2.tgz",
-            "integrity": "sha512-Pr/7HGH6H6yKgnVFNEj2MVlreu3ADqftqjqwUvDy/OJzKFgxKeTQ+eeUf20FOTuHVkDON2iNa25rAXVYtWJCjw==",
-            "dependencies": {
-                "@babel/helper-module-imports": "^7.12.13",
-                "@babel/plugin-syntax-jsx": "^7.12.13",
-                "@babel/runtime": "^7.13.10",
-                "@emotion/hash": "^0.8.0",
-                "@emotion/memoize": "^0.7.5",
-                "@emotion/serialize": "^1.0.2",
-                "babel-plugin-macros": "^2.6.1",
-                "convert-source-map": "^1.5.0",
-                "escape-string-regexp": "^4.0.0",
-                "find-root": "^1.1.0",
-                "source-map": "^0.5.7",
-                "stylis": "4.0.13"
-            },
-            "peerDependencies": {
-                "@babel/core": "^7.0.0"
-            }
-        },
-        "node_modules/@emotion/babel-plugin/node_modules/@emotion/memoize": {
-            "version": "0.7.5",
-            "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz",
-            "integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ=="
-        },
-        "node_modules/@emotion/babel-plugin/node_modules/@emotion/serialize": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.3.tgz",
-            "integrity": "sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==",
-            "dependencies": {
-                "@emotion/hash": "^0.8.0",
-                "@emotion/memoize": "^0.7.4",
-                "@emotion/unitless": "^0.7.5",
-                "@emotion/utils": "^1.0.0",
-                "csstype": "^3.0.2"
-            }
-        },
-        "node_modules/@emotion/babel-plugin/node_modules/@emotion/utils": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.1.0.tgz",
-            "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
-        },
-        "node_modules/@emotion/babel-plugin/node_modules/csstype": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-            "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
-        },
-        "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-            "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/@emotion/cache": {
-            "version": "10.0.29",
-            "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz",
-            "integrity": "sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==",
-            "dependencies": {
-                "@emotion/sheet": "0.9.4",
-                "@emotion/stylis": "0.8.5",
-                "@emotion/utils": "0.11.3",
-                "@emotion/weak-memoize": "0.2.5"
-            }
-        },
-        "node_modules/@emotion/core": {
-            "version": "10.3.1",
-            "resolved": "https://registry.npmjs.org/@emotion/core/-/core-10.3.1.tgz",
-            "integrity": "sha512-447aUEjPIm0MnE6QYIaFz9VQOHSXf4Iu6EWOIqq11EAPqinkSZmfymPTmlOE3QjLv846lH4JVZBUOtwGbuQoww==",
-            "dependencies": {
-                "@babel/runtime": "^7.5.5",
-                "@emotion/cache": "^10.0.27",
-                "@emotion/css": "^10.0.27",
-                "@emotion/serialize": "^0.11.15",
-                "@emotion/sheet": "0.9.4",
-                "@emotion/utils": "0.11.3"
-            },
-            "peerDependencies": {
-                "react": ">=16.3.0"
-            }
-        },
-        "node_modules/@emotion/core/node_modules/@emotion/css": {
-            "version": "10.0.27",
-            "resolved": "https://registry.npmjs.org/@emotion/css/-/css-10.0.27.tgz",
-            "integrity": "sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw==",
-            "dependencies": {
-                "@emotion/serialize": "^0.11.15",
-                "@emotion/utils": "0.11.3",
-                "babel-plugin-emotion": "^10.0.27"
-            }
-        },
-        "node_modules/@emotion/css": {
-            "version": "11.9.0",
-            "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.9.0.tgz",
-            "integrity": "sha512-S9UjCxSrxEHawOLnWw4upTwfYKb0gVQdatHejn3W9kPyXxmKv3HmjVfJ84kDLmdX8jR20OuDQwaJ4Um24qD9vA==",
-            "dependencies": {
-                "@emotion/babel-plugin": "^11.7.1",
-                "@emotion/cache": "^11.7.1",
-                "@emotion/serialize": "^1.0.3",
-                "@emotion/sheet": "^1.0.3",
-                "@emotion/utils": "^1.0.0"
-            },
-            "peerDependencies": {
-                "@babel/core": "^7.0.0"
-            },
-            "peerDependenciesMeta": {
-                "@babel/core": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@emotion/css/node_modules/@emotion/cache": {
-            "version": "11.7.1",
-            "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.7.1.tgz",
-            "integrity": "sha512-r65Zy4Iljb8oyjtLeCuBH8Qjiy107dOYC6SJq7g7GV5UCQWMObY4SJDPGFjiiVpPrOJ2hmJOoBiYTC7hwx9E2A==",
-            "dependencies": {
-                "@emotion/memoize": "^0.7.4",
-                "@emotion/sheet": "^1.1.0",
-                "@emotion/utils": "^1.0.0",
-                "@emotion/weak-memoize": "^0.2.5",
-                "stylis": "4.0.13"
-            }
-        },
-        "node_modules/@emotion/css/node_modules/@emotion/serialize": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.3.tgz",
-            "integrity": "sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==",
-            "dependencies": {
-                "@emotion/hash": "^0.8.0",
-                "@emotion/memoize": "^0.7.4",
-                "@emotion/unitless": "^0.7.5",
-                "@emotion/utils": "^1.0.0",
-                "csstype": "^3.0.2"
-            }
-        },
-        "node_modules/@emotion/css/node_modules/@emotion/sheet": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.1.0.tgz",
-            "integrity": "sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g=="
-        },
-        "node_modules/@emotion/css/node_modules/@emotion/utils": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.1.0.tgz",
-            "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
-        },
-        "node_modules/@emotion/css/node_modules/csstype": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-            "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
-        },
-        "node_modules/@emotion/hash": {
-            "version": "0.8.0",
-            "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
-            "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
-        },
-        "node_modules/@emotion/is-prop-valid": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.1.2.tgz",
-            "integrity": "sha512-3QnhqeL+WW88YjYbQL5gUIkthuMw7a0NGbZ7wfFVk2kg/CK5w8w5FFa0RzWjyY1+sujN0NWbtSHH6OJmWHtJpQ==",
-            "dependencies": {
-                "@emotion/memoize": "^0.7.4"
-            }
-        },
-        "node_modules/@emotion/memoize": {
-            "version": "0.7.4",
-            "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz",
-            "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw=="
-        },
-        "node_modules/@emotion/react": {
-            "version": "11.9.0",
-            "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.9.0.tgz",
-            "integrity": "sha512-lBVSF5d0ceKtfKCDQJveNAtkC7ayxpVlgOohLgXqRwqWr9bOf4TZAFFyIcNngnV6xK6X4x2ZeXq7vliHkoVkxQ==",
-            "dependencies": {
-                "@babel/runtime": "^7.13.10",
-                "@emotion/babel-plugin": "^11.7.1",
-                "@emotion/cache": "^11.7.1",
-                "@emotion/serialize": "^1.0.3",
-                "@emotion/utils": "^1.1.0",
-                "@emotion/weak-memoize": "^0.2.5",
-                "hoist-non-react-statics": "^3.3.1"
-            },
-            "peerDependencies": {
-                "@babel/core": "^7.0.0",
-                "react": ">=16.8.0"
-            },
-            "peerDependenciesMeta": {
-                "@babel/core": {
-                    "optional": true
-                },
-                "@types/react": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@emotion/react/node_modules/@emotion/cache": {
-            "version": "11.7.1",
-            "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.7.1.tgz",
-            "integrity": "sha512-r65Zy4Iljb8oyjtLeCuBH8Qjiy107dOYC6SJq7g7GV5UCQWMObY4SJDPGFjiiVpPrOJ2hmJOoBiYTC7hwx9E2A==",
-            "dependencies": {
-                "@emotion/memoize": "^0.7.4",
-                "@emotion/sheet": "^1.1.0",
-                "@emotion/utils": "^1.0.0",
-                "@emotion/weak-memoize": "^0.2.5",
-                "stylis": "4.0.13"
-            }
-        },
-        "node_modules/@emotion/react/node_modules/@emotion/serialize": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.3.tgz",
-            "integrity": "sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==",
-            "dependencies": {
-                "@emotion/hash": "^0.8.0",
-                "@emotion/memoize": "^0.7.4",
-                "@emotion/unitless": "^0.7.5",
-                "@emotion/utils": "^1.0.0",
-                "csstype": "^3.0.2"
-            }
-        },
-        "node_modules/@emotion/react/node_modules/@emotion/sheet": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.1.0.tgz",
-            "integrity": "sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g=="
-        },
-        "node_modules/@emotion/react/node_modules/@emotion/utils": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.1.0.tgz",
-            "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
-        },
-        "node_modules/@emotion/react/node_modules/csstype": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-            "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
-        },
-        "node_modules/@emotion/serialize": {
-            "version": "0.11.16",
-            "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.11.16.tgz",
-            "integrity": "sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg==",
-            "dependencies": {
-                "@emotion/hash": "0.8.0",
-                "@emotion/memoize": "0.7.4",
-                "@emotion/unitless": "0.7.5",
-                "@emotion/utils": "0.11.3",
-                "csstype": "^2.5.7"
-            }
-        },
-        "node_modules/@emotion/sheet": {
-            "version": "0.9.4",
-            "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-0.9.4.tgz",
-            "integrity": "sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA=="
-        },
-        "node_modules/@emotion/styled": {
-            "version": "11.8.1",
-            "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.8.1.tgz",
-            "integrity": "sha512-OghEVAYBZMpEquHZwuelXcRjRJQOVayvbmNR0zr174NHdmMgrNkLC6TljKC5h9lZLkN5WGrdUcrKlOJ4phhoTQ==",
-            "dependencies": {
-                "@babel/runtime": "^7.13.10",
-                "@emotion/babel-plugin": "^11.7.1",
-                "@emotion/is-prop-valid": "^1.1.2",
-                "@emotion/serialize": "^1.0.2",
-                "@emotion/utils": "^1.1.0"
-            },
-            "peerDependencies": {
-                "@babel/core": "^7.0.0",
-                "@emotion/react": "^11.0.0-rc.0",
-                "react": ">=16.8.0"
-            },
-            "peerDependenciesMeta": {
-                "@babel/core": {
-                    "optional": true
-                },
-                "@types/react": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@emotion/styled/node_modules/@emotion/serialize": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.3.tgz",
-            "integrity": "sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==",
-            "dependencies": {
-                "@emotion/hash": "^0.8.0",
-                "@emotion/memoize": "^0.7.4",
-                "@emotion/unitless": "^0.7.5",
-                "@emotion/utils": "^1.0.0",
-                "csstype": "^3.0.2"
-            }
-        },
-        "node_modules/@emotion/styled/node_modules/@emotion/utils": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.1.0.tgz",
-            "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
-        },
-        "node_modules/@emotion/styled/node_modules/csstype": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-            "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
-        },
-        "node_modules/@emotion/stylis": {
-            "version": "0.8.5",
-            "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz",
-            "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ=="
-        },
-        "node_modules/@emotion/unitless": {
-            "version": "0.7.5",
-            "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
-            "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
-        },
-        "node_modules/@emotion/utils": {
-            "version": "0.11.3",
-            "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.11.3.tgz",
-            "integrity": "sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw=="
-        },
-        "node_modules/@emotion/weak-memoize": {
-            "version": "0.2.5",
-            "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz",
-            "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA=="
-        },
-        "node_modules/@eslint/eslintrc": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz",
-            "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==",
-            "dev": true,
-            "dependencies": {
-                "ajv": "^6.12.4",
-                "debug": "^4.3.2",
-                "espree": "^9.3.2",
-                "globals": "^13.15.0",
-                "ignore": "^5.2.0",
-                "import-fresh": "^3.2.1",
-                "js-yaml": "^4.1.0",
-                "minimatch": "^3.1.2",
-                "strip-json-comments": "^3.1.1"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            }
-        },
-        "node_modules/@eslint/eslintrc/node_modules/argparse": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
-            "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
-            "dev": true
-        },
-        "node_modules/@eslint/eslintrc/node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dev": true,
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@eslint/eslintrc/node_modules/globals": {
-            "version": "13.16.0",
-            "resolved": "https://registry.npmjs.org/globals/-/globals-13.16.0.tgz",
-            "integrity": "sha512-A1lrQfpNF+McdPOnnFqY3kSN0AFTy485bTi1bkLk4mVPODIUEcSfhHgRqA+QdXPksrSTTztYXx37NFV+GpGk3Q==",
-            "dev": true,
-            "dependencies": {
-                "type-fest": "^0.20.2"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/@eslint/eslintrc/node_modules/ignore": {
-            "version": "5.2.0",
-            "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
-            "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
-            "dev": true,
-            "engines": {
-                "node": ">= 4"
-            }
-        },
-        "node_modules/@eslint/eslintrc/node_modules/js-yaml": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
-            "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-            "dev": true,
-            "dependencies": {
-                "argparse": "^2.0.1"
-            },
-            "bin": {
-                "js-yaml": "bin/js-yaml.js"
-            }
-        },
-        "node_modules/@eslint/eslintrc/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-            "dev": true
-        },
-        "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
-            "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/@ffmpeg/core": {
-            "version": "0.10.0",
-            "resolved": "https://registry.npmjs.org/@ffmpeg/core/-/core-0.10.0.tgz",
-            "integrity": "sha512-qunWJl5PezpXEm31tb8Qu5z37B5KVA1VYZCpXchMhuAb3X9T7PuE3SlhOwphEoRhzaOa3lpofDfzihAUMFaVPQ=="
-        },
-        "node_modules/@ffmpeg/ffmpeg": {
-            "version": "0.10.0",
-            "resolved": "https://registry.npmjs.org/@ffmpeg/ffmpeg/-/ffmpeg-0.10.0.tgz",
-            "integrity": "sha512-W+d0ysYTO6d4vue/0KMYrxaprh9wvmnPqh6qyHXavBWLrDcE7gI3cJ/EQVfwe9nrt2e0Pi7873P2I18VEDgRfA==",
-            "dependencies": {
-                "is-url": "^1.2.4",
-                "node-fetch": "^2.6.1",
-                "regenerator-runtime": "^0.13.7",
-                "resolve-url": "^0.2.1"
-            },
-            "engines": {
-                "node": ">=12.16.1"
-            }
-        },
-        "node_modules/@ffmpeg/ffmpeg/node_modules/node-fetch": {
-            "version": "2.6.7",
-            "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
-            "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
-            "dependencies": {
-                "whatwg-url": "^5.0.0"
-            },
-            "engines": {
-                "node": "4.x || >=6.0.0"
-            },
-            "peerDependencies": {
-                "encoding": "^0.1.0"
-            },
-            "peerDependenciesMeta": {
-                "encoding": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@fortawesome/fontawesome-common-types": {
-            "version": "0.3.0",
-            "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.3.0.tgz",
-            "integrity": "sha512-CA3MAZBTxVsF6SkfkHXDerkhcQs0QPofy43eFdbWJJkZiq3SfiaH1msOkac59rQaqto5EqWnASboY1dBuKen5w==",
-            "deprecated": "Please upgrade to 6.1.0. https://fontawesome.com/docs/changelog/",
-            "hasInstallScript": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/@fortawesome/fontawesome-svg-core": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.3.0.tgz",
-            "integrity": "sha512-UIL6crBWhjTNQcONt96ExjUnKt1D68foe3xjEensLDclqQ6YagwCRYVQdrp/hW0ALRp/5Fv/VKw+MqTUWYYvPg==",
-            "deprecated": "Please upgrade to 6.1.0. https://fontawesome.com/docs/changelog/",
-            "hasInstallScript": true,
-            "dependencies": {
-                "@fortawesome/fontawesome-common-types": "^0.3.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/@fortawesome/free-brands-svg-icons": {
-            "version": "5.15.4",
-            "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.4.tgz",
-            "integrity": "sha512-f1witbwycL9cTENJegcmcZRYyawAFbm8+c6IirLmwbbpqz46wyjbQYLuxOc7weXFXfB7QR8/Vd2u5R3q6JYD9g==",
-            "hasInstallScript": true,
-            "dependencies": {
-                "@fortawesome/fontawesome-common-types": "^0.2.36"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/@fortawesome/free-brands-svg-icons/node_modules/@fortawesome/fontawesome-common-types": {
-            "version": "0.2.36",
-            "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz",
-            "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==",
-            "hasInstallScript": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/@fortawesome/free-regular-svg-icons": {
-            "version": "5.15.4",
-            "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.4.tgz",
-            "integrity": "sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==",
-            "hasInstallScript": true,
-            "dependencies": {
-                "@fortawesome/fontawesome-common-types": "^0.2.36"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/@fortawesome/free-regular-svg-icons/node_modules/@fortawesome/fontawesome-common-types": {
-            "version": "0.2.36",
-            "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz",
-            "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==",
-            "hasInstallScript": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/@fortawesome/free-solid-svg-icons": {
-            "version": "5.15.4",
-            "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz",
-            "integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==",
-            "hasInstallScript": true,
-            "dependencies": {
-                "@fortawesome/fontawesome-common-types": "^0.2.36"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/@fortawesome/free-solid-svg-icons/node_modules/@fortawesome/fontawesome-common-types": {
-            "version": "0.2.36",
-            "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz",
-            "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==",
-            "hasInstallScript": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/@fortawesome/react-fontawesome": {
-            "version": "0.1.19",
-            "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.19.tgz",
-            "integrity": "sha512-Hyb+lB8T18cvLNX0S3llz7PcSOAJMLwiVKBuuzwM/nI5uoBw+gQjnf9il0fR1C3DKOI5Kc79pkJ4/xB0Uw9aFQ==",
-            "dependencies": {
-                "prop-types": "^15.8.1"
-            },
-            "peerDependencies": {
-                "@fortawesome/fontawesome-svg-core": "~1 || ~6",
-                "react": ">=16.x"
-            }
-        },
-        "node_modules/@googlemaps/js-api-loader": {
-            "version": "1.14.3",
-            "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.14.3.tgz",
-            "integrity": "sha512-6iIb+qpGgQpgIHmIFO44WhE1rDUxPVHuezNFL30wRJnkvhwFm94tD291UvNg9L05hLDSoL16jd0lbqqmdy4C5g==",
-            "dependencies": {
-                "fast-deep-equal": "^3.1.3"
-            }
-        },
-        "node_modules/@googlemaps/markerclusterer": {
-            "version": "2.0.7",
-            "resolved": "https://registry.npmjs.org/@googlemaps/markerclusterer/-/markerclusterer-2.0.7.tgz",
-            "integrity": "sha512-/xADL31ERrNoVsF+O2A+H+obxOki4DHPQkU/STS5gFG6ZZVpvNV4WLisW2aOlOsH3rUXSq3MFjqFOEDXSQcvog==",
-            "dependencies": {
-                "fast-deep-equal": "^3.1.3",
-                "supercluster": "^7.1.3"
-            }
-        },
-        "node_modules/@hig/flyout": {
-            "version": "1.3.1",
-            "resolved": "https://registry.npmjs.org/@hig/flyout/-/flyout-1.3.1.tgz",
-            "integrity": "sha512-dj69PnHtvXQ+IbbFv167ObHCuSVVv5ycMdFIOPMY+SCqSCssYiu1PkEI6eQxOePAb3MYhF4u7oi3Vy2XmxfkgA==",
-            "dependencies": {
-                "@hig/utils": "^0.4.1",
-                "emotion": "^10.0.0",
-                "prop-types": "^15.7.1",
-                "react-transition-group": "^2.3.1"
-            },
-            "peerDependencies": {
-                "@hig/theme-context": "^3.0.3",
-                "@hig/theme-data": "^2.22.0",
-                "react": "^15.4.1 || ^16.3.2"
-            }
-        },
-        "node_modules/@hig/flyout/node_modules/react-transition-group": {
-            "version": "2.9.0",
-            "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
-            "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==",
-            "dependencies": {
-                "dom-helpers": "^3.4.0",
-                "loose-envify": "^1.4.0",
-                "prop-types": "^15.6.2",
-                "react-lifecycles-compat": "^3.0.4"
-            },
-            "peerDependencies": {
-                "react": ">=15.0.0",
-                "react-dom": ">=15.0.0"
-            }
-        },
-        "node_modules/@hig/theme-context": {
-            "version": "2.1.3",
-            "resolved": "https://registry.npmjs.org/@hig/theme-context/-/theme-context-2.1.3.tgz",
-            "integrity": "sha512-c0Ju+Z8C532ZZtjwOLzN+XeO+pL3kqUawu6ZG3J084MH5RM9W8JCKyMf4D9Qr38jFWoiX6u8yiSxxjV/mz9Sqw==",
-            "dependencies": {
-                "create-react-context": "^0.2.3",
-                "prop-types": "^15.6.1"
-            },
-            "peerDependencies": {
-                "@hig/theme-data": "*",
-                "react": "^15.4.1 || ^16.3.2"
-            }
-        },
-        "node_modules/@hig/theme-data": {
-            "version": "2.26.0",
-            "resolved": "https://registry.npmjs.org/@hig/theme-data/-/theme-data-2.26.0.tgz",
-            "integrity": "sha512-jEiCieyafBePgFLlIPRPIhNPulWELeOgWJUY4wxdvozRdFUEq50ydx0ysuYPQOh4ucy0jI7Q8FcsBd+aEe7WXQ==",
-            "dependencies": {
-                "tinycolor2": "^1.4.1"
-            }
-        },
-        "node_modules/@hig/utils": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/@hig/utils/-/utils-0.4.1.tgz",
-            "integrity": "sha512-yx8HF5dLNo/WwwF5dR9P1pZu0tKhCuItrqbGbg52HpLUsptODBs/1ATT76cBaAJ7dSBCeNOKKiE4WKSrsA8bdQ==",
-            "dependencies": {
-                "emotion": "^10.0.0",
-                "lodash.memoize": "^4.1.2"
-            }
-        },
-        "node_modules/@humanwhocodes/config-array": {
-            "version": "0.9.5",
-            "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
-            "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==",
-            "dev": true,
-            "dependencies": {
-                "@humanwhocodes/object-schema": "^1.2.1",
-                "debug": "^4.1.1",
-                "minimatch": "^3.0.4"
-            },
-            "engines": {
-                "node": ">=10.10.0"
-            }
-        },
-        "node_modules/@humanwhocodes/config-array/node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dev": true,
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@humanwhocodes/config-array/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-            "dev": true
-        },
-        "node_modules/@humanwhocodes/object-schema": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
-            "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
-            "dev": true
-        },
-        "node_modules/@hypnosphi/create-react-context": {
-            "version": "0.3.1",
-            "resolved": "https://registry.npmjs.org/@hypnosphi/create-react-context/-/create-react-context-0.3.1.tgz",
-            "integrity": "sha512-V1klUed202XahrWJLLOT3EXNeCpFHCcJntdFGI15ntCwau+jfT386w7OFTMaCqOgXUH1fa0w/I1oZs+i/Rfr0A==",
-            "dependencies": {
-                "gud": "^1.0.0",
-                "warning": "^4.0.3"
-            },
-            "peerDependencies": {
-                "prop-types": "^15.0.0",
-                "react": ">=0.14.0"
-            }
-        },
-        "node_modules/@hypnosphi/create-react-context/node_modules/warning": {
-            "version": "4.0.3",
-            "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
-            "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
-            "dependencies": {
-                "loose-envify": "^1.0.0"
-            }
-        },
-        "node_modules/@icons/material": {
-            "version": "0.2.4",
-            "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz",
-            "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==",
-            "peerDependencies": {
-                "react": "*"
-            }
-        },
-        "node_modules/@jridgewell/gen-mapping": {
-            "version": "0.3.1",
-            "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz",
-            "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==",
-            "dependencies": {
-                "@jridgewell/set-array": "^1.0.0",
-                "@jridgewell/sourcemap-codec": "^1.4.10",
-                "@jridgewell/trace-mapping": "^0.3.9"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/@jridgewell/resolve-uri": {
-            "version": "3.0.7",
-            "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz",
-            "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==",
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/@jridgewell/set-array": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz",
-            "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==",
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/@jridgewell/source-map": {
-            "version": "0.3.2",
-            "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
-            "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
-            "dependencies": {
-                "@jridgewell/gen-mapping": "^0.3.0",
-                "@jridgewell/trace-mapping": "^0.3.9"
-            }
-        },
-        "node_modules/@jridgewell/sourcemap-codec": {
-            "version": "1.4.13",
-            "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz",
-            "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w=="
-        },
-        "node_modules/@jridgewell/trace-mapping": {
-            "version": "0.3.13",
-            "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz",
-            "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==",
-            "dependencies": {
-                "@jridgewell/resolve-uri": "^3.0.3",
-                "@jridgewell/sourcemap-codec": "^1.4.10"
-            }
-        },
-        "node_modules/@log4js-node/log4js-api": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/@log4js-node/log4js-api/-/log4js-api-1.0.2.tgz",
-            "integrity": "sha512-6SJfx949YEWooh/CUPpJ+F491y4BYJmknz4hUN1+RHvKoUEynKbRmhnwbk/VLmh4OthLLDNCyWXfbh4DG1cTXA=="
-        },
-        "node_modules/@mapbox/node-pre-gyp": {
-            "version": "1.0.9",
-            "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz",
-            "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==",
-            "dependencies": {
-                "detect-libc": "^2.0.0",
-                "https-proxy-agent": "^5.0.0",
-                "make-dir": "^3.1.0",
-                "node-fetch": "^2.6.7",
-                "nopt": "^5.0.0",
-                "npmlog": "^5.0.1",
-                "rimraf": "^3.0.2",
-                "semver": "^7.3.5",
-                "tar": "^6.1.11"
-            },
-            "bin": {
-                "node-pre-gyp": "bin/node-pre-gyp"
-            }
-        },
-        "node_modules/@mapbox/node-pre-gyp/node_modules/node-fetch": {
-            "version": "2.6.7",
-            "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
-            "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
-            "dependencies": {
-                "whatwg-url": "^5.0.0"
-            },
-            "engines": {
-                "node": "4.x || >=6.0.0"
-            },
-            "peerDependencies": {
-                "encoding": "^0.1.0"
-            },
-            "peerDependenciesMeta": {
-                "encoding": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@mapbox/node-pre-gyp/node_modules/semver": {
-            "version": "7.3.7",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
-            "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
-            "dependencies": {
-                "lru-cache": "^6.0.0"
-            },
-            "bin": {
-                "semver": "bin/semver.js"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/@material-ui/core": {
-            "version": "4.12.4",
-            "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.4.tgz",
-            "integrity": "sha512-tr7xekNlM9LjA6pagJmL8QCgZXaubWUwkJnoYcMKd4gw/t4XiyvnTkjdGrUVicyB2BsdaAv1tvow45bPM4sSwQ==",
-            "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.",
-            "dependencies": {
-                "@babel/runtime": "^7.4.4",
-                "@material-ui/styles": "^4.11.5",
-                "@material-ui/system": "^4.12.2",
-                "@material-ui/types": "5.1.0",
-                "@material-ui/utils": "^4.11.3",
-                "@types/react-transition-group": "^4.2.0",
-                "clsx": "^1.0.4",
-                "hoist-non-react-statics": "^3.3.2",
-                "popper.js": "1.16.1-lts",
-                "prop-types": "^15.7.2",
-                "react-is": "^16.8.0 || ^17.0.0",
-                "react-transition-group": "^4.4.0"
-            },
-            "engines": {
-                "node": ">=8.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/material-ui"
-            },
-            "peerDependencies": {
-                "@types/react": "^16.8.6 || ^17.0.0",
-                "react": "^16.8.0 || ^17.0.0",
-                "react-dom": "^16.8.0 || ^17.0.0"
-            },
-            "peerDependenciesMeta": {
-                "@types/react": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@material-ui/core/node_modules/csstype": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-            "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
-        },
-        "node_modules/@material-ui/core/node_modules/dom-helpers": {
-            "version": "5.2.1",
-            "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
-            "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
-            "dependencies": {
-                "@babel/runtime": "^7.8.7",
-                "csstype": "^3.0.2"
-            }
-        },
-        "node_modules/@material-ui/core/node_modules/react-transition-group": {
-            "version": "4.4.2",
-            "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz",
-            "integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==",
-            "dependencies": {
-                "@babel/runtime": "^7.5.5",
-                "dom-helpers": "^5.0.1",
-                "loose-envify": "^1.4.0",
-                "prop-types": "^15.6.2"
-            },
-            "peerDependencies": {
-                "react": ">=16.6.0",
-                "react-dom": ">=16.6.0"
-            }
-        },
-        "node_modules/@material-ui/styles": {
-            "version": "4.11.5",
-            "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.5.tgz",
-            "integrity": "sha512-o/41ot5JJiUsIETME9wVLAJrmIWL3j0R0Bj2kCOLbSfqEkKf0fmaPt+5vtblUh5eXr2S+J/8J3DaCb10+CzPGA==",
-            "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.",
-            "dependencies": {
-                "@babel/runtime": "^7.4.4",
-                "@emotion/hash": "^0.8.0",
-                "@material-ui/types": "5.1.0",
-                "@material-ui/utils": "^4.11.3",
-                "clsx": "^1.0.4",
-                "csstype": "^2.5.2",
-                "hoist-non-react-statics": "^3.3.2",
-                "jss": "^10.5.1",
-                "jss-plugin-camel-case": "^10.5.1",
-                "jss-plugin-default-unit": "^10.5.1",
-                "jss-plugin-global": "^10.5.1",
-                "jss-plugin-nested": "^10.5.1",
-                "jss-plugin-props-sort": "^10.5.1",
-                "jss-plugin-rule-value-function": "^10.5.1",
-                "jss-plugin-vendor-prefixer": "^10.5.1",
-                "prop-types": "^15.7.2"
-            },
-            "engines": {
-                "node": ">=8.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/material-ui"
-            },
-            "peerDependencies": {
-                "@types/react": "^16.8.6 || ^17.0.0",
-                "react": "^16.8.0 || ^17.0.0",
-                "react-dom": "^16.8.0 || ^17.0.0"
-            },
-            "peerDependenciesMeta": {
-                "@types/react": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@material-ui/system": {
-            "version": "4.12.2",
-            "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.2.tgz",
-            "integrity": "sha512-6CSKu2MtmiJgcCGf6nBQpM8fLkuB9F55EKfbdTC80NND5wpTmKzwdhLYLH3zL4cLlK0gVaaltW7/wMuyTnN0Lw==",
-            "dependencies": {
-                "@babel/runtime": "^7.4.4",
-                "@material-ui/utils": "^4.11.3",
-                "csstype": "^2.5.2",
-                "prop-types": "^15.7.2"
-            },
-            "engines": {
-                "node": ">=8.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/material-ui"
-            },
-            "peerDependencies": {
-                "@types/react": "^16.8.6 || ^17.0.0",
-                "react": "^16.8.0 || ^17.0.0",
-                "react-dom": "^16.8.0 || ^17.0.0"
-            },
-            "peerDependenciesMeta": {
-                "@types/react": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@material-ui/types": {
-            "version": "5.1.0",
-            "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz",
-            "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==",
-            "peerDependencies": {
-                "@types/react": "*"
-            },
-            "peerDependenciesMeta": {
-                "@types/react": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@material-ui/utils": {
-            "version": "4.11.3",
-            "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.3.tgz",
-            "integrity": "sha512-ZuQPV4rBK/V1j2dIkSSEcH5uT6AaHuKWFfotADHsC0wVL1NLd2WkFCm4ZZbX33iO4ydl6V0GPngKm8HZQ2oujg==",
-            "dependencies": {
-                "@babel/runtime": "^7.4.4",
-                "prop-types": "^15.7.2",
-                "react-is": "^16.8.0 || ^17.0.0"
-            },
-            "engines": {
-                "node": ">=8.0.0"
-            },
-            "peerDependencies": {
-                "react": "^16.8.0 || ^17.0.0",
-                "react-dom": "^16.8.0 || ^17.0.0"
-            }
-        },
-        "node_modules/@octokit/auth-token": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.0.tgz",
-            "integrity": "sha512-MDNFUBcJIptB9At7HiV7VCvU3NcL4GnfCQaP8C5lrxWrRPMJBnemYtehaKSOlaM7AYxeRyj9etenu8LVpSpVaQ==",
-            "dependencies": {
-                "@octokit/types": "^6.0.3"
-            },
-            "engines": {
-                "node": ">= 14"
-            }
-        },
-        "node_modules/@octokit/core": {
-            "version": "4.0.4",
-            "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.0.4.tgz",
-            "integrity": "sha512-sUpR/hc4Gc7K34o60bWC7WUH6Q7T6ftZ2dUmepSyJr9PRF76/qqkWjE2SOEzCqLA5W83SaISymwKtxks+96hPQ==",
-            "dependencies": {
-                "@octokit/auth-token": "^3.0.0",
-                "@octokit/graphql": "^5.0.0",
-                "@octokit/request": "^6.0.0",
-                "@octokit/request-error": "^3.0.0",
-                "@octokit/types": "^6.0.3",
-                "before-after-hook": "^2.2.0",
-                "universal-user-agent": "^6.0.0"
-            },
-            "engines": {
-                "node": ">= 14"
-            }
-        },
-        "node_modules/@octokit/endpoint": {
-            "version": "7.0.0",
-            "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.0.tgz",
-            "integrity": "sha512-Kz/mIkOTjs9rV50hf/JK9pIDl4aGwAtT8pry6Rpy+hVXkAPhXanNQRxMoq6AeRgDCZR6t/A1zKniY2V1YhrzlQ==",
-            "dependencies": {
-                "@octokit/types": "^6.0.3",
-                "is-plain-object": "^5.0.0",
-                "universal-user-agent": "^6.0.0"
-            },
-            "engines": {
-                "node": ">= 14"
-            }
-        },
-        "node_modules/@octokit/endpoint/node_modules/is-plain-object": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
-            "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/@octokit/graphql": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.0.tgz",
-            "integrity": "sha512-1ZZ8tX4lUEcLPvHagfIVu5S2xpHYXAmgN0+95eAOPoaVPzCfUXJtA5vASafcpWcO86ze0Pzn30TAx72aB2aguQ==",
-            "dependencies": {
-                "@octokit/request": "^6.0.0",
-                "@octokit/types": "^6.0.3",
-                "universal-user-agent": "^6.0.0"
-            },
-            "engines": {
-                "node": ">= 14"
-            }
-        },
-        "node_modules/@octokit/openapi-types": {
-            "version": "12.11.0",
-            "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
-            "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="
-        },
-        "node_modules/@octokit/request": {
-            "version": "6.2.0",
-            "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.0.tgz",
-            "integrity": "sha512-7IAmHnaezZrgUqtRShMlByJK33MT9ZDnMRgZjnRrRV9a/jzzFwKGz0vxhFU6i7VMLraYcQ1qmcAOin37Kryq+Q==",
-            "dependencies": {
-                "@octokit/endpoint": "^7.0.0",
-                "@octokit/request-error": "^3.0.0",
-                "@octokit/types": "^6.16.1",
-                "is-plain-object": "^5.0.0",
-                "node-fetch": "^2.6.7",
-                "universal-user-agent": "^6.0.0"
-            },
-            "engines": {
-                "node": ">= 14"
-            }
-        },
-        "node_modules/@octokit/request-error": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.0.tgz",
-            "integrity": "sha512-WBtpzm9lR8z4IHIMtOqr6XwfkGvMOOILNLxsWvDwtzm/n7f5AWuqJTXQXdDtOvPfTDrH4TPhEvW2qMlR4JFA2w==",
-            "dependencies": {
-                "@octokit/types": "^6.0.3",
-                "deprecation": "^2.0.0",
-                "once": "^1.4.0"
-            },
-            "engines": {
-                "node": ">= 14"
-            }
-        },
-        "node_modules/@octokit/request/node_modules/is-plain-object": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
-            "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/@octokit/request/node_modules/node-fetch": {
-            "version": "2.6.7",
-            "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
-            "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
-            "dependencies": {
-                "whatwg-url": "^5.0.0"
-            },
-            "engines": {
-                "node": "4.x || >=6.0.0"
-            },
-            "peerDependencies": {
-                "encoding": "^0.1.0"
-            },
-            "peerDependenciesMeta": {
-                "encoding": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@octokit/types": {
-            "version": "6.41.0",
-            "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
-            "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
-            "dependencies": {
-                "@octokit/openapi-types": "^12.11.0"
-            }
-        },
-        "node_modules/@react-google-maps/api": {
-            "version": "2.12.0",
-            "resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-2.12.0.tgz",
-            "integrity": "sha512-BqsclJ9p2I6yZa++0R3oEcneECcH7PFsULhn8UDlWQ9uNAQR/aqvqGb9SXYvdpIAOJdk3E737iTrGhFg4j5Ucw==",
-            "dependencies": {
-                "@googlemaps/js-api-loader": "1.14.3",
-                "@googlemaps/markerclusterer": "2.0.7",
-                "@react-google-maps/infobox": "2.11.8",
-                "@react-google-maps/marker-clusterer": "2.11.8",
-                "@types/google.maps": "3.49.1",
-                "invariant": "2.2.4"
-            },
-            "peerDependencies": {
-                "react": "^16.8 || ^17 || ^18",
-                "react-dom": "^16.8 || ^17 || ^18"
-            }
-        },
-        "node_modules/@react-google-maps/infobox": {
-            "version": "2.11.8",
-            "resolved": "https://registry.npmjs.org/@react-google-maps/infobox/-/infobox-2.11.8.tgz",
-            "integrity": "sha512-15y3dniys1Op5HREyLwiJI2pAdeeHRJT5b4WPrS+vyL5KF6iXK1P3y/9bXtnxHiKe2v6iPreaEhR3VgvfRA50Q=="
-        },
-        "node_modules/@react-google-maps/marker-clusterer": {
-            "version": "2.11.8",
-            "resolved": "https://registry.npmjs.org/@react-google-maps/marker-clusterer/-/marker-clusterer-2.11.8.tgz",
-            "integrity": "sha512-OEcdbTXEgPwdpGvVuSrhIhjcZPhlzPz2TvaKCBLraf1PKiDyLOPhlTVRlbIziLiu0xN89pJcill1w9UVIVFF+Q=="
-        },
-        "node_modules/@react-three/fiber": {
-            "version": "6.2.3",
-            "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-6.2.3.tgz",
-            "integrity": "sha512-XuL3683iVcwjm3enour57k4OjkA1MQztqpRL2oQh30v7ygf1vJg95gKo8cqqgPJctc2pZAMUW1eRpr+Xqjwqrg==",
-            "dependencies": {
-                "@babel/runtime": "^7.13.10",
-                "react-merge-refs": "^1.1.0",
-                "react-reconciler": "^0.26.2",
-                "react-three-fiber": "0.0.0-deprecated",
-                "react-use-measure": "^2.0.4",
-                "resize-observer-polyfill": "^1.5.1",
-                "scheduler": "^0.20.2",
-                "use-asset": "^1.0.4",
-                "utility-types": "^3.10.0",
-                "zustand": "^3.5.1"
-            },
-            "peerDependencies": {
-                "react": ">=17.0",
-                "react-dom": ">=17.0",
-                "three": ">=0.126"
-            },
-            "peerDependenciesMeta": {
-                "react-dom": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@rkusa/linebreak": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/@rkusa/linebreak/-/linebreak-1.0.0.tgz",
-            "integrity": "sha512-yCSm87XA1aYMgfcABSxcIkk3JtCw3AihNceHY+DnZGLvVP/g2z3UWZbi0xIoYpZWAJEVPr5Zt3QE37Q80wF1pA==",
-            "dependencies": {
-                "unicode-trie": "^0.3.0"
-            }
-        },
-        "node_modules/@sindresorhus/is": {
-            "version": "4.6.0",
-            "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
-            "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sindresorhus/is?sponsor=1"
-            }
-        },
-        "node_modules/@szmarczak/http-timer": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz",
-            "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==",
-            "dependencies": {
-                "defer-to-connect": "^2.0.1"
-            },
-            "engines": {
-                "node": ">=14.16"
-            }
-        },
-        "node_modules/@tsconfig/node10": {
-            "version": "1.0.9",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
-            "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
-            "dev": true
-        },
-        "node_modules/@tsconfig/node12": {
-            "version": "1.0.11",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
-            "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
-            "dev": true
-        },
-        "node_modules/@tsconfig/node14": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
-            "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
-            "dev": true
-        },
-        "node_modules/@tsconfig/node16": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
-            "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
-            "dev": true
-        },
-        "node_modules/@types/adm-zip": {
-            "version": "0.4.34",
-            "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.4.34.tgz",
-            "integrity": "sha512-8ToYLLAYhkRfcmmljrKi22gT2pqu7hGMDtORP1emwIEGmgUTZOsaDjzWFzW5N2frcFRz/50CWt4zA1CxJ73pmQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/animejs": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/@types/animejs/-/animejs-2.0.2.tgz",
-            "integrity": "sha512-ACymFQ5qgSrZNR1Fqjk7Wv9gH6dFgejn2gpLkkceWxTKzivRJsshX4xhBVALgvF79gUdXiMCRIdusN728XpeGA==",
-            "dev": true
-        },
-        "node_modules/@types/archiver": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-3.1.1.tgz",
-            "integrity": "sha512-TzVZ9204sH1TuFylfr1cw/AA/3/VldAAXswEwKLXUOzA9mDg+m6gHF9EaqKNlozcjc6knX5m1KAqJzksPLSEfw==",
-            "dev": true,
-            "dependencies": {
-                "@types/glob": "*"
-            }
-        },
-        "node_modules/@types/assert": {
-            "version": "1.5.6",
-            "resolved": "https://registry.npmjs.org/@types/assert/-/assert-1.5.6.tgz",
-            "integrity": "sha512-Y7gDJiIqb9qKUHfBQYOWGngUpLORtirAVPuj/CWJrU2C6ZM4/y3XLwuwfGMF8s7QzW746LQZx23m0+1FSgjfug=="
-        },
-        "node_modules/@types/async": {
-            "version": "2.4.2",
-            "resolved": "https://registry.npmjs.org/@types/async/-/async-2.4.2.tgz",
-            "integrity": "sha512-bWBbC7VG2jdjbgZMX0qpds8U/3h3anfIqE81L8jmVrgFZw/urEDnBA78ymGGKTTK6ciBXmmJ/xlok+Re41S8ww==",
-            "dev": true
-        },
-        "node_modules/@types/babel-types": {
-            "version": "7.0.11",
-            "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.11.tgz",
-            "integrity": "sha512-pkPtJUUY+Vwv6B1inAz55rQvivClHJxc9aVEPPmaq2cbyeMLCiDpbKpcKyX4LAwpNGi+SHBv0tHv6+0gXv0P2A=="
-        },
-        "node_modules/@types/babylon": {
-            "version": "6.16.6",
-            "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.6.tgz",
-            "integrity": "sha512-G4yqdVlhr6YhzLXFKy5F7HtRBU8Y23+iWy7UKthMq/OSQnL1hbsoeXESQ2LY8zEDlknipDG3nRGhUC9tkwvy/w==",
-            "dependencies": {
-                "@types/babel-types": "*"
-            }
-        },
-        "node_modules/@types/bcrypt-nodejs": {
-            "version": "0.0.30",
-            "resolved": "https://registry.npmjs.org/@types/bcrypt-nodejs/-/bcrypt-nodejs-0.0.30.tgz",
-            "integrity": "sha1-TN2WtJKTs5MhIuS34pVD415rrlg=",
-            "dev": true
-        },
-        "node_modules/@types/bezier-js": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/@types/bezier-js/-/bezier-js-4.1.0.tgz",
-            "integrity": "sha512-ElU16s8E6Pr6magp8ihwH1O8pbUJASbMND/qgUc9RsLmP3lMLHiDMRXdjtaObwW5GPtOVYOsXDUIhTIluT+yaw=="
-        },
-        "node_modules/@types/bluebird": {
-            "version": "3.5.36",
-            "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz",
-            "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==",
-            "dev": true
-        },
-        "node_modules/@types/body-parser": {
-            "version": "1.19.2",
-            "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
-            "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
-            "dev": true,
-            "dependencies": {
-                "@types/connect": "*",
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/bson": {
-            "version": "4.0.5",
-            "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.5.tgz",
-            "integrity": "sha512-vVLwMUqhYJSQ/WKcE60eFqcyuWse5fGH+NMAXHuKrUAPoryq3ATxk5o4bgYNtg5aOM4APVg7Hnb3ASqUYG0PKg==",
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/bson/node_modules/@types/node": {
-            "version": "17.0.41",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.41.tgz",
-            "integrity": "sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw=="
-        },
-        "node_modules/@types/cacheable-request": {
-            "version": "6.0.2",
-            "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz",
-            "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==",
-            "dependencies": {
-                "@types/http-cache-semantics": "*",
-                "@types/keyv": "*",
-                "@types/node": "*",
-                "@types/responselike": "*"
-            }
-        },
-        "node_modules/@types/cacheable-request/node_modules/@types/node": {
-            "version": "17.0.41",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.41.tgz",
-            "integrity": "sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw=="
-        },
-        "node_modules/@types/caseless": {
-            "version": "0.12.2",
-            "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
-            "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==",
-            "dev": true
-        },
-        "node_modules/@types/chai": {
-            "version": "4.3.1",
-            "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.1.tgz",
-            "integrity": "sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ==",
-            "dev": true
-        },
-        "node_modules/@types/color": {
-            "version": "3.0.3",
-            "resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.3.tgz",
-            "integrity": "sha512-X//qzJ3d3Zj82J9sC/C18ZY5f43utPbAJ6PhYt/M7uG6etcF6MRpKdN880KBy43B0BMzSfeT96MzrsNjFI3GbA==",
-            "dev": true,
-            "dependencies": {
-                "@types/color-convert": "*"
-            }
-        },
-        "node_modules/@types/color-convert": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.0.tgz",
-            "integrity": "sha512-m7GG7IKKGuJUXvkZ1qqG3ChccdIM/qBBo913z+Xft0nKCX4hAU/IxKwZBU4cpRZ7GS5kV4vOblUkILtSShCPXQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/color-name": "*"
-            }
-        },
-        "node_modules/@types/color-name": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
-            "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
-            "dev": true
-        },
-        "node_modules/@types/connect": {
-            "version": "3.4.35",
-            "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
-            "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/connect-flash": {
-            "version": "0.0.34",
-            "resolved": "https://registry.npmjs.org/@types/connect-flash/-/connect-flash-0.0.34.tgz",
-            "integrity": "sha512-QC93TwnTZ0sk//bfT81o7U4GOedbOZAcgvqi0v1vJqCESC8tqIVnhzB1CHiAUBUWFjoxG5JQF0TYaNa6DMb6Ig==",
-            "dev": true,
-            "dependencies": {
-                "@types/express": "*"
-            }
-        },
-        "node_modules/@types/cookie-parser": {
-            "version": "1.4.3",
-            "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.3.tgz",
-            "integrity": "sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w==",
-            "dev": true,
-            "dependencies": {
-                "@types/express": "*"
-            }
-        },
-        "node_modules/@types/cookie-session": {
-            "version": "2.0.44",
-            "resolved": "https://registry.npmjs.org/@types/cookie-session/-/cookie-session-2.0.44.tgz",
-            "integrity": "sha512-3DheOZ41pql6raSIkqEPphJdhA2dX2bkS+s2Qacv8YMKkoCbAIEXbsDil7351ARzMqvfyDUGNeHGiRZveIzhqQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/express": "*",
-                "@types/keygrip": "*"
-            }
-        },
-        "node_modules/@types/cors": {
-            "version": "2.8.12",
-            "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz",
-            "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw=="
-        },
-        "node_modules/@types/d3-axis": {
-            "version": "2.1.3",
-            "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-2.1.3.tgz",
-            "integrity": "sha512-QjXjwZ0xzyrW2ndkmkb09ErgWDEYtbLBKGui73QLMFm3woqWpxptfD5Y7vqQdybMcu7WEbjZ5q+w2w5+uh2IjA==",
-            "dependencies": {
-                "@types/d3-selection": "^2"
-            }
-        },
-        "node_modules/@types/d3-color": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-2.0.3.tgz",
-            "integrity": "sha512-+0EtEjBfKEDtH9Rk3u3kLOUXM5F+iZK+WvASPb0MhIZl8J8NUvGeZRwKCXl+P3HkYx5TdU4YtcibpqHkSR9n7w=="
-        },
-        "node_modules/@types/d3-scale": {
-            "version": "3.3.2",
-            "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-3.3.2.tgz",
-            "integrity": "sha512-gGqr7x1ost9px3FvIfUMi5XA/F/yAf4UkUDtdQhpH92XCT0Oa7zkkRzY61gPVJq+DxpHn/btouw5ohWkbBsCzQ==",
-            "dependencies": {
-                "@types/d3-time": "^2"
-            }
-        },
-        "node_modules/@types/d3-selection": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-2.0.1.tgz",
-            "integrity": "sha512-3mhtPnGE+c71rl/T5HMy+ykg7migAZ4T6gzU0HxpgBFKcasBrSnwRbYV1/UZR6o5fkpySxhWxAhd7yhjj8jL7g=="
-        },
-        "node_modules/@types/d3-time": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-2.1.1.tgz",
-            "integrity": "sha512-9MVYlmIgmRR31C5b4FVSWtuMmBHh2mOWQYfl7XAYOa8dsnb7iEmUmRSWSFgXFtkjxO65d7hTUHQC+RhR/9IWFg=="
-        },
-        "node_modules/@types/debug": {
-            "version": "4.1.7",
-            "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz",
-            "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==",
-            "dependencies": {
-                "@types/ms": "*"
-            }
-        },
-        "node_modules/@types/dom-speech-recognition": {
-            "version": "0.0.1",
-            "resolved": "https://registry.npmjs.org/@types/dom-speech-recognition/-/dom-speech-recognition-0.0.1.tgz",
-            "integrity": "sha512-udCxb8DvjcDKfk1WTBzDsxFbLgYxmQGKrE/ricoMqHRNjSlSUCcamVTA5lIQqzY10mY5qCY0QDwBfFEwhfoDPw=="
-        },
-        "node_modules/@types/dotenv": {
-            "version": "6.1.1",
-            "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-6.1.1.tgz",
-            "integrity": "sha512-ftQl3DtBvqHl9L16tpqqzA4YzCSXZfi7g8cQceTz5rOlYtk/IZbFjAv3mLOQlNIgOaylCQWQoBdDQHPgEBJPHg==",
-            "dev": true,
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/engine.io": {
-            "version": "3.1.7",
-            "resolved": "https://registry.npmjs.org/@types/engine.io/-/engine.io-3.1.7.tgz",
-            "integrity": "sha512-qNjVXcrp+1sS8YpRUa714r0pgzOwESdW5UjHL7D/2ZFdBX0BXUXtg1LUrp+ylvqbvMcMWUy73YpRoxPN2VoKAQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/eslint": {
-            "version": "8.4.3",
-            "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.3.tgz",
-            "integrity": "sha512-YP1S7YJRMPs+7KZKDb9G63n8YejIwW9BALq7a5j2+H4yl6iOv9CB29edho+cuFRrvmJbbaH2yiVChKLJVysDGw==",
-            "dependencies": {
-                "@types/estree": "*",
-                "@types/json-schema": "*"
-            }
-        },
-        "node_modules/@types/eslint-scope": {
-            "version": "3.7.3",
-            "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz",
-            "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==",
-            "dependencies": {
-                "@types/eslint": "*",
-                "@types/estree": "*"
-            }
-        },
-        "node_modules/@types/estree": {
-            "version": "0.0.51",
-            "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz",
-            "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ=="
-        },
-        "node_modules/@types/events": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
-            "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g=="
-        },
-        "node_modules/@types/exif": {
-            "version": "0.6.3",
-            "resolved": "https://registry.npmjs.org/@types/exif/-/exif-0.6.3.tgz",
-            "integrity": "sha512-OMthUry1d2/gpXL2H3RGaj7KWRw0EWdxI0OANeUWbYMotBxljFuAl3eydCgDaBYTyD+d4Q3atdVcmimwS6KvGg==",
-            "dev": true,
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/express": {
-            "version": "4.17.13",
-            "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz",
-            "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==",
-            "dev": true,
-            "dependencies": {
-                "@types/body-parser": "*",
-                "@types/express-serve-static-core": "^4.17.18",
-                "@types/qs": "*",
-                "@types/serve-static": "*"
-            }
-        },
-        "node_modules/@types/express-flash": {
-            "version": "0.0.0",
-            "resolved": "https://registry.npmjs.org/@types/express-flash/-/express-flash-0.0.0.tgz",
-            "integrity": "sha512-zs1xXRIZOjghUBriJPSnhPmfDpqf/EQxT21ggi/9XZ9/RHYrUi+5vK2jnQrP2pD1abbuZvm7owLICiNCLBQzEQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/connect-flash": "*",
-                "@types/express": "*"
-            }
-        },
-        "node_modules/@types/express-serve-static-core": {
-            "version": "4.17.28",
-            "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz",
-            "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==",
-            "dev": true,
-            "dependencies": {
-                "@types/node": "*",
-                "@types/qs": "*",
-                "@types/range-parser": "*"
-            }
-        },
-        "node_modules/@types/express-session": {
-            "version": "1.17.5",
-            "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.17.5.tgz",
-            "integrity": "sha512-l0DhkvNVfyUPEEis8fcwbd46VptfA/jmMwHfob2TfDMf3HyPLiB9mKD71LXhz5TMUobODXPD27zXSwtFQLHm+w==",
-            "dev": true,
-            "dependencies": {
-                "@types/express": "*"
-            }
-        },
-        "node_modules/@types/express-validator": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/@types/express-validator/-/express-validator-3.0.0.tgz",
-            "integrity": "sha512-LusnB0YhTXpBT25PXyGPQlK7leE1e41Vezq1hHEUwjfkopM1Pkv2X2Ppxqh9c+w/HZ6Udzki8AJotKNjDTGdkQ==",
-            "deprecated": "This is a stub types definition for express-validator (https://github.com/ctavan/express-validator). express-validator provides its own type definitions, so you don't need @types/express-validator installed!",
-            "dev": true,
-            "dependencies": {
-                "express-validator": "*"
-            }
-        },
-        "node_modules/@types/file-saver": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.5.tgz",
-            "integrity": "sha512-zv9kNf3keYegP5oThGLaPk8E081DFDuwfqjtiTzm6PoxChdJ1raSuADf2YGCVIyrSynLrgc8JWv296s7Q7pQSQ==",
-            "dev": true
-        },
-        "node_modules/@types/formidable": {
-            "version": "1.0.31",
-            "resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-1.0.31.tgz",
-            "integrity": "sha512-dIhM5t8lRP0oWe2HF8MuPvdd1TpPTjhDMAqemcq6oIZQCBQTovhBAdTQ5L5veJB4pdQChadmHuxtB0YzqvfU3Q==",
-            "dependencies": {
-                "@types/events": "*",
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/formidable/node_modules/@types/node": {
-            "version": "17.0.41",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.41.tgz",
-            "integrity": "sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw=="
-        },
-        "node_modules/@types/geojson": {
-            "version": "7946.0.8",
-            "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz",
-            "integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA=="
-        },
-        "node_modules/@types/glob": {
-            "version": "7.2.0",
-            "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
-            "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
-            "dev": true,
-            "dependencies": {
-                "@types/minimatch": "*",
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/google-maps": {
-            "version": "3.2.3",
-            "resolved": "https://registry.npmjs.org/@types/google-maps/-/google-maps-3.2.3.tgz",
-            "integrity": "sha512-+GR/7sMvo2bENS26H4t2QqoCqE4FE5qhsG8aaDM9mJAlsorkLyaFdTQra8VkmS1RNE09fx9c1kac+GKG0RtA2A==",
-            "dependencies": {
-                "@types/google.maps": "*"
-            }
-        },
-        "node_modules/@types/google-maps-react": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/@types/google-maps-react/-/google-maps-react-2.0.5.tgz",
-            "integrity": "sha512-qcsYlHiNH169Vf7jmkEwbzBDqBfqqzYkTgK1vL7qkWVZI04wFESADYVITuQunrZ9swY/SG+tTWUIXMlY4W8byw==",
-            "deprecated": "This is a stub types definition. google-maps-react provides its own type definitions, so you do not need this installed.",
-            "dev": true,
-            "dependencies": {
-                "google-maps-react": "*"
-            }
-        },
-        "node_modules/@types/google.maps": {
-            "version": "3.49.1",
-            "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.49.1.tgz",
-            "integrity": "sha512-Sbl5anucT7LUcUxXsRxkCozHdXIkUiY+Tyru+OVl5rot0+VIZuuulmABC7X+nF7rL7BRTAguSBSAD/e/AfIkkA=="
-        },
-        "node_modules/@types/hast": {
-            "version": "2.3.4",
-            "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz",
-            "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==",
-            "dependencies": {
-                "@types/unist": "*"
-            }
-        },
-        "node_modules/@types/hoist-non-react-statics": {
-            "version": "3.3.1",
-            "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
-            "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
-            "dependencies": {
-                "@types/react": "*",
-                "hoist-non-react-statics": "^3.3.0"
-            }
-        },
-        "node_modules/@types/hoist-non-react-statics/node_modules/@types/react": {
-            "version": "18.0.12",
-            "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.12.tgz",
-            "integrity": "sha512-duF1OTASSBQtcigUvhuiTB1Ya3OvSy+xORCiEf20H0P0lzx+/KeVsA99U5UjLXSbyo1DRJDlLKqTeM1ngosqtg==",
-            "dependencies": {
-                "@types/prop-types": "*",
-                "@types/scheduler": "*",
-                "csstype": "^3.0.2"
-            }
-        },
-        "node_modules/@types/hoist-non-react-statics/node_modules/csstype": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-            "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
-        },
-        "node_modules/@types/html-minifier-terser": {
-            "version": "6.1.0",
-            "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
-            "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg=="
-        },
-        "node_modules/@types/http-cache-semantics": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
-            "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ=="
-        },
-        "node_modules/@types/jquery": {
-            "version": "3.5.14",
-            "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz",
-            "integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==",
-            "dev": true,
-            "dependencies": {
-                "@types/sizzle": "*"
-            }
-        },
-        "node_modules/@types/jsdom": {
-            "version": "16.2.14",
-            "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-16.2.14.tgz",
-            "integrity": "sha512-6BAy1xXEmMuHeAJ4Fv4yXKwBDTGTOseExKE3OaHiNycdHdZw59KfYzrt0DkDluvwmik1HRt6QS7bImxUmpSy+w==",
-            "dependencies": {
-                "@types/node": "*",
-                "@types/parse5": "*",
-                "@types/tough-cookie": "*"
-            }
-        },
-        "node_modules/@types/jsdom/node_modules/@types/node": {
-            "version": "17.0.41",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.41.tgz",
-            "integrity": "sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw=="
-        },
-        "node_modules/@types/json-buffer": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/@types/json-buffer/-/json-buffer-3.0.0.tgz",
-            "integrity": "sha512-3YP80IxxFJB4b5tYC2SUPwkg0XQLiu0nWvhRgEatgjf+29IcWO9X1k8xRv5DGssJ/lCrjYTjQPcobJr2yWIVuQ=="
-        },
-        "node_modules/@types/json-schema": {
-            "version": "7.0.11",
-            "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
-            "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ=="
-        },
-        "node_modules/@types/json5": {
-            "version": "0.0.29",
-            "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
-            "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
-            "dev": true
-        },
-        "node_modules/@types/keygrip": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz",
-            "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==",
-            "dev": true
-        },
-        "node_modules/@types/keyv": {
-            "version": "3.1.4",
-            "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
-            "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/keyv/node_modules/@types/node": {
-            "version": "17.0.41",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.41.tgz",
-            "integrity": "sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw=="
-        },
-        "node_modules/@types/libxmljs": {
-            "version": "0.18.7",
-            "resolved": "https://registry.npmjs.org/@types/libxmljs/-/libxmljs-0.18.7.tgz",
-            "integrity": "sha512-g88L5tS5UJKfzmPZbvGckcULvPHzguy24lFFTXUVm2UfezQBC5adHmA15RlTx0y0+s/+TyrCV1oPvxn+KqfH8A==",
-            "dev": true,
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/lodash": {
-            "version": "4.14.182",
-            "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz",
-            "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==",
-            "dev": true
-        },
-        "node_modules/@types/mdast": {
-            "version": "3.0.10",
-            "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz",
-            "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==",
-            "dependencies": {
-                "@types/unist": "*"
-            }
-        },
-        "node_modules/@types/mdurl": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz",
-            "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA=="
-        },
-        "node_modules/@types/mime": {
-            "version": "1.3.2",
-            "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
-            "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==",
-            "dev": true
-        },
-        "node_modules/@types/minimatch": {
-            "version": "3.0.5",
-            "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
-            "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
-            "dev": true
-        },
-        "node_modules/@types/mobile-detect": {
-            "version": "1.3.4",
-            "resolved": "https://registry.npmjs.org/@types/mobile-detect/-/mobile-detect-1.3.4.tgz",
-            "integrity": "sha512-MGBTvT5c7aH8eX6szFYP3dWPryNLt5iGlo31XNaJtt8o6jsg6tjn99eEMq9l8T6cPZymsr+J4Jth8+/G/04ZDw==",
-            "deprecated": "This is a stub types definition for mobile-detect (http://hgoebl.github.io/mobile-detect.js/). mobile-detect provides its own type definitions, so you don't need @types/mobile-detect installed!",
-            "dev": true,
-            "dependencies": {
-                "mobile-detect": "*"
-            }
-        },
-        "node_modules/@types/mocha": {
-            "version": "5.2.7",
-            "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
-            "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==",
-            "dev": true
-        },
-        "node_modules/@types/mongodb": {
-            "version": "3.6.20",
-            "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.20.tgz",
-            "integrity": "sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ==",
-            "dependencies": {
-                "@types/bson": "*",
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/mongodb/node_modules/@types/node": {
-            "version": "17.0.41",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.41.tgz",
-            "integrity": "sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw=="
-        },
-        "node_modules/@types/mongoose": {
-            "version": "5.11.97",
-            "resolved": "https://registry.npmjs.org/@types/mongoose/-/mongoose-5.11.97.tgz",
-            "integrity": "sha512-cqwOVYT3qXyLiGw7ueU2kX9noE8DPGRY6z8eUxudhXY8NZ7DMKYAxyZkLSevGfhCX3dO/AoX5/SO9lAzfjon0Q==",
-            "deprecated": "Mongoose publishes its own types, so you do not need to install this package.",
-            "dev": true,
-            "dependencies": {
-                "mongoose": "*"
-            }
-        },
-        "node_modules/@types/ms": {
-            "version": "0.7.31",
-            "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz",
-            "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA=="
-        },
-        "node_modules/@types/node": {
-            "version": "10.17.60",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz",
-            "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw=="
-        },
-        "node_modules/@types/nodemailer": {
-            "version": "4.6.8",
-            "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-4.6.8.tgz",
-            "integrity": "sha512-IX1P3bxDP1VIdZf6/kIWYNmSejkYm9MOyMEtoDFi4DVzKjJ3kY4GhOcOAKs6lZRjqVVmF9UjPOZXuQczlpZThw==",
-            "dev": true,
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/oauth": {
-            "version": "0.9.1",
-            "resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.1.tgz",
-            "integrity": "sha512-a1iY62/a3yhZ7qH7cNUsxoI3U/0Fe9+RnuFrpTKr+0WVOzbKlSLojShCKe20aOD1Sppv+i8Zlq0pLDuTJnwS4A==",
-            "dev": true,
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/orderedmap": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/@types/orderedmap/-/orderedmap-1.0.0.tgz",
-            "integrity": "sha512-dxKo80TqYx3YtBipHwA/SdFmMMyLCnP+5mkEqN0eMjcTBzHkiiX0ES118DsjDBjvD+zeSsSU9jULTZ+frog+Gw==",
-            "dev": true
-        },
-        "node_modules/@types/parse-json": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
-            "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
-        },
-        "node_modules/@types/parse5": {
-            "version": "6.0.3",
-            "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz",
-            "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g=="
-        },
-        "node_modules/@types/passport": {
-            "version": "1.0.9",
-            "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.9.tgz",
-            "integrity": "sha512-9+ilzUhmZQR4JP49GdC2O4UdDE3POPLwpmaTC/iLkW7l0TZCXOo1zsTnnlXPq6rP1UsUZPfbAV4IUdiwiXyC7g==",
-            "dev": true,
-            "dependencies": {
-                "@types/express": "*"
-            }
-        },
-        "node_modules/@types/passport-google-oauth20": {
-            "version": "2.0.11",
-            "resolved": "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.11.tgz",
-            "integrity": "sha512-9XMT1GfwhZL7UQEiCepLef55RNPHkbrCtsU7rsWPTEOsmu5qVIW8nSemtB4p+P24CuOhA+IKkv8LsPThYghGww==",
-            "dev": true,
-            "dependencies": {
-                "@types/express": "*",
-                "@types/passport": "*",
-                "@types/passport-oauth2": "*"
-            }
-        },
-        "node_modules/@types/passport-local": {
-            "version": "1.0.34",
-            "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.34.tgz",
-            "integrity": "sha512-PSc07UdYx+jhadySxxIYWuv6sAnY5e+gesn/5lkPKfBeGuIYn9OPR+AAEDq73VRUh6NBTpvE/iPE62rzZUslog==",
-            "dev": true,
-            "dependencies": {
-                "@types/express": "*",
-                "@types/passport": "*",
-                "@types/passport-strategy": "*"
-            }
-        },
-        "node_modules/@types/passport-oauth2": {
-            "version": "1.4.11",
-            "resolved": "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.4.11.tgz",
-            "integrity": "sha512-KUNwmGhe/3xPbjkzkPwwcPmyFwfyiSgtV1qOrPBLaU4i4q9GSCdAOyCbkFG0gUxAyEmYwqo9OAF/rjPjJ6ImdA==",
-            "dev": true,
-            "dependencies": {
-                "@types/express": "*",
-                "@types/oauth": "*",
-                "@types/passport": "*"
-            }
-        },
-        "node_modules/@types/passport-strategy": {
-            "version": "0.2.35",
-            "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.35.tgz",
-            "integrity": "sha512-o5D19Jy2XPFoX2rKApykY15et3Apgax00RRLf0RUotPDUsYrQa7x4howLYr9El2mlUApHmCMv5CZ1IXqKFQ2+g==",
-            "dev": true,
-            "dependencies": {
-                "@types/express": "*",
-                "@types/passport": "*"
-            }
-        },
-        "node_modules/@types/pdfjs-dist": {
-            "version": "2.10.378",
-            "resolved": "https://registry.npmjs.org/@types/pdfjs-dist/-/pdfjs-dist-2.10.378.tgz",
-            "integrity": "sha512-TRdIPqdsvKmPla44kVy4jv5Nt5vjMfVjbIEke1CRULIrwKNRC4lIiZvNYDJvbUMNCFPNIUcOKhXTyMJrX18IMA==",
-            "deprecated": "This is a stub types definition. pdfjs-dist provides its own type definitions, so you do not need this installed.",
-            "dev": true,
-            "dependencies": {
-                "pdfjs-dist": "*"
-            }
-        },
-        "node_modules/@types/prop-types": {
-            "version": "15.7.5",
-            "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
-            "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
-        },
-        "node_modules/@types/prosemirror-commands": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-commands/-/prosemirror-commands-1.0.4.tgz",
-            "integrity": "sha512-utDNYB3EXLjAfYIcRWJe6pn3kcQ5kG4RijbT/0Y/TFOm6yhvYS/D9eJVnijdg9LDjykapcezchxGRqFD5LcyaQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/prosemirror-model": "*",
-                "@types/prosemirror-state": "*",
-                "@types/prosemirror-view": "*"
-            }
-        },
-        "node_modules/@types/prosemirror-dev-tools": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-dev-tools/-/prosemirror-dev-tools-2.1.0.tgz",
-            "integrity": "sha512-OhnSaC4yrrEMLPRUkEWcHAIPVqgKlLkE4kISqL3cHeAYxASouSPvPMLqhBIbWkGwaozy43DjjVC1OXkxTo+y5Q==",
-            "dev": true,
-            "dependencies": {
-                "@types/prosemirror-state": "*",
-                "@types/prosemirror-view": "*"
-            }
-        },
-        "node_modules/@types/prosemirror-history": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-history/-/prosemirror-history-1.0.3.tgz",
-            "integrity": "sha512-5TloMDRavgLjOAKXp1Li8u0xcsspzbT1Cm9F2pwHOkgvQOz1jWQb2VIXO7RVNsFjLBZdIXlyfSLivro3DuMWXg==",
-            "dev": true,
-            "dependencies": {
-                "@types/prosemirror-model": "*",
-                "@types/prosemirror-state": "*"
-            }
-        },
-        "node_modules/@types/prosemirror-inputrules": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-inputrules/-/prosemirror-inputrules-1.0.4.tgz",
-            "integrity": "sha512-lJIMpOjO47SYozQybUkpV6QmfuQt7GZKHtVrvS+mR5UekA8NMC5HRIVMyaIauJLWhKU6oaNjpVaXdw41kh165g==",
-            "dev": true,
-            "dependencies": {
-                "@types/prosemirror-model": "*",
-                "@types/prosemirror-state": "*"
-            }
-        },
-        "node_modules/@types/prosemirror-keymap": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-keymap/-/prosemirror-keymap-1.0.4.tgz",
-            "integrity": "sha512-ycevwkqUh+jEQtPwqO7sWGcm+Sybmhu8MpBsM8DlO3+YTKnXbKA6SDz/+q14q1wK3UA8lHJyfR+v+GPxfUSemg==",
-            "dev": true,
-            "dependencies": {
-                "@types/prosemirror-commands": "*",
-                "@types/prosemirror-model": "*",
-                "@types/prosemirror-state": "*",
-                "@types/prosemirror-view": "*"
-            }
-        },
-        "node_modules/@types/prosemirror-menu": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-menu/-/prosemirror-menu-1.0.6.tgz",
-            "integrity": "sha512-teKfCPnnbYeB8DJiUIof4N0f8kyWbQP3BagEBRP6r+7/o0fiqHsnrex8GXuCSNNUqlpSpDQkJy52aq4jvzmDpg==",
-            "dev": true,
-            "dependencies": {
-                "@types/prosemirror-model": "*",
-                "@types/prosemirror-state": "*",
-                "@types/prosemirror-view": "*"
-            }
-        },
-        "node_modules/@types/prosemirror-model": {
-            "version": "1.16.2",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-model/-/prosemirror-model-1.16.2.tgz",
-            "integrity": "sha512-1XPJopkKP3oHSBP61uuSuW13DIDZPWvAzP6Pv2/6mixk8EBPUeRGIW548DjJTicMo23gEg1zvCZy9asblQdWag==",
-            "dev": true,
-            "dependencies": {
-                "@types/orderedmap": "*"
-            }
-        },
-        "node_modules/@types/prosemirror-schema-list": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-schema-list/-/prosemirror-schema-list-1.0.3.tgz",
-            "integrity": "sha512-uWybOf+M2Ea7rlbs0yLsS4YJYNGXYtn4N+w8HCw3Vvfl6wBAROzlMt0gV/D/VW/7J/LlAjwMezuGe8xi24HzXA==",
-            "dev": true,
-            "dependencies": {
-                "@types/orderedmap": "*",
-                "@types/prosemirror-model": "*",
-                "@types/prosemirror-state": "*"
-            }
-        },
-        "node_modules/@types/prosemirror-state": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-state/-/prosemirror-state-1.3.0.tgz",
-            "integrity": "sha512-nMdUF6w8B++NH4V54X+4GvDty7M02UfuHQW0s1AS25Z4ZrOW4RSY2+s57doXBbeMSjzYV/QoMxCY2sT3KQ2VdQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/prosemirror-model": "*",
-                "@types/prosemirror-transform": "*",
-                "@types/prosemirror-view": "*"
-            }
-        },
-        "node_modules/@types/prosemirror-transform": {
-            "version": "1.4.2",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-transform/-/prosemirror-transform-1.4.2.tgz",
-            "integrity": "sha512-FZNzjYm6YUkb1XXOrw2193TiFzwM92ui1nycNaRSd5JDbugf9yBLkXm4Rq3HGJJxBBkRcUE8niqUW5aWlXQQiQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/prosemirror-model": "*"
-            }
-        },
-        "node_modules/@types/prosemirror-view": {
-            "version": "1.23.3",
-            "resolved": "https://registry.npmjs.org/@types/prosemirror-view/-/prosemirror-view-1.23.3.tgz",
-            "integrity": "sha512-T5dPDmZiXAazJVSvnx55D6h4mcpiH2q2wTyO9zIeOdox5zx964+zcDl9dFNaXG3qCGlERwMPckhBZL1HCxyygw==",
-            "dev": true,
-            "dependencies": {
-                "@types/prosemirror-model": "*",
-                "@types/prosemirror-state": "*",
-                "@types/prosemirror-transform": "*"
-            }
-        },
-        "node_modules/@types/qs": {
-            "version": "6.9.7",
-            "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
-            "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
-            "dev": true
-        },
-        "node_modules/@types/range-parser": {
-            "version": "1.2.4",
-            "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
-            "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
-            "dev": true
-        },
-        "node_modules/@types/rc-switch": {
-            "version": "1.9.2",
-            "resolved": "https://registry.npmjs.org/@types/rc-switch/-/rc-switch-1.9.2.tgz",
-            "integrity": "sha512-+2e+KP23qqJ4RMb63aeb866cPPZv8g7rCu2NYJlwyxRveH3Gm/OT25Zj3BfRLViCrxwGhpwKq49ugiUBZkr9AQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/react": "*"
-            }
-        },
-        "node_modules/@types/react": {
-            "version": "18.0.15",
-            "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.15.tgz",
-            "integrity": "sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow==",
-            "dependencies": {
-                "@types/prop-types": "*",
-                "@types/scheduler": "*",
-                "csstype": "^3.0.2"
-            }
-        },
-        "node_modules/@types/react-autosuggest": {
-            "version": "9.3.14",
-            "resolved": "https://registry.npmjs.org/@types/react-autosuggest/-/react-autosuggest-9.3.14.tgz",
-            "integrity": "sha512-cvGpKaQaNsFbDxTwP56VKVj2FO6SpJ9PsrQtlVzN7aVa/SsMZoQrBLEUx5HQKfIS4Zupb6K4tHmIyTjF7AEcow==",
-            "dev": true,
-            "dependencies": {
-                "@types/react": "*"
-            }
-        },
-        "node_modules/@types/react-color": {
-            "version": "2.17.6",
-            "resolved": "https://registry.npmjs.org/@types/react-color/-/react-color-2.17.6.tgz",
-            "integrity": "sha512-5CEKnrpvgZz8v5UYbpLgBeK+V6K7KdszksSDK6mNjL/8wrsqQfIyKB45CQOAEYtRgn+tWqTeqbUtvFWjXDpURQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/react": "*",
-                "@types/reactcss": "*"
-            }
-        },
-        "node_modules/@types/react-datepicker": {
-            "version": "3.1.8",
-            "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-3.1.8.tgz",
-            "integrity": "sha512-RFEg7++xhosMq02i2lsuaUPEbZGn66U3dxtvw9LU/ZRqLkBGr9Ft2LTz6vbeYYVtaBdOr0NcQatOLnlfUaS8kw==",
-            "dev": true,
-            "dependencies": {
-                "@types/react": "*",
-                "date-fns": "^2.0.1",
-                "popper.js": "^1.14.1"
-            }
-        },
-        "node_modules/@types/react-datepicker/node_modules/popper.js": {
-            "version": "1.16.1",
-            "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
-            "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
-            "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1",
-            "dev": true,
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/popperjs"
-            }
-        },
-        "node_modules/@types/react-dom": {
-            "version": "18.0.6",
-            "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.6.tgz",
-            "integrity": "sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==",
-            "dev": true,
-            "dependencies": {
-                "@types/react": "*"
-            }
-        },
-        "node_modules/@types/react-grid-layout": {
-            "version": "1.3.2",
-            "resolved": "https://registry.npmjs.org/@types/react-grid-layout/-/react-grid-layout-1.3.2.tgz",
-            "integrity": "sha512-ZzpBEOC1JTQ7MGe1h1cPKSLP4jSWuxc+yvT4TsAlEW9+EFPzAf8nxQfFd7ea9gL17Em7PbwJZAsiwfQQBUklZQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/react": "*"
-            }
-        },
-        "node_modules/@types/react-icons": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/@types/react-icons/-/react-icons-3.0.0.tgz",
-            "integrity": "sha512-Vefs6LkLqF61vfV7AiAqls+vpR94q67gunhMueDznG+msAkrYgRxl7gYjNem/kZ+as2l2mNChmF1jRZzzQQtMg==",
-            "deprecated": "This is a stub types definition. react-icons provides its own type definitions, so you do not need this installed.",
-            "dev": true,
-            "dependencies": {
-                "react-icons": "*"
-            }
-        },
-        "node_modules/@types/react-measure": {
-            "version": "2.0.8",
-            "resolved": "https://registry.npmjs.org/@types/react-measure/-/react-measure-2.0.8.tgz",
-            "integrity": "sha512-Pu4/hQ/1AKVN6efoawtcM+l376WYOI8e1fiM6ir4pdLkHilDCkJLjUGvAm0mWKJ0GE6hzu55yCrcJ/xNyEdFwA==",
-            "dev": true,
-            "dependencies": {
-                "@types/react": "*"
-            }
-        },
-        "node_modules/@types/react-reconciler": {
-            "version": "0.26.7",
-            "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.26.7.tgz",
-            "integrity": "sha512-mBDYl8x+oyPX/VBb3E638N0B7xG+SPk/EAMcVPeexqus/5aTpTphQi0curhhshOqRrc9t6OPoJfEUkbymse/lQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/react": "*"
-            }
-        },
-        "node_modules/@types/react-reconciler/node_modules/@types/react": {
-            "version": "18.0.12",
-            "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.12.tgz",
-            "integrity": "sha512-duF1OTASSBQtcigUvhuiTB1Ya3OvSy+xORCiEf20H0P0lzx+/KeVsA99U5UjLXSbyo1DRJDlLKqTeM1ngosqtg==",
-            "dev": true,
-            "dependencies": {
-                "@types/prop-types": "*",
-                "@types/scheduler": "*",
-                "csstype": "^3.0.2"
-            }
-        },
-        "node_modules/@types/react-reconciler/node_modules/csstype": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-            "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==",
-            "dev": true
-        },
-        "node_modules/@types/react-redux": {
-            "version": "7.1.24",
-            "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz",
-            "integrity": "sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==",
-            "dependencies": {
-                "@types/hoist-non-react-statics": "^3.3.0",
-                "@types/react": "*",
-                "hoist-non-react-statics": "^3.3.0",
-                "redux": "^4.0.0"
-            }
-        },
-        "node_modules/@types/react-redux/node_modules/@types/react": {
-            "version": "18.0.12",
-            "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.12.tgz",
-            "integrity": "sha512-duF1OTASSBQtcigUvhuiTB1Ya3OvSy+xORCiEf20H0P0lzx+/KeVsA99U5UjLXSbyo1DRJDlLKqTeM1ngosqtg==",
-            "dependencies": {
-                "@types/prop-types": "*",
-                "@types/scheduler": "*",
-                "csstype": "^3.0.2"
-            }
-        },
-        "node_modules/@types/react-redux/node_modules/csstype": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-            "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
-        },
-        "node_modules/@types/react-select": {
-            "version": "3.1.2",
-            "resolved": "https://registry.npmjs.org/@types/react-select/-/react-select-3.1.2.tgz",
-            "integrity": "sha512-ygvR/2FL87R2OLObEWFootYzkvm67LRA+URYEAcBuvKk7IXmdsnIwSGm60cVXGaqkJQHozb2Cy1t94tCYb6rJA==",
-            "dev": true,
-            "dependencies": {
-                "@types/react": "*",
-                "@types/react-dom": "*",
-                "@types/react-transition-group": "*"
-            }
-        },
-        "node_modules/@types/react-table": {
-            "version": "6.8.9",
-            "resolved": "https://registry.npmjs.org/@types/react-table/-/react-table-6.8.9.tgz",
-            "integrity": "sha512-fVQXjy/EYDbgraScgjDONA291McKqGrw0R0NeK639fx2bS4T19TnXMjg3FjOPlkI3qYTQtFTPADlRYysaQIMpA==",
-            "dev": true,
-            "dependencies": {
-                "@types/react": "*"
-            }
-        },
-        "node_modules/@types/react-transition-group": {
-            "version": "4.4.5",
-            "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz",
-            "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==",
-            "dependencies": {
-                "@types/react": "*"
-            }
-        },
-        "node_modules/@types/react/node_modules/csstype": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-            "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
-        },
-        "node_modules/@types/reactcss": {
-            "version": "1.2.6",
-            "resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.6.tgz",
-            "integrity": "sha512-qaIzpCuXNWomGR1Xq8SCFTtF4v8V27Y6f+b9+bzHiv087MylI/nTCqqdChNeWS7tslgROmYB7yeiruWX7WnqNg==",
-            "dev": true,
-            "dependencies": {
-                "@types/react": "*"
-            }
-        },
-        "node_modules/@types/request": {
-            "version": "2.48.8",
-            "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.8.tgz",
-            "integrity": "sha512-whjk1EDJPcAR2kYHRbFl/lKeeKYTi05A15K9bnLInCVroNDCtXce57xKdI0/rQaA3K+6q0eFyUBPmqfSndUZdQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/caseless": "*",
-                "@types/node": "*",
-                "@types/tough-cookie": "*",
-                "form-data": "^2.5.0"
-            }
-        },
-        "node_modules/@types/request-promise": {
-            "version": "4.1.48",
-            "resolved": "https://registry.npmjs.org/@types/request-promise/-/request-promise-4.1.48.tgz",
-            "integrity": "sha512-sLsfxfwP5G3E3U64QXxKwA6ctsxZ7uKyl4I28pMj3JvV+ztWECRns73GL71KMOOJME5u1A5Vs5dkBqyiR1Zcnw==",
-            "dev": true,
-            "dependencies": {
-                "@types/bluebird": "*",
-                "@types/request": "*"
-            }
-        },
-        "node_modules/@types/request/node_modules/form-data": {
-            "version": "2.5.1",
-            "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
-            "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
-            "dev": true,
-            "dependencies": {
-                "asynckit": "^0.4.0",
-                "combined-stream": "^1.0.6",
-                "mime-types": "^2.1.12"
-            },
-            "engines": {
-                "node": ">= 0.12"
-            }
-        },
-        "node_modules/@types/responselike": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz",
-            "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==",
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/responselike/node_modules/@types/node": {
-            "version": "17.0.41",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.41.tgz",
-            "integrity": "sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw=="
-        },
-        "node_modules/@types/reveal": {
-            "version": "3.3.33",
-            "resolved": "https://registry.npmjs.org/@types/reveal/-/reveal-3.3.33.tgz",
-            "integrity": "sha512-lKbezA9Oa5LfdSRwFDc/FHEGH4+FjiXh/a/PCSZAmN+KCeQJL/3ClOdAQwOxt3zdHc8XyioT+cNvIOletwRI7A=="
-        },
-        "node_modules/@types/rimraf": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-2.0.5.tgz",
-            "integrity": "sha512-YyP+VfeaqAyFmXoTh3HChxOQMyjByRMsHU7kc5KOJkSlXudhMhQIALbYV7rHh/l8d2lX3VUQzprrcAgWdRuU8g==",
-            "dev": true,
-            "dependencies": {
-                "@types/glob": "*",
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/scheduler": {
-            "version": "0.16.2",
-            "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
-            "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
-        },
-        "node_modules/@types/serve-static": {
-            "version": "1.13.10",
-            "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz",
-            "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/mime": "^1",
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/sharp": {
-            "version": "0.23.1",
-            "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.23.1.tgz",
-            "integrity": "sha512-iBRM9RjRF9pkIkukk6imlxfaKMRuiRND8L0yYKl5PJu5uLvxuNzp5f0x8aoTG5VX85M8O//BwbttzFVZL1j/FQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/shelljs": {
-            "version": "0.8.11",
-            "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.11.tgz",
-            "integrity": "sha512-x9yaMvEh5BEaZKeVQC4vp3l+QoFj3BXcd4aYfuKSzIIyihjdVARAadYy3SMNIz0WCCdS2vB9JL/U6GQk5PaxQw==",
-            "dev": true,
-            "dependencies": {
-                "@types/glob": "*",
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/sizzle": {
-            "version": "2.3.3",
-            "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
-            "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
-            "dev": true
-        },
-        "node_modules/@types/socket.io": {
-            "version": "2.1.13",
-            "resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.13.tgz",
-            "integrity": "sha512-JRgH3nCgsWel4OPANkhH8TelpXvacAJ9VeryjuqCDiaVDMpLysd6sbt0dr6Z15pqH3p2YpOT3T1C5vQ+O/7uyg==",
-            "dev": true,
-            "dependencies": {
-                "@types/engine.io": "*",
-                "@types/node": "*",
-                "@types/socket.io-parser": "*"
-            }
-        },
-        "node_modules/@types/socket.io-client": {
-            "version": "1.4.36",
-            "resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-1.4.36.tgz",
-            "integrity": "sha512-ZJWjtFBeBy1kRSYpVbeGYTElf6BqPQUkXDlHHD4k/42byCN5Rh027f4yARHCink9sKAkbtGZXEAmR0ZCnc2/Ag==",
-            "dev": true
-        },
-        "node_modules/@types/socket.io-parser": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/@types/socket.io-parser/-/socket.io-parser-3.0.0.tgz",
-            "integrity": "sha512-Ry/rbTE6HQNL9eu3LpL1Ocup5VexXu1bSSGlSho/IR5LuRc8YvxwSNJ3JxqTltVJEATLbZkMQETSbxfKNgp4Ew==",
-            "deprecated": "This is a stub types definition. socket.io-parser provides its own type definitions, so you do not need this installed.",
-            "dev": true,
-            "dependencies": {
-                "socket.io-parser": "*"
-            }
-        },
-        "node_modules/@types/source-list-map": {
-            "version": "0.1.2",
-            "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
-            "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==",
-            "dev": true
-        },
-        "node_modules/@types/strip-bom": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
-            "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=",
-            "dev": true
-        },
-        "node_modules/@types/strip-json-comments": {
-            "version": "0.0.30",
-            "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
-            "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
-            "dev": true
-        },
-        "node_modules/@types/supercluster": {
-            "version": "7.1.0",
-            "resolved": "https://registry.npmjs.org/@types/supercluster/-/supercluster-7.1.0.tgz",
-            "integrity": "sha512-6JapQ2GmEkH66r23BK49I+u6zczVDGTtiJEVvKDYZVSm/vepWaJuTq6BXzJ6I4agG5s8vA1KM7m/gXWDg03O4Q==",
-            "dependencies": {
-                "@types/geojson": "*"
-            }
-        },
-        "node_modules/@types/tapable": {
-            "version": "1.0.8",
-            "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz",
-            "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==",
-            "dev": true
-        },
-        "node_modules/@types/three": {
-            "version": "0.126.2",
-            "resolved": "https://registry.npmjs.org/@types/three/-/three-0.126.2.tgz",
-            "integrity": "sha512-6JqTgijtfXcTJik8NtiNxr2L90ex6ElM00qilOGeUcrEsJLOdzLJSIkXHUYS+KPAYQYtRJQKD6XaXds3HjS+gg=="
-        },
-        "node_modules/@types/tough-cookie": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz",
-            "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw=="
-        },
-        "node_modules/@types/typescript": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/@types/typescript/-/typescript-2.0.0.tgz",
-            "integrity": "sha1-xDNTnJi64oaCswfqp6D9IRW4PCg=",
-            "deprecated": "This is a stub types definition for TypeScript (https://github.com/Microsoft/TypeScript). TypeScript provides its own type definitions, so you don't need @types/typescript installed!",
-            "dev": true,
-            "dependencies": {
-                "typescript": "*"
-            }
-        },
-        "node_modules/@types/uglify-js": {
-            "version": "3.13.3",
-            "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.3.tgz",
-            "integrity": "sha512-9dmBYXt/rKxedUXfCvXSxyiPvpDXLkiRlv17DnqdhS+pRustL1967rI1jZVt1xysTO+xJGMoZzcy3cWC9+b6Tw==",
-            "dev": true,
-            "dependencies": {
-                "source-map": "^0.6.1"
-            }
-        },
-        "node_modules/@types/uglify-js/node_modules/source-map": {
-            "version": "0.6.1",
-            "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-            "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/@types/unist": {
-            "version": "2.0.6",
-            "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
-            "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ=="
-        },
-        "node_modules/@types/uuid": {
-            "version": "3.4.10",
-            "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.10.tgz",
-            "integrity": "sha512-BgeaZuElf7DEYZhWYDTc/XcLZXdVgFkVSTa13BqKvbnmUrxr3TJFKofUxCtDO9UQOdhnV+HPOESdHiHKZOJV1A==",
-            "dev": true
-        },
-        "node_modules/@types/valid-url": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/@types/valid-url/-/valid-url-1.0.3.tgz",
-            "integrity": "sha512-+33x29mg+ecU88ODdWpqaie2upIuRkhujVLA7TuJjM823cNMbeggfI6NhxewaRaRF8dy+g33e4uIg/m5Mb3xDQ==",
-            "dev": true
-        },
-        "node_modules/@types/web": {
-            "version": "0.0.53",
-            "resolved": "https://registry.npmjs.org/@types/web/-/web-0.0.53.tgz",
-            "integrity": "sha512-ULJJgHevSiiD/QaSWcpAfWHXHEaeXUXGGJ82XVderV4TAWdI22NFyjWcRfzJwjEIdUi0gvfVRlTFDeLTZpvF4Q=="
-        },
-        "node_modules/@types/webpack": {
-            "version": "4.41.32",
-            "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz",
-            "integrity": "sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg==",
-            "dev": true,
-            "dependencies": {
-                "@types/node": "*",
-                "@types/tapable": "^1",
-                "@types/uglify-js": "*",
-                "@types/webpack-sources": "*",
-                "anymatch": "^3.0.0",
-                "source-map": "^0.6.0"
-            }
-        },
-        "node_modules/@types/webpack-hot-middleware": {
-            "version": "2.25.6",
-            "resolved": "https://registry.npmjs.org/@types/webpack-hot-middleware/-/webpack-hot-middleware-2.25.6.tgz",
-            "integrity": "sha512-1Q9ClNvZR30HIsEAHYQL3bXJK1K7IsrqjGMTfIureFjphsGOZ3TkbeoCupbCmi26pSLjVTPHp+pFrJNpOkBSVg==",
-            "dev": true,
-            "dependencies": {
-                "@types/connect": "*",
-                "tapable": "^2.2.0",
-                "webpack": "^5"
-            }
-        },
-        "node_modules/@types/webpack-sources": {
-            "version": "3.2.0",
-            "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz",
-            "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==",
-            "dev": true,
-            "dependencies": {
-                "@types/node": "*",
-                "@types/source-list-map": "*",
-                "source-map": "^0.7.3"
-            }
-        },
-        "node_modules/@types/webpack-sources/node_modules/source-map": {
-            "version": "0.7.4",
-            "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
-            "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
-            "dev": true,
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/@types/webpack/node_modules/anymatch": {
-            "version": "3.1.2",
-            "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
-            "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
-            "dev": true,
-            "dependencies": {
-                "normalize-path": "^3.0.0",
-                "picomatch": "^2.0.4"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/@types/webpack/node_modules/source-map": {
-            "version": "0.6.1",
-            "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-            "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/@types/xregexp": {
-            "version": "4.4.0",
-            "resolved": "https://registry.npmjs.org/@types/xregexp/-/xregexp-4.4.0.tgz",
-            "integrity": "sha512-RJJHNci1sRRq8nZjWxzCbQdLhJVq+JcDHpsdzoTtFAR9qdsMhAWqKQ1NHsNcenKDtLsOwCBe/kfSKM82yXtocg==",
-            "deprecated": "This is a stub types definition. xregexp provides its own type definitions, so you do not need this installed.",
-            "dev": true,
-            "dependencies": {
-                "xregexp": "*"
-            }
-        },
-        "node_modules/@types/yauzl": {
-            "version": "2.10.0",
-            "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
-            "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==",
-            "optional": true,
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/yauzl/node_modules/@types/node": {
-            "version": "17.0.41",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.41.tgz",
-            "integrity": "sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw==",
-            "optional": true
-        },
-        "node_modules/@types/youtube": {
-            "version": "0.0.39",
-            "resolved": "https://registry.npmjs.org/@types/youtube/-/youtube-0.0.39.tgz",
-            "integrity": "sha512-naVjyTZT/CoNwEQW3+mf9E/x6sgB7QIPbRDtVlPUpHlmuQTk+j6gQBy0T5CRkV8oC0GYQjMgfr3VdueTSVLTjw==",
-            "dev": true
-        },
-        "node_modules/@webassemblyjs/ast": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz",
-            "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==",
-            "dependencies": {
-                "@webassemblyjs/helper-numbers": "1.11.1",
-                "@webassemblyjs/helper-wasm-bytecode": "1.11.1"
-            }
-        },
-        "node_modules/@webassemblyjs/floating-point-hex-parser": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz",
-            "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ=="
-        },
-        "node_modules/@webassemblyjs/helper-api-error": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz",
-            "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg=="
-        },
-        "node_modules/@webassemblyjs/helper-buffer": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz",
-            "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA=="
-        },
-        "node_modules/@webassemblyjs/helper-numbers": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz",
-            "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==",
-            "dependencies": {
-                "@webassemblyjs/floating-point-hex-parser": "1.11.1",
-                "@webassemblyjs/helper-api-error": "1.11.1",
-                "@xtuc/long": "4.2.2"
-            }
-        },
-        "node_modules/@webassemblyjs/helper-wasm-bytecode": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz",
-            "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q=="
-        },
-        "node_modules/@webassemblyjs/helper-wasm-section": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz",
-            "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==",
-            "dependencies": {
-                "@webassemblyjs/ast": "1.11.1",
-                "@webassemblyjs/helper-buffer": "1.11.1",
-                "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
-                "@webassemblyjs/wasm-gen": "1.11.1"
-            }
-        },
-        "node_modules/@webassemblyjs/ieee754": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz",
-            "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==",
-            "dependencies": {
-                "@xtuc/ieee754": "^1.2.0"
-            }
-        },
-        "node_modules/@webassemblyjs/leb128": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz",
-            "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==",
-            "dependencies": {
-                "@xtuc/long": "4.2.2"
-            }
-        },
-        "node_modules/@webassemblyjs/utf8": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz",
-            "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ=="
-        },
-        "node_modules/@webassemblyjs/wasm-edit": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz",
-            "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==",
-            "dependencies": {
-                "@webassemblyjs/ast": "1.11.1",
-                "@webassemblyjs/helper-buffer": "1.11.1",
-                "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
-                "@webassemblyjs/helper-wasm-section": "1.11.1",
-                "@webassemblyjs/wasm-gen": "1.11.1",
-                "@webassemblyjs/wasm-opt": "1.11.1",
-                "@webassemblyjs/wasm-parser": "1.11.1",
-                "@webassemblyjs/wast-printer": "1.11.1"
-            }
-        },
-        "node_modules/@webassemblyjs/wasm-gen": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz",
-            "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==",
-            "dependencies": {
-                "@webassemblyjs/ast": "1.11.1",
-                "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
-                "@webassemblyjs/ieee754": "1.11.1",
-                "@webassemblyjs/leb128": "1.11.1",
-                "@webassemblyjs/utf8": "1.11.1"
-            }
-        },
-        "node_modules/@webassemblyjs/wasm-opt": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz",
-            "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==",
-            "dependencies": {
-                "@webassemblyjs/ast": "1.11.1",
-                "@webassemblyjs/helper-buffer": "1.11.1",
-                "@webassemblyjs/wasm-gen": "1.11.1",
-                "@webassemblyjs/wasm-parser": "1.11.1"
-            }
-        },
-        "node_modules/@webassemblyjs/wasm-parser": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz",
-            "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==",
-            "dependencies": {
-                "@webassemblyjs/ast": "1.11.1",
-                "@webassemblyjs/helper-api-error": "1.11.1",
-                "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
-                "@webassemblyjs/ieee754": "1.11.1",
-                "@webassemblyjs/leb128": "1.11.1",
-                "@webassemblyjs/utf8": "1.11.1"
-            }
-        },
-        "node_modules/@webassemblyjs/wast-printer": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz",
-            "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==",
-            "dependencies": {
-                "@webassemblyjs/ast": "1.11.1",
-                "@xtuc/long": "4.2.2"
-            }
-        },
-        "node_modules/@webpack-cli/configtest": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz",
-            "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==",
-            "peerDependencies": {
-                "webpack": "4.x.x || 5.x.x",
-                "webpack-cli": "4.x.x"
-            }
-        },
-        "node_modules/@webpack-cli/info": {
-            "version": "1.5.0",
-            "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz",
-            "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==",
-            "dependencies": {
-                "envinfo": "^7.7.3"
-            },
-            "peerDependencies": {
-                "webpack-cli": "4.x.x"
-            }
-        },
-        "node_modules/@webpack-cli/serve": {
-            "version": "1.7.0",
-            "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz",
-            "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==",
-            "peerDependencies": {
-                "webpack-cli": "4.x.x"
-            },
-            "peerDependenciesMeta": {
-                "webpack-dev-server": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@webscopeio/react-textarea-autocomplete": {
-            "version": "4.9.1",
-            "resolved": "https://registry.npmjs.org/@webscopeio/react-textarea-autocomplete/-/react-textarea-autocomplete-4.9.1.tgz",
-            "integrity": "sha512-g5cnRRXQQBGH5Km/0eSq8xFlnHZeG2WVRr+uu/3PKbHcgvNUIHKEy2tjOA9m4MK8KFzbFtfnj2MqdPf9R+5/Cw==",
-            "dependencies": {
-                "custom-event": "^1.0.1",
-                "textarea-caret": "3.0.2"
-            },
-            "peerDependencies": {
-                "prop-types": "^15.0.0",
-                "react": "^16.0.0 || ^17",
-                "react-dom": "^16.0.0 || ^17"
-            }
-        },
-        "node_modules/@webscopeio/react-textarea-autocomplete/node_modules/textarea-caret": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/textarea-caret/-/textarea-caret-3.0.2.tgz",
-            "integrity": "sha512-gRzeti2YS4did7UJnPQ47wrjD+vp+CJIe9zbsu0bJ987d8QVLvLNG9757rqiQTIy4hGIeFauTTJt5Xkn51UkXg=="
-        },
-        "node_modules/@xtuc/ieee754": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
-            "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="
-        },
-        "node_modules/@xtuc/long": {
-            "version": "4.2.2",
-            "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
-            "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
-        },
-        "node_modules/abab": {
-            "version": "2.0.6",
-            "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
-            "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
-            "dev": true
-        },
-        "node_modules/abbrev": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
-            "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
-        },
-        "node_modules/abort-controller": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
-            "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
-            "dependencies": {
-                "event-target-shim": "^5.0.0"
-            },
-            "engines": {
-                "node": ">=6.5"
-            }
-        },
-        "node_modules/accepts": {
-            "version": "1.3.8",
-            "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
-            "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
-            "dependencies": {
-                "mime-types": "~2.1.34",
-                "negotiator": "0.6.3"
-            },
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/acorn": {
-            "version": "8.7.1",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
-            "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==",
-            "bin": {
-                "acorn": "bin/acorn"
-            },
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/acorn-globals": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz",
-            "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=",
-            "dependencies": {
-                "acorn": "^4.0.4"
-            }
-        },
-        "node_modules/acorn-globals/node_modules/acorn": {
-            "version": "4.0.13",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
-            "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=",
-            "bin": {
-                "acorn": "bin/acorn"
-            },
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/acorn-import-assertions": {
-            "version": "1.8.0",
-            "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
-            "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
-            "peerDependencies": {
-                "acorn": "^8"
-            }
-        },
-        "node_modules/acorn-jsx": {
-            "version": "5.3.2",
-            "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
-            "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
-            "peerDependencies": {
-                "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
-            }
-        },
-        "node_modules/acorn-walk": {
-            "version": "6.2.0",
-            "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
-            "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/adm-zip": {
-            "version": "0.4.16",
-            "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz",
-            "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==",
-            "engines": {
-                "node": ">=0.3.0"
-            }
-        },
-        "node_modules/after": {
-            "version": "0.8.2",
-            "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
-            "integrity": "sha512-QbJ0NTQ/I9DI3uSJA4cbexiwQeRAfjPScqIbSjUDd9TOrcg6pTkdgziesOqxBMBzit8vFCTwrP27t13vFOORRA=="
-        },
-        "node_modules/agent-base": {
-            "version": "6.0.2",
-            "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
-            "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
-            "dependencies": {
-                "debug": "4"
-            },
-            "engines": {
-                "node": ">= 6.0.0"
-            }
-        },
-        "node_modules/agent-base/node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/agent-base/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
-        },
-        "node_modules/ajv": {
-            "version": "6.12.6",
-            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
-            "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
-            "dependencies": {
-                "fast-deep-equal": "^3.1.1",
-                "fast-json-stable-stringify": "^2.0.0",
-                "json-schema-traverse": "^0.4.1",
-                "uri-js": "^4.2.2"
-            },
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/epoberezkin"
-            }
-        },
-        "node_modules/ajv-errors": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
-            "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
-            "peerDependencies": {
-                "ajv": ">=5.0.0"
-            }
-        },
-        "node_modules/ajv-formats": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
-            "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
-            "dependencies": {
-                "ajv": "^8.0.0"
-            },
-            "peerDependencies": {
-                "ajv": "^8.0.0"
-            },
-            "peerDependenciesMeta": {
-                "ajv": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/ajv-formats/node_modules/ajv": {
-            "version": "8.11.0",
-            "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
-            "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
-            "dependencies": {
-                "fast-deep-equal": "^3.1.1",
-                "json-schema-traverse": "^1.0.0",
-                "require-from-string": "^2.0.2",
-                "uri-js": "^4.2.2"
-            },
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/epoberezkin"
-            }
-        },
-        "node_modules/ajv-formats/node_modules/json-schema-traverse": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
-            "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
-        },
-        "node_modules/ajv-keywords": {
-            "version": "3.5.2",
-            "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
-            "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
-            "peerDependencies": {
-                "ajv": "^6.9.1"
-            }
-        },
-        "node_modules/align-text": {
-            "version": "0.1.4",
-            "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
-            "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
-            "dependencies": {
-                "kind-of": "^3.0.2",
-                "longest": "^1.0.1",
-                "repeat-string": "^1.5.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/align-text/node_modules/is-buffer": {
-            "version": "1.1.6",
-            "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-            "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
-        },
-        "node_modules/align-text/node_modules/kind-of": {
-            "version": "3.2.2",
-            "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-            "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-            "dependencies": {
-                "is-buffer": "^1.1.5"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/amdefine": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
-            "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
-            "engines": {
-                "node": ">=0.4.2"
-            }
-        },
-        "node_modules/ansi-align": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz",
-            "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=",
-            "dependencies": {
-                "string-width": "^2.0.0"
-            }
-        },
-        "node_modules/ansi-colors": {
-            "version": "3.2.3",
-            "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
-            "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/ansi-escape-sequences": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz",
-            "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==",
-            "dependencies": {
-                "array-back": "^3.0.1"
-            },
-            "engines": {
-                "node": ">=8.0.0"
-            }
-        },
-        "node_modules/ansi-escape-sequences/node_modules/array-back": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz",
-            "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/ansi-escapes": {
-            "version": "4.3.2",
-            "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
-            "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
-            "dev": true,
-            "dependencies": {
-                "type-fest": "^0.21.3"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/ansi-escapes/node_modules/type-fest": {
-            "version": "0.21.3",
-            "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
-            "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
-            "dev": true,
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/ansi-html-community": {
-            "version": "0.0.8",
-            "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
-            "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==",
-            "dev": true,
-            "engines": [
-                "node >= 0.8.0"
-            ],
-            "bin": {
-                "ansi-html": "bin/ansi-html"
-            }
-        },
-        "node_modules/ansi-regex": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz",
-            "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/ansi-styles": {
-            "version": "3.2.1",
-            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-            "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-            "dependencies": {
-                "color-convert": "^1.9.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/any-promise": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
-            "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
-        },
-        "node_modules/anymatch": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
-            "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
-            "dependencies": {
-                "micromatch": "^3.1.4",
-                "normalize-path": "^2.1.1"
-            }
-        },
-        "node_modules/anymatch/node_modules/normalize-path": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
-            "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
-            "dependencies": {
-                "remove-trailing-separator": "^1.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/aproba": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
-            "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="
-        },
-        "node_modules/archiver": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/archiver/-/archiver-3.1.1.tgz",
-            "integrity": "sha512-5Hxxcig7gw5Jod/8Gq0OneVgLYET+oNHcxgWItq4TbhOzRLKNAFUb9edAftiMKXvXfCB0vbGrJdZDNq0dWMsxg==",
-            "dependencies": {
-                "archiver-utils": "^2.1.0",
-                "async": "^2.6.3",
-                "buffer-crc32": "^0.2.1",
-                "glob": "^7.1.4",
-                "readable-stream": "^3.4.0",
-                "tar-stream": "^2.1.0",
-                "zip-stream": "^2.1.2"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/archiver-utils": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz",
-            "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
-            "dependencies": {
-                "glob": "^7.1.4",
-                "graceful-fs": "^4.2.0",
-                "lazystream": "^1.0.0",
-                "lodash.defaults": "^4.2.0",
-                "lodash.difference": "^4.5.0",
-                "lodash.flatten": "^4.4.0",
-                "lodash.isplainobject": "^4.0.6",
-                "lodash.union": "^4.6.0",
-                "normalize-path": "^3.0.0",
-                "readable-stream": "^2.0.0"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/archiver-utils/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/are-we-there-yet": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
-            "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
-            "dependencies": {
-                "delegates": "^1.0.0",
-                "readable-stream": "^3.6.0"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/arg": {
-            "version": "4.1.3",
-            "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
-            "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
-            "dev": true
-        },
-        "node_modules/argparse": {
-            "version": "1.0.10",
-            "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
-            "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
-            "dependencies": {
-                "sprintf-js": "~1.0.2"
-            }
-        },
-        "node_modules/aria-query": {
-            "version": "4.2.2",
-            "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz",
-            "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==",
-            "dev": true,
-            "dependencies": {
-                "@babel/runtime": "^7.10.2",
-                "@babel/runtime-corejs3": "^7.10.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            }
-        },
-        "node_modules/arr-diff": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
-            "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/arr-flatten": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
-            "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/arr-union": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
-            "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/array-back": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz",
-            "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==",
-            "dependencies": {
-                "typical": "^2.6.1"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/array-batcher": {
-            "version": "1.2.3",
-            "resolved": "https://registry.npmjs.org/array-batcher/-/array-batcher-1.2.3.tgz",
-            "integrity": "sha512-/IOrwn4ZJi7YqTZrs3k+wQN5nKhjtTqL5ZKkzB+sKJlPeJzpMnRc3o8T9yt8/ZJiSldd+PwTHjM+//UsaszOOw==",
-            "dependencies": {
-                "@types/node": "^12.7.5",
-                "chai": "^4.2.0",
-                "mocha": "^6.2.0",
-                "request": "^2.88.0",
-                "request-promise": "^4.2.4"
-            }
-        },
-        "node_modules/array-batcher/node_modules/@types/node": {
-            "version": "12.20.55",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
-            "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="
-        },
-        "node_modules/array-batcher/node_modules/glob": {
-            "version": "7.1.3",
-            "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
-            "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
-            "dependencies": {
-                "fs.realpath": "^1.0.0",
-                "inflight": "^1.0.4",
-                "inherits": "2",
-                "minimatch": "^3.0.4",
-                "once": "^1.3.0",
-                "path-is-absolute": "^1.0.0"
-            },
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/array-batcher/node_modules/minimatch": {
-            "version": "3.0.4",
-            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-            "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
-            "dependencies": {
-                "brace-expansion": "^1.1.7"
-            },
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/array-batcher/node_modules/mocha": {
-            "version": "6.2.3",
-            "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz",
-            "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==",
-            "dependencies": {
-                "ansi-colors": "3.2.3",
-                "browser-stdout": "1.3.1",
-                "debug": "3.2.6",
-                "diff": "3.5.0",
-                "escape-string-regexp": "1.0.5",
-                "find-up": "3.0.0",
-                "glob": "7.1.3",
-                "growl": "1.10.5",
-                "he": "1.2.0",
-                "js-yaml": "3.13.1",
-                "log-symbols": "2.2.0",
-                "minimatch": "3.0.4",
-                "mkdirp": "0.5.4",
-                "ms": "2.1.1",
-                "node-environment-flags": "1.0.5",
-                "object.assign": "4.1.0",
-                "strip-json-comments": "2.0.1",
-                "supports-color": "6.0.0",
-                "which": "1.3.1",
-                "wide-align": "1.1.3",
-                "yargs": "13.3.2",
-                "yargs-parser": "13.1.2",
-                "yargs-unparser": "1.6.0"
-            },
-            "bin": {
-                "_mocha": "bin/_mocha",
-                "mocha": "bin/mocha"
-            },
-            "engines": {
-                "node": ">= 6.0.0"
-            }
-        },
-        "node_modules/array-batcher/node_modules/supports-color": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz",
-            "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==",
-            "dependencies": {
-                "has-flag": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/array-equal": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
-            "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
-            "dev": true
-        },
-        "node_modules/array-find-index": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
-            "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/array-flatten": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
-            "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
-        },
-        "node_modules/array-includes": {
-            "version": "3.1.5",
-            "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz",
-            "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.4",
-                "es-abstract": "^1.19.5",
-                "get-intrinsic": "^1.1.1",
-                "is-string": "^1.0.7"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/array-union": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
-            "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
-            "dev": true,
-            "dependencies": {
-                "array-uniq": "^1.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/array-uniq": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
-            "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/array-unique": {
-            "version": "0.3.2",
-            "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
-            "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/array.prototype.flat": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz",
-            "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.19.2",
-                "es-shim-unscopables": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/array.prototype.flatmap": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz",
-            "integrity": "sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.19.2",
-                "es-shim-unscopables": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/array.prototype.reduce": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.4.tgz",
-            "integrity": "sha512-WnM+AjG/DvLRLo4DDl+r+SvCzYtD2Jd9oeBYMcEaI7t3fFrHY9M53/wdLcTvmZNQ70IU6Htj0emFkZ5TS+lrdw==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.19.2",
-                "es-array-method-boxes-properly": "^1.0.0",
-                "is-string": "^1.0.7"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/arraybuffer.slice": {
-            "version": "0.0.7",
-            "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
-            "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog=="
-        },
-        "node_modules/arrify": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
-            "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/asap": {
-            "version": "2.0.6",
-            "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
-            "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
-        },
-        "node_modules/asn1": {
-            "version": "0.2.6",
-            "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
-            "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
-            "dependencies": {
-                "safer-buffer": "~2.1.0"
-            }
-        },
-        "node_modules/assert-plus": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
-            "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
-            "engines": {
-                "node": ">=0.8"
-            }
-        },
-        "node_modules/assertion-error": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
-            "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/assign-symbols": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
-            "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/ast-types-flow": {
-            "version": "0.0.7",
-            "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
-            "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
-            "dev": true
-        },
-        "node_modules/astral-regex": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
-            "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/async": {
-            "version": "2.6.4",
-            "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
-            "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
-            "dependencies": {
-                "lodash": "^4.17.14"
-            }
-        },
-        "node_modules/async-each": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
-            "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ=="
-        },
-        "node_modules/async-foreach": {
-            "version": "0.1.3",
-            "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
-            "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/async-limiter": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
-            "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
-            "dev": true
-        },
-        "node_modules/asynckit": {
-            "version": "0.4.0",
-            "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-            "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
-        },
-        "node_modules/atob": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
-            "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
-            "bin": {
-                "atob": "bin/atob.js"
-            },
-            "engines": {
-                "node": ">= 4.5.0"
-            }
-        },
-        "node_modules/available-typed-arrays": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
-            "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/awesome-typescript-loader": {
-            "version": "5.2.1",
-            "resolved": "https://registry.npmjs.org/awesome-typescript-loader/-/awesome-typescript-loader-5.2.1.tgz",
-            "integrity": "sha512-slv66OAJB8orL+UUaTI3pKlLorwIvS4ARZzYR9iJJyGsEgOqueMfOMdKySWzZ73vIkEe3fcwFgsKMg4d8zyb1g==",
-            "dev": true,
-            "dependencies": {
-                "chalk": "^2.4.1",
-                "enhanced-resolve": "^4.0.0",
-                "loader-utils": "^1.1.0",
-                "lodash": "^4.17.5",
-                "micromatch": "^3.1.9",
-                "mkdirp": "^0.5.1",
-                "source-map-support": "^0.5.3",
-                "webpack-log": "^1.2.0"
-            },
-            "peerDependencies": {
-                "typescript": "^2.7 || ^3"
-            }
-        },
-        "node_modules/awesome-typescript-loader/node_modules/enhanced-resolve": {
-            "version": "4.5.0",
-            "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz",
-            "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==",
-            "dev": true,
-            "dependencies": {
-                "graceful-fs": "^4.1.2",
-                "memory-fs": "^0.5.0",
-                "tapable": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/awesome-typescript-loader/node_modules/tapable": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
-            "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/aws-sign2": {
-            "version": "0.7.0",
-            "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
-            "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/aws4": {
-            "version": "1.11.0",
-            "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
-            "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
-        },
-        "node_modules/axe-core": {
-            "version": "4.4.2",
-            "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.2.tgz",
-            "integrity": "sha512-LVAaGp/wkkgYJcjmHsoKx4juT1aQvJyPcW09MLCjVTh3V2cc6PnyempiLMNH5iMdfIX/zdbjUx2KDjMLCTdPeA==",
-            "dev": true,
-            "engines": {
-                "node": ">=12"
-            }
-        },
-        "node_modules/axios": {
-            "version": "0.19.2",
-            "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
-            "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
-            "deprecated": "Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410",
-            "dependencies": {
-                "follow-redirects": "1.5.10"
-            }
-        },
-        "node_modules/axobject-query": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
-            "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==",
-            "dev": true
-        },
-        "node_modules/babel": {
-            "version": "6.23.0",
-            "resolved": "https://registry.npmjs.org/babel/-/babel-6.23.0.tgz",
-            "integrity": "sha1-0NHn2APpdHZb7qMjLU4VPA77kPQ=",
-            "deprecated": "In 6.x, the babel package has been deprecated in favor of babel-cli. Check https://opencollective.com/babel to support the Babel maintainers",
-            "bin": {
-                "babel": "lib/cli.js",
-                "babel-external-helpers": "lib/cli.js",
-                "babel-node": "lib/cli.js"
-            }
-        },
-        "node_modules/babel-code-frame": {
-            "version": "6.26.0",
-            "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
-            "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
-            "dev": true,
-            "dependencies": {
-                "chalk": "^1.1.3",
-                "esutils": "^2.0.2",
-                "js-tokens": "^3.0.2"
-            }
-        },
-        "node_modules/babel-code-frame/node_modules/ansi-regex": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-            "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/babel-code-frame/node_modules/ansi-styles": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-            "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/babel-code-frame/node_modules/chalk": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-            "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-            "dev": true,
-            "dependencies": {
-                "ansi-styles": "^2.2.1",
-                "escape-string-regexp": "^1.0.2",
-                "has-ansi": "^2.0.0",
-                "strip-ansi": "^3.0.0",
-                "supports-color": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/babel-code-frame/node_modules/js-tokens": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
-            "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
-            "dev": true
-        },
-        "node_modules/babel-code-frame/node_modules/strip-ansi": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-            "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
-            "dev": true,
-            "dependencies": {
-                "ansi-regex": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/babel-code-frame/node_modules/supports-color": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-            "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
-            "dev": true,
-            "engines": {
-                "node": ">=0.8.0"
-            }
-        },
-        "node_modules/babel-eslint": {
-            "version": "10.1.0",
-            "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz",
-            "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==",
-            "deprecated": "babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.",
-            "dev": true,
-            "dependencies": {
-                "@babel/code-frame": "^7.0.0",
-                "@babel/parser": "^7.7.0",
-                "@babel/traverse": "^7.7.0",
-                "@babel/types": "^7.7.0",
-                "eslint-visitor-keys": "^1.0.0",
-                "resolve": "^1.12.0"
-            },
-            "engines": {
-                "node": ">=6"
-            },
-            "peerDependencies": {
-                "eslint": ">= 4.12.1"
-            }
-        },
-        "node_modules/babel-eslint/node_modules/eslint-visitor-keys": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
-            "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/babel-plugin-emotion": {
-            "version": "10.2.2",
-            "resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-10.2.2.tgz",
-            "integrity": "sha512-SMSkGoqTbTyUTDeuVuPIWifPdUGkTk1Kf9BWRiXIOIcuyMfsdp2EjeiiFvOzX8NOBvEh/ypKYvUh2rkgAJMCLA==",
-            "dependencies": {
-                "@babel/helper-module-imports": "^7.0.0",
-                "@emotion/hash": "0.8.0",
-                "@emotion/memoize": "0.7.4",
-                "@emotion/serialize": "^0.11.16",
-                "babel-plugin-macros": "^2.0.0",
-                "babel-plugin-syntax-jsx": "^6.18.0",
-                "convert-source-map": "^1.5.0",
-                "escape-string-regexp": "^1.0.5",
-                "find-root": "^1.1.0",
-                "source-map": "^0.5.7"
-            }
-        },
-        "node_modules/babel-plugin-macros": {
-            "version": "2.8.0",
-            "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz",
-            "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==",
-            "dependencies": {
-                "@babel/runtime": "^7.7.2",
-                "cosmiconfig": "^6.0.0",
-                "resolve": "^1.12.0"
-            }
-        },
-        "node_modules/babel-plugin-styled-components": {
-            "version": "2.0.7",
-            "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz",
-            "integrity": "sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==",
-            "dependencies": {
-                "@babel/helper-annotate-as-pure": "^7.16.0",
-                "@babel/helper-module-imports": "^7.16.0",
-                "babel-plugin-syntax-jsx": "^6.18.0",
-                "lodash": "^4.17.11",
-                "picomatch": "^2.3.0"
-            },
-            "peerDependencies": {
-                "styled-components": ">= 2"
-            }
-        },
-        "node_modules/babel-plugin-syntax-jsx": {
-            "version": "6.18.0",
-            "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
-            "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
-        },
-        "node_modules/babel-runtime": {
-            "version": "6.26.0",
-            "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
-            "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
-            "dependencies": {
-                "core-js": "^2.4.0",
-                "regenerator-runtime": "^0.11.0"
-            }
-        },
-        "node_modules/babel-runtime/node_modules/core-js": {
-            "version": "2.6.12",
-            "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
-            "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
-            "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
-            "hasInstallScript": true
-        },
-        "node_modules/babel-runtime/node_modules/regenerator-runtime": {
-            "version": "0.11.1",
-            "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
-            "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
-        },
-        "node_modules/babel-types": {
-            "version": "6.26.0",
-            "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
-            "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
-            "dependencies": {
-                "babel-runtime": "^6.26.0",
-                "esutils": "^2.0.2",
-                "lodash": "^4.17.4",
-                "to-fast-properties": "^1.0.3"
-            }
-        },
-        "node_modules/babel-types/node_modules/to-fast-properties": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
-            "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/babylon": {
-            "version": "6.18.0",
-            "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
-            "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
-            "bin": {
-                "babylon": "bin/babylon.js"
-            }
-        },
-        "node_modules/backo2": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
-            "integrity": "sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA=="
-        },
-        "node_modules/bail": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
-            "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==",
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/wooorm"
-            }
-        },
-        "node_modules/balanced-match": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-            "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
-        },
-        "node_modules/base": {
-            "version": "0.11.2",
-            "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
-            "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
-            "dependencies": {
-                "cache-base": "^1.0.1",
-                "class-utils": "^0.3.5",
-                "component-emitter": "^1.2.1",
-                "define-property": "^1.0.0",
-                "isobject": "^3.0.1",
-                "mixin-deep": "^1.2.0",
-                "pascalcase": "^0.1.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/base/node_modules/define-property": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-            "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
-            "dependencies": {
-                "is-descriptor": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/base/node_modules/is-accessor-descriptor": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-            "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-            "dependencies": {
-                "kind-of": "^6.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/base/node_modules/is-data-descriptor": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-            "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-            "dependencies": {
-                "kind-of": "^6.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/base/node_modules/is-descriptor": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-            "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-            "dependencies": {
-                "is-accessor-descriptor": "^1.0.0",
-                "is-data-descriptor": "^1.0.0",
-                "kind-of": "^6.0.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/base16": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz",
-            "integrity": "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA="
-        },
-        "node_modules/Base64": {
-            "version": "0.2.1",
-            "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz",
-            "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg="
-        },
-        "node_modules/base64-arraybuffer": {
-            "version": "0.1.4",
-            "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz",
-            "integrity": "sha512-a1eIFi4R9ySrbiMuyTGx5e92uRH5tQY6kArNcFaKBUleIoLjdjBg7Zxm3Mqm3Kmkf27HLR/1fnxX9q8GQ7Iavg==",
-            "engines": {
-                "node": ">= 0.6.0"
-            }
-        },
-        "node_modules/base64-js": {
-            "version": "1.5.1",
-            "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
-            "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ]
-        },
-        "node_modules/base64id": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
-            "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
-            "engines": {
-                "node": "^4.5.0 || >= 5.9"
-            }
-        },
-        "node_modules/base64url": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz",
-            "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==",
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/batch": {
-            "version": "0.6.1",
-            "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
-            "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
-            "dev": true
-        },
-        "node_modules/bcrypt-nodejs": {
-            "version": "0.0.3",
-            "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz",
-            "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs=",
-            "deprecated": "bcrypt-nodejs is no longer actively maintained. Please use bcrypt or bcryptjs. See https://github.com/kelektiv/node.bcrypt.js/wiki/bcrypt-vs-brypt.js to learn more about these two options"
-        },
-        "node_modules/bcrypt-pbkdf": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
-            "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
-            "dependencies": {
-                "tweetnacl": "^0.14.3"
-            }
-        },
-        "node_modules/before-after-hook": {
-            "version": "2.2.2",
-            "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz",
-            "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ=="
-        },
-        "node_modules/bezier-curve": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/bezier-curve/-/bezier-curve-1.0.0.tgz",
-            "integrity": "sha1-o9+v6rEqlMRicw1QeYxSqEBdc3k="
-        },
-        "node_modules/bezier-js": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/bezier-js/-/bezier-js-4.1.1.tgz",
-            "integrity": "sha512-oVOS6SSFFFlfnZdzC+lsfvhs/RRcbxJ47U04M4s5QIBaJmr3YWmTIL3qmrOK9uW+nUUcl9Jccmo/xpTrG+bBoQ==",
-            "funding": {
-                "type": "individual",
-                "url": "https://github.com/Pomax/bezierjs/blob/master/FUNDING.md"
-            }
-        },
-        "node_modules/big.js": {
-            "version": "5.2.2",
-            "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
-            "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/bignumber.js": {
-            "version": "9.0.2",
-            "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz",
-            "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/binary-extensions": {
-            "version": "1.13.1",
-            "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
-            "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/bindings": {
-            "version": "1.5.0",
-            "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
-            "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
-            "optional": true,
-            "dependencies": {
-                "file-uri-to-path": "1.0.0"
-            }
-        },
-        "node_modules/bl": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
-            "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
-            "dependencies": {
-                "buffer": "^5.5.0",
-                "inherits": "^2.0.4",
-                "readable-stream": "^3.4.0"
-            }
-        },
-        "node_modules/blob": {
-            "version": "0.0.5",
-            "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
-            "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig=="
-        },
-        "node_modules/block-stream": {
-            "version": "0.0.9",
-            "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
-            "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
-            "dependencies": {
-                "inherits": "~2.0.0"
-            },
-            "engines": {
-                "node": "0.4 || >=0.5.8"
-            }
-        },
-        "node_modules/bluebird": {
-            "version": "3.7.2",
-            "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
-            "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
-        },
-        "node_modules/body-parser": {
-            "version": "1.20.0",
-            "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
-            "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
-            "dependencies": {
-                "bytes": "3.1.2",
-                "content-type": "~1.0.4",
-                "debug": "2.6.9",
-                "depd": "2.0.0",
-                "destroy": "1.2.0",
-                "http-errors": "2.0.0",
-                "iconv-lite": "0.4.24",
-                "on-finished": "2.4.1",
-                "qs": "6.10.3",
-                "raw-body": "2.5.1",
-                "type-is": "~1.6.18",
-                "unpipe": "1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.8",
-                "npm": "1.2.8000 || >= 1.4.16"
-            }
-        },
-        "node_modules/body-parser/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/body-parser/node_modules/iconv-lite": {
-            "version": "0.4.24",
-            "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
-            "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
-            "dependencies": {
-                "safer-buffer": ">= 2.1.2 < 3"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/body-parser/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
-        },
-        "node_modules/body-parser/node_modules/qs": {
-            "version": "6.10.3",
-            "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
-            "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
-            "dependencies": {
-                "side-channel": "^1.0.4"
-            },
-            "engines": {
-                "node": ">=0.6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/bonjour": {
-            "version": "3.5.0",
-            "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
-            "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
-            "dev": true,
-            "dependencies": {
-                "array-flatten": "^2.1.0",
-                "deep-equal": "^1.0.1",
-                "dns-equal": "^1.0.0",
-                "dns-txt": "^2.0.2",
-                "multicast-dns": "^6.0.1",
-                "multicast-dns-service-types": "^1.1.0"
-            }
-        },
-        "node_modules/bonjour/node_modules/array-flatten": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
-            "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
-            "dev": true
-        },
-        "node_modules/boolbase": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
-            "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
-        },
-        "node_modules/bootstrap": {
-            "version": "4.6.1",
-            "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.1.tgz",
-            "integrity": "sha512-0dj+VgI9Ecom+rvvpNZ4MUZJz8dcX7WCX+eTID9+/8HgOkv3dsRzi8BGeZJCQU6flWQVYxwTQnEZFrmJSEO7og==",
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/bootstrap"
-            },
-            "peerDependencies": {
-                "jquery": "1.9.1 - 3",
-                "popper.js": "^1.16.1"
-            }
-        },
-        "node_modules/bowser": {
-            "version": "1.9.4",
-            "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz",
-            "integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ=="
-        },
-        "node_modules/boxen": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
-            "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==",
-            "dependencies": {
-                "ansi-align": "^2.0.0",
-                "camelcase": "^4.0.0",
-                "chalk": "^2.0.1",
-                "cli-boxes": "^1.0.0",
-                "string-width": "^2.0.0",
-                "term-size": "^1.2.0",
-                "widest-line": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/boxen/node_modules/camelcase": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-            "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/brace-expansion": {
-            "version": "1.1.11",
-            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-            "dependencies": {
-                "balanced-match": "^1.0.0",
-                "concat-map": "0.0.1"
-            }
-        },
-        "node_modules/braces": {
-            "version": "2.3.2",
-            "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
-            "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
-            "dependencies": {
-                "arr-flatten": "^1.1.0",
-                "array-unique": "^0.3.2",
-                "extend-shallow": "^2.0.1",
-                "fill-range": "^4.0.0",
-                "isobject": "^3.0.1",
-                "repeat-element": "^1.1.2",
-                "snapdragon": "^0.8.1",
-                "snapdragon-node": "^2.0.1",
-                "split-string": "^3.0.2",
-                "to-regex": "^3.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/braces/node_modules/extend-shallow": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-            "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-            "dependencies": {
-                "is-extendable": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/browndash-components": {
-            "version": "0.0.22",
-            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.0.22.tgz",
-            "integrity": "sha512-S5J644Ah+C179Xy2wrOfsRMaVw82+JE1wt8iVzE+1SbhQzAuXdv8W/AR1F4u907S5Un9413YHeiWs8s7wbytCg==",
-            "dependencies": {
-                "color": "^4.2.3",
-                "react-color": "^2.19.3",
-                "react-icons": "^4.3.1",
-                "react-measure": "^2.5.2"
-            }
-        },
-        "node_modules/browndash-components/node_modules/color": {
-            "version": "4.2.3",
-            "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
-            "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
-            "dependencies": {
-                "color-convert": "^2.0.1",
-                "color-string": "^1.9.0"
-            },
-            "engines": {
-                "node": ">=12.5.0"
-            }
-        },
-        "node_modules/browndash-components/node_modules/color-convert": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-            "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-            "dependencies": {
-                "color-name": "~1.1.4"
-            },
-            "engines": {
-                "node": ">=7.0.0"
-            }
-        },
-        "node_modules/browndash-components/node_modules/color-name": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-            "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
-        },
-        "node_modules/browser-assert": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz",
-            "integrity": "sha1-mqpaKox0aFwq4Fv+Ru/WBvBowgA="
-        },
-        "node_modules/browser-process-hrtime": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
-            "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==",
-            "dev": true
-        },
-        "node_modules/browser-stdout": {
-            "version": "1.3.1",
-            "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
-            "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
-        },
-        "node_modules/browserslist": {
-            "version": "4.20.4",
-            "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.4.tgz",
-            "integrity": "sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==",
-            "funding": [
-                {
-                    "type": "opencollective",
-                    "url": "https://opencollective.com/browserslist"
-                },
-                {
-                    "type": "tidelift",
-                    "url": "https://tidelift.com/funding/github/npm/browserslist"
-                }
-            ],
-            "dependencies": {
-                "caniuse-lite": "^1.0.30001349",
-                "electron-to-chromium": "^1.4.147",
-                "escalade": "^3.1.1",
-                "node-releases": "^2.0.5",
-                "picocolors": "^1.0.0"
-            },
-            "bin": {
-                "browserslist": "cli.js"
-            },
-            "engines": {
-                "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
-            }
-        },
-        "node_modules/bson": {
-            "version": "4.6.4",
-            "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.4.tgz",
-            "integrity": "sha512-TdQ3FzguAu5HKPPlr0kYQCyrYUYh8tFM+CMTpxjNzVzxeiJY00Rtuj3LXLHSgiGvmaWlZ8PE+4KyM2thqE38pQ==",
-            "dependencies": {
-                "buffer": "^5.6.0"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/buffer": {
-            "version": "5.7.1",
-            "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
-            "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ],
-            "dependencies": {
-                "base64-js": "^1.3.1",
-                "ieee754": "^1.1.13"
-            }
-        },
-        "node_modules/buffer-crc32": {
-            "version": "0.2.13",
-            "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
-            "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/buffer-equal-constant-time": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
-            "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
-        },
-        "node_modules/buffer-from": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
-            "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
-        },
-        "node_modules/buffer-indexof": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
-            "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==",
-            "dev": true
-        },
-        "node_modules/buffer-shims": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
-            "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E="
-        },
-        "node_modules/built-in-math-eval": {
-            "version": "0.3.0",
-            "resolved": "https://registry.npmjs.org/built-in-math-eval/-/built-in-math-eval-0.3.0.tgz",
-            "integrity": "sha1-JA3CHLOJQ5WIxhxGDrAHZJfvxBw=",
-            "dependencies": {
-                "math-codegen": "^0.3.5"
-            }
-        },
-        "node_modules/builtin-modules": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
-            "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
-            "engines": {
-                "node": ">=6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/bytes": {
-            "version": "3.1.2",
-            "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
-            "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/cacache": {
-            "version": "10.0.4",
-            "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
-            "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==",
-            "dev": true,
-            "dependencies": {
-                "bluebird": "^3.5.1",
-                "chownr": "^1.0.1",
-                "glob": "^7.1.2",
-                "graceful-fs": "^4.1.11",
-                "lru-cache": "^4.1.1",
-                "mississippi": "^2.0.0",
-                "mkdirp": "^0.5.1",
-                "move-concurrently": "^1.0.1",
-                "promise-inflight": "^1.0.1",
-                "rimraf": "^2.6.2",
-                "ssri": "^5.2.4",
-                "unique-filename": "^1.1.0",
-                "y18n": "^4.0.0"
-            }
-        },
-        "node_modules/cacache/node_modules/chownr": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
-            "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
-            "dev": true
-        },
-        "node_modules/cacache/node_modules/lru-cache": {
-            "version": "4.1.5",
-            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
-            "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
-            "dev": true,
-            "dependencies": {
-                "pseudomap": "^1.0.2",
-                "yallist": "^2.1.2"
-            }
-        },
-        "node_modules/cacache/node_modules/rimraf": {
-            "version": "2.7.1",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-            "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-            "dev": true,
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            }
-        },
-        "node_modules/cacache/node_modules/yallist": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
-            "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
-            "dev": true
-        },
-        "node_modules/cache-base": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
-            "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
-            "dependencies": {
-                "collection-visit": "^1.0.0",
-                "component-emitter": "^1.2.1",
-                "get-value": "^2.0.6",
-                "has-value": "^1.0.0",
-                "isobject": "^3.0.1",
-                "set-value": "^2.0.0",
-                "to-object-path": "^0.3.0",
-                "union-value": "^1.0.0",
-                "unset-value": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/cacheable-lookup": {
-            "version": "6.0.4",
-            "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-6.0.4.tgz",
-            "integrity": "sha512-mbcDEZCkv2CZF4G01kr8eBd/5agkt9oCqz75tJMSIsquvRZ2sL6Hi5zGVKi/0OSC9oO1GHfJ2AV0ZIOY9vye0A==",
-            "engines": {
-                "node": ">=10.6.0"
-            }
-        },
-        "node_modules/cacheable-request": {
-            "version": "7.0.2",
-            "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz",
-            "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==",
-            "dependencies": {
-                "clone-response": "^1.0.2",
-                "get-stream": "^5.1.0",
-                "http-cache-semantics": "^4.0.0",
-                "keyv": "^4.0.0",
-                "lowercase-keys": "^2.0.0",
-                "normalize-url": "^6.0.1",
-                "responselike": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/cacheable-request/node_modules/get-stream": {
-            "version": "5.2.0",
-            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
-            "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
-            "dependencies": {
-                "pump": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/cacheable-request/node_modules/lowercase-keys": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
-            "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/call-bind": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
-            "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
-            "dependencies": {
-                "function-bind": "^1.1.1",
-                "get-intrinsic": "^1.0.2"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/caller-callsite": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
-            "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
-            "dependencies": {
-                "callsites": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/caller-callsite/node_modules/callsites": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
-            "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/caller-path": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
-            "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
-            "dependencies": {
-                "caller-callsite": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/callsites": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
-            "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/camel-case": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
-            "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
-            "dependencies": {
-                "pascal-case": "^3.1.2",
-                "tslib": "^2.0.3"
-            }
-        },
-        "node_modules/camelcase": {
-            "version": "5.3.1",
-            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
-            "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/camelcase-keys": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
-            "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
-            "dependencies": {
-                "camelcase": "^2.0.0",
-                "map-obj": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/camelcase-keys/node_modules/camelcase": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
-            "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/camelize": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
-            "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
-        },
-        "node_modules/caniuse-lite": {
-            "version": "1.0.30001351",
-            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001351.tgz",
-            "integrity": "sha512-u+Ll+RDaiQEproTQjZLjZwyfNgNezA1fERMT7/54npcz+PkbVJUAHXMUz4bkXQYRPWrcFNO0Fbi1mwjfXg6N5g==",
-            "funding": [
-                {
-                    "type": "opencollective",
-                    "url": "https://opencollective.com/browserslist"
-                },
-                {
-                    "type": "tidelift",
-                    "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
-                }
-            ]
-        },
-        "node_modules/canvas": {
-            "version": "2.9.3",
-            "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.9.3.tgz",
-            "integrity": "sha512-WOUM7ghii5TV2rbhaZkh1youv/vW1/Canev6Yx6BG2W+1S07w8jKZqKkPnbiPpQEDsnJdN8ouDd7OvQEGXDcUw==",
-            "hasInstallScript": true,
-            "dependencies": {
-                "@mapbox/node-pre-gyp": "^1.0.0",
-                "nan": "^2.15.0",
-                "simple-get": "^3.0.3"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/capture-stack-trace": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz",
-            "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/caseless": {
-            "version": "0.12.0",
-            "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
-            "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
-        },
-        "node_modules/ccount": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
-            "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/wooorm"
-            }
-        },
-        "node_modules/center-align": {
-            "version": "0.1.3",
-            "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
-            "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
-            "dependencies": {
-                "align-text": "^0.1.3",
-                "lazy-cache": "^1.0.3"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/chai": {
-            "version": "4.3.6",
-            "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
-            "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
-            "dependencies": {
-                "assertion-error": "^1.1.0",
-                "check-error": "^1.0.2",
-                "deep-eql": "^3.0.1",
-                "get-func-name": "^2.0.0",
-                "loupe": "^2.3.1",
-                "pathval": "^1.1.1",
-                "type-detect": "^4.0.5"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/chain-function": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/chain-function/-/chain-function-1.0.1.tgz",
-            "integrity": "sha512-SxltgMwL9uCko5/ZCLiyG2B7R9fY4pDZUw7hJ4MhirdjBLosoDqkWABi3XMucddHdLiFJMb7PD2MZifZriuMTg=="
-        },
-        "node_modules/chalk": {
-            "version": "2.4.2",
-            "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-            "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-            "dependencies": {
-                "ansi-styles": "^3.2.1",
-                "escape-string-regexp": "^1.0.5",
-                "supports-color": "^5.3.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/change-emitter": {
-            "version": "0.1.6",
-            "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz",
-            "integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU="
-        },
-        "node_modules/character-entities": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
-            "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==",
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/wooorm"
-            }
-        },
-        "node_modules/character-parser": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz",
-            "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=",
-            "dependencies": {
-                "is-regex": "^1.0.3"
-            }
-        },
-        "node_modules/chardet": {
-            "version": "0.7.0",
-            "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
-            "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
-            "dev": true
-        },
-        "node_modules/check-error": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
-            "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/child_process": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz",
-            "integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o="
-        },
-        "node_modules/chokidar": {
-            "version": "2.1.8",
-            "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
-            "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
-            "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies",
-            "dependencies": {
-                "anymatch": "^2.0.0",
-                "async-each": "^1.0.1",
-                "braces": "^2.3.2",
-                "glob-parent": "^3.1.0",
-                "inherits": "^2.0.3",
-                "is-binary-path": "^1.0.0",
-                "is-glob": "^4.0.0",
-                "normalize-path": "^3.0.0",
-                "path-is-absolute": "^1.0.0",
-                "readdirp": "^2.2.1",
-                "upath": "^1.1.1"
-            },
-            "optionalDependencies": {
-                "fsevents": "^1.2.7"
-            }
-        },
-        "node_modules/chownr": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
-            "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/chrome": {
-            "version": "0.1.0",
-            "resolved": "https://registry.npmjs.org/chrome/-/chrome-0.1.0.tgz",
-            "integrity": "sha1-9h2beS/v6MGUxwVt3BAscmqGQyk=",
-            "dependencies": {
-                "exeq": "^2.2.0",
-                "plist": "^1.1.0"
-            },
-            "bin": {
-                "chrome": "index.js"
-            }
-        },
-        "node_modules/chrome-trace-event": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
-            "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
-            "engines": {
-                "node": ">=6.0"
-            }
-        },
-        "node_modules/ci-info": {
-            "version": "1.6.0",
-            "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
-            "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A=="
-        },
-        "node_modules/clamp": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz",
-            "integrity": "sha1-ZqDmQBGBbjcZaCj9yMjBRzEshjQ="
-        },
-        "node_modules/class-transformer": {
-            "version": "0.2.3",
-            "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.2.3.tgz",
-            "integrity": "sha512-qsP+0xoavpOlJHuYsQJsN58HXSl8Jvveo+T37rEvCEeRfMWoytAyR0Ua/YsFgpM6AZYZ/og2PJwArwzJl1aXtQ=="
-        },
-        "node_modules/class-utils": {
-            "version": "0.3.6",
-            "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
-            "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
-            "dependencies": {
-                "arr-union": "^3.1.0",
-                "define-property": "^0.2.5",
-                "isobject": "^3.0.0",
-                "static-extend": "^0.1.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/class-utils/node_modules/define-property": {
-            "version": "0.2.5",
-            "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-            "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-            "dependencies": {
-                "is-descriptor": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/classnames": {
-            "version": "2.3.1",
-            "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
-            "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA=="
-        },
-        "node_modules/clean-css": {
-            "version": "5.3.0",
-            "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz",
-            "integrity": "sha512-YYuuxv4H/iNb1Z/5IbMRoxgrzjWGhOEFfd+groZ5dMCVkpENiMZmwspdrzBo9286JjM1gZJPAyL7ZIdzuvu2AQ==",
-            "dependencies": {
-                "source-map": "~0.6.0"
-            },
-            "engines": {
-                "node": ">= 10.0"
-            }
-        },
-        "node_modules/clean-css/node_modules/source-map": {
-            "version": "0.6.1",
-            "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-            "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/cli-boxes": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
-            "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/cli-cursor": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
-            "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
-            "dev": true,
-            "dependencies": {
-                "restore-cursor": "^3.1.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/cli-width": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
-            "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
-            "dev": true,
-            "engines": {
-                "node": ">= 10"
-            }
-        },
-        "node_modules/clipboard": {
-            "version": "1.7.1",
-            "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-1.7.1.tgz",
-            "integrity": "sha1-Ng1taUbpmnof7zleQrqStem1oWs=",
-            "dependencies": {
-                "good-listener": "^1.2.2",
-                "select": "^1.1.2",
-                "tiny-emitter": "^2.0.0"
-            }
-        },
-        "node_modules/cliss": {
-            "version": "0.0.2",
-            "resolved": "https://registry.npmjs.org/cliss/-/cliss-0.0.2.tgz",
-            "integrity": "sha512-6rj9pgdukjT994Md13JCUAgTk91abAKrygL9sAvmHY4F6AKMOV8ccGaxhUUfcBuyg3sundWnn3JE0Mc9W6ZYqw==",
-            "dependencies": {
-                "command-line-usage": "^4.0.1",
-                "deepmerge": "^2.0.0",
-                "get-stdin": "^5.0.1",
-                "inspect-parameters-declaration": "0.0.9",
-                "object-to-arguments": "0.0.8",
-                "pipe-functions": "^1.3.0",
-                "strip-ansi": "^4.0.0",
-                "yargs-parser": "^7.0.0"
-            }
-        },
-        "node_modules/cliss/node_modules/camelcase": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-            "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/cliss/node_modules/yargs-parser": {
-            "version": "7.0.0",
-            "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz",
-            "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=",
-            "dependencies": {
-                "camelcase": "^4.1.0"
-            }
-        },
-        "node_modules/cliui": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
-            "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
-            "dependencies": {
-                "string-width": "^3.1.0",
-                "strip-ansi": "^5.2.0",
-                "wrap-ansi": "^5.1.0"
-            }
-        },
-        "node_modules/cliui/node_modules/ansi-regex": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
-            "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/cliui/node_modules/string-width": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-            "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
-            "dependencies": {
-                "emoji-regex": "^7.0.1",
-                "is-fullwidth-code-point": "^2.0.0",
-                "strip-ansi": "^5.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/cliui/node_modules/strip-ansi": {
-            "version": "5.2.0",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-            "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
-            "dependencies": {
-                "ansi-regex": "^4.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/clj-fuzzy": {
-            "version": "0.3.3",
-            "resolved": "https://registry.npmjs.org/clj-fuzzy/-/clj-fuzzy-0.3.3.tgz",
-            "integrity": "sha1-seU0MJHFIC28UlMoY+HEp4RX8D0=",
-            "deprecated": "use the `talisman` library instead"
-        },
-        "node_modules/clone-deep": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
-            "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
-            "dependencies": {
-                "is-plain-object": "^2.0.4",
-                "kind-of": "^6.0.2",
-                "shallow-clone": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/clone-response": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
-            "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
-            "dependencies": {
-                "mimic-response": "^1.0.0"
-            }
-        },
-        "node_modules/clone-response/node_modules/mimic-response": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
-            "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/clsx": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz",
-            "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/code-point-at": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
-            "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/collection-visit": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
-            "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
-            "dependencies": {
-                "map-visit": "^1.0.0",
-                "object-visit": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/color": {
-            "version": "3.2.1",
-            "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
-            "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
-            "dependencies": {
-                "color-convert": "^1.9.3",
-                "color-string": "^1.6.0"
-            }
-        },
-        "node_modules/color-convert": {
-            "version": "1.9.3",
-            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-            "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-            "dependencies": {
-                "color-name": "1.1.3"
-            }
-        },
-        "node_modules/color-name": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-            "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
-        },
-        "node_modules/color-string": {
-            "version": "1.9.1",
-            "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
-            "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
-            "dependencies": {
-                "color-name": "^1.0.0",
-                "simple-swizzle": "^0.2.2"
-            }
-        },
-        "node_modules/color-support": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
-            "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
-            "bin": {
-                "color-support": "bin.js"
-            }
-        },
-        "node_modules/colorette": {
-            "version": "2.0.17",
-            "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.17.tgz",
-            "integrity": "sha512-hJo+3Bkn0NCHybn9Tu35fIeoOKGOk5OCC32y4Hz2It+qlCO2Q3DeQ1hRn/tDDMQKRYUEzqsl7jbF6dYKjlE60g=="
-        },
-        "node_modules/colors": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
-            "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
-            "engines": {
-                "node": ">=0.1.90"
-            }
-        },
-        "node_modules/combined-stream": {
-            "version": "1.0.8",
-            "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
-            "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
-            "dependencies": {
-                "delayed-stream": "~1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/comma-separated-tokens": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.2.tgz",
-            "integrity": "sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg==",
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/wooorm"
-            }
-        },
-        "node_modules/command-exists": {
-            "version": "1.2.6",
-            "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.6.tgz",
-            "integrity": "sha512-Qst/zUUNmS/z3WziPxyqjrcz09pm+2Knbs5mAZL4VAE0sSrNY1/w8+/YxeHcoBTsO6iojA6BW7eFf27Eg2MRuw=="
-        },
-        "node_modules/command-line-usage": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz",
-            "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==",
-            "dependencies": {
-                "ansi-escape-sequences": "^4.0.0",
-                "array-back": "^2.0.0",
-                "table-layout": "^0.4.2",
-                "typical": "^2.6.1"
-            },
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/commander": {
-            "version": "8.3.0",
-            "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
-            "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
-            "engines": {
-                "node": ">= 12"
-            }
-        },
-        "node_modules/commondir": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
-            "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
-            "dev": true
-        },
-        "node_modules/component-bind": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
-            "integrity": "sha512-WZveuKPeKAG9qY+FkYDeADzdHyTYdIboXS59ixDeRJL5ZhxpqUnxSOwop4FQjMsiYm3/Or8cegVbpAHNA7pHxw=="
-        },
-        "node_modules/component-emitter": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
-            "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
-        },
-        "node_modules/component-inherit": {
-            "version": "0.0.3",
-            "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
-            "integrity": "sha512-w+LhYREhatpVqTESyGFg3NlP6Iu0kEKUHETY9GoZP/pQyW4mHFZuFWRUCIqVPZ36ueVLtoOEZaAqbCF2RDndaA=="
-        },
-        "node_modules/compress-brotli": {
-            "version": "1.3.8",
-            "resolved": "https://registry.npmjs.org/compress-brotli/-/compress-brotli-1.3.8.tgz",
-            "integrity": "sha512-lVcQsjhxhIXsuupfy9fmZUFtAIdBmXA7EGY6GBdgZ++qkM9zG4YFT8iU7FoBxzryNDMOpD1HIFHUSX4D87oqhQ==",
-            "dependencies": {
-                "@types/json-buffer": "~3.0.0",
-                "json-buffer": "~3.0.1"
-            },
-            "engines": {
-                "node": ">= 12"
-            }
-        },
-        "node_modules/compress-commons": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-2.1.1.tgz",
-            "integrity": "sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==",
-            "dependencies": {
-                "buffer-crc32": "^0.2.13",
-                "crc32-stream": "^3.0.1",
-                "normalize-path": "^3.0.0",
-                "readable-stream": "^2.3.6"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/compress-commons/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/compressible": {
-            "version": "2.0.18",
-            "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
-            "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
-            "dev": true,
-            "dependencies": {
-                "mime-db": ">= 1.43.0 < 2"
-            },
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/compression": {
-            "version": "1.7.4",
-            "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
-            "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
-            "dev": true,
-            "dependencies": {
-                "accepts": "~1.3.5",
-                "bytes": "3.0.0",
-                "compressible": "~2.0.16",
-                "debug": "2.6.9",
-                "on-headers": "~1.0.2",
-                "safe-buffer": "5.1.2",
-                "vary": "~1.1.2"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/compression/node_modules/bytes": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
-            "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
-            "dev": true,
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/compression/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "dev": true,
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/compression/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
-            "dev": true
-        },
-        "node_modules/concat-map": {
-            "version": "0.0.1",
-            "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-            "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
-        },
-        "node_modules/concat-stream": {
-            "version": "1.6.2",
-            "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
-            "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
-            "engines": [
-                "node >= 0.8"
-            ],
-            "dependencies": {
-                "buffer-from": "^1.0.0",
-                "inherits": "^2.0.3",
-                "readable-stream": "^2.2.2",
-                "typedarray": "^0.0.6"
-            }
-        },
-        "node_modules/concat-stream/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/configstore": {
-            "version": "3.1.5",
-            "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.5.tgz",
-            "integrity": "sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA==",
-            "dependencies": {
-                "dot-prop": "^4.2.1",
-                "graceful-fs": "^4.1.2",
-                "make-dir": "^1.0.0",
-                "unique-string": "^1.0.0",
-                "write-file-atomic": "^2.0.0",
-                "xdg-basedir": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/configstore/node_modules/make-dir": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
-            "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
-            "dependencies": {
-                "pify": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/configstore/node_modules/pify": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-            "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/confusing-browser-globals": {
-            "version": "1.0.11",
-            "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz",
-            "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==",
-            "dev": true
-        },
-        "node_modules/connect-flash": {
-            "version": "0.1.1",
-            "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz",
-            "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=",
-            "engines": {
-                "node": ">= 0.4.0"
-            }
-        },
-        "node_modules/connect-history-api-fallback": {
-            "version": "1.6.0",
-            "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
-            "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.8"
-            }
-        },
-        "node_modules/connect-mongo": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/connect-mongo/-/connect-mongo-2.0.3.tgz",
-            "integrity": "sha512-Vs+QZ/6X6gbCrP1Ls7Oh/wlyY6pgpbPSrUKF5yRT+zd+4GZPNbjNquxquZ+Clv2+03HBXE7T4lVM0PUcaBhihg==",
-            "dependencies": {
-                "mongodb": "^2.0.36"
-            }
-        },
-        "node_modules/connect-mongo/node_modules/mongodb": {
-            "version": "2.2.36",
-            "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.36.tgz",
-            "integrity": "sha512-P2SBLQ8Z0PVx71ngoXwo12+FiSfbNfGOClAao03/bant5DgLNkOPAck5IaJcEk4gKlQhDEURzfR3xuBG1/B+IA==",
-            "dependencies": {
-                "es6-promise": "3.2.1",
-                "mongodb-core": "2.1.20",
-                "readable-stream": "2.2.7"
-            },
-            "engines": {
-                "node": ">=0.10.3"
-            }
-        },
-        "node_modules/connect-mongo/node_modules/process-nextick-args": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
-            "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
-        },
-        "node_modules/connect-mongo/node_modules/readable-stream": {
-            "version": "2.2.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz",
-            "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=",
-            "dependencies": {
-                "buffer-shims": "~1.0.0",
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.1",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~1.0.6",
-                "string_decoder": "~1.0.0",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/connect-mongo/node_modules/string_decoder": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
-            "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
-            "dependencies": {
-                "safe-buffer": "~5.1.0"
-            }
-        },
-        "node_modules/console-control-strings": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
-            "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
-        },
-        "node_modules/constantinople": {
-            "version": "3.1.2",
-            "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.2.tgz",
-            "integrity": "sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw==",
-            "dependencies": {
-                "@types/babel-types": "^7.0.0",
-                "@types/babylon": "^6.16.2",
-                "babel-types": "^6.26.0",
-                "babylon": "^6.18.0"
-            }
-        },
-        "node_modules/content-disposition": {
-            "version": "0.5.4",
-            "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
-            "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
-            "dependencies": {
-                "safe-buffer": "5.2.1"
-            },
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/content-disposition/node_modules/safe-buffer": {
-            "version": "5.2.1",
-            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-            "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ]
-        },
-        "node_modules/content-type": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
-            "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/convert-source-map": {
-            "version": "1.8.0",
-            "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
-            "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==",
-            "dependencies": {
-                "safe-buffer": "~5.1.1"
-            }
-        },
-        "node_modules/cookie": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
-            "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/cookie-parser": {
-            "version": "1.4.6",
-            "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz",
-            "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==",
-            "dependencies": {
-                "cookie": "0.4.1",
-                "cookie-signature": "1.0.6"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/cookie-session": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/cookie-session/-/cookie-session-2.0.0.tgz",
-            "integrity": "sha512-hKvgoThbw00zQOleSlUr2qpvuNweoqBtxrmx0UFosx6AGi9lYtLoA+RbsvknrEX8Pr6MDbdWAb2j6SnMn+lPsg==",
-            "dependencies": {
-                "cookies": "0.8.0",
-                "debug": "3.2.7",
-                "on-headers": "~1.0.2",
-                "safe-buffer": "5.2.1"
-            },
-            "engines": {
-                "node": ">= 0.10"
-            }
-        },
-        "node_modules/cookie-session/node_modules/debug": {
-            "version": "3.2.7",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
-            "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
-            "dependencies": {
-                "ms": "^2.1.1"
-            }
-        },
-        "node_modules/cookie-session/node_modules/safe-buffer": {
-            "version": "5.2.1",
-            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-            "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ]
-        },
-        "node_modules/cookie-signature": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
-            "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
-        },
-        "node_modules/cookies": {
-            "version": "0.8.0",
-            "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz",
-            "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==",
-            "dependencies": {
-                "depd": "~2.0.0",
-                "keygrip": "~1.1.0"
-            },
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/copy-concurrently": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
-            "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
-            "dev": true,
-            "dependencies": {
-                "aproba": "^1.1.1",
-                "fs-write-stream-atomic": "^1.0.8",
-                "iferr": "^0.1.5",
-                "mkdirp": "^0.5.1",
-                "rimraf": "^2.5.4",
-                "run-queue": "^1.0.0"
-            }
-        },
-        "node_modules/copy-concurrently/node_modules/aproba": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-            "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
-            "dev": true
-        },
-        "node_modules/copy-concurrently/node_modules/rimraf": {
-            "version": "2.7.1",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-            "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-            "dev": true,
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            }
-        },
-        "node_modules/copy-descriptor": {
-            "version": "0.1.1",
-            "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
-            "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/copy-webpack-plugin": {
-            "version": "4.6.0",
-            "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz",
-            "integrity": "sha512-Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==",
-            "dev": true,
-            "dependencies": {
-                "cacache": "^10.0.4",
-                "find-cache-dir": "^1.0.0",
-                "globby": "^7.1.1",
-                "is-glob": "^4.0.0",
-                "loader-utils": "^1.1.0",
-                "minimatch": "^3.0.4",
-                "p-limit": "^1.0.0",
-                "serialize-javascript": "^1.4.0"
-            },
-            "engines": {
-                "node": ">= 4"
-            }
-        },
-        "node_modules/copy-webpack-plugin/node_modules/p-limit": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
-            "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
-            "dev": true,
-            "dependencies": {
-                "p-try": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/copy-webpack-plugin/node_modules/p-try": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
-            "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/copy-webpack-plugin/node_modules/serialize-javascript": {
-            "version": "1.9.1",
-            "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz",
-            "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==",
-            "dev": true
-        },
-        "node_modules/core-js": {
-            "version": "1.2.7",
-            "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
-            "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=",
-            "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js."
-        },
-        "node_modules/core-js-pure": {
-            "version": "3.22.8",
-            "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.22.8.tgz",
-            "integrity": "sha512-bOxbZIy9S5n4OVH63XaLVXZ49QKicjowDx/UELyJ68vxfCRpYsbyh/WNZNfEfAk+ekA8vSjt+gCDpvh672bc3w==",
-            "deprecated": "core-js-pure@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js-pure.",
-            "hasInstallScript": true,
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/core-js"
-            }
-        },
-        "node_modules/core-util-is": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
-            "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
-        },
-        "node_modules/cors": {
-            "version": "2.8.5",
-            "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
-            "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
-            "dependencies": {
-                "object-assign": "^4",
-                "vary": "^1"
-            },
-            "engines": {
-                "node": ">= 0.10"
-            }
-        },
-        "node_modules/cosmiconfig": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
-            "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
-            "dependencies": {
-                "@types/parse-json": "^4.0.0",
-                "import-fresh": "^3.1.0",
-                "parse-json": "^5.0.0",
-                "path-type": "^4.0.0",
-                "yaml": "^1.7.2"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/crc": {
-            "version": "3.8.0",
-            "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz",
-            "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==",
-            "dependencies": {
-                "buffer": "^5.1.0"
-            }
-        },
-        "node_modules/crc32-stream": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-3.0.1.tgz",
-            "integrity": "sha512-mctvpXlbzsvK+6z8kJwSJ5crm7yBwrQMTybJzMw1O4lLGJqjlDCXY2Zw7KheiA6XBEcBmfLx1D88mjRGVJtY9w==",
-            "dependencies": {
-                "crc": "^3.4.4",
-                "readable-stream": "^3.4.0"
-            },
-            "engines": {
-                "node": ">= 6.9.0"
-            }
-        },
-        "node_modules/create-emotion": {
-            "version": "10.0.27",
-            "resolved": "https://registry.npmjs.org/create-emotion/-/create-emotion-10.0.27.tgz",
-            "integrity": "sha512-fIK73w82HPPn/RsAij7+Zt8eCE8SptcJ3WoRMfxMtjteYxud8GDTKKld7MYwAX2TVhrw29uR1N/bVGxeStHILg==",
-            "dependencies": {
-                "@emotion/cache": "^10.0.27",
-                "@emotion/serialize": "^0.11.15",
-                "@emotion/sheet": "0.9.4",
-                "@emotion/utils": "0.11.3"
-            }
-        },
-        "node_modules/create-error-class": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
-            "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=",
-            "dependencies": {
-                "capture-stack-trace": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/create-react-context": {
-            "version": "0.2.3",
-            "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.2.3.tgz",
-            "integrity": "sha512-CQBmD0+QGgTaxDL3OX1IDXYqjkp2It4RIbcb99jS6AEg27Ga+a9G3JtK6SIu0HBwPLZlmwt9F7UwWA4Bn92Rag==",
-            "dependencies": {
-                "fbjs": "^0.8.0",
-                "gud": "^1.0.0"
-            },
-            "peerDependencies": {
-                "prop-types": "^15.0.0",
-                "react": "^0.14.0 || ^15.0.0 || ^16.0.0"
-            }
-        },
-        "node_modules/create-require": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
-            "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
-            "dev": true
-        },
-        "node_modules/cross-env": {
-            "version": "5.2.1",
-            "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.1.tgz",
-            "integrity": "sha512-1yHhtcfAd1r4nwQgknowuUNfIT9E8dOMMspC36g45dN+iD1blloi7xp8X/xAIDnjHWyt1uQ8PHk2fkNaym7soQ==",
-            "dev": true,
-            "dependencies": {
-                "cross-spawn": "^6.0.5"
-            },
-            "bin": {
-                "cross-env": "dist/bin/cross-env.js",
-                "cross-env-shell": "dist/bin/cross-env-shell.js"
-            },
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/cross-env/node_modules/cross-spawn": {
-            "version": "6.0.5",
-            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
-            "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
-            "dev": true,
-            "dependencies": {
-                "nice-try": "^1.0.4",
-                "path-key": "^2.0.1",
-                "semver": "^5.5.0",
-                "shebang-command": "^1.2.0",
-                "which": "^1.2.9"
-            },
-            "engines": {
-                "node": ">=4.8"
-            }
-        },
-        "node_modules/cross-fetch": {
-            "version": "3.1.5",
-            "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
-            "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
-            "dependencies": {
-                "node-fetch": "2.6.7"
-            }
-        },
-        "node_modules/cross-fetch/node_modules/node-fetch": {
-            "version": "2.6.7",
-            "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
-            "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
-            "dependencies": {
-                "whatwg-url": "^5.0.0"
-            },
-            "engines": {
-                "node": "4.x || >=6.0.0"
-            },
-            "peerDependencies": {
-                "encoding": "^0.1.0"
-            },
-            "peerDependenciesMeta": {
-                "encoding": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/cross-spawn": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
-            "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
-            "dependencies": {
-                "lru-cache": "^4.0.1",
-                "which": "^1.2.9"
-            }
-        },
-        "node_modules/cross-spawn/node_modules/lru-cache": {
-            "version": "4.1.5",
-            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
-            "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
-            "dependencies": {
-                "pseudomap": "^1.0.2",
-                "yallist": "^2.1.2"
-            }
-        },
-        "node_modules/cross-spawn/node_modules/yallist": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
-            "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
-        },
-        "node_modules/crypto-js": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.3.0.tgz",
-            "integrity": "sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q=="
-        },
-        "node_modules/crypto-random-string": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
-            "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/css-box-model": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
-            "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==",
-            "dependencies": {
-                "tiny-invariant": "^1.0.6"
-            }
-        },
-        "node_modules/css-color-keywords": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
-            "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/css-in-js-utils": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz",
-            "integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==",
-            "dependencies": {
-                "hyphenate-style-name": "^1.0.2",
-                "isobject": "^3.0.1"
-            }
-        },
-        "node_modules/css-loader": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.1.tgz",
-            "integrity": "sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w==",
-            "dev": true,
-            "dependencies": {
-                "camelcase": "^5.2.0",
-                "icss-utils": "^4.1.0",
-                "loader-utils": "^1.2.3",
-                "normalize-path": "^3.0.0",
-                "postcss": "^7.0.14",
-                "postcss-modules-extract-imports": "^2.0.0",
-                "postcss-modules-local-by-default": "^2.0.6",
-                "postcss-modules-scope": "^2.1.0",
-                "postcss-modules-values": "^2.0.0",
-                "postcss-value-parser": "^3.3.0",
-                "schema-utils": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 6.9.0"
-            },
-            "peerDependencies": {
-                "webpack": "^4.0.0"
-            }
-        },
-        "node_modules/css-select": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
-            "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
-            "dependencies": {
-                "boolbase": "^1.0.0",
-                "css-what": "^6.0.1",
-                "domhandler": "^4.3.1",
-                "domutils": "^2.8.0",
-                "nth-check": "^2.0.1"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/fb55"
-            }
-        },
-        "node_modules/css-select/node_modules/dom-serializer": {
-            "version": "1.4.1",
-            "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
-            "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
-            "dependencies": {
-                "domelementtype": "^2.0.1",
-                "domhandler": "^4.2.0",
-                "entities": "^2.0.0"
-            },
-            "funding": {
-                "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
-            }
-        },
-        "node_modules/css-select/node_modules/domelementtype": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
-            "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/fb55"
-                }
-            ]
-        },
-        "node_modules/css-select/node_modules/domhandler": {
-            "version": "4.3.1",
-            "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
-            "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
-            "dependencies": {
-                "domelementtype": "^2.2.0"
-            },
-            "engines": {
-                "node": ">= 4"
-            },
-            "funding": {
-                "url": "https://github.com/fb55/domhandler?sponsor=1"
-            }
-        },
-        "node_modules/css-select/node_modules/domutils": {
-            "version": "2.8.0",
-            "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
-            "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
-            "dependencies": {
-                "dom-serializer": "^1.0.1",
-                "domelementtype": "^2.2.0",
-                "domhandler": "^4.2.0"
-            },
-            "funding": {
-                "url": "https://github.com/fb55/domutils?sponsor=1"
-            }
-        },
-        "node_modules/css-select/node_modules/entities": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
-            "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
-            "funding": {
-                "url": "https://github.com/fb55/entities?sponsor=1"
-            }
-        },
-        "node_modules/css-to-react-native": {
-            "version": "2.3.2",
-            "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-2.3.2.tgz",
-            "integrity": "sha512-VOFaeZA053BqvvvqIA8c9n0+9vFppVBAHCp6JgFTtTMU3Mzi+XnelJ9XC9ul3BqFzZyQ5N+H0SnwsWT2Ebchxw==",
-            "dependencies": {
-                "camelize": "^1.0.0",
-                "css-color-keywords": "^1.0.0",
-                "postcss-value-parser": "^3.3.0"
-            }
-        },
-        "node_modules/css-vendor": {
-            "version": "2.0.8",
-            "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz",
-            "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==",
-            "dependencies": {
-                "@babel/runtime": "^7.8.3",
-                "is-in-browser": "^1.0.2"
-            }
-        },
-        "node_modules/css-what": {
-            "version": "6.1.0",
-            "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
-            "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
-            "engines": {
-                "node": ">= 6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/fb55"
-            }
-        },
-        "node_modules/cssesc": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
-            "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
-            "dev": true,
-            "bin": {
-                "cssesc": "bin/cssesc"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/cssom": {
-            "version": "0.4.4",
-            "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz",
-            "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==",
-            "dev": true
-        },
-        "node_modules/cssstyle": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz",
-            "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==",
-            "dev": true,
-            "dependencies": {
-                "cssom": "~0.3.6"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/cssstyle/node_modules/cssom": {
-            "version": "0.3.8",
-            "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
-            "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==",
-            "dev": true
-        },
-        "node_modules/csstype": {
-            "version": "2.6.20",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz",
-            "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA=="
-        },
-        "node_modules/currently-unhandled": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
-            "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
-            "dependencies": {
-                "array-find-index": "^1.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/custom-event": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz",
-            "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg=="
-        },
-        "node_modules/cyclist": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
-            "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
-            "dev": true
-        },
-        "node_modules/D": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/D/-/D-1.0.0.tgz",
-            "integrity": "sha512-nQvrCBu7K2pSSEtIM0EEF03FVjcczCXInMt3moLNFbjlWx6bZrX72uT6/1uAXDbnzGUAx9gTyDiQ+vrFi663oA==",
-            "deprecated": "Package no longer supported. Contact support@npmjs.com for more info."
-        },
-        "node_modules/d3-array": {
-            "version": "2.12.1",
-            "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
-            "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
-            "dependencies": {
-                "internmap": "^1.0.0"
-            }
-        },
-        "node_modules/d3-axis": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-2.1.0.tgz",
-            "integrity": "sha512-z/G2TQMyuf0X3qP+Mh+2PimoJD41VOCjViJzT0BHeL/+JQAofkiWZbWxlwFGb1N8EN+Cl/CW+MUKbVzr1689Cw=="
-        },
-        "node_modules/d3-color": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz",
-            "integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ=="
-        },
-        "node_modules/d3-dispatch": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz",
-            "integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA=="
-        },
-        "node_modules/d3-drag": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-2.0.0.tgz",
-            "integrity": "sha512-g9y9WbMnF5uqB9qKqwIIa/921RYWzlUDv9Jl1/yONQwxbOfszAWTCm8u7HOTgJgRDXiRZN56cHT9pd24dmXs8w==",
-            "dependencies": {
-                "d3-dispatch": "1 - 2",
-                "d3-selection": "2"
-            }
-        },
-        "node_modules/d3-ease": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-2.0.0.tgz",
-            "integrity": "sha512-68/n9JWarxXkOWMshcT5IcjbB+agblQUaIsbnXmrzejn2O82n3p2A9R2zEB9HIEFWKFwPAEDDN8gR0VdSAyyAQ=="
-        },
-        "node_modules/d3-format": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz",
-            "integrity": "sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA=="
-        },
-        "node_modules/d3-interpolate": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz",
-            "integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==",
-            "dependencies": {
-                "d3-color": "1 - 2"
-            }
-        },
-        "node_modules/d3-path": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-2.0.0.tgz",
-            "integrity": "sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA=="
-        },
-        "node_modules/d3-scale": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.3.0.tgz",
-            "integrity": "sha512-1JGp44NQCt5d1g+Yy+GeOnZP7xHo0ii8zsQp6PGzd+C1/dl0KGsp9A7Mxwp+1D1o4unbTTxVdU/ZOIEBoeZPbQ==",
-            "dependencies": {
-                "d3-array": "^2.3.0",
-                "d3-format": "1 - 2",
-                "d3-interpolate": "1.2.0 - 2",
-                "d3-time": "^2.1.1",
-                "d3-time-format": "2 - 3"
-            }
-        },
-        "node_modules/d3-selection": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-2.0.0.tgz",
-            "integrity": "sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA=="
-        },
-        "node_modules/d3-shape": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-2.1.0.tgz",
-            "integrity": "sha512-PnjUqfM2PpskbSLTJvAzp2Wv4CZsnAgTfcVRTwW03QR3MkXF8Uo7B1y/lWkAsmbKwuecto++4NlsYcvYpXpTHA==",
-            "dependencies": {
-                "d3-path": "1 - 2"
-            }
-        },
-        "node_modules/d3-time": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.1.1.tgz",
-            "integrity": "sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==",
-            "dependencies": {
-                "d3-array": "2"
-            }
-        },
-        "node_modules/d3-time-format": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz",
-            "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==",
-            "dependencies": {
-                "d3-time": "1 - 2"
-            }
-        },
-        "node_modules/d3-timer": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-2.0.0.tgz",
-            "integrity": "sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA=="
-        },
-        "node_modules/d3-transition": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-2.0.0.tgz",
-            "integrity": "sha512-42ltAGgJesfQE3u9LuuBHNbGrI/AJjNL2OAUdclE70UE6Vy239GCBEYD38uBPoLeNsOhFStGpPI0BAOV+HMxog==",
-            "dependencies": {
-                "d3-color": "1 - 2",
-                "d3-dispatch": "1 - 2",
-                "d3-ease": "1 - 2",
-                "d3-interpolate": "1 - 2",
-                "d3-timer": "1 - 2"
-            },
-            "peerDependencies": {
-                "d3-selection": "2"
-            }
-        },
-        "node_modules/d3-zoom": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-2.0.0.tgz",
-            "integrity": "sha512-fFg7aoaEm9/jf+qfstak0IYpnesZLiMX6GZvXtUSdv8RH2o4E2qeelgdU09eKS6wGuiGMfcnMI0nTIqWzRHGpw==",
-            "dependencies": {
-                "d3-dispatch": "1 - 2",
-                "d3-drag": "2",
-                "d3-interpolate": "1 - 2",
-                "d3-selection": "2",
-                "d3-transition": "2"
-            }
-        },
-        "node_modules/damerau-levenshtein": {
-            "version": "1.0.8",
-            "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
-            "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
-            "dev": true
-        },
-        "node_modules/dashdash": {
-            "version": "1.14.1",
-            "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
-            "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
-            "dependencies": {
-                "assert-plus": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10"
-            }
-        },
-        "node_modules/data-urls": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz",
-            "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==",
-            "dev": true,
-            "dependencies": {
-                "abab": "^2.0.0",
-                "whatwg-mimetype": "^2.2.0",
-                "whatwg-url": "^7.0.0"
-            }
-        },
-        "node_modules/data-urls/node_modules/tr46": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
-            "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
-            "dev": true,
-            "dependencies": {
-                "punycode": "^2.1.0"
-            }
-        },
-        "node_modules/data-urls/node_modules/webidl-conversions": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
-            "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
-            "dev": true
-        },
-        "node_modules/data-urls/node_modules/whatwg-url": {
-            "version": "7.1.0",
-            "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
-            "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
-            "dev": true,
-            "dependencies": {
-                "lodash.sortby": "^4.7.0",
-                "tr46": "^1.0.1",
-                "webidl-conversions": "^4.0.2"
-            }
-        },
-        "node_modules/date-fns": {
-            "version": "2.28.0",
-            "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz",
-            "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==",
-            "engines": {
-                "node": ">=0.11"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/date-fns"
-            }
-        },
-        "node_modules/de-indent": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
-            "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0="
-        },
-        "node_modules/debounce": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
-            "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug=="
-        },
-        "node_modules/debug": {
-            "version": "3.2.6",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
-            "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
-            "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
-            "dependencies": {
-                "ms": "^2.1.1"
-            }
-        },
-        "node_modules/decamelize": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
-            "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/decode-named-character-reference": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz",
-            "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==",
-            "dependencies": {
-                "character-entities": "^2.0.0"
-            },
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/wooorm"
-            }
-        },
-        "node_modules/decode-uri-component": {
-            "version": "0.2.0",
-            "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
-            "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
-            "engines": {
-                "node": ">=0.10"
-            }
-        },
-        "node_modules/decompress-response": {
-            "version": "4.2.1",
-            "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
-            "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
-            "dependencies": {
-                "mimic-response": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/deep-eql": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
-            "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
-            "dependencies": {
-                "type-detect": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=0.12"
-            }
-        },
-        "node_modules/deep-equal": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
-            "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
-            "dependencies": {
-                "is-arguments": "^1.0.4",
-                "is-date-object": "^1.0.1",
-                "is-regex": "^1.0.4",
-                "object-is": "^1.0.1",
-                "object-keys": "^1.1.1",
-                "regexp.prototype.flags": "^1.2.0"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/deep-extend": {
-            "version": "0.6.0",
-            "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
-            "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/deep-is": {
-            "version": "0.1.4",
-            "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
-            "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
-            "dev": true
-        },
-        "node_modules/deepmerge": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz",
-            "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/default-gateway": {
-            "version": "4.2.0",
-            "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz",
-            "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==",
-            "dev": true,
-            "dependencies": {
-                "execa": "^1.0.0",
-                "ip-regex": "^2.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/default-gateway/node_modules/cross-spawn": {
-            "version": "6.0.5",
-            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
-            "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
-            "dev": true,
-            "dependencies": {
-                "nice-try": "^1.0.4",
-                "path-key": "^2.0.1",
-                "semver": "^5.5.0",
-                "shebang-command": "^1.2.0",
-                "which": "^1.2.9"
-            },
-            "engines": {
-                "node": ">=4.8"
-            }
-        },
-        "node_modules/default-gateway/node_modules/execa": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
-            "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
-            "dev": true,
-            "dependencies": {
-                "cross-spawn": "^6.0.0",
-                "get-stream": "^4.0.0",
-                "is-stream": "^1.1.0",
-                "npm-run-path": "^2.0.0",
-                "p-finally": "^1.0.0",
-                "signal-exit": "^3.0.0",
-                "strip-eof": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/default-gateway/node_modules/get-stream": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
-            "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
-            "dev": true,
-            "dependencies": {
-                "pump": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/defer-to-connect": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
-            "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/define-properties": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
-            "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
-            "dependencies": {
-                "has-property-descriptors": "^1.0.0",
-                "object-keys": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/define-property": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
-            "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
-            "dependencies": {
-                "is-descriptor": "^1.0.2",
-                "isobject": "^3.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/define-property/node_modules/is-accessor-descriptor": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-            "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-            "dependencies": {
-                "kind-of": "^6.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/define-property/node_modules/is-data-descriptor": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-            "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-            "dependencies": {
-                "kind-of": "^6.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/define-property/node_modules/is-descriptor": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-            "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-            "dependencies": {
-                "is-accessor-descriptor": "^1.0.0",
-                "is-data-descriptor": "^1.0.0",
-                "kind-of": "^6.0.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/del": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz",
-            "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/glob": "^7.1.1",
-                "globby": "^6.1.0",
-                "is-path-cwd": "^2.0.0",
-                "is-path-in-cwd": "^2.0.0",
-                "p-map": "^2.0.0",
-                "pify": "^4.0.1",
-                "rimraf": "^2.6.3"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/del/node_modules/globby": {
-            "version": "6.1.0",
-            "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
-            "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
-            "dev": true,
-            "dependencies": {
-                "array-union": "^1.0.1",
-                "glob": "^7.0.3",
-                "object-assign": "^4.0.1",
-                "pify": "^2.0.0",
-                "pinkie-promise": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/del/node_modules/globby/node_modules/pify": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-            "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/del/node_modules/pify": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
-            "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/del/node_modules/rimraf": {
-            "version": "2.7.1",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-            "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-            "dev": true,
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            }
-        },
-        "node_modules/delayed-stream": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-            "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/delegate": {
-            "version": "3.2.0",
-            "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
-            "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
-        },
-        "node_modules/delegates": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
-            "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
-        },
-        "node_modules/denque": {
-            "version": "1.5.1",
-            "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz",
-            "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==",
-            "engines": {
-                "node": ">=0.10"
-            }
-        },
-        "node_modules/depcheck": {
-            "version": "0.9.2",
-            "resolved": "https://registry.npmjs.org/depcheck/-/depcheck-0.9.2.tgz",
-            "integrity": "sha512-w5f+lSZqLJJkk58s44eOd0Vor7hLZot4PlFL0y2JsIX5LuHQ2eAjHlDVeGBD4Mj6ZQSKakvKWRRCcPlvrdU2Sg==",
-            "dependencies": {
-                "@babel/parser": "^7.7.7",
-                "@babel/traverse": "^7.7.4",
-                "builtin-modules": "^3.0.0",
-                "camelcase": "^5.3.1",
-                "cosmiconfig": "^5.2.1",
-                "debug": "^4.1.1",
-                "deps-regex": "^0.1.4",
-                "js-yaml": "^3.4.2",
-                "lodash": "^4.17.15",
-                "minimatch": "^3.0.2",
-                "node-sass-tilde-importer": "^1.0.2",
-                "please-upgrade-node": "^3.2.0",
-                "require-package-name": "^2.0.1",
-                "resolve": "^1.14.1",
-                "vue-template-compiler": "^2.6.11",
-                "walkdir": "^0.4.1",
-                "yargs": "^15.0.2"
-            },
-            "bin": {
-                "depcheck": "bin/depcheck.js"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/depcheck/node_modules/ansi-regex": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/depcheck/node_modules/ansi-styles": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-            "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-            "dependencies": {
-                "color-convert": "^2.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-            }
-        },
-        "node_modules/depcheck/node_modules/cliui": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
-            "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
-            "dependencies": {
-                "string-width": "^4.2.0",
-                "strip-ansi": "^6.0.0",
-                "wrap-ansi": "^6.2.0"
-            }
-        },
-        "node_modules/depcheck/node_modules/color-convert": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-            "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-            "dependencies": {
-                "color-name": "~1.1.4"
-            },
-            "engines": {
-                "node": ">=7.0.0"
-            }
-        },
-        "node_modules/depcheck/node_modules/color-name": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-            "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
-        },
-        "node_modules/depcheck/node_modules/cosmiconfig": {
-            "version": "5.2.1",
-            "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
-            "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
-            "dependencies": {
-                "import-fresh": "^2.0.0",
-                "is-directory": "^0.3.1",
-                "js-yaml": "^3.13.1",
-                "parse-json": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/depcheck/node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/depcheck/node_modules/emoji-regex": {
-            "version": "8.0.0",
-            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
-        },
-        "node_modules/depcheck/node_modules/find-up": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
-            "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
-            "dependencies": {
-                "locate-path": "^5.0.0",
-                "path-exists": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/depcheck/node_modules/import-fresh": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
-            "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
-            "dependencies": {
-                "caller-path": "^2.0.0",
-                "resolve-from": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/depcheck/node_modules/is-fullwidth-code-point": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-            "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/depcheck/node_modules/locate-path": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
-            "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
-            "dependencies": {
-                "p-locate": "^4.1.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/depcheck/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
-        },
-        "node_modules/depcheck/node_modules/p-locate": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
-            "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
-            "dependencies": {
-                "p-limit": "^2.2.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/depcheck/node_modules/parse-json": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
-            "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
-            "dependencies": {
-                "error-ex": "^1.3.1",
-                "json-parse-better-errors": "^1.0.1"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/depcheck/node_modules/path-exists": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
-            "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/depcheck/node_modules/resolve-from": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
-            "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/depcheck/node_modules/string-width": {
-            "version": "4.2.3",
-            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-            "dependencies": {
-                "emoji-regex": "^8.0.0",
-                "is-fullwidth-code-point": "^3.0.0",
-                "strip-ansi": "^6.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/depcheck/node_modules/strip-ansi": {
-            "version": "6.0.1",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-            "dependencies": {
-                "ansi-regex": "^5.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/depcheck/node_modules/wrap-ansi": {
-            "version": "6.2.0",
-            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
-            "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
-            "dependencies": {
-                "ansi-styles": "^4.0.0",
-                "string-width": "^4.1.0",
-                "strip-ansi": "^6.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/depcheck/node_modules/yargs": {
-            "version": "15.4.1",
-            "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
-            "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
-            "dependencies": {
-                "cliui": "^6.0.0",
-                "decamelize": "^1.2.0",
-                "find-up": "^4.1.0",
-                "get-caller-file": "^2.0.1",
-                "require-directory": "^2.1.1",
-                "require-main-filename": "^2.0.0",
-                "set-blocking": "^2.0.0",
-                "string-width": "^4.2.0",
-                "which-module": "^2.0.0",
-                "y18n": "^4.0.0",
-                "yargs-parser": "^18.1.2"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/depcheck/node_modules/yargs-parser": {
-            "version": "18.1.3",
-            "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
-            "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
-            "dependencies": {
-                "camelcase": "^5.0.0",
-                "decamelize": "^1.2.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/depd": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
-            "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/deprecation": {
-            "version": "2.3.1",
-            "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
-            "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
-        },
-        "node_modules/deps-regex": {
-            "version": "0.1.4",
-            "resolved": "https://registry.npmjs.org/deps-regex/-/deps-regex-0.1.4.tgz",
-            "integrity": "sha1-UYZnt2kUYKXn4KNBvnbrfOgJAYQ="
-        },
-        "node_modules/dequal": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
-            "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/destroy": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
-            "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
-            "engines": {
-                "node": ">= 0.8",
-                "npm": "1.2.8000 || >= 1.4.16"
-            }
-        },
-        "node_modules/detect-libc": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
-            "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/detect-node": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
-            "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
-            "dev": true
-        },
-        "node_modules/diff": {
-            "version": "3.5.0",
-            "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
-            "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
-            "engines": {
-                "node": ">=0.3.1"
-            }
-        },
-        "node_modules/diff-match-patch": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz",
-            "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw=="
-        },
-        "node_modules/dir-glob": {
-            "version": "2.2.2",
-            "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
-            "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==",
-            "dev": true,
-            "dependencies": {
-                "path-type": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/dir-glob/node_modules/path-type": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
-            "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
-            "dev": true,
-            "dependencies": {
-                "pify": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/dir-glob/node_modules/pify": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-            "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/dns-equal": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
-            "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
-            "dev": true
-        },
-        "node_modules/dns-packet": {
-            "version": "1.3.4",
-            "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz",
-            "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==",
-            "dev": true,
-            "dependencies": {
-                "ip": "^1.1.0",
-                "safe-buffer": "^5.0.1"
-            }
-        },
-        "node_modules/dns-txt": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
-            "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
-            "dev": true,
-            "dependencies": {
-                "buffer-indexof": "^1.0.0"
-            }
-        },
-        "node_modules/doctrine": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
-            "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
-            "dev": true,
-            "dependencies": {
-                "esutils": "^2.0.2"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/doctypes": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz",
-            "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk="
-        },
-        "node_modules/dom-converter": {
-            "version": "0.2.0",
-            "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
-            "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==",
-            "dependencies": {
-                "utila": "~0.4"
-            }
-        },
-        "node_modules/dom-helpers": {
-            "version": "3.4.0",
-            "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
-            "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==",
-            "dependencies": {
-                "@babel/runtime": "^7.1.2"
-            }
-        },
-        "node_modules/dom-serializer": {
-            "version": "0.2.2",
-            "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
-            "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
-            "dependencies": {
-                "domelementtype": "^2.0.1",
-                "entities": "^2.0.0"
-            }
-        },
-        "node_modules/dom-serializer/node_modules/domelementtype": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
-            "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/fb55"
-                }
-            ]
-        },
-        "node_modules/dom-serializer/node_modules/entities": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
-            "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
-            "funding": {
-                "url": "https://github.com/fb55/entities?sponsor=1"
-            }
-        },
-        "node_modules/domelementtype": {
-            "version": "1.3.1",
-            "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
-            "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
-        },
-        "node_modules/domexception": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz",
-            "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==",
-            "dev": true,
-            "dependencies": {
-                "webidl-conversions": "^4.0.2"
-            }
-        },
-        "node_modules/domexception/node_modules/webidl-conversions": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
-            "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
-            "dev": true
-        },
-        "node_modules/domhandler": {
-            "version": "2.4.2",
-            "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
-            "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
-            "dependencies": {
-                "domelementtype": "1"
-            }
-        },
-        "node_modules/dommatrix": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/dommatrix/-/dommatrix-1.0.3.tgz",
-            "integrity": "sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww=="
-        },
-        "node_modules/domutils": {
-            "version": "1.7.0",
-            "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
-            "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
-            "dependencies": {
-                "dom-serializer": "0",
-                "domelementtype": "1"
-            }
-        },
-        "node_modules/dot-case": {
-            "version": "3.0.4",
-            "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
-            "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
-            "dependencies": {
-                "no-case": "^3.0.4",
-                "tslib": "^2.0.3"
-            }
-        },
-        "node_modules/dot-prop": {
-            "version": "4.2.1",
-            "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz",
-            "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==",
-            "dependencies": {
-                "is-obj": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/dotenv": {
-            "version": "8.6.0",
-            "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz",
-            "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==",
-            "dev": true,
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/double-bits": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/double-bits/-/double-bits-1.1.1.tgz",
-            "integrity": "sha1-WKu6RUlNpND6Nrc60RoobJGEscY="
-        },
-        "node_modules/duplexer3": {
-            "version": "0.1.4",
-            "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
-            "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
-        },
-        "node_modules/duplexify": {
-            "version": "3.7.1",
-            "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
-            "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
-            "dev": true,
-            "dependencies": {
-                "end-of-stream": "^1.0.0",
-                "inherits": "^2.0.1",
-                "readable-stream": "^2.0.0",
-                "stream-shift": "^1.0.0"
-            }
-        },
-        "node_modules/duplexify/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dev": true,
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/dynamic-dedupe": {
-            "version": "0.3.0",
-            "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
-            "integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=",
-            "dev": true,
-            "dependencies": {
-                "xtend": "^4.0.0"
-            }
-        },
-        "node_modules/ecc-jsbn": {
-            "version": "0.1.2",
-            "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
-            "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
-            "dependencies": {
-                "jsbn": "~0.1.0",
-                "safer-buffer": "^2.1.0"
-            }
-        },
-        "node_modules/ecdsa-sig-formatter": {
-            "version": "1.0.11",
-            "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
-            "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
-            "dependencies": {
-                "safe-buffer": "^5.0.1"
-            }
-        },
-        "node_modules/ee-first": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-            "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
-        },
-        "node_modules/electron-to-chromium": {
-            "version": "1.4.149",
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.149.tgz",
-            "integrity": "sha512-SR6ZQ8gfXX7LIS3UTDXu1CbFMUnluP3TS+jP7QwDwOnoH5CcHbejFdaaaEnGxR6I76E55eFnUV9mxI8GKufkEg=="
-        },
-        "node_modules/emoji-regex": {
-            "version": "7.0.3",
-            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
-            "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
-        },
-        "node_modules/emojis-list": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
-            "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
-            "engines": {
-                "node": ">= 4"
-            }
-        },
-        "node_modules/emotion": {
-            "version": "10.0.27",
-            "resolved": "https://registry.npmjs.org/emotion/-/emotion-10.0.27.tgz",
-            "integrity": "sha512-2xdDzdWWzue8R8lu4G76uWX5WhyQuzATon9LmNeCy/2BHVC6dsEpfhN1a0qhELgtDVdjyEA6J8Y/VlI5ZnaH0g==",
-            "dependencies": {
-                "babel-plugin-emotion": "^10.0.27",
-                "create-emotion": "^10.0.27"
-            }
-        },
-        "node_modules/encodeurl": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
-            "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/encoding": {
-            "version": "0.1.13",
-            "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
-            "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
-            "dependencies": {
-                "iconv-lite": "^0.6.2"
-            }
-        },
-        "node_modules/end-of-stream": {
-            "version": "1.4.4",
-            "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
-            "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
-            "dependencies": {
-                "once": "^1.4.0"
-            }
-        },
-        "node_modules/engine.io": {
-            "version": "3.6.0",
-            "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.6.0.tgz",
-            "integrity": "sha512-Kc8fo5bbg8F4a2f3HPHTEpGyq/IRIQpyeHu3H1ThR14XDD7VrLcsGBo16HUpahgp8YkHJDaU5gNxJZbuGcuueg==",
-            "dependencies": {
-                "accepts": "~1.3.4",
-                "base64id": "2.0.0",
-                "cookie": "~0.4.1",
-                "debug": "~4.1.0",
-                "engine.io-parser": "~2.2.0",
-                "ws": "~7.4.2"
-            },
-            "engines": {
-                "node": ">=8.0.0"
-            }
-        },
-        "node_modules/engine.io-client": {
-            "version": "3.5.2",
-            "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.2.tgz",
-            "integrity": "sha512-QEqIp+gJ/kMHeUun7f5Vv3bteRHppHH/FMBQX/esFj/fuYfjyUKWGMo3VCvIP/V8bE9KcjHmRZrhIz2Z9oNsDA==",
-            "dependencies": {
-                "component-emitter": "~1.3.0",
-                "component-inherit": "0.0.3",
-                "debug": "~3.1.0",
-                "engine.io-parser": "~2.2.0",
-                "has-cors": "1.1.0",
-                "indexof": "0.0.1",
-                "parseqs": "0.0.6",
-                "parseuri": "0.0.6",
-                "ws": "~7.4.2",
-                "xmlhttprequest-ssl": "~1.6.2",
-                "yeast": "0.1.2"
-            }
-        },
-        "node_modules/engine.io-client/node_modules/debug": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-            "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/engine.io-client/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
-        },
-        "node_modules/engine.io-client/node_modules/ws": {
-            "version": "7.4.6",
-            "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
-            "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
-            "engines": {
-                "node": ">=8.3.0"
-            },
-            "peerDependencies": {
-                "bufferutil": "^4.0.1",
-                "utf-8-validate": "^5.0.2"
-            },
-            "peerDependenciesMeta": {
-                "bufferutil": {
-                    "optional": true
-                },
-                "utf-8-validate": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/engine.io-parser": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz",
-            "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==",
-            "dependencies": {
-                "after": "0.8.2",
-                "arraybuffer.slice": "~0.0.7",
-                "base64-arraybuffer": "0.1.4",
-                "blob": "0.0.5",
-                "has-binary2": "~1.0.2"
-            }
-        },
-        "node_modules/engine.io/node_modules/debug": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-            "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
-            "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
-            "dependencies": {
-                "ms": "^2.1.1"
-            }
-        },
-        "node_modules/engine.io/node_modules/ws": {
-            "version": "7.4.6",
-            "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
-            "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
-            "engines": {
-                "node": ">=8.3.0"
-            },
-            "peerDependencies": {
-                "bufferutil": "^4.0.1",
-                "utf-8-validate": "^5.0.2"
-            },
-            "peerDependenciesMeta": {
-                "bufferutil": {
-                    "optional": true
-                },
-                "utf-8-validate": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/enhanced-resolve": {
-            "version": "5.9.3",
-            "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz",
-            "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==",
-            "dependencies": {
-                "graceful-fs": "^4.2.4",
-                "tapable": "^2.2.0"
-            },
-            "engines": {
-                "node": ">=10.13.0"
-            }
-        },
-        "node_modules/entities": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
-            "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
-        },
-        "node_modules/envinfo": {
-            "version": "7.8.1",
-            "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz",
-            "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==",
-            "bin": {
-                "envinfo": "dist/cli.js"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/equation-editor-react": {
-            "version": "0.0.6",
-            "resolved": "git+ssh://git@github.com/bobzel/equation-editor-react.git#75915e852b4b36a6a4cd3e1cbc80598da6b65227",
-            "integrity": "sha512-ctU569x4psKy2sfv9GmNX1HMA9HMUZH8bzt0pku1fYyhx5MZ9E/GXlcB5svqvFo+ZeaySEe4+DdDwm5kVP4ySA==",
-            "license": "MIT",
-            "dependencies": {
-                "jquery": "^3.4.1",
-                "mathquill": "^0.10.1-a"
-            },
-            "peerDependencies": {
-                "react": "^16.0.0",
-                "react-dom": "^16.0.0"
-            }
-        },
-        "node_modules/errno": {
-            "version": "0.1.8",
-            "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
-            "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
-            "dev": true,
-            "dependencies": {
-                "prr": "~1.0.1"
-            },
-            "bin": {
-                "errno": "cli.js"
-            }
-        },
-        "node_modules/error-ex": {
-            "version": "1.3.2",
-            "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
-            "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
-            "dependencies": {
-                "is-arrayish": "^0.2.1"
-            }
-        },
-        "node_modules/es-abstract": {
-            "version": "1.20.1",
-            "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz",
-            "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "es-to-primitive": "^1.2.1",
-                "function-bind": "^1.1.1",
-                "function.prototype.name": "^1.1.5",
-                "get-intrinsic": "^1.1.1",
-                "get-symbol-description": "^1.0.0",
-                "has": "^1.0.3",
-                "has-property-descriptors": "^1.0.0",
-                "has-symbols": "^1.0.3",
-                "internal-slot": "^1.0.3",
-                "is-callable": "^1.2.4",
-                "is-negative-zero": "^2.0.2",
-                "is-regex": "^1.1.4",
-                "is-shared-array-buffer": "^1.0.2",
-                "is-string": "^1.0.7",
-                "is-weakref": "^1.0.2",
-                "object-inspect": "^1.12.0",
-                "object-keys": "^1.1.1",
-                "object.assign": "^4.1.2",
-                "regexp.prototype.flags": "^1.4.3",
-                "string.prototype.trimend": "^1.0.5",
-                "string.prototype.trimstart": "^1.0.5",
-                "unbox-primitive": "^1.0.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/es-abstract/node_modules/object.assign": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
-            "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
-            "dependencies": {
-                "call-bind": "^1.0.0",
-                "define-properties": "^1.1.3",
-                "has-symbols": "^1.0.1",
-                "object-keys": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/es-array-method-boxes-properly": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz",
-            "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA=="
-        },
-        "node_modules/es-module-lexer": {
-            "version": "0.9.3",
-            "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz",
-            "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ=="
-        },
-        "node_modules/es-shim-unscopables": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
-            "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
-            "dev": true,
-            "dependencies": {
-                "has": "^1.0.3"
-            }
-        },
-        "node_modules/es-to-primitive": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
-            "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
-            "dependencies": {
-                "is-callable": "^1.1.4",
-                "is-date-object": "^1.0.1",
-                "is-symbol": "^1.0.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/es6-promise": {
-            "version": "3.2.1",
-            "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz",
-            "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q="
-        },
-        "node_modules/es6-symbol": {
-            "version": "3.1.3",
-            "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
-            "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
-            "dev": true,
-            "dependencies": {
-                "d": "^1.0.1",
-                "ext": "^1.1.2"
-            }
-        },
-        "node_modules/escalade": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
-            "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/escape-html": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-            "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
-        },
-        "node_modules/escape-string-regexp": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-            "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
-            "engines": {
-                "node": ">=0.8.0"
-            }
-        },
-        "node_modules/escodegen": {
-            "version": "1.14.3",
-            "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
-            "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
-            "dev": true,
-            "dependencies": {
-                "esprima": "^4.0.1",
-                "estraverse": "^4.2.0",
-                "esutils": "^2.0.2",
-                "optionator": "^0.8.1"
-            },
-            "bin": {
-                "escodegen": "bin/escodegen.js",
-                "esgenerate": "bin/esgenerate.js"
-            },
-            "engines": {
-                "node": ">=4.0"
-            },
-            "optionalDependencies": {
-                "source-map": "~0.6.1"
-            }
-        },
-        "node_modules/escodegen/node_modules/source-map": {
-            "version": "0.6.1",
-            "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-            "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-            "dev": true,
-            "optional": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/eslint": {
-            "version": "8.19.0",
-            "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.19.0.tgz",
-            "integrity": "sha512-SXOPj3x9VKvPe81TjjUJCYlV4oJjQw68Uek+AM0X4p+33dj2HY5bpTZOgnQHcG2eAm1mtCU9uNMnJi7exU/kYw==",
-            "dev": true,
-            "dependencies": {
-                "@eslint/eslintrc": "^1.3.0",
-                "@humanwhocodes/config-array": "^0.9.2",
-                "ajv": "^6.10.0",
-                "chalk": "^4.0.0",
-                "cross-spawn": "^7.0.2",
-                "debug": "^4.3.2",
-                "doctrine": "^3.0.0",
-                "escape-string-regexp": "^4.0.0",
-                "eslint-scope": "^7.1.1",
-                "eslint-utils": "^3.0.0",
-                "eslint-visitor-keys": "^3.3.0",
-                "espree": "^9.3.2",
-                "esquery": "^1.4.0",
-                "esutils": "^2.0.2",
-                "fast-deep-equal": "^3.1.3",
-                "file-entry-cache": "^6.0.1",
-                "functional-red-black-tree": "^1.0.1",
-                "glob-parent": "^6.0.1",
-                "globals": "^13.15.0",
-                "ignore": "^5.2.0",
-                "import-fresh": "^3.0.0",
-                "imurmurhash": "^0.1.4",
-                "is-glob": "^4.0.0",
-                "js-yaml": "^4.1.0",
-                "json-stable-stringify-without-jsonify": "^1.0.1",
-                "levn": "^0.4.1",
-                "lodash.merge": "^4.6.2",
-                "minimatch": "^3.1.2",
-                "natural-compare": "^1.4.0",
-                "optionator": "^0.9.1",
-                "regexpp": "^3.2.0",
-                "strip-ansi": "^6.0.1",
-                "strip-json-comments": "^3.1.0",
-                "text-table": "^0.2.0",
-                "v8-compile-cache": "^2.0.3"
-            },
-            "bin": {
-                "eslint": "bin/eslint.js"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/eslint-config-airbnb": {
-            "version": "19.0.4",
-            "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz",
-            "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==",
-            "dev": true,
-            "dependencies": {
-                "eslint-config-airbnb-base": "^15.0.0",
-                "object.assign": "^4.1.2",
-                "object.entries": "^1.1.5"
-            },
-            "engines": {
-                "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "peerDependencies": {
-                "eslint": "^7.32.0 || ^8.2.0",
-                "eslint-plugin-import": "^2.25.3",
-                "eslint-plugin-jsx-a11y": "^6.5.1",
-                "eslint-plugin-react": "^7.28.0",
-                "eslint-plugin-react-hooks": "^4.3.0"
-            }
-        },
-        "node_modules/eslint-config-airbnb-base": {
-            "version": "15.0.0",
-            "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz",
-            "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==",
-            "dev": true,
-            "dependencies": {
-                "confusing-browser-globals": "^1.0.10",
-                "object.assign": "^4.1.2",
-                "object.entries": "^1.1.5",
-                "semver": "^6.3.0"
-            },
-            "engines": {
-                "node": "^10.12.0 || >=12.0.0"
-            },
-            "peerDependencies": {
-                "eslint": "^7.32.0 || ^8.2.0",
-                "eslint-plugin-import": "^2.25.2"
-            }
-        },
-        "node_modules/eslint-config-airbnb-base/node_modules/object.assign": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
-            "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.0",
-                "define-properties": "^1.1.3",
-                "has-symbols": "^1.0.1",
-                "object-keys": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/eslint-config-airbnb-base/node_modules/semver": {
-            "version": "6.3.0",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-            "dev": true,
-            "bin": {
-                "semver": "bin/semver.js"
-            }
-        },
-        "node_modules/eslint-config-airbnb/node_modules/object.assign": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
-            "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.0",
-                "define-properties": "^1.1.3",
-                "has-symbols": "^1.0.1",
-                "object-keys": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/eslint-config-esnext": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/eslint-config-esnext/-/eslint-config-esnext-4.1.0.tgz",
-            "integrity": "sha512-GhfVEXdqYKEIIj7j+Fw2SQdL9qyZMekgXfq6PyXM66cQw0B435ddjz3P3kxOBVihMRJ0xGYjosaveQz5Y6z0uA==",
-            "dev": true,
-            "dependencies": {
-                "babel-eslint": "^10.0.1",
-                "eslint": "^6.8.0",
-                "eslint-plugin-babel": "^5.2.1",
-                "eslint-plugin-import": "^2.14.0"
-            },
-            "peerDependencies": {
-                "eslint": "^6.0.0"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/acorn": {
-            "version": "7.4.1",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
-            "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
-            "dev": true,
-            "bin": {
-                "acorn": "bin/acorn"
-            },
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/ansi-regex": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
-            "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/cross-spawn": {
-            "version": "6.0.5",
-            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
-            "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
-            "dev": true,
-            "dependencies": {
-                "nice-try": "^1.0.4",
-                "path-key": "^2.0.1",
-                "semver": "^5.5.0",
-                "shebang-command": "^1.2.0",
-                "which": "^1.2.9"
-            },
-            "engines": {
-                "node": ">=4.8"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/cross-spawn/node_modules/semver": {
-            "version": "5.7.1",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-            "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-            "dev": true,
-            "bin": {
-                "semver": "bin/semver"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dev": true,
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/eslint": {
-            "version": "6.8.0",
-            "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz",
-            "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==",
-            "dev": true,
-            "dependencies": {
-                "@babel/code-frame": "^7.0.0",
-                "ajv": "^6.10.0",
-                "chalk": "^2.1.0",
-                "cross-spawn": "^6.0.5",
-                "debug": "^4.0.1",
-                "doctrine": "^3.0.0",
-                "eslint-scope": "^5.0.0",
-                "eslint-utils": "^1.4.3",
-                "eslint-visitor-keys": "^1.1.0",
-                "espree": "^6.1.2",
-                "esquery": "^1.0.1",
-                "esutils": "^2.0.2",
-                "file-entry-cache": "^5.0.1",
-                "functional-red-black-tree": "^1.0.1",
-                "glob-parent": "^5.0.0",
-                "globals": "^12.1.0",
-                "ignore": "^4.0.6",
-                "import-fresh": "^3.0.0",
-                "imurmurhash": "^0.1.4",
-                "inquirer": "^7.0.0",
-                "is-glob": "^4.0.0",
-                "js-yaml": "^3.13.1",
-                "json-stable-stringify-without-jsonify": "^1.0.1",
-                "levn": "^0.3.0",
-                "lodash": "^4.17.14",
-                "minimatch": "^3.0.4",
-                "mkdirp": "^0.5.1",
-                "natural-compare": "^1.4.0",
-                "optionator": "^0.8.3",
-                "progress": "^2.0.0",
-                "regexpp": "^2.0.1",
-                "semver": "^6.1.2",
-                "strip-ansi": "^5.2.0",
-                "strip-json-comments": "^3.0.1",
-                "table": "^5.2.3",
-                "text-table": "^0.2.0",
-                "v8-compile-cache": "^2.0.3"
-            },
-            "bin": {
-                "eslint": "bin/eslint.js"
-            },
-            "engines": {
-                "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/eslint-utils": {
-            "version": "1.4.3",
-            "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
-            "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
-            "dev": true,
-            "dependencies": {
-                "eslint-visitor-keys": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/eslint-visitor-keys": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
-            "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/espree": {
-            "version": "6.2.1",
-            "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",
-            "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==",
-            "dev": true,
-            "dependencies": {
-                "acorn": "^7.1.1",
-                "acorn-jsx": "^5.2.0",
-                "eslint-visitor-keys": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/file-entry-cache": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
-            "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
-            "dev": true,
-            "dependencies": {
-                "flat-cache": "^2.0.1"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/flat-cache": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
-            "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
-            "dev": true,
-            "dependencies": {
-                "flatted": "^2.0.0",
-                "rimraf": "2.6.3",
-                "write": "1.0.3"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/flatted": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
-            "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
-            "dev": true
-        },
-        "node_modules/eslint-config-esnext/node_modules/glob-parent": {
-            "version": "5.1.2",
-            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-            "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-            "dev": true,
-            "dependencies": {
-                "is-glob": "^4.0.1"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/globals": {
-            "version": "12.4.0",
-            "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
-            "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
-            "dev": true,
-            "dependencies": {
-                "type-fest": "^0.8.1"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/ignore": {
-            "version": "4.0.6",
-            "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
-            "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
-            "dev": true,
-            "engines": {
-                "node": ">= 4"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-            "dev": true
-        },
-        "node_modules/eslint-config-esnext/node_modules/regexpp": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
-            "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
-            "dev": true,
-            "engines": {
-                "node": ">=6.5.0"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/rimraf": {
-            "version": "2.6.3",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
-            "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
-            "dev": true,
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/semver": {
-            "version": "6.3.0",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-            "dev": true,
-            "bin": {
-                "semver": "bin/semver.js"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/strip-ansi": {
-            "version": "5.2.0",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-            "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
-            "dev": true,
-            "dependencies": {
-                "ansi-regex": "^4.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/strip-json-comments": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
-            "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/eslint-config-esnext/node_modules/type-fest": {
-            "version": "0.8.1",
-            "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
-            "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/eslint-config-node": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/eslint-config-node/-/eslint-config-node-4.1.0.tgz",
-            "integrity": "sha512-Wz17xV5O2WFG8fGdMYEBdbiL6TL7YNJSJvSX9V4sXQownewfYmoqlly7wxqLkOUv/57pq6LnnotMiQQrrPjCqQ==",
-            "dev": true,
-            "dependencies": {
-                "eslint": "^6.8.0",
-                "eslint-config-esnext": "^4.1.0"
-            },
-            "peerDependencies": {
-                "eslint": "^6.0.0"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/acorn": {
-            "version": "7.4.1",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
-            "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
-            "dev": true,
-            "bin": {
-                "acorn": "bin/acorn"
-            },
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/ansi-regex": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
-            "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/cross-spawn": {
-            "version": "6.0.5",
-            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
-            "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
-            "dev": true,
-            "dependencies": {
-                "nice-try": "^1.0.4",
-                "path-key": "^2.0.1",
-                "semver": "^5.5.0",
-                "shebang-command": "^1.2.0",
-                "which": "^1.2.9"
-            },
-            "engines": {
-                "node": ">=4.8"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/cross-spawn/node_modules/semver": {
-            "version": "5.7.1",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-            "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-            "dev": true,
-            "bin": {
-                "semver": "bin/semver"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dev": true,
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/eslint": {
-            "version": "6.8.0",
-            "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz",
-            "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==",
-            "dev": true,
-            "dependencies": {
-                "@babel/code-frame": "^7.0.0",
-                "ajv": "^6.10.0",
-                "chalk": "^2.1.0",
-                "cross-spawn": "^6.0.5",
-                "debug": "^4.0.1",
-                "doctrine": "^3.0.0",
-                "eslint-scope": "^5.0.0",
-                "eslint-utils": "^1.4.3",
-                "eslint-visitor-keys": "^1.1.0",
-                "espree": "^6.1.2",
-                "esquery": "^1.0.1",
-                "esutils": "^2.0.2",
-                "file-entry-cache": "^5.0.1",
-                "functional-red-black-tree": "^1.0.1",
-                "glob-parent": "^5.0.0",
-                "globals": "^12.1.0",
-                "ignore": "^4.0.6",
-                "import-fresh": "^3.0.0",
-                "imurmurhash": "^0.1.4",
-                "inquirer": "^7.0.0",
-                "is-glob": "^4.0.0",
-                "js-yaml": "^3.13.1",
-                "json-stable-stringify-without-jsonify": "^1.0.1",
-                "levn": "^0.3.0",
-                "lodash": "^4.17.14",
-                "minimatch": "^3.0.4",
-                "mkdirp": "^0.5.1",
-                "natural-compare": "^1.4.0",
-                "optionator": "^0.8.3",
-                "progress": "^2.0.0",
-                "regexpp": "^2.0.1",
-                "semver": "^6.1.2",
-                "strip-ansi": "^5.2.0",
-                "strip-json-comments": "^3.0.1",
-                "table": "^5.2.3",
-                "text-table": "^0.2.0",
-                "v8-compile-cache": "^2.0.3"
-            },
-            "bin": {
-                "eslint": "bin/eslint.js"
-            },
-            "engines": {
-                "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/eslint-utils": {
-            "version": "1.4.3",
-            "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
-            "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
-            "dev": true,
-            "dependencies": {
-                "eslint-visitor-keys": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/eslint-visitor-keys": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
-            "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/espree": {
-            "version": "6.2.1",
-            "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",
-            "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==",
-            "dev": true,
-            "dependencies": {
-                "acorn": "^7.1.1",
-                "acorn-jsx": "^5.2.0",
-                "eslint-visitor-keys": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/file-entry-cache": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
-            "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
-            "dev": true,
-            "dependencies": {
-                "flat-cache": "^2.0.1"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/flat-cache": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
-            "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
-            "dev": true,
-            "dependencies": {
-                "flatted": "^2.0.0",
-                "rimraf": "2.6.3",
-                "write": "1.0.3"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/flatted": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
-            "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
-            "dev": true
-        },
-        "node_modules/eslint-config-node/node_modules/glob-parent": {
-            "version": "5.1.2",
-            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-            "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-            "dev": true,
-            "dependencies": {
-                "is-glob": "^4.0.1"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/globals": {
-            "version": "12.4.0",
-            "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
-            "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
-            "dev": true,
-            "dependencies": {
-                "type-fest": "^0.8.1"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/ignore": {
-            "version": "4.0.6",
-            "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
-            "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
-            "dev": true,
-            "engines": {
-                "node": ">= 4"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-            "dev": true
-        },
-        "node_modules/eslint-config-node/node_modules/regexpp": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
-            "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
-            "dev": true,
-            "engines": {
-                "node": ">=6.5.0"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/rimraf": {
-            "version": "2.6.3",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
-            "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
-            "dev": true,
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/semver": {
-            "version": "6.3.0",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-            "dev": true,
-            "bin": {
-                "semver": "bin/semver.js"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/strip-ansi": {
-            "version": "5.2.0",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-            "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
-            "dev": true,
-            "dependencies": {
-                "ansi-regex": "^4.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/strip-json-comments": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
-            "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/eslint-config-node/node_modules/type-fest": {
-            "version": "0.8.1",
-            "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
-            "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/eslint-config-prettier": {
-            "version": "8.5.0",
-            "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz",
-            "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==",
-            "dev": true,
-            "bin": {
-                "eslint-config-prettier": "bin/cli.js"
-            },
-            "peerDependencies": {
-                "eslint": ">=7.0.0"
-            }
-        },
-        "node_modules/eslint-import-resolver-node": {
-            "version": "0.3.6",
-            "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz",
-            "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==",
-            "dev": true,
-            "dependencies": {
-                "debug": "^3.2.7",
-                "resolve": "^1.20.0"
-            }
-        },
-        "node_modules/eslint-import-resolver-node/node_modules/debug": {
-            "version": "3.2.7",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
-            "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
-            "dev": true,
-            "dependencies": {
-                "ms": "^2.1.1"
-            }
-        },
-        "node_modules/eslint-module-utils": {
-            "version": "2.7.3",
-            "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz",
-            "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==",
-            "dev": true,
-            "dependencies": {
-                "debug": "^3.2.7",
-                "find-up": "^2.1.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/eslint-module-utils/node_modules/debug": {
-            "version": "3.2.7",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
-            "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
-            "dev": true,
-            "dependencies": {
-                "ms": "^2.1.1"
-            }
-        },
-        "node_modules/eslint-module-utils/node_modules/find-up": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
-            "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
-            "dev": true,
-            "dependencies": {
-                "locate-path": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/eslint-module-utils/node_modules/locate-path": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
-            "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
-            "dev": true,
-            "dependencies": {
-                "p-locate": "^2.0.0",
-                "path-exists": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/eslint-module-utils/node_modules/p-limit": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
-            "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
-            "dev": true,
-            "dependencies": {
-                "p-try": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/eslint-module-utils/node_modules/p-locate": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
-            "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
-            "dev": true,
-            "dependencies": {
-                "p-limit": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/eslint-module-utils/node_modules/p-try": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
-            "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/eslint-plugin-babel": {
-            "version": "5.3.1",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-babel/-/eslint-plugin-babel-5.3.1.tgz",
-            "integrity": "sha512-VsQEr6NH3dj664+EyxJwO4FCYm/00JhYb3Sk3ft8o+fpKuIfQ9TaW6uVUfvwMXHcf/lsnRIoyFPsLMyiWCSL/g==",
-            "dev": true,
-            "dependencies": {
-                "eslint-rule-composer": "^0.3.0"
-            },
-            "engines": {
-                "node": ">=4"
-            },
-            "peerDependencies": {
-                "eslint": ">=4.0.0"
-            }
-        },
-        "node_modules/eslint-plugin-es": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz",
-            "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==",
-            "dev": true,
-            "dependencies": {
-                "eslint-utils": "^2.0.0",
-                "regexpp": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=8.10.0"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/mysticatea"
-            },
-            "peerDependencies": {
-                "eslint": ">=4.19.1"
-            }
-        },
-        "node_modules/eslint-plugin-es/node_modules/eslint-utils": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
-            "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
-            "dev": true,
-            "dependencies": {
-                "eslint-visitor-keys": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/mysticatea"
-            }
-        },
-        "node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
-            "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/eslint-plugin-import": {
-            "version": "2.26.0",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz",
-            "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==",
-            "dev": true,
-            "dependencies": {
-                "array-includes": "^3.1.4",
-                "array.prototype.flat": "^1.2.5",
-                "debug": "^2.6.9",
-                "doctrine": "^2.1.0",
-                "eslint-import-resolver-node": "^0.3.6",
-                "eslint-module-utils": "^2.7.3",
-                "has": "^1.0.3",
-                "is-core-module": "^2.8.1",
-                "is-glob": "^4.0.3",
-                "minimatch": "^3.1.2",
-                "object.values": "^1.1.5",
-                "resolve": "^1.22.0",
-                "tsconfig-paths": "^3.14.1"
-            },
-            "engines": {
-                "node": ">=4"
-            },
-            "peerDependencies": {
-                "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
-            }
-        },
-        "node_modules/eslint-plugin-import/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "dev": true,
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/eslint-plugin-import/node_modules/doctrine": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
-            "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
-            "dev": true,
-            "dependencies": {
-                "esutils": "^2.0.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/eslint-plugin-import/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-            "dev": true
-        },
-        "node_modules/eslint-plugin-jsx-a11y": {
-            "version": "6.6.0",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.0.tgz",
-            "integrity": "sha512-kTeLuIzpNhXL2CwLlc8AHI0aFRwWHcg483yepO9VQiHzM9bZwJdzTkzBszbuPrbgGmq2rlX/FaT2fJQsjUSHsw==",
-            "dev": true,
-            "dependencies": {
-                "@babel/runtime": "^7.18.3",
-                "aria-query": "^4.2.2",
-                "array-includes": "^3.1.5",
-                "ast-types-flow": "^0.0.7",
-                "axe-core": "^4.4.2",
-                "axobject-query": "^2.2.0",
-                "damerau-levenshtein": "^1.0.8",
-                "emoji-regex": "^9.2.2",
-                "has": "^1.0.3",
-                "jsx-ast-utils": "^3.3.1",
-                "language-tags": "^1.0.5",
-                "minimatch": "^3.1.2",
-                "semver": "^6.3.0"
-            },
-            "engines": {
-                "node": ">=4.0"
-            },
-            "peerDependencies": {
-                "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
-            }
-        },
-        "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": {
-            "version": "9.2.2",
-            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
-            "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
-            "dev": true
-        },
-        "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": {
-            "version": "6.3.0",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-            "dev": true,
-            "bin": {
-                "semver": "bin/semver.js"
-            }
-        },
-        "node_modules/eslint-plugin-node": {
-            "version": "11.1.0",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz",
-            "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==",
-            "dev": true,
-            "dependencies": {
-                "eslint-plugin-es": "^3.0.0",
-                "eslint-utils": "^2.0.0",
-                "ignore": "^5.1.1",
-                "minimatch": "^3.0.4",
-                "resolve": "^1.10.1",
-                "semver": "^6.1.0"
-            },
-            "engines": {
-                "node": ">=8.10.0"
-            },
-            "peerDependencies": {
-                "eslint": ">=5.16.0"
-            }
-        },
-        "node_modules/eslint-plugin-node/node_modules/eslint-utils": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
-            "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
-            "dev": true,
-            "dependencies": {
-                "eslint-visitor-keys": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/mysticatea"
-            }
-        },
-        "node_modules/eslint-plugin-node/node_modules/eslint-visitor-keys": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
-            "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/eslint-plugin-node/node_modules/ignore": {
-            "version": "5.2.0",
-            "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
-            "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
-            "dev": true,
-            "engines": {
-                "node": ">= 4"
-            }
-        },
-        "node_modules/eslint-plugin-node/node_modules/semver": {
-            "version": "6.3.0",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-            "dev": true,
-            "bin": {
-                "semver": "bin/semver.js"
-            }
-        },
-        "node_modules/eslint-plugin-prettier": {
-            "version": "4.2.1",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
-            "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
-            "dev": true,
-            "dependencies": {
-                "prettier-linter-helpers": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=12.0.0"
-            },
-            "peerDependencies": {
-                "eslint": ">=7.28.0",
-                "prettier": ">=2.0.0"
-            },
-            "peerDependenciesMeta": {
-                "eslint-config-prettier": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/eslint-plugin-react": {
-            "version": "7.30.1",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz",
-            "integrity": "sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg==",
-            "dev": true,
-            "dependencies": {
-                "array-includes": "^3.1.5",
-                "array.prototype.flatmap": "^1.3.0",
-                "doctrine": "^2.1.0",
-                "estraverse": "^5.3.0",
-                "jsx-ast-utils": "^2.4.1 || ^3.0.0",
-                "minimatch": "^3.1.2",
-                "object.entries": "^1.1.5",
-                "object.fromentries": "^2.0.5",
-                "object.hasown": "^1.1.1",
-                "object.values": "^1.1.5",
-                "prop-types": "^15.8.1",
-                "resolve": "^2.0.0-next.3",
-                "semver": "^6.3.0",
-                "string.prototype.matchall": "^4.0.7"
-            },
-            "engines": {
-                "node": ">=4"
-            },
-            "peerDependencies": {
-                "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
-            }
-        },
-        "node_modules/eslint-plugin-react-hooks": {
-            "version": "4.6.0",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
-            "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
-            "dev": true,
-            "engines": {
-                "node": ">=10"
-            },
-            "peerDependencies": {
-                "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
-            }
-        },
-        "node_modules/eslint-plugin-react/node_modules/doctrine": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
-            "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
-            "dev": true,
-            "dependencies": {
-                "esutils": "^2.0.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/eslint-plugin-react/node_modules/estraverse": {
-            "version": "5.3.0",
-            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-            "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-            "dev": true,
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/eslint-plugin-react/node_modules/resolve": {
-            "version": "2.0.0-next.4",
-            "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz",
-            "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==",
-            "dev": true,
-            "dependencies": {
-                "is-core-module": "^2.9.0",
-                "path-parse": "^1.0.7",
-                "supports-preserve-symlinks-flag": "^1.0.0"
-            },
-            "bin": {
-                "resolve": "bin/resolve"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/eslint-plugin-react/node_modules/semver": {
-            "version": "6.3.0",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-            "dev": true,
-            "bin": {
-                "semver": "bin/semver.js"
-            }
-        },
-        "node_modules/eslint-rule-composer": {
-            "version": "0.3.0",
-            "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz",
-            "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==",
-            "dev": true,
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/eslint-scope": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
-            "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
-            "dependencies": {
-                "esrecurse": "^4.3.0",
-                "estraverse": "^4.1.1"
-            },
-            "engines": {
-                "node": ">=8.0.0"
-            }
-        },
-        "node_modules/eslint-utils": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
-            "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
-            "dev": true,
-            "dependencies": {
-                "eslint-visitor-keys": "^2.0.0"
-            },
-            "engines": {
-                "node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/mysticatea"
-            },
-            "peerDependencies": {
-                "eslint": ">=5"
-            }
-        },
-        "node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
-            "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
-            "dev": true,
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/eslint-visitor-keys": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
-            "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
-            "dev": true,
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            }
-        },
-        "node_modules/eslint/node_modules/ansi-regex": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/eslint/node_modules/ansi-styles": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-            "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-            "dev": true,
-            "dependencies": {
-                "color-convert": "^2.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-            }
-        },
-        "node_modules/eslint/node_modules/argparse": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
-            "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
-            "dev": true
-        },
-        "node_modules/eslint/node_modules/chalk": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-            "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-            "dev": true,
-            "dependencies": {
-                "ansi-styles": "^4.1.0",
-                "supports-color": "^7.1.0"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/chalk/chalk?sponsor=1"
-            }
-        },
-        "node_modules/eslint/node_modules/color-convert": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-            "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-            "dev": true,
-            "dependencies": {
-                "color-name": "~1.1.4"
-            },
-            "engines": {
-                "node": ">=7.0.0"
-            }
-        },
-        "node_modules/eslint/node_modules/color-name": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-            "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-            "dev": true
-        },
-        "node_modules/eslint/node_modules/cross-spawn": {
-            "version": "7.0.3",
-            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-            "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
-            "dev": true,
-            "dependencies": {
-                "path-key": "^3.1.0",
-                "shebang-command": "^2.0.0",
-                "which": "^2.0.1"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/eslint/node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dev": true,
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/eslint/node_modules/escape-string-regexp": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-            "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-            "dev": true,
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/eslint/node_modules/eslint-scope": {
-            "version": "7.1.1",
-            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
-            "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
-            "dev": true,
-            "dependencies": {
-                "esrecurse": "^4.3.0",
-                "estraverse": "^5.2.0"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            }
-        },
-        "node_modules/eslint/node_modules/estraverse": {
-            "version": "5.3.0",
-            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-            "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-            "dev": true,
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/eslint/node_modules/glob-parent": {
-            "version": "6.0.2",
-            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
-            "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
-            "dev": true,
-            "dependencies": {
-                "is-glob": "^4.0.3"
-            },
-            "engines": {
-                "node": ">=10.13.0"
-            }
-        },
-        "node_modules/eslint/node_modules/globals": {
-            "version": "13.16.0",
-            "resolved": "https://registry.npmjs.org/globals/-/globals-13.16.0.tgz",
-            "integrity": "sha512-A1lrQfpNF+McdPOnnFqY3kSN0AFTy485bTi1bkLk4mVPODIUEcSfhHgRqA+QdXPksrSTTztYXx37NFV+GpGk3Q==",
-            "dev": true,
-            "dependencies": {
-                "type-fest": "^0.20.2"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/eslint/node_modules/has-flag": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-            "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/eslint/node_modules/ignore": {
-            "version": "5.2.0",
-            "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
-            "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
-            "dev": true,
-            "engines": {
-                "node": ">= 4"
-            }
-        },
-        "node_modules/eslint/node_modules/js-yaml": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
-            "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-            "dev": true,
-            "dependencies": {
-                "argparse": "^2.0.1"
-            },
-            "bin": {
-                "js-yaml": "bin/js-yaml.js"
-            }
-        },
-        "node_modules/eslint/node_modules/levn": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
-            "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
-            "dev": true,
-            "dependencies": {
-                "prelude-ls": "^1.2.1",
-                "type-check": "~0.4.0"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/eslint/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-            "dev": true
-        },
-        "node_modules/eslint/node_modules/optionator": {
-            "version": "0.9.1",
-            "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
-            "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
-            "dev": true,
-            "dependencies": {
-                "deep-is": "^0.1.3",
-                "fast-levenshtein": "^2.0.6",
-                "levn": "^0.4.1",
-                "prelude-ls": "^1.2.1",
-                "type-check": "^0.4.0",
-                "word-wrap": "^1.2.3"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/eslint/node_modules/path-key": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
-            "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/eslint/node_modules/prelude-ls": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
-            "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
-            "dev": true,
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/eslint/node_modules/shebang-command": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
-            "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
-            "dev": true,
-            "dependencies": {
-                "shebang-regex": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/eslint/node_modules/shebang-regex": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
-            "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/eslint/node_modules/strip-ansi": {
-            "version": "6.0.1",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-            "dev": true,
-            "dependencies": {
-                "ansi-regex": "^5.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/eslint/node_modules/strip-json-comments": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
-            "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/eslint/node_modules/supports-color": {
-            "version": "7.2.0",
-            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-            "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-            "dev": true,
-            "dependencies": {
-                "has-flag": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/eslint/node_modules/type-check": {
-            "version": "0.4.0",
-            "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
-            "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
-            "dev": true,
-            "dependencies": {
-                "prelude-ls": "^1.2.1"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/eslint/node_modules/which": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
-            "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
-            "dev": true,
-            "dependencies": {
-                "isexe": "^2.0.0"
-            },
-            "bin": {
-                "node-which": "bin/node-which"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/espree": {
-            "version": "9.3.2",
-            "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz",
-            "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==",
-            "dev": true,
-            "dependencies": {
-                "acorn": "^8.7.1",
-                "acorn-jsx": "^5.3.2",
-                "eslint-visitor-keys": "^3.3.0"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            }
-        },
-        "node_modules/esprima": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
-            "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
-            "bin": {
-                "esparse": "bin/esparse.js",
-                "esvalidate": "bin/esvalidate.js"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/esquery": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
-            "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
-            "dev": true,
-            "dependencies": {
-                "estraverse": "^5.1.0"
-            },
-            "engines": {
-                "node": ">=0.10"
-            }
-        },
-        "node_modules/esquery/node_modules/estraverse": {
-            "version": "5.3.0",
-            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-            "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-            "dev": true,
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/esrecurse": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
-            "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
-            "dependencies": {
-                "estraverse": "^5.2.0"
-            },
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/esrecurse/node_modules/estraverse": {
-            "version": "5.3.0",
-            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-            "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/estraverse": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
-            "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/esutils": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
-            "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/etag": {
-            "version": "1.8.1",
-            "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-            "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/event-target-shim": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
-            "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/eventemitter3": {
-            "version": "4.0.7",
-            "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
-            "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
-            "dev": true
-        },
-        "node_modules/events": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
-            "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
-            "engines": {
-                "node": ">=0.8.x"
-            }
-        },
-        "node_modules/eventsource": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz",
-            "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==",
-            "dev": true,
-            "engines": {
-                "node": ">=12.0.0"
-            }
-        },
-        "node_modules/execa": {
-            "version": "0.7.0",
-            "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
-            "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
-            "dependencies": {
-                "cross-spawn": "^5.0.1",
-                "get-stream": "^3.0.0",
-                "is-stream": "^1.1.0",
-                "npm-run-path": "^2.0.0",
-                "p-finally": "^1.0.0",
-                "signal-exit": "^3.0.0",
-                "strip-eof": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/execa/node_modules/cross-spawn": {
-            "version": "5.1.0",
-            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
-            "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
-            "dependencies": {
-                "lru-cache": "^4.0.1",
-                "shebang-command": "^1.2.0",
-                "which": "^1.2.9"
-            }
-        },
-        "node_modules/execa/node_modules/get-stream": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
-            "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/execa/node_modules/lru-cache": {
-            "version": "4.1.5",
-            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
-            "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
-            "dependencies": {
-                "pseudomap": "^1.0.2",
-                "yallist": "^2.1.2"
-            }
-        },
-        "node_modules/execa/node_modules/yallist": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
-            "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
-        },
-        "node_modules/exeq": {
-            "version": "2.4.0",
-            "resolved": "https://registry.npmjs.org/exeq/-/exeq-2.4.0.tgz",
-            "integrity": "sha1-Td8qaEZIxCeteZNJzzO9dTWPiEo=",
-            "dependencies": {
-                "bluebird": "^3.0.3",
-                "native-or-bluebird": "^1.2.0"
-            },
-            "engines": {
-                "node": ">= 0.10.0"
-            }
-        },
-        "node_modules/exif": {
-            "version": "0.6.0",
-            "resolved": "https://registry.npmjs.org/exif/-/exif-0.6.0.tgz",
-            "integrity": "sha1-YKYmaAdlQst+T1cZnUrG830sX0o=",
-            "dependencies": {
-                "debug": "^2.2"
-            }
-        },
-        "node_modules/exif/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/exif/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
-        },
-        "node_modules/exifr": {
-            "version": "7.1.3",
-            "resolved": "https://registry.npmjs.org/exifr/-/exifr-7.1.3.tgz",
-            "integrity": "sha512-g/aje2noHivrRSLbAUtBPWFbxKdKhgj/xr1vATDdUXPOFYJlQ62Ft0oy+72V6XLIpDJfHs6gXLbBLAolqOXYRw=="
-        },
-        "node_modules/expand-brackets": {
-            "version": "2.1.4",
-            "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
-            "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
-            "dependencies": {
-                "debug": "^2.3.3",
-                "define-property": "^0.2.5",
-                "extend-shallow": "^2.0.1",
-                "posix-character-classes": "^0.1.0",
-                "regex-not": "^1.0.0",
-                "snapdragon": "^0.8.1",
-                "to-regex": "^3.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/expand-brackets/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/expand-brackets/node_modules/define-property": {
-            "version": "0.2.5",
-            "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-            "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-            "dependencies": {
-                "is-descriptor": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/expand-brackets/node_modules/extend-shallow": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-            "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-            "dependencies": {
-                "is-extendable": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/expand-brackets/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
-        },
-        "node_modules/expand-template": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
-            "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/express": {
-            "version": "4.18.1",
-            "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
-            "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
-            "dependencies": {
-                "accepts": "~1.3.8",
-                "array-flatten": "1.1.1",
-                "body-parser": "1.20.0",
-                "content-disposition": "0.5.4",
-                "content-type": "~1.0.4",
-                "cookie": "0.5.0",
-                "cookie-signature": "1.0.6",
-                "debug": "2.6.9",
-                "depd": "2.0.0",
-                "encodeurl": "~1.0.2",
-                "escape-html": "~1.0.3",
-                "etag": "~1.8.1",
-                "finalhandler": "1.2.0",
-                "fresh": "0.5.2",
-                "http-errors": "2.0.0",
-                "merge-descriptors": "1.0.1",
-                "methods": "~1.1.2",
-                "on-finished": "2.4.1",
-                "parseurl": "~1.3.3",
-                "path-to-regexp": "0.1.7",
-                "proxy-addr": "~2.0.7",
-                "qs": "6.10.3",
-                "range-parser": "~1.2.1",
-                "safe-buffer": "5.2.1",
-                "send": "0.18.0",
-                "serve-static": "1.15.0",
-                "setprototypeof": "1.2.0",
-                "statuses": "2.0.1",
-                "type-is": "~1.6.18",
-                "utils-merge": "1.0.1",
-                "vary": "~1.1.2"
-            },
-            "engines": {
-                "node": ">= 0.10.0"
-            }
-        },
-        "node_modules/express-flash": {
-            "version": "0.0.2",
-            "resolved": "https://registry.npmjs.org/express-flash/-/express-flash-0.0.2.tgz",
-            "integrity": "sha1-I9GovPP5DXB5KOSJ+Whp7K0KzaI=",
-            "dependencies": {
-                "connect-flash": "0.1.x"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/express-session": {
-            "version": "1.17.3",
-            "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz",
-            "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==",
-            "dependencies": {
-                "cookie": "0.4.2",
-                "cookie-signature": "1.0.6",
-                "debug": "2.6.9",
-                "depd": "~2.0.0",
-                "on-headers": "~1.0.2",
-                "parseurl": "~1.3.3",
-                "safe-buffer": "5.2.1",
-                "uid-safe": "~2.1.5"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/express-session/node_modules/cookie": {
-            "version": "0.4.2",
-            "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
-            "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/express-session/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/express-session/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
-        },
-        "node_modules/express-session/node_modules/safe-buffer": {
-            "version": "5.2.1",
-            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-            "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ]
-        },
-        "node_modules/express-validator": {
-            "version": "5.3.1",
-            "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-5.3.1.tgz",
-            "integrity": "sha512-g8xkipBF6VxHbO1+ksC7nxUU7+pWif0+OZXjZTybKJ/V0aTVhuCoHbyhIPgSYVldwQLocGExPtB2pE0DqK4jsw==",
-            "dependencies": {
-                "lodash": "^4.17.10",
-                "validator": "^10.4.0"
-            },
-            "engines": {
-                "node": ">= 6.0.0"
-            }
-        },
-        "node_modules/express/node_modules/cookie": {
-            "version": "0.5.0",
-            "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
-            "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/express/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/express/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
-        },
-        "node_modules/express/node_modules/qs": {
-            "version": "6.10.3",
-            "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
-            "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
-            "dependencies": {
-                "side-channel": "^1.0.4"
-            },
-            "engines": {
-                "node": ">=0.6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/express/node_modules/safe-buffer": {
-            "version": "5.2.1",
-            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-            "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ]
-        },
-        "node_modules/expressjs": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/expressjs/-/expressjs-1.0.1.tgz",
-            "integrity": "sha1-IgMoRpoY31rWFeK3oM6ZXxf7ru8=",
-            "deprecated": "This is a typosquat on the popular Express package. This is not maintained nor is the original Express package."
-        },
-        "node_modules/ext": {
-            "version": "1.6.0",
-            "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz",
-            "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==",
-            "dev": true,
-            "dependencies": {
-                "type": "^2.5.0"
-            }
-        },
-        "node_modules/ext/node_modules/type": {
-            "version": "2.6.0",
-            "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz",
-            "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==",
-            "dev": true
-        },
-        "node_modules/extend": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
-            "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
-        },
-        "node_modules/extend-shallow": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
-            "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
-            "dependencies": {
-                "assign-symbols": "^1.0.0",
-                "is-extendable": "^1.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/extend-shallow/node_modules/is-extendable": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
-            "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
-            "dependencies": {
-                "is-plain-object": "^2.0.4"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/external-editor": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
-            "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
-            "dev": true,
-            "dependencies": {
-                "chardet": "^0.7.0",
-                "iconv-lite": "^0.4.24",
-                "tmp": "^0.0.33"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/external-editor/node_modules/iconv-lite": {
-            "version": "0.4.24",
-            "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
-            "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
-            "dev": true,
-            "dependencies": {
-                "safer-buffer": ">= 2.1.2 < 3"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/extglob": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
-            "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
-            "dependencies": {
-                "array-unique": "^0.3.2",
-                "define-property": "^1.0.0",
-                "expand-brackets": "^2.1.4",
-                "extend-shallow": "^2.0.1",
-                "fragment-cache": "^0.2.1",
-                "regex-not": "^1.0.0",
-                "snapdragon": "^0.8.1",
-                "to-regex": "^3.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/extglob/node_modules/define-property": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-            "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
-            "dependencies": {
-                "is-descriptor": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/extglob/node_modules/extend-shallow": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-            "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-            "dependencies": {
-                "is-extendable": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/extglob/node_modules/is-accessor-descriptor": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-            "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-            "dependencies": {
-                "kind-of": "^6.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/extglob/node_modules/is-data-descriptor": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-            "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-            "dependencies": {
-                "kind-of": "^6.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/extglob/node_modules/is-descriptor": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-            "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-            "dependencies": {
-                "is-accessor-descriptor": "^1.0.0",
-                "is-data-descriptor": "^1.0.0",
-                "kind-of": "^6.0.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/extract-zip": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
-            "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
-            "dependencies": {
-                "debug": "^4.1.1",
-                "get-stream": "^5.1.0",
-                "yauzl": "^2.10.0"
-            },
-            "bin": {
-                "extract-zip": "cli.js"
-            },
-            "engines": {
-                "node": ">= 10.17.0"
-            },
-            "optionalDependencies": {
-                "@types/yauzl": "^2.9.1"
-            }
-        },
-        "node_modules/extract-zip/node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/extract-zip/node_modules/get-stream": {
-            "version": "5.2.0",
-            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
-            "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
-            "dependencies": {
-                "pump": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/extract-zip/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
-        },
-        "node_modules/extsprintf": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
-            "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
-            "engines": [
-                "node >=0.6.0"
-            ]
-        },
-        "node_modules/fast-deep-equal": {
-            "version": "3.1.3",
-            "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-            "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
-        },
-        "node_modules/fast-diff": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
-            "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
-            "dev": true
-        },
-        "node_modules/fast-json-stable-stringify": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
-            "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
-        },
-        "node_modules/fast-levenshtein": {
-            "version": "2.0.6",
-            "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-            "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
-            "dev": true
-        },
-        "node_modules/fast-text-encoding": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz",
-            "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig=="
-        },
-        "node_modules/fastest-levenshtein": {
-            "version": "1.0.12",
-            "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz",
-            "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow=="
-        },
-        "node_modules/faye-websocket": {
-            "version": "0.11.4",
-            "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
-            "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
-            "dev": true,
-            "dependencies": {
-                "websocket-driver": ">=0.5.1"
-            },
-            "engines": {
-                "node": ">=0.8.0"
-            }
-        },
-        "node_modules/fbjs": {
-            "version": "0.8.18",
-            "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.18.tgz",
-            "integrity": "sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==",
-            "dependencies": {
-                "core-js": "^1.0.0",
-                "isomorphic-fetch": "^2.1.1",
-                "loose-envify": "^1.0.0",
-                "object-assign": "^4.1.0",
-                "promise": "^7.1.1",
-                "setimmediate": "^1.0.5",
-                "ua-parser-js": "^0.7.30"
-            }
-        },
-        "node_modules/fd-slicer": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
-            "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
-            "dependencies": {
-                "pend": "~1.2.0"
-            }
-        },
-        "node_modules/ffmpeg": {
-            "version": "0.0.4",
-            "resolved": "https://registry.npmjs.org/ffmpeg/-/ffmpeg-0.0.4.tgz",
-            "integrity": "sha1-HEYN+OfaUSf2LO70v6BsWciWMMs=",
-            "dependencies": {
-                "when": ">= 0.0.1"
-            }
-        },
-        "node_modules/figures": {
-            "version": "3.2.0",
-            "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
-            "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
-            "dev": true,
-            "dependencies": {
-                "escape-string-regexp": "^1.0.5"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/file-entry-cache": {
-            "version": "6.0.1",
-            "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
-            "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
-            "dev": true,
-            "dependencies": {
-                "flat-cache": "^3.0.4"
-            },
-            "engines": {
-                "node": "^10.12.0 || >=12.0.0"
-            }
-        },
-        "node_modules/file-loader": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz",
-            "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==",
-            "dev": true,
-            "dependencies": {
-                "loader-utils": "^1.0.2",
-                "schema-utils": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 6.9.0"
-            },
-            "peerDependencies": {
-                "webpack": "^4.0.0"
-            }
-        },
-        "node_modules/file-saver": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
-            "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
-        },
-        "node_modules/file-uri-to-path": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
-            "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
-            "optional": true
-        },
-        "node_modules/fill-range": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
-            "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
-            "dependencies": {
-                "extend-shallow": "^2.0.1",
-                "is-number": "^3.0.0",
-                "repeat-string": "^1.6.1",
-                "to-regex-range": "^2.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/fill-range/node_modules/extend-shallow": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-            "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-            "dependencies": {
-                "is-extendable": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/filter-obj": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
-            "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/finalhandler": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
-            "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
-            "dependencies": {
-                "debug": "2.6.9",
-                "encodeurl": "~1.0.2",
-                "escape-html": "~1.0.3",
-                "on-finished": "2.4.1",
-                "parseurl": "~1.3.3",
-                "statuses": "2.0.1",
-                "unpipe": "~1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/finalhandler/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/finalhandler/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
-        },
-        "node_modules/find": {
-            "version": "0.1.7",
-            "resolved": "https://registry.npmjs.org/find/-/find-0.1.7.tgz",
-            "integrity": "sha1-yGyHrxqxjyIrvjjeyGy8dg0Wpvs=",
-            "dependencies": {
-                "traverse-chain": "~0.1.0"
-            }
-        },
-        "node_modules/find-cache-dir": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
-            "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
-            "dev": true,
-            "dependencies": {
-                "commondir": "^1.0.1",
-                "make-dir": "^1.0.0",
-                "pkg-dir": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/find-cache-dir/node_modules/find-up": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
-            "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
-            "dev": true,
-            "dependencies": {
-                "locate-path": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/find-cache-dir/node_modules/locate-path": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
-            "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
-            "dev": true,
-            "dependencies": {
-                "p-locate": "^2.0.0",
-                "path-exists": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/find-cache-dir/node_modules/make-dir": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
-            "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
-            "dev": true,
-            "dependencies": {
-                "pify": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/find-cache-dir/node_modules/p-limit": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
-            "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
-            "dev": true,
-            "dependencies": {
-                "p-try": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/find-cache-dir/node_modules/p-locate": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
-            "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
-            "dev": true,
-            "dependencies": {
-                "p-limit": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/find-cache-dir/node_modules/p-try": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
-            "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/find-cache-dir/node_modules/pify": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-            "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/find-cache-dir/node_modules/pkg-dir": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
-            "integrity": "sha512-ojakdnUgL5pzJYWw2AIDEupaQCX5OPbM688ZevubICjdIX01PRSYKqm33fJoCOJBRseYCTUlQRnBNX+Pchaejw==",
-            "dev": true,
-            "dependencies": {
-                "find-up": "^2.1.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/find-in-files": {
-            "version": "0.5.0",
-            "resolved": "https://registry.npmjs.org/find-in-files/-/find-in-files-0.5.0.tgz",
-            "integrity": "sha512-VraTc6HdtdSHmAp0yJpAy20yPttGKzyBWc7b7FPnnsX9TOgmKx0g9xajizpF/iuu4IvNK4TP0SpyBT9zAlwG+g==",
-            "dependencies": {
-                "find": "^0.1.5",
-                "q": "^1.0.1"
-            }
-        },
-        "node_modules/find-parent-dir": {
-            "version": "0.3.1",
-            "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.1.tgz",
-            "integrity": "sha512-o4UcykWV/XN9wm+jMEtWLPlV8RXCZnMhQI6F6OdHeSez7iiJWePw8ijOlskJZMsaQoGR/b7dH6lO02HhaTN7+A=="
-        },
-        "node_modules/find-root": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
-            "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
-        },
-        "node_modules/find-up": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
-            "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
-            "dependencies": {
-                "locate-path": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/fit-curve": {
-            "version": "0.1.7",
-            "resolved": "https://registry.npmjs.org/fit-curve/-/fit-curve-0.1.7.tgz",
-            "integrity": "sha512-Md3b3ReA/qJwwYvKXeHpOV1fhPqwhJ9/29zc9lfi8ijyg00J0S9C7+5XMZDFhlDAKbwOvVgBxVIG1EHoMSC3vw=="
-        },
-        "node_modules/flat": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz",
-            "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==",
-            "dependencies": {
-                "is-buffer": "~2.0.3"
-            },
-            "bin": {
-                "flat": "cli.js"
-            }
-        },
-        "node_modules/flat-cache": {
-            "version": "3.0.4",
-            "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
-            "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
-            "dev": true,
-            "dependencies": {
-                "flatted": "^3.1.0",
-                "rimraf": "^3.0.2"
-            },
-            "engines": {
-                "node": "^10.12.0 || >=12.0.0"
-            }
-        },
-        "node_modules/flatted": {
-            "version": "3.2.6",
-            "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz",
-            "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==",
-            "dev": true
-        },
-        "node_modules/flexlayout-react": {
-            "version": "0.3.11",
-            "resolved": "https://registry.npmjs.org/flexlayout-react/-/flexlayout-react-0.3.11.tgz",
-            "integrity": "sha512-V+rEfyYJBqNk9oBgotPoXg8rmom4/ji9Mvr6f7T8sIJs83RuyK1D3oOrya2ydZIUCP2T6BIvj7rFTmRRkzpU8w==",
-            "peerDependencies": {
-                "react": "^16.13.1",
-                "react-dom": "^16.13.1"
-            }
-        },
-        "node_modules/fluent-ffmpeg": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz",
-            "integrity": "sha1-yVLeIkD4EuvaCqgAbXd27irPfXQ=",
-            "dependencies": {
-                "async": ">=0.2.9",
-                "which": "^1.1.1"
-            },
-            "engines": {
-                "node": ">=0.8.0"
-            }
-        },
-        "node_modules/flush-write-stream": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
-            "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==",
-            "dev": true,
-            "dependencies": {
-                "inherits": "^2.0.3",
-                "readable-stream": "^2.3.6"
-            }
-        },
-        "node_modules/flush-write-stream/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dev": true,
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/follow-redirects": {
-            "version": "1.5.10",
-            "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
-            "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
-            "dependencies": {
-                "debug": "=3.1.0"
-            },
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/follow-redirects/node_modules/debug": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-            "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/follow-redirects/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
-        },
-        "node_modules/for-each": {
-            "version": "0.3.3",
-            "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
-            "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
-            "dependencies": {
-                "is-callable": "^1.1.3"
-            }
-        },
-        "node_modules/for-each-property": {
-            "version": "0.0.4",
-            "resolved": "https://registry.npmjs.org/for-each-property/-/for-each-property-0.0.4.tgz",
-            "integrity": "sha1-z6hXrsFCLh0Sb/CHhPz2Jim8g/Y=",
-            "dependencies": {
-                "get-prototype-chain": "^1.0.1"
-            }
-        },
-        "node_modules/for-each-property-deep": {
-            "version": "0.0.3",
-            "resolved": "https://registry.npmjs.org/for-each-property-deep/-/for-each-property-deep-0.0.3.tgz",
-            "integrity": "sha1-MTCaSvw4qcygbxsiP1PWSm0IP60=",
-            "dependencies": {
-                "for-each-property": "0.0.4"
-            }
-        },
-        "node_modules/for-in": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
-            "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/forever-agent": {
-            "version": "0.6.1",
-            "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
-            "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/fork-ts-checker-webpack-plugin": {
-            "version": "1.6.0",
-            "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-1.6.0.tgz",
-            "integrity": "sha512-vqOY5gakcoon2s12V7MMe01OPwfgqulUWFzm+geQaPPOBKjW1I7aqqoBVlU0ECn97liMB0ECs16pRdIGe9qdRw==",
-            "dev": true,
-            "dependencies": {
-                "babel-code-frame": "^6.22.0",
-                "chalk": "^2.4.1",
-                "chokidar": "^2.0.4",
-                "micromatch": "^3.1.10",
-                "minimatch": "^3.0.4",
-                "semver": "^5.6.0",
-                "tapable": "^1.0.0",
-                "worker-rpc": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=6.11.5",
-                "yarn": ">=1.0.0"
-            }
-        },
-        "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
-            "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/form-data": {
-            "version": "2.3.3",
-            "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
-            "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
-            "dependencies": {
-                "asynckit": "^0.4.0",
-                "combined-stream": "^1.0.6",
-                "mime-types": "^2.1.12"
-            },
-            "engines": {
-                "node": ">= 0.12"
-            }
-        },
-        "node_modules/form-data-encoder": {
-            "version": "1.7.1",
-            "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.1.tgz",
-            "integrity": "sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg=="
-        },
-        "node_modules/formidable": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
-            "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==",
-            "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau"
-        },
-        "node_modules/forwarded": {
-            "version": "0.2.0",
-            "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
-            "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/fragment-cache": {
-            "version": "0.2.1",
-            "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
-            "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
-            "dependencies": {
-                "map-cache": "^0.2.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/fresh": {
-            "version": "0.5.2",
-            "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
-            "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/from2": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
-            "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
-            "dev": true,
-            "dependencies": {
-                "inherits": "^2.0.1",
-                "readable-stream": "^2.0.0"
-            }
-        },
-        "node_modules/from2/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dev": true,
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/fs-constants": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
-            "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
-        },
-        "node_modules/fs-extra": {
-            "version": "0.26.7",
-            "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz",
-            "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=",
-            "dependencies": {
-                "graceful-fs": "^4.1.2",
-                "jsonfile": "^2.1.0",
-                "klaw": "^1.0.0",
-                "path-is-absolute": "^1.0.0",
-                "rimraf": "^2.2.8"
-            }
-        },
-        "node_modules/fs-extra/node_modules/rimraf": {
-            "version": "2.7.1",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-            "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            }
-        },
-        "node_modules/fs-minipass": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
-            "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
-            "dependencies": {
-                "minipass": "^3.0.0"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/fs-monkey": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz",
-            "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q=="
-        },
-        "node_modules/fs-write-stream-atomic": {
-            "version": "1.0.10",
-            "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
-            "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
-            "dev": true,
-            "dependencies": {
-                "graceful-fs": "^4.1.2",
-                "iferr": "^0.1.5",
-                "imurmurhash": "^0.1.4",
-                "readable-stream": "1 || 2"
-            }
-        },
-        "node_modules/fs-write-stream-atomic/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dev": true,
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/fs.realpath": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-            "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
-        },
-        "node_modules/fsevents": {
-            "version": "1.2.13",
-            "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
-            "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
-            "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.",
-            "hasInstallScript": true,
-            "optional": true,
-            "os": [
-                "darwin"
-            ],
-            "dependencies": {
-                "bindings": "^1.5.0",
-                "nan": "^2.12.1"
-            },
-            "engines": {
-                "node": ">= 4.0"
-            }
-        },
-        "node_modules/fstream": {
-            "version": "1.0.12",
-            "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
-            "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
-            "dependencies": {
-                "graceful-fs": "^4.1.2",
-                "inherits": "~2.0.0",
-                "mkdirp": ">=0.5 0",
-                "rimraf": "2"
-            },
-            "engines": {
-                "node": ">=0.6"
-            }
-        },
-        "node_modules/fstream/node_modules/rimraf": {
-            "version": "2.7.1",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-            "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            }
-        },
-        "node_modules/function-bind": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
-            "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
-        },
-        "node_modules/function-plot": {
-            "version": "1.22.8",
-            "resolved": "https://registry.npmjs.org/function-plot/-/function-plot-1.22.8.tgz",
-            "integrity": "sha512-VGqY3Lxu+LoC2ZvdesEiK8n0jMThjEI1gAGHOcWcRED5ip0Kt018swygtKl+lmBlbvmXDXOhYW6KOPa0dbky2w==",
-            "dependencies": {
-                "built-in-math-eval": "^0.3.0",
-                "clamp": "^1.0.1",
-                "d3-axis": "^2.0.0",
-                "d3-color": "^2.0.0",
-                "d3-format": "^2.0.0",
-                "d3-interpolate": "^2.0.1",
-                "d3-scale": "^3.2.2",
-                "d3-selection": "^2.0.0",
-                "d3-shape": "^2.0.0",
-                "d3-zoom": "^2.0.0",
-                "interval-arithmetic-eval": "^0.4.7"
-            }
-        },
-        "node_modules/function.prototype.name": {
-            "version": "1.1.5",
-            "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
-            "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.19.0",
-                "functions-have-names": "^1.2.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/functional-red-black-tree": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
-            "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
-            "dev": true
-        },
-        "node_modules/functions-have-names": {
-            "version": "1.2.3",
-            "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
-            "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/gauge": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
-            "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
-            "dependencies": {
-                "aproba": "^1.0.3 || ^2.0.0",
-                "color-support": "^1.1.2",
-                "console-control-strings": "^1.0.0",
-                "has-unicode": "^2.0.1",
-                "object-assign": "^4.1.1",
-                "signal-exit": "^3.0.0",
-                "string-width": "^4.2.3",
-                "strip-ansi": "^6.0.1",
-                "wide-align": "^1.1.2"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/gauge/node_modules/ansi-regex": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/gauge/node_modules/emoji-regex": {
-            "version": "8.0.0",
-            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
-        },
-        "node_modules/gauge/node_modules/is-fullwidth-code-point": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-            "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/gauge/node_modules/string-width": {
-            "version": "4.2.3",
-            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-            "dependencies": {
-                "emoji-regex": "^8.0.0",
-                "is-fullwidth-code-point": "^3.0.0",
-                "strip-ansi": "^6.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/gauge/node_modules/strip-ansi": {
-            "version": "6.0.1",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-            "dependencies": {
-                "ansi-regex": "^5.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/gaxios": {
-            "version": "2.3.4",
-            "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-2.3.4.tgz",
-            "integrity": "sha512-US8UMj8C5pRnao3Zykc4AAVr+cffoNKRTg9Rsf2GiuZCW69vgJj38VK2PzlPuQU73FZ/nTk9/Av6/JGcE1N9vA==",
-            "dependencies": {
-                "abort-controller": "^3.0.0",
-                "extend": "^3.0.2",
-                "https-proxy-agent": "^5.0.0",
-                "is-stream": "^2.0.0",
-                "node-fetch": "^2.3.0"
-            },
-            "engines": {
-                "node": ">=8.10.0"
-            }
-        },
-        "node_modules/gaxios/node_modules/is-stream": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
-            "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/gaxios/node_modules/node-fetch": {
-            "version": "2.6.7",
-            "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
-            "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
-            "dependencies": {
-                "whatwg-url": "^5.0.0"
-            },
-            "engines": {
-                "node": "4.x || >=6.0.0"
-            },
-            "peerDependencies": {
-                "encoding": "^0.1.0"
-            },
-            "peerDependenciesMeta": {
-                "encoding": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/gaze": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz",
-            "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==",
-            "dependencies": {
-                "globule": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 4.0.0"
-            }
-        },
-        "node_modules/gcp-metadata": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-2.0.4.tgz",
-            "integrity": "sha512-p1lXhJvcKvJHWfQXhkd4Za1kyXRsGZA0JH7Cjs07W9hrg84d/j5tqQhbGewlSLx9gNyuQUid69uLux48YbggLg==",
-            "dependencies": {
-                "gaxios": "^2.0.1",
-                "json-bigint": "^0.3.0"
-            },
-            "engines": {
-                "node": ">=8.10.0"
-            }
-        },
-        "node_modules/get-caller-file": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
-            "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
-            "engines": {
-                "node": "6.* || 8.* || >= 10.*"
-            }
-        },
-        "node_modules/get-func-name": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
-            "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/get-intrinsic": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz",
-            "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==",
-            "dependencies": {
-                "function-bind": "^1.1.1",
-                "has": "^1.0.3",
-                "has-symbols": "^1.0.3"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/get-node-dimensions": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/get-node-dimensions/-/get-node-dimensions-1.2.1.tgz",
-            "integrity": "sha512-2MSPMu7S1iOTL+BOa6K1S62hB2zUAYNF/lV0gSVlOaacd087lc6nR1H1r0e3B1CerTo+RceOmi1iJW+vp21xcQ=="
-        },
-        "node_modules/get-prototype-chain": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/get-prototype-chain/-/get-prototype-chain-1.0.1.tgz",
-            "integrity": "sha1-oXGhFeoeSQbG7ThDofABwYUQQW8=",
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/get-stdin": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz",
-            "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=",
-            "engines": {
-                "node": ">=0.12.0"
-            }
-        },
-        "node_modules/get-stream": {
-            "version": "6.0.1",
-            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
-            "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/get-symbol-description": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
-            "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "get-intrinsic": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/get-value": {
-            "version": "2.0.6",
-            "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
-            "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/getpass": {
-            "version": "0.1.7",
-            "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
-            "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
-            "dependencies": {
-                "assert-plus": "^1.0.0"
-            }
-        },
-        "node_modules/github-from-package": {
-            "version": "0.0.0",
-            "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
-            "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4="
-        },
-        "node_modules/glob": {
-            "version": "7.2.3",
-            "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-            "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-            "dependencies": {
-                "fs.realpath": "^1.0.0",
-                "inflight": "^1.0.4",
-                "inherits": "2",
-                "minimatch": "^3.1.1",
-                "once": "^1.3.0",
-                "path-is-absolute": "^1.0.0"
-            },
-            "engines": {
-                "node": "*"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/isaacs"
-            }
-        },
-        "node_modules/glob-parent": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
-            "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
-            "dependencies": {
-                "is-glob": "^3.1.0",
-                "path-dirname": "^1.0.0"
-            }
-        },
-        "node_modules/glob-parent/node_modules/is-glob": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
-            "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
-            "dependencies": {
-                "is-extglob": "^2.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/glob-to-regexp": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
-            "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
-        },
-        "node_modules/global-dirs": {
-            "version": "0.1.1",
-            "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
-            "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=",
-            "dependencies": {
-                "ini": "^1.3.4"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/globals": {
-            "version": "11.12.0",
-            "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
-            "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/globby": {
-            "version": "7.1.1",
-            "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
-            "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
-            "dev": true,
-            "dependencies": {
-                "array-union": "^1.0.1",
-                "dir-glob": "^2.0.0",
-                "glob": "^7.1.2",
-                "ignore": "^3.3.5",
-                "pify": "^3.0.0",
-                "slash": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/globby/node_modules/pify": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-            "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/globule": {
-            "version": "1.3.3",
-            "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.3.tgz",
-            "integrity": "sha512-mb1aYtDbIjTu4ShMB85m3UzjX9BVKe9WCzsnfMSZk+K5GpIbBOexgg4PPCt5eHDEG5/ZQAUX2Kct02zfiPLsKg==",
-            "dependencies": {
-                "glob": "~7.1.1",
-                "lodash": "~4.17.10",
-                "minimatch": "~3.0.2"
-            },
-            "engines": {
-                "node": ">= 0.10"
-            }
-        },
-        "node_modules/globule/node_modules/glob": {
-            "version": "7.1.7",
-            "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
-            "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
-            "dependencies": {
-                "fs.realpath": "^1.0.0",
-                "inflight": "^1.0.4",
-                "inherits": "2",
-                "minimatch": "^3.0.4",
-                "once": "^1.3.0",
-                "path-is-absolute": "^1.0.0"
-            },
-            "engines": {
-                "node": "*"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/isaacs"
-            }
-        },
-        "node_modules/globule/node_modules/minimatch": {
-            "version": "3.0.8",
-            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz",
-            "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==",
-            "dependencies": {
-                "brace-expansion": "^1.1.7"
-            },
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/golden-layout": {
-            "version": "1.5.9",
-            "resolved": "https://registry.npmjs.org/golden-layout/-/golden-layout-1.5.9.tgz",
-            "integrity": "sha1-o5vB9qZ+b4hreXwBbdkk6UJrp38=",
-            "dependencies": {
-                "jquery": "*"
-            }
-        },
-        "node_modules/good-listener": {
-            "version": "1.2.2",
-            "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
-            "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
-            "dependencies": {
-                "delegate": "^3.1.2"
-            }
-        },
-        "node_modules/google-auth-library": {
-            "version": "4.2.6",
-            "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-4.2.6.tgz",
-            "integrity": "sha512-oJ6tCA9rbsYeIVY+mcLPFHa2hatz3XO6idYIrlI/KhhlMxZrO3tKyU8O2Pxu5KnSBBP7Wj4HtbM1LLKngNFaFw==",
-            "dependencies": {
-                "arrify": "^2.0.0",
-                "base64-js": "^1.3.0",
-                "fast-text-encoding": "^1.0.0",
-                "gaxios": "^2.0.0",
-                "gcp-metadata": "^2.0.0",
-                "gtoken": "^3.0.0",
-                "jws": "^3.1.5",
-                "lru-cache": "^5.0.0"
-            },
-            "engines": {
-                "node": ">=8.10.0"
-            }
-        },
-        "node_modules/google-auth-library/node_modules/lru-cache": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
-            "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
-            "dependencies": {
-                "yallist": "^3.0.2"
-            }
-        },
-        "node_modules/google-auth-library/node_modules/yallist": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
-            "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
-        },
-        "node_modules/google-maps-react": {
-            "version": "2.0.6",
-            "resolved": "https://registry.npmjs.org/google-maps-react/-/google-maps-react-2.0.6.tgz",
-            "integrity": "sha512-M8Eo9WndfQEfxcmm6yRq03qdJgw1x6rQmJ9DN+a+xPQ3K7yNDGkVDbinrf4/8vcox7nELbeopbm4bpefKewWfQ==",
-            "peerDependencies": {
-                "react": "~0.14.8 || ^15.0.0 || ^16.0.0",
-                "react-dom": "~0.14.8 || ^15.0.0 || ^16.0.0"
-            }
-        },
-        "node_modules/google-p12-pem": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.5.tgz",
-            "integrity": "sha512-7RLkxwSsMsYh9wQ5Vb2zRtkAHvqPvfoMGag+nugl1noYO7gf0844Yr9TIFA5NEBMAeVt2Z+Imu7CQMp3oNatzQ==",
-            "dependencies": {
-                "node-forge": "^0.10.0"
-            },
-            "bin": {
-                "gp12-pem": "build/src/bin/gp12-pem.js"
-            },
-            "engines": {
-                "node": ">=8.10.0"
-            }
-        },
-        "node_modules/googleapis": {
-            "version": "40.0.1",
-            "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-40.0.1.tgz",
-            "integrity": "sha512-B6qZVCautOOspEhru9GZ814I+ztkGWyA4ZEUfaXwXHBruX/HAWqedbsuUEx1w3nCECywK/FLTNUdcbH9zpaMaw==",
-            "dependencies": {
-                "google-auth-library": "^4.0.0",
-                "googleapis-common": "^2.0.2"
-            },
-            "engines": {
-                "node": ">=8.10.0"
-            }
-        },
-        "node_modules/googleapis-common": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-2.0.4.tgz",
-            "integrity": "sha512-8RRkxr24v1jIKCC1onFWA8RGnwFV55m3Qpil9DLX1yLc9e5qvOJsRoDOhhD2e7jFRONYEhT/BzT8vJZANqSr9w==",
-            "dependencies": {
-                "extend": "^3.0.2",
-                "gaxios": "^2.0.1",
-                "google-auth-library": "^4.2.5",
-                "qs": "^6.7.0",
-                "url-template": "^2.0.8",
-                "uuid": "^3.3.2"
-            },
-            "engines": {
-                "node": ">=8.10.0"
-            }
-        },
-        "node_modules/googleapis-common/node_modules/qs": {
-            "version": "6.10.5",
-            "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.5.tgz",
-            "integrity": "sha512-O5RlPh0VFtR78y79rgcgKK4wbAI0C5zGVLztOIdpWX6ep368q5Hv6XRxDvXuZ9q3C6v+e3n8UfZZJw7IIG27eQ==",
-            "deprecated": "when using stringify with arrayFormat comma, `[]` is appended on single-item arrays. Upgrade to v6.11.0 or downgrade to v6.10.4 to fix.",
-            "dependencies": {
-                "side-channel": "^1.0.4"
-            },
-            "engines": {
-                "node": ">=0.6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/googlephotos": {
-            "version": "0.2.5",
-            "resolved": "https://registry.npmjs.org/googlephotos/-/googlephotos-0.2.5.tgz",
-            "integrity": "sha512-XPmD3gu8aMVuwauKVzzahD2Vn8Cn8WtBRGgSF5J9A85Fn6N2GM0OToxWbEoTfyKahK+ryGHGcIYzDX98ndxE9g==",
-            "dependencies": {
-                "lodash.chunk": "^4.2.0",
-                "request": "^2.86.0",
-                "request-promise": "^4.2.2"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/got": {
-            "version": "12.1.0",
-            "resolved": "https://registry.npmjs.org/got/-/got-12.1.0.tgz",
-            "integrity": "sha512-hBv2ty9QN2RdbJJMK3hesmSkFTjVIHyIDDbssCKnSmq62edGgImJWD10Eb1k77TiV1bxloxqcFAVK8+9pkhOig==",
-            "dependencies": {
-                "@sindresorhus/is": "^4.6.0",
-                "@szmarczak/http-timer": "^5.0.1",
-                "@types/cacheable-request": "^6.0.2",
-                "@types/responselike": "^1.0.0",
-                "cacheable-lookup": "^6.0.4",
-                "cacheable-request": "^7.0.2",
-                "decompress-response": "^6.0.0",
-                "form-data-encoder": "1.7.1",
-                "get-stream": "^6.0.1",
-                "http2-wrapper": "^2.1.10",
-                "lowercase-keys": "^3.0.0",
-                "p-cancelable": "^3.0.0",
-                "responselike": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=14.16"
-            },
-            "funding": {
-                "url": "https://github.com/sindresorhus/got?sponsor=1"
-            }
-        },
-        "node_modules/got/node_modules/decompress-response": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
-            "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
-            "dependencies": {
-                "mimic-response": "^3.1.0"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/got/node_modules/mimic-response": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
-            "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/graceful-fs": {
-            "version": "4.2.10",
-            "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
-            "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
-        },
-        "node_modules/growl": {
-            "version": "1.10.5",
-            "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
-            "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
-            "engines": {
-                "node": ">=4.x"
-            }
-        },
-        "node_modules/gtoken": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-3.0.2.tgz",
-            "integrity": "sha512-BOBi6Zz31JfxhSHRZBIDdbwIbOPyux10WxJHdx8wz/FMP1zyN1xFrsAWsgcLe5ww5v/OZu/MePUEZAjgJXSauA==",
-            "dependencies": {
-                "gaxios": "^2.0.0",
-                "google-p12-pem": "^2.0.0",
-                "jws": "^3.1.5",
-                "mime": "^2.2.0"
-            },
-            "engines": {
-                "node": ">=8.10.0"
-            }
-        },
-        "node_modules/gtoken/node_modules/mime": {
-            "version": "2.6.0",
-            "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
-            "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
-            "bin": {
-                "mime": "cli.js"
-            },
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/gud": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz",
-            "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw=="
-        },
-        "node_modules/handle-thing": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
-            "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==",
-            "dev": true
-        },
-        "node_modules/har-schema": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
-            "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/har-validator": {
-            "version": "5.1.5",
-            "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
-            "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
-            "deprecated": "this library is no longer supported",
-            "dependencies": {
-                "ajv": "^6.12.3",
-                "har-schema": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/has": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
-            "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
-            "dependencies": {
-                "function-bind": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4.0"
-            }
-        },
-        "node_modules/has-ansi": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
-            "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
-            "dependencies": {
-                "ansi-regex": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/has-ansi/node_modules/ansi-regex": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-            "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/has-bigints": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
-            "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/has-binary2": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
-            "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==",
-            "dependencies": {
-                "isarray": "2.0.1"
-            }
-        },
-        "node_modules/has-binary2/node_modules/isarray": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
-            "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ=="
-        },
-        "node_modules/has-cors": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
-            "integrity": "sha512-g5VNKdkFuUuVCP9gYfDJHjK2nqdQJ7aDLTnycnc2+RvsOQbuLdF5pm7vuE5J76SEBIQjs4kQY/BWq74JUmjbXA=="
-        },
-        "node_modules/has-flag": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-            "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/has-property-descriptors": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
-            "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
-            "dependencies": {
-                "get-intrinsic": "^1.1.1"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/has-symbols": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
-            "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/has-tostringtag": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
-            "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
-            "dependencies": {
-                "has-symbols": "^1.0.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/has-unicode": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
-            "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
-        },
-        "node_modules/has-value": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
-            "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
-            "dependencies": {
-                "get-value": "^2.0.6",
-                "has-values": "^1.0.0",
-                "isobject": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/has-values": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
-            "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
-            "dependencies": {
-                "is-number": "^3.0.0",
-                "kind-of": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/has-values/node_modules/is-buffer": {
-            "version": "1.1.6",
-            "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-            "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
-        },
-        "node_modules/has-values/node_modules/kind-of": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
-            "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
-            "dependencies": {
-                "is-buffer": "^1.1.5"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/hast-to-hyperscript": {
-            "version": "10.0.1",
-            "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-10.0.1.tgz",
-            "integrity": "sha512-dhIVGoKCQVewFi+vz3Vt567E4ejMppS1haBRL6TEmeLeJVB1i/FJIIg/e6s1Bwn0g5qtYojHEKvyGA+OZuyifw==",
-            "dependencies": {
-                "@types/unist": "^2.0.0",
-                "comma-separated-tokens": "^2.0.0",
-                "property-information": "^6.0.0",
-                "space-separated-tokens": "^2.0.0",
-                "style-to-object": "^0.3.0",
-                "unist-util-is": "^5.0.0",
-                "web-namespaces": "^2.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/hast-util-from-parse5": {
-            "version": "7.1.0",
-            "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.0.tgz",
-            "integrity": "sha512-m8yhANIAccpU4K6+121KpPP55sSl9/samzQSQGpb0mTExcNh2WlvjtMwSWFhg6uqD4Rr6Nfa8N6TMypQM51rzQ==",
-            "dependencies": {
-                "@types/hast": "^2.0.0",
-                "@types/parse5": "^6.0.0",
-                "@types/unist": "^2.0.0",
-                "hastscript": "^7.0.0",
-                "property-information": "^6.0.0",
-                "vfile": "^5.0.0",
-                "vfile-location": "^4.0.0",
-                "web-namespaces": "^2.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/hast-util-parse-selector": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.0.tgz",
-            "integrity": "sha512-AyjlI2pTAZEOeu7GeBPZhROx0RHBnydkQIXlhnFzDi0qfXTmGUWoCYZtomHbrdrheV4VFUlPcfJ6LMF5T6sQzg==",
-            "dependencies": {
-                "@types/hast": "^2.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/hast-util-raw": {
-            "version": "7.2.2",
-            "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-7.2.2.tgz",
-            "integrity": "sha512-0x3BhhdlBcqRIKyc095lBSDvmQNMY3Eulj2PLsT5XCyKYrxssI5yr3P4Kv/PBo1s/DMkZy2voGkMXECnFCZRLQ==",
-            "dependencies": {
-                "@types/hast": "^2.0.0",
-                "@types/parse5": "^6.0.0",
-                "hast-util-from-parse5": "^7.0.0",
-                "hast-util-to-parse5": "^7.0.0",
-                "html-void-elements": "^2.0.0",
-                "parse5": "^6.0.0",
-                "unist-util-position": "^4.0.0",
-                "unist-util-visit": "^4.0.0",
-                "vfile": "^5.0.0",
-                "web-namespaces": "^2.0.0",
-                "zwitch": "^2.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/hast-util-raw/node_modules/parse5": {
-            "version": "6.0.1",
-            "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
-            "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
-        },
-        "node_modules/hast-util-to-parse5": {
-            "version": "7.0.0",
-            "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-7.0.0.tgz",
-            "integrity": "sha512-YHiS6aTaZ3N0Q3nxaY/Tj98D6kM8QX5Q8xqgg8G45zR7PvWnPGPP0vcKCgb/moIydEJ/QWczVrX0JODCVeoV7A==",
-            "dependencies": {
-                "@types/hast": "^2.0.0",
-                "@types/parse5": "^6.0.0",
-                "hast-to-hyperscript": "^10.0.0",
-                "property-information": "^6.0.0",
-                "web-namespaces": "^2.0.0",
-                "zwitch": "^2.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/hast-util-whitespace": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz",
-            "integrity": "sha512-Pkw+xBHuV6xFeJprJe2BBEoDV+AvQySaz3pPDRUs5PNZEMQjpXJJueqrpcHIXxnWTcAGi/UOCgVShlkY6kLoqg==",
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/hastscript": {
-            "version": "7.0.2",
-            "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.0.2.tgz",
-            "integrity": "sha512-uA8ooUY4ipaBvKcMuPehTAB/YfFLSSzCwFSwT6ltJbocFUKH/GDHLN+tflq7lSRf9H86uOuxOFkh1KgIy3Gg2g==",
-            "dependencies": {
-                "@types/hast": "^2.0.0",
-                "comma-separated-tokens": "^2.0.0",
-                "hast-util-parse-selector": "^3.0.0",
-                "property-information": "^6.0.0",
-                "space-separated-tokens": "^2.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/he": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
-            "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
-            "bin": {
-                "he": "bin/he"
-            }
-        },
-        "node_modules/hoist-non-react-statics": {
-            "version": "3.3.2",
-            "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
-            "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
-            "dependencies": {
-                "react-is": "^16.7.0"
-            }
-        },
-        "node_modules/hosted-git-info": {
-            "version": "2.8.9",
-            "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
-            "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="
-        },
-        "node_modules/howler": {
-            "version": "2.2.3",
-            "resolved": "https://registry.npmjs.org/howler/-/howler-2.2.3.tgz",
-            "integrity": "sha512-QM0FFkw0LRX1PR8pNzJVAY25JhIWvbKMBFM4gqk+QdV+kPXOhleWGCB6AiAF/goGjIHK2e/nIElplvjQwhr0jg=="
-        },
-        "node_modules/hpack.js": {
-            "version": "2.1.6",
-            "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
-            "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
-            "dev": true,
-            "dependencies": {
-                "inherits": "^2.0.1",
-                "obuf": "^1.0.0",
-                "readable-stream": "^2.0.1",
-                "wbuf": "^1.1.0"
-            }
-        },
-        "node_modules/hpack.js/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dev": true,
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/html": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/html/-/html-1.0.0.tgz",
-            "integrity": "sha1-pUT6nqVJK/s6LMqCEKEL57WvH2E=",
-            "dependencies": {
-                "concat-stream": "^1.4.7"
-            },
-            "bin": {
-                "html": "bin/html.js"
-            }
-        },
-        "node_modules/html-encoding-sniffer": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz",
-            "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==",
-            "dev": true,
-            "dependencies": {
-                "whatwg-encoding": "^1.0.1"
-            }
-        },
-        "node_modules/html-entities": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz",
-            "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==",
-            "dev": true
-        },
-        "node_modules/html-minifier-terser": {
-            "version": "6.1.0",
-            "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
-            "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==",
-            "dependencies": {
-                "camel-case": "^4.1.2",
-                "clean-css": "^5.2.2",
-                "commander": "^8.3.0",
-                "he": "^1.2.0",
-                "param-case": "^3.0.4",
-                "relateurl": "^0.2.7",
-                "terser": "^5.10.0"
-            },
-            "bin": {
-                "html-minifier-terser": "cli.js"
-            },
-            "engines": {
-                "node": ">=12"
-            }
-        },
-        "node_modules/html-to-image": {
-            "version": "0.1.3",
-            "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-0.1.3.tgz",
-            "integrity": "sha512-8JTGEAAdJGL/nlp3wb/WI8fLMx2dHKOFZMdsvdon23D45ZdtsXDeRm39Wddf04ludQe3OPmvjMJ9nPjI/7hPlg=="
-        },
-        "node_modules/html-to-text": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-5.1.1.tgz",
-            "integrity": "sha512-Bci6bD/JIfZSvG4s0gW/9mMKwBRoe/1RWLxUME/d6WUSZCdY7T60bssf/jFf7EYXRyqU4P5xdClVqiYU0/ypdA==",
-            "dependencies": {
-                "he": "^1.2.0",
-                "htmlparser2": "^3.10.1",
-                "lodash": "^4.17.11",
-                "minimist": "^1.2.0"
-            },
-            "bin": {
-                "html-to-text": "bin/cli.js"
-            },
-            "engines": {
-                "node": ">= 4.0.0"
-            }
-        },
-        "node_modules/html-void-elements": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz",
-            "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==",
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/wooorm"
-            }
-        },
-        "node_modules/html-webpack-plugin": {
-            "version": "5.5.0",
-            "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz",
-            "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==",
-            "dependencies": {
-                "@types/html-minifier-terser": "^6.0.0",
-                "html-minifier-terser": "^6.0.2",
-                "lodash": "^4.17.21",
-                "pretty-error": "^4.0.0",
-                "tapable": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=10.13.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/html-webpack-plugin"
-            },
-            "peerDependencies": {
-                "webpack": "^5.20.0"
-            }
-        },
-        "node_modules/htmlparser2": {
-            "version": "3.10.1",
-            "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
-            "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
-            "dependencies": {
-                "domelementtype": "^1.3.1",
-                "domhandler": "^2.3.0",
-                "domutils": "^1.5.1",
-                "entities": "^1.1.1",
-                "inherits": "^2.0.1",
-                "readable-stream": "^3.1.1"
-            }
-        },
-        "node_modules/http-browserify": {
-            "version": "1.7.0",
-            "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz",
-            "integrity": "sha1-M3la3nLfiKz7/TZ3PO/tp2RzWyA=",
-            "dependencies": {
-                "Base64": "~0.2.0",
-                "inherits": "~2.0.1"
-            }
-        },
-        "node_modules/http-cache-semantics": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
-            "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ=="
-        },
-        "node_modules/http-deceiver": {
-            "version": "1.2.7",
-            "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
-            "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
-            "dev": true
-        },
-        "node_modules/http-errors": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
-            "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
-            "dependencies": {
-                "depd": "2.0.0",
-                "inherits": "2.0.4",
-                "setprototypeof": "1.2.0",
-                "statuses": "2.0.1",
-                "toidentifier": "1.0.1"
-            },
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/http-parser-js": {
-            "version": "0.5.6",
-            "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz",
-            "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==",
-            "dev": true
-        },
-        "node_modules/http-proxy": {
-            "version": "1.18.1",
-            "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
-            "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
-            "dev": true,
-            "dependencies": {
-                "eventemitter3": "^4.0.0",
-                "follow-redirects": "^1.0.0",
-                "requires-port": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=8.0.0"
-            }
-        },
-        "node_modules/http-proxy-middleware": {
-            "version": "0.19.1",
-            "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz",
-            "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==",
-            "dev": true,
-            "dependencies": {
-                "http-proxy": "^1.17.0",
-                "is-glob": "^4.0.0",
-                "lodash": "^4.17.11",
-                "micromatch": "^3.1.10"
-            },
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/http-signature": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
-            "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
-            "dependencies": {
-                "assert-plus": "^1.0.0",
-                "jsprim": "^1.2.2",
-                "sshpk": "^1.7.0"
-            },
-            "engines": {
-                "node": ">=0.8",
-                "npm": ">=1.3.7"
-            }
-        },
-        "node_modules/http2-wrapper": {
-            "version": "2.1.11",
-            "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.1.11.tgz",
-            "integrity": "sha512-aNAk5JzLturWEUiuhAN73Jcbq96R7rTitAoXV54FYMatvihnpD2+6PUgU4ce3D/m5VDbw+F5CsyKSF176ptitQ==",
-            "dependencies": {
-                "quick-lru": "^5.1.1",
-                "resolve-alpn": "^1.2.0"
-            },
-            "engines": {
-                "node": ">=10.19.0"
-            }
-        },
-        "node_modules/https": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/https/-/https-1.0.0.tgz",
-            "integrity": "sha1-PDfHrhqO65ZpBKKtHpdaGUt+06Q="
-        },
-        "node_modules/https-browserify": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
-            "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
-        },
-        "node_modules/https-proxy-agent": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
-            "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
-            "dependencies": {
-                "agent-base": "6",
-                "debug": "4"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/https-proxy-agent/node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/https-proxy-agent/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
-        },
-        "node_modules/hyntax": {
-            "version": "1.1.9",
-            "resolved": "https://registry.npmjs.org/hyntax/-/hyntax-1.1.9.tgz",
-            "integrity": "sha512-xjxyDLbVDdLgjPnl4NM+Iu6il3UPmk6PNCBXruQKeuKDc/HtaZx1hk1AtMgw3vsn9YnLZRfoBpPxYMXcoT5KAA==",
-            "engines": {
-                "node": ">=6.11.1",
-                "npm": ">=5.3.0"
-            }
-        },
-        "node_modules/hyphenate-style-name": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
-            "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
-        },
-        "node_modules/i": {
-            "version": "0.3.7",
-            "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz",
-            "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==",
-            "engines": {
-                "node": ">=0.4"
-            }
-        },
-        "node_modules/iconv-lite": {
-            "version": "0.6.3",
-            "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
-            "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
-            "dependencies": {
-                "safer-buffer": ">= 2.1.2 < 3.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/icss-replace-symbols": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz",
-            "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=",
-            "dev": true
-        },
-        "node_modules/icss-utils": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz",
-            "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==",
-            "dev": true,
-            "dependencies": {
-                "postcss": "^7.0.14"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/ieee754": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
-            "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ]
-        },
-        "node_modules/iferr": {
-            "version": "0.1.5",
-            "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
-            "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
-            "dev": true
-        },
-        "node_modules/ignore": {
-            "version": "3.3.10",
-            "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
-            "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
-            "dev": true
-        },
-        "node_modules/ignore-by-default": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
-            "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk="
-        },
-        "node_modules/iink-js": {
-            "version": "1.5.4",
-            "resolved": "https://registry.npmjs.org/iink-js/-/iink-js-1.5.4.tgz",
-            "integrity": "sha512-WcjMmyXbSo4GY56AVVTKRyxlguh2KAGFyoH24+Zmm87ZWII12or2uLiovAyOK4IE+VVz7m0U5RMuv8i/RV/3Nw==",
-            "dependencies": {
-                "@babel/runtime": "^7.9.2",
-                "clipboard": "^1.7.1",
-                "crypto-js": "^3.3.0",
-                "d3-selection": "^1.4.1",
-                "json-css": "^1.5.6",
-                "lodash.merge": "^4.6.2",
-                "loglevel": "^1.6.8",
-                "perfect-scrollbar": "^1.5.0",
-                "uuid-js": "^0.7.5"
-            }
-        },
-        "node_modules/iink-js/node_modules/d3-selection": {
-            "version": "1.4.2",
-            "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz",
-            "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg=="
-        },
-        "node_modules/image-data-uri": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/image-data-uri/-/image-data-uri-2.0.1.tgz",
-            "integrity": "sha512-BZh721F2Q5TwBdwpiqrBrHEdj8daj8KuMZK/DOCyqQlz1CqFhhuZWbK5ZCUnAvFJr8LaKHTaWl9ja3/a3DC2Ew==",
-            "dependencies": {
-                "fs-extra": "^0.26.7",
-                "magicli": "0.0.8",
-                "mime-types": "^2.1.18",
-                "request": "^2.88.0"
-            },
-            "bin": {
-                "image-data-uri": "bin/magicli.js"
-            }
-        },
-        "node_modules/image-size": {
-            "version": "0.7.5",
-            "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.7.5.tgz",
-            "integrity": "sha512-Hiyv+mXHfFEP7LzUL/llg9RwFxxY+o9N3JVLIeG5E7iFIFAalxvRU9UZthBdYDEVnzHMgjnKJPPpay5BWf1g9g==",
-            "bin": {
-                "image-size": "bin/image-size.js"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/image-size-stream": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/image-size-stream/-/image-size-stream-1.1.0.tgz",
-            "integrity": "sha1-Ivou2mbG31AQh0bacUkmSy0l+Gs=",
-            "dependencies": {
-                "image-size": "git+https://github.com/netroy/image-size#da2c863807a3e9602617bdd357b0de3ab4a064c1",
-                "readable-stream": "^1.0.33",
-                "tryit": "^1.0.1"
-            }
-        },
-        "node_modules/image-size-stream/node_modules/image-size": {
-            "version": "0.3.5",
-            "resolved": "git+ssh://git@github.com/netroy/image-size.git#da2c863807a3e9602617bdd357b0de3ab4a064c1",
-            "integrity": "sha512-uyD859OMLz7/XjPgTOsyk5G/zL3xq1iBaPKLdslIEeMt7SBxsLbMeTsey5NSFnEEbHeRNl2CTw9jA5z1NYd2pw==",
-            "license": "MIT",
-            "bin": {
-                "image-size": "bin/image-size"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/image-size-stream/node_modules/isarray": {
-            "version": "0.0.1",
-            "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
-            "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
-        },
-        "node_modules/image-size-stream/node_modules/readable-stream": {
-            "version": "1.1.14",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
-            "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.1",
-                "isarray": "0.0.1",
-                "string_decoder": "~0.10.x"
-            }
-        },
-        "node_modules/image-size-stream/node_modules/string_decoder": {
-            "version": "0.10.31",
-            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
-            "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
-        },
-        "node_modules/immediate": {
-            "version": "3.0.6",
-            "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
-            "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
-        },
-        "node_modules/import-fresh": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
-            "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
-            "dependencies": {
-                "parent-module": "^1.0.0",
-                "resolve-from": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/import-lazy": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
-            "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/import-local": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
-            "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
-            "dependencies": {
-                "pkg-dir": "^4.2.0",
-                "resolve-cwd": "^3.0.0"
-            },
-            "bin": {
-                "import-local-fixture": "fixtures/cli.js"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/imurmurhash": {
-            "version": "0.1.4",
-            "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-            "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
-            "engines": {
-                "node": ">=0.8.19"
-            }
-        },
-        "node_modules/in-publish": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz",
-            "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==",
-            "bin": {
-                "in-install": "in-install.js",
-                "in-publish": "in-publish.js",
-                "not-in-install": "not-in-install.js",
-                "not-in-publish": "not-in-publish.js"
-            }
-        },
-        "node_modules/indent-string": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
-            "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
-            "dependencies": {
-                "repeating": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/indexof": {
-            "version": "0.0.1",
-            "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
-            "integrity": "sha512-i0G7hLJ1z0DE8dsqJa2rycj9dBmNKgXBvotXtZYXakU9oivfB9Uj2ZBC27qqef2U58/ZLwalxa1X/RDCdkHtVg=="
-        },
-        "node_modules/inflight": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-            "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
-            "dependencies": {
-                "once": "^1.3.0",
-                "wrappy": "1"
-            }
-        },
-        "node_modules/infobox-parser": {
-            "version": "3.6.2",
-            "resolved": "https://registry.npmjs.org/infobox-parser/-/infobox-parser-3.6.2.tgz",
-            "integrity": "sha512-lasdwvbtjCtDDO6mArAs/ueFEnBJRyo2UbZPAkd5rEG5NVJ3XFCOvbMwNTT/rJlFv1+ORw8D3UvZV4brpgATCg==",
-            "dependencies": {
-                "camelcase": "^4.1.0"
-            },
-            "funding": {
-                "type": "individual",
-                "url": "https://www.buymeacoffee.com/2tmRKi9"
-            }
-        },
-        "node_modules/infobox-parser/node_modules/camelcase": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-            "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/inherits": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-            "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
-        },
-        "node_modules/ini": {
-            "version": "1.3.8",
-            "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
-            "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
-        },
-        "node_modules/inline-style-parser": {
-            "version": "0.1.1",
-            "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz",
-            "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="
-        },
-        "node_modules/inline-style-prefixer": {
-            "version": "3.0.8",
-            "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-3.0.8.tgz",
-            "integrity": "sha1-hVG45bTVcyROZqNLBPfTIHaitTQ=",
-            "dependencies": {
-                "bowser": "^1.7.3",
-                "css-in-js-utils": "^2.0.0"
-            }
-        },
-        "node_modules/inquirer": {
-            "version": "7.3.3",
-            "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz",
-            "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==",
-            "dev": true,
-            "dependencies": {
-                "ansi-escapes": "^4.2.1",
-                "chalk": "^4.1.0",
-                "cli-cursor": "^3.1.0",
-                "cli-width": "^3.0.0",
-                "external-editor": "^3.0.3",
-                "figures": "^3.0.0",
-                "lodash": "^4.17.19",
-                "mute-stream": "0.0.8",
-                "run-async": "^2.4.0",
-                "rxjs": "^6.6.0",
-                "string-width": "^4.1.0",
-                "strip-ansi": "^6.0.0",
-                "through": "^2.3.6"
-            },
-            "engines": {
-                "node": ">=8.0.0"
-            }
-        },
-        "node_modules/inquirer/node_modules/ansi-regex": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/inquirer/node_modules/ansi-styles": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-            "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-            "dev": true,
-            "dependencies": {
-                "color-convert": "^2.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-            }
-        },
-        "node_modules/inquirer/node_modules/chalk": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-            "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-            "dev": true,
-            "dependencies": {
-                "ansi-styles": "^4.1.0",
-                "supports-color": "^7.1.0"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/chalk/chalk?sponsor=1"
-            }
-        },
-        "node_modules/inquirer/node_modules/color-convert": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-            "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-            "dev": true,
-            "dependencies": {
-                "color-name": "~1.1.4"
-            },
-            "engines": {
-                "node": ">=7.0.0"
-            }
-        },
-        "node_modules/inquirer/node_modules/color-name": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-            "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-            "dev": true
-        },
-        "node_modules/inquirer/node_modules/emoji-regex": {
-            "version": "8.0.0",
-            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
-            "dev": true
-        },
-        "node_modules/inquirer/node_modules/has-flag": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-            "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/inquirer/node_modules/is-fullwidth-code-point": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-            "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/inquirer/node_modules/string-width": {
-            "version": "4.2.3",
-            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-            "dev": true,
-            "dependencies": {
-                "emoji-regex": "^8.0.0",
-                "is-fullwidth-code-point": "^3.0.0",
-                "strip-ansi": "^6.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/inquirer/node_modules/strip-ansi": {
-            "version": "6.0.1",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-            "dev": true,
-            "dependencies": {
-                "ansi-regex": "^5.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/inquirer/node_modules/supports-color": {
-            "version": "7.2.0",
-            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-            "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-            "dev": true,
-            "dependencies": {
-                "has-flag": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/inspect-function": {
-            "version": "0.2.2",
-            "resolved": "https://registry.npmjs.org/inspect-function/-/inspect-function-0.2.2.tgz",
-            "integrity": "sha1-hdoMUli8TDMK4yg7Z0fgdZ2QpjU=",
-            "dependencies": {
-                "split-skip": "0.0.1",
-                "unpack-string": "0.0.2"
-            }
-        },
-        "node_modules/inspect-function/node_modules/split-skip": {
-            "version": "0.0.1",
-            "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.1.tgz",
-            "integrity": "sha1-gK2ONumOV2RUzDtmfB3SXYZejwA="
-        },
-        "node_modules/inspect-parameters-declaration": {
-            "version": "0.0.9",
-            "resolved": "https://registry.npmjs.org/inspect-parameters-declaration/-/inspect-parameters-declaration-0.0.9.tgz",
-            "integrity": "sha512-c3jrKKA1rwwrsjdGMAo2hFWV0vNe3/RKHxpE/OBt41LP3ynOVI1qmgxpZYK5SQu3jtWCyaho8L7AZzCjJ4mEUw==",
-            "dependencies": {
-                "magicli": "0.0.5",
-                "split-skip": "0.0.2",
-                "stringify-parameters": "0.0.4",
-                "unpack-string": "0.0.2"
-            },
-            "bin": {
-                "inspect-parameters-declaration": "bin/cli.js"
-            }
-        },
-        "node_modules/inspect-parameters-declaration/node_modules/commander": {
-            "version": "2.20.3",
-            "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-            "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
-        },
-        "node_modules/inspect-parameters-declaration/node_modules/magicli": {
-            "version": "0.0.5",
-            "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-            "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
-            "dependencies": {
-                "commander": "^2.9.0",
-                "get-stdin": "^5.0.1",
-                "inspect-function": "^0.2.1",
-                "pipe-functions": "^1.2.0"
-            }
-        },
-        "node_modules/inspect-property": {
-            "version": "0.0.6",
-            "resolved": "https://registry.npmjs.org/inspect-property/-/inspect-property-0.0.6.tgz",
-            "integrity": "sha512-LgjHkRl9W6bj2n+kWrAOgvCYPTYt+LanE4rtd/vKNq6yEb+SvVV7UTLzoSPpDX6/U1cAz7VfqPr+lPAIz7wHaQ==",
-            "dependencies": {
-                "for-each-property": "0.0.4",
-                "for-each-property-deep": "0.0.3",
-                "inspect-function": "^0.3.1"
-            }
-        },
-        "node_modules/inspect-property/node_modules/commander": {
-            "version": "2.20.3",
-            "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-            "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
-        },
-        "node_modules/inspect-property/node_modules/inspect-function": {
-            "version": "0.3.4",
-            "resolved": "https://registry.npmjs.org/inspect-function/-/inspect-function-0.3.4.tgz",
-            "integrity": "sha512-s0RsbJqK/sNZ+U1mykGoTickog3ea1A9Qk4mXniogOBu4PgkkZ56elScO7QC/r8D94lhGmJ2NyDI1ipOA/uq/g==",
-            "dependencies": {
-                "inspect-parameters-declaration": "0.0.8",
-                "magicli": "0.0.8",
-                "split-skip": "0.0.1",
-                "stringify-parameters": "0.0.4",
-                "unpack-string": "0.0.2"
-            },
-            "bin": {
-                "inspect-function": "bin/magicli.js"
-            }
-        },
-        "node_modules/inspect-property/node_modules/inspect-parameters-declaration": {
-            "version": "0.0.8",
-            "resolved": "https://registry.npmjs.org/inspect-parameters-declaration/-/inspect-parameters-declaration-0.0.8.tgz",
-            "integrity": "sha512-W4QzN1LgFmasKOM+NoLlDd2OAZM3enNZlVUOXoGQKmYBDFgxoPDOyebF55ALaf8avyM9TavNwibXxg347RrzCg==",
-            "dependencies": {
-                "magicli": "0.0.5",
-                "split-skip": "0.0.2",
-                "stringify-parameters": "0.0.4",
-                "unpack-string": "0.0.2"
-            },
-            "bin": {
-                "inspect-parameters-declaration": "bin/cli.js"
-            }
-        },
-        "node_modules/inspect-property/node_modules/inspect-parameters-declaration/node_modules/inspect-function": {
-            "version": "0.2.2",
-            "resolved": "https://registry.npmjs.org/inspect-function/-/inspect-function-0.2.2.tgz",
-            "integrity": "sha1-hdoMUli8TDMK4yg7Z0fgdZ2QpjU=",
-            "dependencies": {
-                "split-skip": "0.0.1",
-                "unpack-string": "0.0.2"
-            }
-        },
-        "node_modules/inspect-property/node_modules/inspect-parameters-declaration/node_modules/inspect-function/node_modules/split-skip": {
-            "version": "0.0.1",
-            "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.1.tgz",
-            "integrity": "sha1-gK2ONumOV2RUzDtmfB3SXYZejwA="
-        },
-        "node_modules/inspect-property/node_modules/inspect-parameters-declaration/node_modules/magicli": {
-            "version": "0.0.5",
-            "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-            "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
-            "dependencies": {
-                "commander": "^2.9.0",
-                "get-stdin": "^5.0.1",
-                "inspect-function": "^0.2.1",
-                "pipe-functions": "^1.2.0"
-            }
-        },
-        "node_modules/inspect-property/node_modules/inspect-parameters-declaration/node_modules/split-skip": {
-            "version": "0.0.2",
-            "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.2.tgz",
-            "integrity": "sha1-2J2Iu9L3Pka1FYqjcKVhIk6A1GE="
-        },
-        "node_modules/inspect-property/node_modules/split-skip": {
-            "version": "0.0.1",
-            "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.1.tgz",
-            "integrity": "sha1-gK2ONumOV2RUzDtmfB3SXYZejwA="
-        },
-        "node_modules/internal-ip": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz",
-            "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==",
-            "dev": true,
-            "dependencies": {
-                "default-gateway": "^4.2.0",
-                "ipaddr.js": "^1.9.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/internal-slot": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
-            "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
-            "dependencies": {
-                "get-intrinsic": "^1.1.0",
-                "has": "^1.0.3",
-                "side-channel": "^1.0.4"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/internmap": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz",
-            "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="
-        },
-        "node_modules/interpret": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
-            "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
-            "engines": {
-                "node": ">= 0.10"
-            }
-        },
-        "node_modules/interval-arithmetic": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/interval-arithmetic/-/interval-arithmetic-1.0.6.tgz",
-            "integrity": "sha512-eVotDGYPNiEaJ63oa4CeEHgOczZJ3gNHqG5wfVQ2o8sN2CEczQyR82Sjey/Bp36x8e7PtBcBvitcMnw6VUpjgQ==",
-            "dependencies": {
-                "@types/assert": "^1.4.6",
-                "is-safe-integer": "^2.0.0",
-                "nextafter": "^1.0.0",
-                "typedarray": "0.0.6"
-            }
-        },
-        "node_modules/interval-arithmetic-eval": {
-            "version": "0.4.7",
-            "resolved": "https://registry.npmjs.org/interval-arithmetic-eval/-/interval-arithmetic-eval-0.4.7.tgz",
-            "integrity": "sha512-ClK+N4efbsgjlZR8h0qd0LQbyzUzJ9IkrjmTnD5MVb4Ytebd0lesoVP4AxLclcsEI+nIieskQ8cepHIWUPaRhQ==",
-            "dependencies": {
-                "interval-arithmetic": "^1.0.6",
-                "math-codegen": "^0.3.5"
-            }
-        },
-        "node_modules/invariant": {
-            "version": "2.2.4",
-            "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
-            "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
-            "dependencies": {
-                "loose-envify": "^1.0.0"
-            }
-        },
-        "node_modules/ip": {
-            "version": "1.1.8",
-            "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz",
-            "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==",
-            "dev": true
-        },
-        "node_modules/ip-regex": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
-            "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/ipaddr.js": {
-            "version": "1.9.1",
-            "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
-            "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
-            "engines": {
-                "node": ">= 0.10"
-            }
-        },
-        "node_modules/is-absolute-url": {
-            "version": "3.0.3",
-            "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz",
-            "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/is-accessor-descriptor": {
-            "version": "0.1.6",
-            "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-            "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
-            "dependencies": {
-                "kind-of": "^3.0.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-accessor-descriptor/node_modules/is-buffer": {
-            "version": "1.1.6",
-            "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-            "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
-        },
-        "node_modules/is-accessor-descriptor/node_modules/kind-of": {
-            "version": "3.2.2",
-            "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-            "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-            "dependencies": {
-                "is-buffer": "^1.1.5"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-arguments": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
-            "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-arrayish": {
-            "version": "0.2.1",
-            "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
-            "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
-        },
-        "node_modules/is-bigint": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
-            "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
-            "dependencies": {
-                "has-bigints": "^1.0.1"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-binary-path": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
-            "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
-            "dependencies": {
-                "binary-extensions": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-boolean-object": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
-            "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-buffer": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
-            "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ],
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/is-callable": {
-            "version": "1.2.4",
-            "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
-            "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-ci": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
-            "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
-            "dependencies": {
-                "ci-info": "^1.5.0"
-            },
-            "bin": {
-                "is-ci": "bin.js"
-            }
-        },
-        "node_modules/is-core-module": {
-            "version": "2.9.0",
-            "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
-            "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
-            "dependencies": {
-                "has": "^1.0.3"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-data-descriptor": {
-            "version": "0.1.4",
-            "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-            "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
-            "dependencies": {
-                "kind-of": "^3.0.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-data-descriptor/node_modules/is-buffer": {
-            "version": "1.1.6",
-            "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-            "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
-        },
-        "node_modules/is-data-descriptor/node_modules/kind-of": {
-            "version": "3.2.2",
-            "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-            "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-            "dependencies": {
-                "is-buffer": "^1.1.5"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-date-object": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
-            "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
-            "dependencies": {
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-descriptor": {
-            "version": "0.1.6",
-            "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
-            "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
-            "dependencies": {
-                "is-accessor-descriptor": "^0.1.6",
-                "is-data-descriptor": "^0.1.4",
-                "kind-of": "^5.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-descriptor/node_modules/kind-of": {
-            "version": "5.1.0",
-            "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
-            "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-directory": {
-            "version": "0.3.1",
-            "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
-            "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-expression": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz",
-            "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=",
-            "dependencies": {
-                "acorn": "~4.0.2",
-                "object-assign": "^4.0.1"
-            }
-        },
-        "node_modules/is-expression/node_modules/acorn": {
-            "version": "4.0.13",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
-            "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=",
-            "bin": {
-                "acorn": "bin/acorn"
-            },
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/is-extendable": {
-            "version": "0.1.1",
-            "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-            "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-extglob": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-            "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-finite": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
-            "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==",
-            "engines": {
-                "node": ">=0.10.0"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/is-fullwidth-code-point": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-            "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/is-generator-function": {
-            "version": "1.0.10",
-            "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
-            "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
-            "dependencies": {
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-glob": {
-            "version": "4.0.3",
-            "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-            "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-            "dependencies": {
-                "is-extglob": "^2.1.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-in-browser": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz",
-            "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU="
-        },
-        "node_modules/is-installed-globally": {
-            "version": "0.1.0",
-            "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
-            "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=",
-            "dependencies": {
-                "global-dirs": "^0.1.0",
-                "is-path-inside": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/is-negative-zero": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
-            "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-npm": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
-            "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-number": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
-            "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
-            "dependencies": {
-                "kind-of": "^3.0.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-number-object": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
-            "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
-            "dependencies": {
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-number/node_modules/is-buffer": {
-            "version": "1.1.6",
-            "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-            "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
-        },
-        "node_modules/is-number/node_modules/kind-of": {
-            "version": "3.2.2",
-            "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-            "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-            "dependencies": {
-                "is-buffer": "^1.1.5"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-obj": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
-            "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-path-cwd": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
-            "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/is-path-in-cwd": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz",
-            "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==",
-            "dev": true,
-            "dependencies": {
-                "is-path-inside": "^2.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/is-path-in-cwd/node_modules/is-path-inside": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz",
-            "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==",
-            "dev": true,
-            "dependencies": {
-                "path-is-inside": "^1.0.2"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/is-path-inside": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
-            "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
-            "dependencies": {
-                "path-is-inside": "^1.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-plain-obj": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
-            "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
-            "engines": {
-                "node": ">=12"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/is-plain-object": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
-            "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
-            "dependencies": {
-                "isobject": "^3.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-promise": {
-            "version": "2.2.2",
-            "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
-            "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
-        },
-        "node_modules/is-redirect": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
-            "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-regex": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
-            "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-retry-allowed": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
-            "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-safe-integer": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/is-safe-integer/-/is-safe-integer-2.0.0.tgz",
-            "integrity": "sha512-eDaA39/1+3SNtYTRP28lRYOHMwiB1gfqXQaXcf/+f4mLwKgm8TTDkwJldsdtbgrK1R5CoDbf6AQ0KqP7BKoGtQ==",
-            "deprecated": "This package is no longer relevant as ES2015 support is widespread.",
-            "dependencies": {
-                "max-safe-integer": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-shared-array-buffer": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
-            "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
-            "dependencies": {
-                "call-bind": "^1.0.2"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-stream": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
-            "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-string": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
-            "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
-            "dependencies": {
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-symbol": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
-            "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
-            "dependencies": {
-                "has-symbols": "^1.0.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-typed-array": {
-            "version": "1.1.9",
-            "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz",
-            "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==",
-            "dependencies": {
-                "available-typed-arrays": "^1.0.5",
-                "call-bind": "^1.0.2",
-                "es-abstract": "^1.20.0",
-                "for-each": "^0.3.3",
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-typedarray": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
-            "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
-        },
-        "node_modules/is-url": {
-            "version": "1.2.4",
-            "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
-            "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww=="
-        },
-        "node_modules/is-utf8": {
-            "version": "0.2.1",
-            "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
-            "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI="
-        },
-        "node_modules/is-weakref": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
-            "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
-            "dependencies": {
-                "call-bind": "^1.0.2"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-what": {
-            "version": "3.14.1",
-            "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz",
-            "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA=="
-        },
-        "node_modules/is-windows": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
-            "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-wsl": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
-            "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/isarray": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-            "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
-        },
-        "node_modules/isexe": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-            "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
-        },
-        "node_modules/isobject": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
-            "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/isomorphic-fetch": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
-            "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
-            "dependencies": {
-                "node-fetch": "^1.0.1",
-                "whatwg-fetch": ">=0.10.0"
-            }
-        },
-        "node_modules/isstream": {
-            "version": "0.1.2",
-            "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
-            "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
-        },
-        "node_modules/its-set": {
-            "version": "1.2.3",
-            "resolved": "https://registry.npmjs.org/its-set/-/its-set-1.2.3.tgz",
-            "integrity": "sha512-UQc+xLLn+0a8KKRXRj3OS2kERK8G7zcayPpPULqZnPwuJ1hGWEO8+j0T5eycu7DKXYjezw3pyF8oV1fJkJxV5w==",
-            "dependencies": {
-                "babel-runtime": "6.x.x",
-                "lodash.get": "^4.4.2"
-            }
-        },
-        "node_modules/jest-worker": {
-            "version": "27.5.1",
-            "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
-            "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
-            "dependencies": {
-                "@types/node": "*",
-                "merge-stream": "^2.0.0",
-                "supports-color": "^8.0.0"
-            },
-            "engines": {
-                "node": ">= 10.13.0"
-            }
-        },
-        "node_modules/jest-worker/node_modules/has-flag": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-            "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/jest-worker/node_modules/supports-color": {
-            "version": "8.1.1",
-            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
-            "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
-            "dependencies": {
-                "has-flag": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/chalk/supports-color?sponsor=1"
-            }
-        },
-        "node_modules/jquery": {
-            "version": "3.6.0",
-            "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
-            "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
-        },
-        "node_modules/js-base64": {
-            "version": "2.6.4",
-            "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz",
-            "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ=="
-        },
-        "node_modules/js-datepicker": {
-            "version": "4.6.6",
-            "resolved": "https://registry.npmjs.org/js-datepicker/-/js-datepicker-4.6.6.tgz",
-            "integrity": "sha512-kLsE2oHfQM6pzdWNA7Y8HwCHaZIVURItPds7YVJnbe1z1OmQFzN7lfg6yFbDDWOyNjdHZGzWDy3jSDN2W0pNZQ=="
-        },
-        "node_modules/js-stringify": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz",
-            "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds="
-        },
-        "node_modules/js-tokens": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-            "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
-        },
-        "node_modules/js-yaml": {
-            "version": "3.13.1",
-            "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
-            "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
-            "dependencies": {
-                "argparse": "^1.0.7",
-                "esprima": "^4.0.0"
-            },
-            "bin": {
-                "js-yaml": "bin/js-yaml.js"
-            }
-        },
-        "node_modules/jsbn": {
-            "version": "0.1.1",
-            "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-            "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
-        },
-        "node_modules/jsdom": {
-            "version": "15.2.1",
-            "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-15.2.1.tgz",
-            "integrity": "sha512-fAl1W0/7T2G5vURSyxBzrJ1LSdQn6Tr5UX/xD4PXDx/PDgwygedfW6El/KIj3xJ7FU61TTYnc/l/B7P49Eqt6g==",
-            "dev": true,
-            "dependencies": {
-                "abab": "^2.0.0",
-                "acorn": "^7.1.0",
-                "acorn-globals": "^4.3.2",
-                "array-equal": "^1.0.0",
-                "cssom": "^0.4.1",
-                "cssstyle": "^2.0.0",
-                "data-urls": "^1.1.0",
-                "domexception": "^1.0.1",
-                "escodegen": "^1.11.1",
-                "html-encoding-sniffer": "^1.0.2",
-                "nwsapi": "^2.2.0",
-                "parse5": "5.1.0",
-                "pn": "^1.1.0",
-                "request": "^2.88.0",
-                "request-promise-native": "^1.0.7",
-                "saxes": "^3.1.9",
-                "symbol-tree": "^3.2.2",
-                "tough-cookie": "^3.0.1",
-                "w3c-hr-time": "^1.0.1",
-                "w3c-xmlserializer": "^1.1.2",
-                "webidl-conversions": "^4.0.2",
-                "whatwg-encoding": "^1.0.5",
-                "whatwg-mimetype": "^2.3.0",
-                "whatwg-url": "^7.0.0",
-                "ws": "^7.0.0",
-                "xml-name-validator": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "peerDependencies": {
-                "canvas": "^2.5.0"
-            },
-            "peerDependenciesMeta": {
-                "canvas": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/jsdom/node_modules/acorn": {
-            "version": "7.4.1",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
-            "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
-            "dev": true,
-            "bin": {
-                "acorn": "bin/acorn"
-            },
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/jsdom/node_modules/acorn-globals": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz",
-            "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==",
-            "dev": true,
-            "dependencies": {
-                "acorn": "^6.0.1",
-                "acorn-walk": "^6.0.1"
-            }
-        },
-        "node_modules/jsdom/node_modules/acorn-globals/node_modules/acorn": {
-            "version": "6.4.2",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
-            "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==",
-            "dev": true,
-            "bin": {
-                "acorn": "bin/acorn"
-            },
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/jsdom/node_modules/tough-cookie": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz",
-            "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==",
-            "dev": true,
-            "dependencies": {
-                "ip-regex": "^2.1.0",
-                "psl": "^1.1.28",
-                "punycode": "^2.1.1"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/jsdom/node_modules/tr46": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
-            "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
-            "dev": true,
-            "dependencies": {
-                "punycode": "^2.1.0"
-            }
-        },
-        "node_modules/jsdom/node_modules/webidl-conversions": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
-            "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
-            "dev": true
-        },
-        "node_modules/jsdom/node_modules/whatwg-url": {
-            "version": "7.1.0",
-            "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
-            "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
-            "dev": true,
-            "dependencies": {
-                "lodash.sortby": "^4.7.0",
-                "tr46": "^1.0.1",
-                "webidl-conversions": "^4.0.2"
-            }
-        },
-        "node_modules/jsesc": {
-            "version": "2.5.2",
-            "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
-            "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
-            "bin": {
-                "jsesc": "bin/jsesc"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/json-bigint": {
-            "version": "0.3.1",
-            "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.1.tgz",
-            "integrity": "sha512-DGWnSzmusIreWlEupsUelHrhwmPPE+FiQvg+drKfk2p+bdEYa5mp4PJ8JsCWqae0M2jQNb0HPvnwvf1qOTThzQ==",
-            "dependencies": {
-                "bignumber.js": "^9.0.0"
-            }
-        },
-        "node_modules/json-buffer": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
-            "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
-        },
-        "node_modules/json-css": {
-            "version": "1.5.6",
-            "resolved": "https://registry.npmjs.org/json-css/-/json-css-1.5.6.tgz",
-            "integrity": "sha1-65ZPg0ouTqobwvaY/12wB6JsfAA="
-        },
-        "node_modules/json-parse-better-errors": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
-            "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
-        },
-        "node_modules/json-parse-even-better-errors": {
-            "version": "2.3.1",
-            "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
-            "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
-        },
-        "node_modules/json-schema": {
-            "version": "0.4.0",
-            "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
-            "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
-        },
-        "node_modules/json-schema-traverse": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
-            "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
-        },
-        "node_modules/json-stable-stringify-without-jsonify": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
-            "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
-            "dev": true
-        },
-        "node_modules/json-stringify-safe": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
-            "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
-        },
-        "node_modules/json5": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
-            "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
-            "dependencies": {
-                "minimist": "^1.2.0"
-            },
-            "bin": {
-                "json5": "lib/cli.js"
-            }
-        },
-        "node_modules/jsondiffpatch": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.4.1.tgz",
-            "integrity": "sha512-t0etAxTUk1w5MYdNOkZBZ8rvYYN5iL+2dHCCx/DpkFm/bW28M6y5nUS83D4XdZiHy35Fpaw6LBb+F88fHZnVCw==",
-            "dependencies": {
-                "chalk": "^2.3.0",
-                "diff-match-patch": "^1.0.0"
-            },
-            "bin": {
-                "jsondiffpatch": "bin/jsondiffpatch"
-            },
-            "engines": {
-                "node": ">=8.17.0"
-            }
-        },
-        "node_modules/jsonfile": {
-            "version": "2.4.0",
-            "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
-            "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
-            "optionalDependencies": {
-                "graceful-fs": "^4.1.6"
-            }
-        },
-        "node_modules/jsonschema": {
-            "version": "1.4.1",
-            "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz",
-            "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/jsprim": {
-            "version": "1.4.2",
-            "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
-            "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
-            "dependencies": {
-                "assert-plus": "1.0.0",
-                "extsprintf": "1.3.0",
-                "json-schema": "0.4.0",
-                "verror": "1.10.0"
-            },
-            "engines": {
-                "node": ">=0.6.0"
-            }
-        },
-        "node_modules/jss": {
-            "version": "10.9.0",
-            "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz",
-            "integrity": "sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==",
-            "dependencies": {
-                "@babel/runtime": "^7.3.1",
-                "csstype": "^3.0.2",
-                "is-in-browser": "^1.1.3",
-                "tiny-warning": "^1.0.2"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/jss"
-            }
-        },
-        "node_modules/jss-plugin-camel-case": {
-            "version": "10.9.0",
-            "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.9.0.tgz",
-            "integrity": "sha512-UH6uPpnDk413/r/2Olmw4+y54yEF2lRIV8XIZyuYpgPYTITLlPOsq6XB9qeqv+75SQSg3KLocq5jUBXW8qWWww==",
-            "dependencies": {
-                "@babel/runtime": "^7.3.1",
-                "hyphenate-style-name": "^1.0.3",
-                "jss": "10.9.0"
-            }
-        },
-        "node_modules/jss-plugin-default-unit": {
-            "version": "10.9.0",
-            "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.9.0.tgz",
-            "integrity": "sha512-7Ju4Q9wJ/MZPsxfu4T84mzdn7pLHWeqoGd/D8O3eDNNJ93Xc8PxnLmV8s8ZPNRYkLdxZqKtm1nPQ0BM4JRlq2w==",
-            "dependencies": {
-                "@babel/runtime": "^7.3.1",
-                "jss": "10.9.0"
-            }
-        },
-        "node_modules/jss-plugin-global": {
-            "version": "10.9.0",
-            "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.9.0.tgz",
-            "integrity": "sha512-4G8PHNJ0x6nwAFsEzcuVDiBlyMsj2y3VjmFAx/uHk/R/gzJV+yRHICjT4MKGGu1cJq2hfowFWCyrr/Gg37FbgQ==",
-            "dependencies": {
-                "@babel/runtime": "^7.3.1",
-                "jss": "10.9.0"
-            }
-        },
-        "node_modules/jss-plugin-nested": {
-            "version": "10.9.0",
-            "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.9.0.tgz",
-            "integrity": "sha512-2UJnDrfCZpMYcpPYR16oZB7VAC6b/1QLsRiAutOt7wJaaqwCBvNsosLEu/fUyKNQNGdvg2PPJFDO5AX7dwxtoA==",
-            "dependencies": {
-                "@babel/runtime": "^7.3.1",
-                "jss": "10.9.0",
-                "tiny-warning": "^1.0.2"
-            }
-        },
-        "node_modules/jss-plugin-props-sort": {
-            "version": "10.9.0",
-            "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.9.0.tgz",
-            "integrity": "sha512-7A76HI8bzwqrsMOJTWKx/uD5v+U8piLnp5bvru7g/3ZEQOu1+PjHvv7bFdNO3DwNPC9oM0a//KwIJsIcDCjDzw==",
-            "dependencies": {
-                "@babel/runtime": "^7.3.1",
-                "jss": "10.9.0"
-            }
-        },
-        "node_modules/jss-plugin-rule-value-function": {
-            "version": "10.9.0",
-            "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.9.0.tgz",
-            "integrity": "sha512-IHJv6YrEf8pRzkY207cPmdbBstBaE+z8pazhPShfz0tZSDtRdQua5jjg6NMz3IbTasVx9FdnmptxPqSWL5tyJg==",
-            "dependencies": {
-                "@babel/runtime": "^7.3.1",
-                "jss": "10.9.0",
-                "tiny-warning": "^1.0.2"
-            }
-        },
-        "node_modules/jss-plugin-vendor-prefixer": {
-            "version": "10.9.0",
-            "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.9.0.tgz",
-            "integrity": "sha512-MbvsaXP7iiVdYVSEoi+blrW+AYnTDvHTW6I6zqi7JcwXdc6I9Kbm234nEblayhF38EftoenbM+5218pidmC5gA==",
-            "dependencies": {
-                "@babel/runtime": "^7.3.1",
-                "css-vendor": "^2.0.8",
-                "jss": "10.9.0"
-            }
-        },
-        "node_modules/jss/node_modules/csstype": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-            "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
-        },
-        "node_modules/jstransformer": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz",
-            "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=",
-            "dependencies": {
-                "is-promise": "^2.0.0",
-                "promise": "^7.0.1"
-            }
-        },
-        "node_modules/jsx-ast-utils": {
-            "version": "3.3.2",
-            "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.2.tgz",
-            "integrity": "sha512-4ZCADZHRkno244xlNnn4AOG6sRQ7iBZ5BbgZ4vW4y5IZw7cVUD1PPeblm1xx/nfmMxPdt/LHsXZW8z/j58+l9Q==",
-            "dev": true,
-            "dependencies": {
-                "array-includes": "^3.1.5",
-                "object.assign": "^4.1.2"
-            },
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/jsx-ast-utils/node_modules/object.assign": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
-            "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.0",
-                "define-properties": "^1.1.3",
-                "has-symbols": "^1.0.1",
-                "object-keys": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/jszip": {
-            "version": "3.10.0",
-            "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.0.tgz",
-            "integrity": "sha512-LDfVtOLtOxb9RXkYOwPyNBTQDL4eUbqahtoY6x07GiDJHwSYvn8sHHIw8wINImV3MqbMNve2gSuM1DDqEKk09Q==",
-            "dependencies": {
-                "lie": "~3.3.0",
-                "pako": "~1.0.2",
-                "readable-stream": "~2.3.6",
-                "setimmediate": "^1.0.5"
-            }
-        },
-        "node_modules/jszip/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/jwa": {
-            "version": "1.4.1",
-            "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
-            "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
-            "dependencies": {
-                "buffer-equal-constant-time": "1.0.1",
-                "ecdsa-sig-formatter": "1.0.11",
-                "safe-buffer": "^5.0.1"
-            }
-        },
-        "node_modules/jws": {
-            "version": "3.2.2",
-            "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
-            "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
-            "dependencies": {
-                "jwa": "^1.4.1",
-                "safe-buffer": "^5.0.1"
-            }
-        },
-        "node_modules/kareem": {
-            "version": "2.3.2",
-            "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz",
-            "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ=="
-        },
-        "node_modules/kdbush": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz",
-            "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew=="
-        },
-        "node_modules/keycode": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.1.tgz",
-            "integrity": "sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg=="
-        },
-        "node_modules/keygrip": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
-            "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==",
-            "dependencies": {
-                "tsscmp": "1.0.6"
-            },
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/keyv": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.3.0.tgz",
-            "integrity": "sha512-C30Un9+63J0CsR7Wka5quXKqYZsT6dcRQ2aOwGcSc3RiQ4HGWpTAHlCA+puNfw2jA/s11EsxA1nCXgZRuRKMQQ==",
-            "dependencies": {
-                "compress-brotli": "^1.3.8",
-                "json-buffer": "3.0.1"
-            }
-        },
-        "node_modules/killable": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
-            "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==",
-            "dev": true
-        },
-        "node_modules/kind-of": {
-            "version": "6.0.3",
-            "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
-            "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/klaw": {
-            "version": "1.3.1",
-            "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
-            "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=",
-            "optionalDependencies": {
-                "graceful-fs": "^4.1.9"
-            }
-        },
-        "node_modules/kleur": {
-            "version": "4.1.5",
-            "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
-            "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/language-subtag-registry": {
-            "version": "0.3.22",
-            "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
-            "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==",
-            "dev": true
-        },
-        "node_modules/language-tags": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz",
-            "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==",
-            "dev": true,
-            "dependencies": {
-                "language-subtag-registry": "~0.3.2"
-            }
-        },
-        "node_modules/latest-version": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
-            "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=",
-            "dependencies": {
-                "package-json": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/lazy-cache": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
-            "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/lazystream": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
-            "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
-            "dependencies": {
-                "readable-stream": "^2.0.5"
-            },
-            "engines": {
-                "node": ">= 0.6.3"
-            }
-        },
-        "node_modules/lazystream/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/levn": {
-            "version": "0.3.0",
-            "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
-            "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
-            "dev": true,
-            "dependencies": {
-                "prelude-ls": "~1.1.2",
-                "type-check": "~0.3.2"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/lie": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
-            "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
-            "dependencies": {
-                "immediate": "~3.0.5"
-            }
-        },
-        "node_modules/lines-and-columns": {
-            "version": "1.2.4",
-            "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
-            "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
-        },
-        "node_modules/load-json-file": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
-            "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
-            "dependencies": {
-                "graceful-fs": "^4.1.2",
-                "parse-json": "^2.2.0",
-                "pify": "^2.0.0",
-                "pinkie-promise": "^2.0.0",
-                "strip-bom": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/load-json-file/node_modules/parse-json": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
-            "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
-            "dependencies": {
-                "error-ex": "^1.2.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/loader-runner": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
-            "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
-            "engines": {
-                "node": ">=6.11.5"
-            }
-        },
-        "node_modules/loader-utils": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
-            "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
-            "dependencies": {
-                "big.js": "^5.2.2",
-                "emojis-list": "^3.0.0",
-                "json5": "^1.0.1"
-            },
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/locate-path": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
-            "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
-            "dependencies": {
-                "p-locate": "^3.0.0",
-                "path-exists": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/lodash": {
-            "version": "4.17.21",
-            "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
-            "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
-        },
-        "node_modules/lodash-es": {
-            "version": "4.17.21",
-            "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
-            "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
-        },
-        "node_modules/lodash._getnative": {
-            "version": "3.9.1",
-            "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
-            "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U="
-        },
-        "node_modules/lodash.chunk": {
-            "version": "4.2.0",
-            "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz",
-            "integrity": "sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw="
-        },
-        "node_modules/lodash.curry": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz",
-            "integrity": "sha1-JI42By7ekGUB11lmIAqG2riyMXA="
-        },
-        "node_modules/lodash.debounce": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-3.1.1.tgz",
-            "integrity": "sha1-gSIRw3ipTMKdWqTjNGzwv846ffU=",
-            "dependencies": {
-                "lodash._getnative": "^3.0.0"
-            }
-        },
-        "node_modules/lodash.defaults": {
-            "version": "4.2.0",
-            "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
-            "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
-        },
-        "node_modules/lodash.difference": {
-            "version": "4.5.0",
-            "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
-            "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw="
-        },
-        "node_modules/lodash.flatten": {
-            "version": "4.4.0",
-            "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
-            "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8="
-        },
-        "node_modules/lodash.flow": {
-            "version": "3.5.0",
-            "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz",
-            "integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o="
-        },
-        "node_modules/lodash.get": {
-            "version": "4.4.2",
-            "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
-            "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
-        },
-        "node_modules/lodash.isequal": {
-            "version": "4.5.0",
-            "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
-            "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
-        },
-        "node_modules/lodash.isplainobject": {
-            "version": "4.0.6",
-            "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
-            "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
-        },
-        "node_modules/lodash.memoize": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
-            "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
-        },
-        "node_modules/lodash.merge": {
-            "version": "4.6.2",
-            "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
-            "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
-        },
-        "node_modules/lodash.padend": {
-            "version": "4.6.1",
-            "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz",
-            "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4="
-        },
-        "node_modules/lodash.sortby": {
-            "version": "4.7.0",
-            "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
-            "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
-            "dev": true
-        },
-        "node_modules/lodash.throttle": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
-            "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
-        },
-        "node_modules/lodash.union": {
-            "version": "4.6.0",
-            "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
-            "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg="
-        },
-        "node_modules/log-symbols": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
-            "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
-            "dependencies": {
-                "chalk": "^2.0.1"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/loglevel": {
-            "version": "1.8.0",
-            "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz",
-            "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==",
-            "engines": {
-                "node": ">= 0.6.0"
-            },
-            "funding": {
-                "type": "tidelift",
-                "url": "https://tidelift.com/funding/github/npm/loglevel"
-            }
-        },
-        "node_modules/loglevelnext": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz",
-            "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==",
-            "dev": true,
-            "dependencies": {
-                "es6-symbol": "^3.1.1",
-                "object.assign": "^4.1.0"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/longest": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
-            "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/longest-streak": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.0.1.tgz",
-            "integrity": "sha512-cHlYSUpL2s7Fb3394mYxwTYj8niTaNHUCLr0qdiCXQfSjfuA7CKofpX2uSwEfFDQ0EB7JcnMnm+GjbqqoinYYg==",
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/wooorm"
-            }
-        },
-        "node_modules/loose-envify": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
-            "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
-            "dependencies": {
-                "js-tokens": "^3.0.0 || ^4.0.0"
-            },
-            "bin": {
-                "loose-envify": "cli.js"
-            }
-        },
-        "node_modules/loud-rejection": {
-            "version": "1.6.0",
-            "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
-            "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
-            "dependencies": {
-                "currently-unhandled": "^0.4.1",
-                "signal-exit": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/loupe": {
-            "version": "2.3.4",
-            "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz",
-            "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==",
-            "dependencies": {
-                "get-func-name": "^2.0.0"
-            }
-        },
-        "node_modules/lower-case": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
-            "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
-            "dependencies": {
-                "tslib": "^2.0.3"
-            }
-        },
-        "node_modules/lowercase-keys": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz",
-            "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==",
-            "engines": {
-                "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/lru-cache": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-            "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-            "dependencies": {
-                "yallist": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/magicli": {
-            "version": "0.0.8",
-            "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.8.tgz",
-            "integrity": "sha512-x/eBenweAHF+DsYy172sK4doRxZl0yrJnfxhLJiN7H6hPM3Ya0PfI6uBZshZ3ScFFSQD7HXgBqMdbnXKEZsO1g==",
-            "dependencies": {
-                "cliss": "0.0.2",
-                "find-up": "^2.1.0",
-                "for-each-property": "0.0.4",
-                "inspect-property": "0.0.6"
-            }
-        },
-        "node_modules/magicli/node_modules/find-up": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
-            "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
-            "dependencies": {
-                "locate-path": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/magicli/node_modules/locate-path": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
-            "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
-            "dependencies": {
-                "p-locate": "^2.0.0",
-                "path-exists": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/magicli/node_modules/p-limit": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
-            "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
-            "dependencies": {
-                "p-try": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/magicli/node_modules/p-locate": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
-            "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
-            "dependencies": {
-                "p-limit": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/magicli/node_modules/p-try": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
-            "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/make-dir": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
-            "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
-            "dependencies": {
-                "semver": "^6.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/make-dir/node_modules/semver": {
-            "version": "6.3.0",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-            "bin": {
-                "semver": "bin/semver.js"
-            }
-        },
-        "node_modules/make-error": {
-            "version": "1.3.6",
-            "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
-            "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
-            "dev": true
-        },
-        "node_modules/map-cache": {
-            "version": "0.2.2",
-            "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
-            "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/map-obj": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
-            "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/map-visit": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
-            "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
-            "dependencies": {
-                "object-visit": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/markdown-table": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.2.tgz",
-            "integrity": "sha512-y8j3a5/DkJCmS5x4dMCQL+OR0+2EAq3DOtio1COSHsmW2BGXnNCK3v12hJt1LrUz5iZH5g0LmuYOjDdI+czghA==",
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/wooorm"
-            }
-        },
-        "node_modules/material-colors": {
-            "version": "1.2.6",
-            "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz",
-            "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg=="
-        },
-        "node_modules/material-ui": {
-            "version": "0.20.2",
-            "resolved": "https://registry.npmjs.org/material-ui/-/material-ui-0.20.2.tgz",
-            "integrity": "sha512-VeqgQkdvtK193w+FFvXDEwlVxI4rWk83eWbpYLeOIHDPWr3rbB9B075JRnJt/8IsI2X8q5Aia5W3+7m4KkleDg==",
-            "deprecated": "You can now upgrade to @material-ui/core",
-            "dependencies": {
-                "babel-runtime": "^6.23.0",
-                "inline-style-prefixer": "^3.0.8",
-                "keycode": "^2.1.8",
-                "lodash.merge": "^4.6.0",
-                "lodash.throttle": "^4.1.1",
-                "prop-types": "^15.5.7",
-                "react-event-listener": "^0.6.2",
-                "react-transition-group": "^1.2.1",
-                "recompose": "^0.26.0",
-                "simple-assign": "^0.1.0",
-                "warning": "^3.0.0"
-            },
-            "peerDependencies": {
-                "react": "^15.4.0 || ^16.0.0",
-                "react-dom": "^15.4.0 || ^16.0.0"
-            }
-        },
-        "node_modules/material-ui/node_modules/react-transition-group": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-1.2.1.tgz",
-            "integrity": "sha512-CWaL3laCmgAFdxdKbhhps+c0HRGF4c+hdM4H23+FI1QBNUyx/AMeIJGWorehPNSaKnQNOAxL7PQmqMu78CDj3Q==",
-            "dependencies": {
-                "chain-function": "^1.0.0",
-                "dom-helpers": "^3.2.0",
-                "loose-envify": "^1.3.1",
-                "prop-types": "^15.5.6",
-                "warning": "^3.0.0"
-            },
-            "peerDependencies": {
-                "react": "^15.0.0 || ^16.0.0",
-                "react-dom": "^15.0.0 || ^16.0.0"
-            }
-        },
-        "node_modules/math-codegen": {
-            "version": "0.3.5",
-            "resolved": "https://registry.npmjs.org/math-codegen/-/math-codegen-0.3.5.tgz",
-            "integrity": "sha1-R5nuRnfe0Ud2bQA8ykt4ee3UDMo=",
-            "dependencies": {
-                "extend": "^3.0.0",
-                "mr-parser": "^0.2.1"
-            }
-        },
-        "node_modules/mathquill": {
-            "version": "0.10.1-a",
-            "resolved": "https://registry.npmjs.org/mathquill/-/mathquill-0.10.1-a.tgz",
-            "integrity": "sha512-snSAEwAtwdwBFSor+nVBnWWQtTw67kgAgKMyAIxuz4ZPboy0qkWZmd7BL3lfOXp/INihhRlU1PcfaAtDaRhmzA==",
-            "dependencies": {
-                "jquery": "^1.12.3"
-            }
-        },
-        "node_modules/mathquill/node_modules/jquery": {
-            "version": "1.12.4",
-            "resolved": "https://registry.npmjs.org/jquery/-/jquery-1.12.4.tgz",
-            "integrity": "sha512-UEVp7PPK9xXYSk8xqXCJrkXnKZtlgWkd2GsAQbMRFK6S/ePU2JN5G2Zum8hIVjzR3CpdfSqdqAzId/xd4TJHeg=="
-        },
-        "node_modules/max-safe-integer": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/max-safe-integer/-/max-safe-integer-1.0.1.tgz",
-            "integrity": "sha1-84BgvixWPYwC5tSK85Ei/YO29BA=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/md5-file": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-5.0.0.tgz",
-            "integrity": "sha512-xbEFXCYVWrSx/gEKS1VPlg84h/4L20znVIulKw6kMfmBUAZNAnF00eczz9ICMl+/hjQGo5KSXRxbL/47X3rmMw==",
-            "bin": {
-                "md5-file": "cli.js"
-            },
-            "engines": {
-                "node": ">=10.13.0"
-            }
-        },
-        "node_modules/mdast-util-definitions": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.1.tgz",
-            "integrity": "sha512-rQ+Gv7mHttxHOBx2dkF4HWTg+EE+UR78ptQWDylzPKaQuVGdG4HIoY3SrS/pCp80nZ04greFvXbVFHT+uf0JVQ==",
-            "dependencies": {
-                "@types/mdast": "^3.0.0",
-                "@types/unist": "^2.0.0",
-                "unist-util-visit": "^4.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/mdast-util-find-and-replace": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.2.1.tgz",
-            "integrity": "sha512-SobxkQXFAdd4b5WmEakmkVoh18icjQRxGy5OWTCzgsLRm1Fu/KCtwD1HIQSsmq5ZRjVH0Ehwg6/Fn3xIUk+nKw==",
-            "dependencies": {
-                "escape-string-regexp": "^5.0.0",
-                "unist-util-is": "^5.0.0",
-                "unist-util-visit-parents": "^5.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
-            "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
-            "engines": {
-                "node": ">=12"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/mdast-util-from-markdown": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.2.0.tgz",
-            "integrity": "sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q==",
-            "dependencies": {
-                "@types/mdast": "^3.0.0",
-                "@types/unist": "^2.0.0",
-                "decode-named-character-reference": "^1.0.0",
-                "mdast-util-to-string": "^3.1.0",
-                "micromark": "^3.0.0",
-                "micromark-util-decode-numeric-character-reference": "^1.0.0",
-                "micromark-util-decode-string": "^1.0.0",
-                "micromark-util-normalize-identifier": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0",
-                "micromark-util-types": "^1.0.0",
-                "unist-util-stringify-position": "^3.0.0",
-                "uvu": "^0.5.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/mdast-util-gfm": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-2.0.1.tgz",
-            "integrity": "sha512-42yHBbfWIFisaAfV1eixlabbsa6q7vHeSPY+cg+BBjX51M8xhgMacqH9g6TftB/9+YkcI0ooV4ncfrJslzm/RQ==",
-            "dependencies": {
-                "mdast-util-from-markdown": "^1.0.0",
-                "mdast-util-gfm-autolink-literal": "^1.0.0",
-                "mdast-util-gfm-footnote": "^1.0.0",
-                "mdast-util-gfm-strikethrough": "^1.0.0",
-                "mdast-util-gfm-table": "^1.0.0",
-                "mdast-util-gfm-task-list-item": "^1.0.0",
-                "mdast-util-to-markdown": "^1.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/mdast-util-gfm-autolink-literal": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.2.tgz",
-            "integrity": "sha512-FzopkOd4xTTBeGXhXSBU0OCDDh5lUj2rd+HQqG92Ld+jL4lpUfgX2AT2OHAVP9aEeDKp7G92fuooSZcYJA3cRg==",
-            "dependencies": {
-                "@types/mdast": "^3.0.0",
-                "ccount": "^2.0.0",
-                "mdast-util-find-and-replace": "^2.0.0",
-                "micromark-util-character": "^1.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/mdast-util-gfm-footnote": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-1.0.1.tgz",
-            "integrity": "sha512-p+PrYlkw9DeCRkTVw1duWqPRHX6Ywh2BNKJQcZbCwAuP/59B0Lk9kakuAd7KbQprVO4GzdW8eS5++A9PUSqIyw==",
-            "dependencies": {
-                "@types/mdast": "^3.0.0",
-                "mdast-util-to-markdown": "^1.3.0",
-                "micromark-util-normalize-identifier": "^1.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/mdast-util-gfm-strikethrough": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.1.tgz",
-            "integrity": "sha512-zKJbEPe+JP6EUv0mZ0tQUyLQOC+FADt0bARldONot/nefuISkaZFlmVK4tU6JgfyZGrky02m/I6PmehgAgZgqg==",
-            "dependencies": {
-                "@types/mdast": "^3.0.0",
-                "mdast-util-to-markdown": "^1.3.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/mdast-util-gfm-table": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.4.tgz",
-            "integrity": "sha512-aEuoPwZyP4iIMkf2cLWXxx3EQ6Bmh2yKy9MVCg4i6Sd3cX80dcLEfXO/V4ul3pGH9czBK4kp+FAl+ZHmSUt9/w==",
-            "dependencies": {
-                "markdown-table": "^3.0.0",
-                "mdast-util-from-markdown": "^1.0.0",
-                "mdast-util-to-markdown": "^1.3.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/mdast-util-gfm-task-list-item": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.1.tgz",
-            "integrity": "sha512-KZ4KLmPdABXOsfnM6JHUIjxEvcx2ulk656Z/4Balw071/5qgnhz+H1uGtf2zIGnrnvDC8xR4Fj9uKbjAFGNIeA==",
-            "dependencies": {
-                "@types/mdast": "^3.0.0",
-                "mdast-util-to-markdown": "^1.3.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/mdast-util-to-hast": {
-            "version": "12.2.0",
-            "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.2.0.tgz",
-            "integrity": "sha512-YDwT5KhGzLgPpSnQhAlK1+WpCW4gsPmNNAxUNMkMTDhxQyPp2eX86WOelnKnLKEvSpfxqJbPbInHFkefXZBhEA==",
-            "dependencies": {
-                "@types/hast": "^2.0.0",
-                "@types/mdast": "^3.0.0",
-                "@types/mdurl": "^1.0.0",
-                "mdast-util-definitions": "^5.0.0",
-                "mdurl": "^1.0.0",
-                "micromark-util-sanitize-uri": "^1.0.0",
-                "trim-lines": "^3.0.0",
-                "unist-builder": "^3.0.0",
-                "unist-util-generated": "^2.0.0",
-                "unist-util-position": "^4.0.0",
-                "unist-util-visit": "^4.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/mdast-util-to-markdown": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.3.0.tgz",
-            "integrity": "sha512-6tUSs4r+KK4JGTTiQ7FfHmVOaDrLQJPmpjD6wPMlHGUVXoG9Vjc3jIeP+uyBWRf8clwB2blM+W7+KrlMYQnftA==",
-            "dependencies": {
-                "@types/mdast": "^3.0.0",
-                "@types/unist": "^2.0.0",
-                "longest-streak": "^3.0.0",
-                "mdast-util-to-string": "^3.0.0",
-                "micromark-util-decode-string": "^1.0.0",
-                "unist-util-visit": "^4.0.0",
-                "zwitch": "^2.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/mdast-util-to-string": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.1.0.tgz",
-            "integrity": "sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA==",
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/mdurl": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
-            "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g=="
-        },
-        "node_modules/media-typer": {
-            "version": "0.3.0",
-            "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
-            "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/memfs": {
-            "version": "3.4.4",
-            "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.4.tgz",
-            "integrity": "sha512-W4gHNUE++1oSJVn8Y68jPXi+mkx3fXR5ITE/Ubz6EQ3xRpCN5k2CQ4AUR8094Z7211F876TyoBACGsIveqgiGA==",
-            "dependencies": {
-                "fs-monkey": "1.0.3"
-            },
-            "engines": {
-                "node": ">= 4.0.0"
-            }
-        },
-        "node_modules/memoize-one": {
-            "version": "5.2.1",
-            "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
-            "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
-        },
-        "node_modules/memory-fs": {
-            "version": "0.5.0",
-            "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
-            "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==",
-            "dev": true,
-            "dependencies": {
-                "errno": "^0.1.3",
-                "readable-stream": "^2.0.1"
-            },
-            "engines": {
-                "node": ">=4.3.0 <5.0.0 || >=5.10"
-            }
-        },
-        "node_modules/memory-fs/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dev": true,
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/memory-pager": {
-            "version": "1.5.0",
-            "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
-            "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
-            "optional": true
-        },
-        "node_modules/memorystream": {
-            "version": "0.3.1",
-            "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
-            "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=",
-            "engines": {
-                "node": ">= 0.10.0"
-            }
-        },
-        "node_modules/meow": {
-            "version": "3.7.0",
-            "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
-            "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
-            "dependencies": {
-                "camelcase-keys": "^2.0.0",
-                "decamelize": "^1.1.2",
-                "loud-rejection": "^1.0.0",
-                "map-obj": "^1.0.1",
-                "minimist": "^1.1.3",
-                "normalize-package-data": "^2.3.4",
-                "object-assign": "^4.0.1",
-                "read-pkg-up": "^1.0.1",
-                "redent": "^1.0.0",
-                "trim-newlines": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/merge-anything": {
-            "version": "2.4.4",
-            "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-2.4.4.tgz",
-            "integrity": "sha512-l5XlriUDJKQT12bH+rVhAHjwIuXWdAIecGwsYjv2LJo+dA1AeRTmeQS+3QBpO6lEthBMDi2IUMpLC1yyRvGlwQ==",
-            "dependencies": {
-                "is-what": "^3.3.1"
-            }
-        },
-        "node_modules/merge-descriptors": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
-            "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
-        },
-        "node_modules/merge-stream": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
-            "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
-        },
-        "node_modules/methods": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
-            "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/microevent.ts": {
-            "version": "0.1.1",
-            "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz",
-            "integrity": "sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g==",
-            "dev": true
-        },
-        "node_modules/micromark": {
-            "version": "3.0.10",
-            "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.0.10.tgz",
-            "integrity": "sha512-ryTDy6UUunOXy2HPjelppgJ2sNfcPz1pLlMdA6Rz9jPzhLikWXv/irpWV/I2jd68Uhmny7hHxAlAhk4+vWggpg==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "@types/debug": "^4.0.0",
-                "debug": "^4.0.0",
-                "decode-named-character-reference": "^1.0.0",
-                "micromark-core-commonmark": "^1.0.1",
-                "micromark-factory-space": "^1.0.0",
-                "micromark-util-character": "^1.0.0",
-                "micromark-util-chunked": "^1.0.0",
-                "micromark-util-combine-extensions": "^1.0.0",
-                "micromark-util-decode-numeric-character-reference": "^1.0.0",
-                "micromark-util-encode": "^1.0.0",
-                "micromark-util-normalize-identifier": "^1.0.0",
-                "micromark-util-resolve-all": "^1.0.0",
-                "micromark-util-sanitize-uri": "^1.0.0",
-                "micromark-util-subtokenize": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0",
-                "micromark-util-types": "^1.0.1",
-                "uvu": "^0.5.0"
-            }
-        },
-        "node_modules/micromark-core-commonmark": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.0.6.tgz",
-            "integrity": "sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "decode-named-character-reference": "^1.0.0",
-                "micromark-factory-destination": "^1.0.0",
-                "micromark-factory-label": "^1.0.0",
-                "micromark-factory-space": "^1.0.0",
-                "micromark-factory-title": "^1.0.0",
-                "micromark-factory-whitespace": "^1.0.0",
-                "micromark-util-character": "^1.0.0",
-                "micromark-util-chunked": "^1.0.0",
-                "micromark-util-classify-character": "^1.0.0",
-                "micromark-util-html-tag-name": "^1.0.0",
-                "micromark-util-normalize-identifier": "^1.0.0",
-                "micromark-util-resolve-all": "^1.0.0",
-                "micromark-util-subtokenize": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0",
-                "micromark-util-types": "^1.0.1",
-                "uvu": "^0.5.0"
-            }
-        },
-        "node_modules/micromark-extension-gfm": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-2.0.1.tgz",
-            "integrity": "sha512-p2sGjajLa0iYiGQdT0oelahRYtMWvLjy8J9LOCxzIQsllMCGLbsLW+Nc+N4vi02jcRJvedVJ68cjelKIO6bpDA==",
-            "dependencies": {
-                "micromark-extension-gfm-autolink-literal": "^1.0.0",
-                "micromark-extension-gfm-footnote": "^1.0.0",
-                "micromark-extension-gfm-strikethrough": "^1.0.0",
-                "micromark-extension-gfm-table": "^1.0.0",
-                "micromark-extension-gfm-tagfilter": "^1.0.0",
-                "micromark-extension-gfm-task-list-item": "^1.0.0",
-                "micromark-util-combine-extensions": "^1.0.0",
-                "micromark-util-types": "^1.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/micromark-extension-gfm-autolink-literal": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.3.tgz",
-            "integrity": "sha512-i3dmvU0htawfWED8aHMMAzAVp/F0Z+0bPh3YrbTPPL1v4YAlCZpy5rBO5p0LPYiZo0zFVkoYh7vDU7yQSiCMjg==",
-            "dependencies": {
-                "micromark-util-character": "^1.0.0",
-                "micromark-util-sanitize-uri": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0",
-                "micromark-util-types": "^1.0.0",
-                "uvu": "^0.5.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/micromark-extension-gfm-footnote": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.0.4.tgz",
-            "integrity": "sha512-E/fmPmDqLiMUP8mLJ8NbJWJ4bTw6tS+FEQS8CcuDtZpILuOb2kjLqPEeAePF1djXROHXChM/wPJw0iS4kHCcIg==",
-            "dependencies": {
-                "micromark-core-commonmark": "^1.0.0",
-                "micromark-factory-space": "^1.0.0",
-                "micromark-util-character": "^1.0.0",
-                "micromark-util-normalize-identifier": "^1.0.0",
-                "micromark-util-sanitize-uri": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0",
-                "micromark-util-types": "^1.0.0",
-                "uvu": "^0.5.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/micromark-extension-gfm-strikethrough": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.4.tgz",
-            "integrity": "sha512-/vjHU/lalmjZCT5xt7CcHVJGq8sYRm80z24qAKXzaHzem/xsDYb2yLL+NNVbYvmpLx3O7SYPuGL5pzusL9CLIQ==",
-            "dependencies": {
-                "micromark-util-chunked": "^1.0.0",
-                "micromark-util-classify-character": "^1.0.0",
-                "micromark-util-resolve-all": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0",
-                "micromark-util-types": "^1.0.0",
-                "uvu": "^0.5.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/micromark-extension-gfm-table": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.5.tgz",
-            "integrity": "sha512-xAZ8J1X9W9K3JTJTUL7G6wSKhp2ZYHrFk5qJgY/4B33scJzE2kpfRL6oiw/veJTbt7jiM/1rngLlOKPWr1G+vg==",
-            "dependencies": {
-                "micromark-factory-space": "^1.0.0",
-                "micromark-util-character": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0",
-                "micromark-util-types": "^1.0.0",
-                "uvu": "^0.5.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/micromark-extension-gfm-tagfilter": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.1.tgz",
-            "integrity": "sha512-Ty6psLAcAjboRa/UKUbbUcwjVAv5plxmpUTy2XC/3nJFL37eHej8jrHrRzkqcpipJliuBH30DTs7+3wqNcQUVA==",
-            "dependencies": {
-                "micromark-util-types": "^1.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/micromark-extension-gfm-task-list-item": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.3.tgz",
-            "integrity": "sha512-PpysK2S1Q/5VXi72IIapbi/jliaiOFzv7THH4amwXeYXLq3l1uo8/2Be0Ac1rEwK20MQEsGH2ltAZLNY2KI/0Q==",
-            "dependencies": {
-                "micromark-factory-space": "^1.0.0",
-                "micromark-util-character": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0",
-                "micromark-util-types": "^1.0.0",
-                "uvu": "^0.5.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/micromark-factory-destination": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz",
-            "integrity": "sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "micromark-util-character": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0",
-                "micromark-util-types": "^1.0.0"
-            }
-        },
-        "node_modules/micromark-factory-label": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.0.2.tgz",
-            "integrity": "sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "micromark-util-character": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0",
-                "micromark-util-types": "^1.0.0",
-                "uvu": "^0.5.0"
-            }
-        },
-        "node_modules/micromark-factory-space": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.0.0.tgz",
-            "integrity": "sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "micromark-util-character": "^1.0.0",
-                "micromark-util-types": "^1.0.0"
-            }
-        },
-        "node_modules/micromark-factory-title": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.0.2.tgz",
-            "integrity": "sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "micromark-factory-space": "^1.0.0",
-                "micromark-util-character": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0",
-                "micromark-util-types": "^1.0.0",
-                "uvu": "^0.5.0"
-            }
-        },
-        "node_modules/micromark-factory-whitespace": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.0.0.tgz",
-            "integrity": "sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "micromark-factory-space": "^1.0.0",
-                "micromark-util-character": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0",
-                "micromark-util-types": "^1.0.0"
-            }
-        },
-        "node_modules/micromark-util-character": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.1.0.tgz",
-            "integrity": "sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "micromark-util-symbol": "^1.0.0",
-                "micromark-util-types": "^1.0.0"
-            }
-        },
-        "node_modules/micromark-util-chunked": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.0.0.tgz",
-            "integrity": "sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "micromark-util-symbol": "^1.0.0"
-            }
-        },
-        "node_modules/micromark-util-classify-character": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.0.0.tgz",
-            "integrity": "sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "micromark-util-character": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0",
-                "micromark-util-types": "^1.0.0"
-            }
-        },
-        "node_modules/micromark-util-combine-extensions": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.0.0.tgz",
-            "integrity": "sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "micromark-util-chunked": "^1.0.0",
-                "micromark-util-types": "^1.0.0"
-            }
-        },
-        "node_modules/micromark-util-decode-numeric-character-reference": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.0.0.tgz",
-            "integrity": "sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "micromark-util-symbol": "^1.0.0"
-            }
-        },
-        "node_modules/micromark-util-decode-string": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.0.2.tgz",
-            "integrity": "sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "decode-named-character-reference": "^1.0.0",
-                "micromark-util-character": "^1.0.0",
-                "micromark-util-decode-numeric-character-reference": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0"
-            }
-        },
-        "node_modules/micromark-util-encode": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.0.1.tgz",
-            "integrity": "sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ]
-        },
-        "node_modules/micromark-util-html-tag-name": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.1.0.tgz",
-            "integrity": "sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ]
-        },
-        "node_modules/micromark-util-normalize-identifier": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.0.0.tgz",
-            "integrity": "sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "micromark-util-symbol": "^1.0.0"
-            }
-        },
-        "node_modules/micromark-util-resolve-all": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.0.0.tgz",
-            "integrity": "sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "micromark-util-types": "^1.0.0"
-            }
-        },
-        "node_modules/micromark-util-sanitize-uri": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.0.0.tgz",
-            "integrity": "sha512-cCxvBKlmac4rxCGx6ejlIviRaMKZc0fWm5HdCHEeDWRSkn44l6NdYVRyU+0nT1XC72EQJMZV8IPHF+jTr56lAg==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "micromark-util-character": "^1.0.0",
-                "micromark-util-encode": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0"
-            }
-        },
-        "node_modules/micromark-util-subtokenize": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.2.tgz",
-            "integrity": "sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ],
-            "dependencies": {
-                "micromark-util-chunked": "^1.0.0",
-                "micromark-util-symbol": "^1.0.0",
-                "micromark-util-types": "^1.0.0",
-                "uvu": "^0.5.0"
-            }
-        },
-        "node_modules/micromark-util-symbol": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.0.1.tgz",
-            "integrity": "sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ]
-        },
-        "node_modules/micromark-util-types": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.0.2.tgz",
-            "integrity": "sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w==",
-            "funding": [
-                {
-                    "type": "GitHub Sponsors",
-                    "url": "https://github.com/sponsors/unifiedjs"
-                },
-                {
-                    "type": "OpenCollective",
-                    "url": "https://opencollective.com/unified"
-                }
-            ]
-        },
-        "node_modules/micromark/node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/micromark/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
-        },
-        "node_modules/micromatch": {
-            "version": "3.1.10",
-            "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
-            "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
-            "dependencies": {
-                "arr-diff": "^4.0.0",
-                "array-unique": "^0.3.2",
-                "braces": "^2.3.1",
-                "define-property": "^2.0.2",
-                "extend-shallow": "^3.0.2",
-                "extglob": "^2.0.4",
-                "fragment-cache": "^0.2.1",
-                "kind-of": "^6.0.2",
-                "nanomatch": "^1.2.9",
-                "object.pick": "^1.3.0",
-                "regex-not": "^1.0.0",
-                "snapdragon": "^0.8.1",
-                "to-regex": "^3.0.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/mime": {
-            "version": "1.6.0",
-            "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
-            "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
-            "bin": {
-                "mime": "cli.js"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/mime-db": {
-            "version": "1.52.0",
-            "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
-            "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/mime-types": {
-            "version": "2.1.35",
-            "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
-            "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
-            "dependencies": {
-                "mime-db": "1.52.0"
-            },
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/mimic-fn": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
-            "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/mimic-response": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
-            "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/minimalistic-assert": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
-            "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
-            "dev": true
-        },
-        "node_modules/minimatch": {
-            "version": "3.1.2",
-            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-            "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-            "dependencies": {
-                "brace-expansion": "^1.1.7"
-            },
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/minimist": {
-            "version": "1.2.6",
-            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
-            "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
-        },
-        "node_modules/minipass": {
-            "version": "3.1.6",
-            "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
-            "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
-            "dependencies": {
-                "yallist": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/minizlib": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
-            "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
-            "dependencies": {
-                "minipass": "^3.0.0",
-                "yallist": "^4.0.0"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/mississippi": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz",
-            "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==",
-            "dev": true,
-            "dependencies": {
-                "concat-stream": "^1.5.0",
-                "duplexify": "^3.4.2",
-                "end-of-stream": "^1.1.0",
-                "flush-write-stream": "^1.0.0",
-                "from2": "^2.1.0",
-                "parallel-transform": "^1.1.0",
-                "pump": "^2.0.1",
-                "pumpify": "^1.3.3",
-                "stream-each": "^1.1.0",
-                "through2": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/mississippi/node_modules/pump": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
-            "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
-            "dev": true,
-            "dependencies": {
-                "end-of-stream": "^1.1.0",
-                "once": "^1.3.1"
-            }
-        },
-        "node_modules/mixin-deep": {
-            "version": "1.3.2",
-            "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
-            "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
-            "dependencies": {
-                "for-in": "^1.0.2",
-                "is-extendable": "^1.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/mixin-deep/node_modules/is-extendable": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
-            "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
-            "dependencies": {
-                "is-plain-object": "^2.0.4"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/mkdirp": {
-            "version": "0.5.4",
-            "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz",
-            "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==",
-            "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)",
-            "dependencies": {
-                "minimist": "^1.2.5"
-            },
-            "bin": {
-                "mkdirp": "bin/cmd.js"
-            }
-        },
-        "node_modules/mkdirp-classic": {
-            "version": "0.5.3",
-            "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
-            "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
-        },
-        "node_modules/mobile-detect": {
-            "version": "1.4.5",
-            "resolved": "https://registry.npmjs.org/mobile-detect/-/mobile-detect-1.4.5.tgz",
-            "integrity": "sha512-yc0LhH6tItlvfLBugVUEtgawwFU2sIe+cSdmRJJCTMZ5GEJyLxNyC/NIOAOGk67Fa8GNpOttO3Xz/1bHpXFD/g=="
-        },
-        "node_modules/mobx": {
-            "version": "5.15.7",
-            "resolved": "https://registry.npmjs.org/mobx/-/mobx-5.15.7.tgz",
-            "integrity": "sha512-wyM3FghTkhmC+hQjyPGGFdpehrcX1KOXsDuERhfK2YbJemkUhEB+6wzEN639T21onxlfYBmriA1PFnvxTUhcKw==",
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/mobx"
-            }
-        },
-        "node_modules/mobx-react": {
-            "version": "5.4.4",
-            "resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-5.4.4.tgz",
-            "integrity": "sha512-2mTzpyEjVB/RGk2i6KbcmP4HWcAUFox5ZRCrGvSyz49w20I4C4qql63grPpYrS9E9GKwgydBHQlA4y665LuRCQ==",
-            "dependencies": {
-                "hoist-non-react-statics": "^3.0.0",
-                "react-lifecycles-compat": "^3.0.2"
-            },
-            "peerDependencies": {
-                "mobx": "^4.0.0 || ^5.0.0",
-                "react": "^0.13.0 || ^0.14.0 || ^15.0.0 || ^16.0.0"
-            }
-        },
-        "node_modules/mobx-react-devtools": {
-            "version": "6.1.1",
-            "resolved": "https://registry.npmjs.org/mobx-react-devtools/-/mobx-react-devtools-6.1.1.tgz",
-            "integrity": "sha512-nc5IXLdEUFLn3wZal65KF3/JFEFd+mbH4KTz/IG5BOPyw7jo8z29w/8qm7+wiCyqVfUIgJ1gL4+HVKmcXIOgqA==",
-            "peerDependencies": {
-                "mobx": "^4.3.1 || ^5.0.0",
-                "mobx-react": "^4.0.0 || ^5.0.0"
-            }
-        },
-        "node_modules/mobx-utils": {
-            "version": "5.6.2",
-            "resolved": "https://registry.npmjs.org/mobx-utils/-/mobx-utils-5.6.2.tgz",
-            "integrity": "sha512-a/WlXyGkp6F12b01sTarENpxbmlRgPHFyR1Xv2bsSjQBm5dcOtd16ONb40/vOqck8L99NHpI+C9MXQ+SZ8f+yw==",
-            "peerDependencies": {
-                "mobx": "^4.13.1 || ^5.13.1"
-            }
-        },
-        "node_modules/mocha": {
-            "version": "5.2.0",
-            "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
-            "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
-            "dev": true,
-            "dependencies": {
-                "browser-stdout": "1.3.1",
-                "commander": "2.15.1",
-                "debug": "3.1.0",
-                "diff": "3.5.0",
-                "escape-string-regexp": "1.0.5",
-                "glob": "7.1.2",
-                "growl": "1.10.5",
-                "he": "1.1.1",
-                "minimatch": "3.0.4",
-                "mkdirp": "0.5.1",
-                "supports-color": "5.4.0"
-            },
-            "bin": {
-                "_mocha": "bin/_mocha",
-                "mocha": "bin/mocha"
-            },
-            "engines": {
-                "node": ">= 4.0.0"
-            }
-        },
-        "node_modules/mocha/node_modules/commander": {
-            "version": "2.15.1",
-            "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
-            "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
-            "dev": true
-        },
-        "node_modules/mocha/node_modules/debug": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-            "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-            "dev": true,
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/mocha/node_modules/glob": {
-            "version": "7.1.2",
-            "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
-            "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
-            "dev": true,
-            "dependencies": {
-                "fs.realpath": "^1.0.0",
-                "inflight": "^1.0.4",
-                "inherits": "2",
-                "minimatch": "^3.0.4",
-                "once": "^1.3.0",
-                "path-is-absolute": "^1.0.0"
-            },
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/mocha/node_modules/he": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
-            "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
-            "dev": true,
-            "bin": {
-                "he": "bin/he"
-            }
-        },
-        "node_modules/mocha/node_modules/minimatch": {
-            "version": "3.0.4",
-            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-            "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
-            "dev": true,
-            "dependencies": {
-                "brace-expansion": "^1.1.7"
-            },
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/mocha/node_modules/minimist": {
-            "version": "0.0.8",
-            "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
-            "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
-            "dev": true
-        },
-        "node_modules/mocha/node_modules/mkdirp": {
-            "version": "0.5.1",
-            "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
-            "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
-            "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)",
-            "dev": true,
-            "dependencies": {
-                "minimist": "0.0.8"
-            },
-            "bin": {
-                "mkdirp": "bin/cmd.js"
-            }
-        },
-        "node_modules/mocha/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
-            "dev": true
-        },
-        "node_modules/mocha/node_modules/supports-color": {
-            "version": "5.4.0",
-            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
-            "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
-            "dev": true,
-            "dependencies": {
-                "has-flag": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/mongodb": {
-            "version": "3.7.3",
-            "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz",
-            "integrity": "sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw==",
-            "dependencies": {
-                "bl": "^2.2.1",
-                "bson": "^1.1.4",
-                "denque": "^1.4.1",
-                "optional-require": "^1.1.8",
-                "safe-buffer": "^5.1.2"
-            },
-            "engines": {
-                "node": ">=4"
-            },
-            "optionalDependencies": {
-                "saslprep": "^1.0.0"
-            },
-            "peerDependenciesMeta": {
-                "aws4": {
-                    "optional": true
-                },
-                "bson-ext": {
-                    "optional": true
-                },
-                "kerberos": {
-                    "optional": true
-                },
-                "mongodb-client-encryption": {
-                    "optional": true
-                },
-                "mongodb-extjson": {
-                    "optional": true
-                },
-                "snappy": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/mongodb-core": {
-            "version": "2.1.20",
-            "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.20.tgz",
-            "integrity": "sha512-IN57CX5/Q1bhDq6ShAR6gIv4koFsZP7L8WOK1S0lR0pVDQaScffSMV5jxubLsmZ7J+UdqmykKw4r9hG3XQEGgQ==",
-            "dependencies": {
-                "bson": "~1.0.4",
-                "require_optional": "~1.0.0"
-            }
-        },
-        "node_modules/mongodb-core/node_modules/bson": {
-            "version": "1.0.9",
-            "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz",
-            "integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg==",
-            "deprecated": "Fixed a critical issue with BSON serialization documented in CVE-2019-2391, see https://bit.ly/2KcpXdo for more details",
-            "engines": {
-                "node": ">=0.6.19"
-            }
-        },
-        "node_modules/mongodb/node_modules/bl": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
-            "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
-            "dependencies": {
-                "readable-stream": "^2.3.5",
-                "safe-buffer": "^5.1.1"
-            }
-        },
-        "node_modules/mongodb/node_modules/bson": {
-            "version": "1.1.6",
-            "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
-            "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==",
-            "engines": {
-                "node": ">=0.6.19"
-            }
-        },
-        "node_modules/mongodb/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/mongoose": {
-            "version": "5.13.14",
-            "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.14.tgz",
-            "integrity": "sha512-j+BlQjjxgZg0iWn42kLeZTB91OejcxWpY2Z50bsZTiKJ7HHcEtcY21Godw496GMkBqJMTzmW7G/kZ04mW+Cb7Q==",
-            "dependencies": {
-                "@types/bson": "1.x || 4.0.x",
-                "@types/mongodb": "^3.5.27",
-                "bson": "^1.1.4",
-                "kareem": "2.3.2",
-                "mongodb": "3.7.3",
-                "mongoose-legacy-pluralize": "1.0.2",
-                "mpath": "0.8.4",
-                "mquery": "3.2.5",
-                "ms": "2.1.2",
-                "optional-require": "1.0.x",
-                "regexp-clone": "1.0.0",
-                "safe-buffer": "5.2.1",
-                "sift": "13.5.2",
-                "sliced": "1.0.1"
-            },
-            "engines": {
-                "node": ">=4.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/mongoose"
-            }
-        },
-        "node_modules/mongoose-legacy-pluralize": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz",
-            "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==",
-            "peerDependencies": {
-                "mongoose": "*"
-            }
-        },
-        "node_modules/mongoose/node_modules/bson": {
-            "version": "1.1.6",
-            "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
-            "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==",
-            "engines": {
-                "node": ">=0.6.19"
-            }
-        },
-        "node_modules/mongoose/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
-        },
-        "node_modules/mongoose/node_modules/optional-require": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz",
-            "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/mongoose/node_modules/safe-buffer": {
-            "version": "5.2.1",
-            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-            "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ]
-        },
-        "node_modules/move-concurrently": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
-            "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
-            "dev": true,
-            "dependencies": {
-                "aproba": "^1.1.1",
-                "copy-concurrently": "^1.0.0",
-                "fs-write-stream-atomic": "^1.0.8",
-                "mkdirp": "^0.5.1",
-                "rimraf": "^2.5.4",
-                "run-queue": "^1.0.3"
-            }
-        },
-        "node_modules/move-concurrently/node_modules/aproba": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-            "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
-            "dev": true
-        },
-        "node_modules/move-concurrently/node_modules/rimraf": {
-            "version": "2.7.1",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-            "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-            "dev": true,
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            }
-        },
-        "node_modules/mpath": {
-            "version": "0.8.4",
-            "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz",
-            "integrity": "sha512-DTxNZomBcTWlrMW76jy1wvV37X/cNNxPW1y2Jzd4DZkAaC5ZGsm8bfGfNOthcDuRJujXLqiuS6o3Tpy0JEoh7g==",
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/mquery": {
-            "version": "3.2.5",
-            "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.5.tgz",
-            "integrity": "sha512-VjOKHHgU84wij7IUoZzFRU07IAxd5kWJaDmyUzQlbjHjyoeK5TNeeo8ZsFDtTYnSgpW6n/nMNIHvE3u8Lbrf4A==",
-            "dependencies": {
-                "bluebird": "3.5.1",
-                "debug": "3.1.0",
-                "regexp-clone": "^1.0.0",
-                "safe-buffer": "5.1.2",
-                "sliced": "1.0.1"
-            },
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/mquery/node_modules/bluebird": {
-            "version": "3.5.1",
-            "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
-            "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
-        },
-        "node_modules/mquery/node_modules/debug": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-            "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/mquery/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
-        },
-        "node_modules/mr-parser": {
-            "version": "0.2.1",
-            "resolved": "https://registry.npmjs.org/mr-parser/-/mr-parser-0.2.1.tgz",
-            "integrity": "sha1-hhi5ukF+KOn0OaQcaVtVTq/u2Sc="
-        },
-        "node_modules/mri": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
-            "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/ms": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-            "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
-        },
-        "node_modules/multicast-dns": {
-            "version": "6.2.3",
-            "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
-            "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
-            "dev": true,
-            "dependencies": {
-                "dns-packet": "^1.3.1",
-                "thunky": "^1.0.2"
-            },
-            "bin": {
-                "multicast-dns": "cli.js"
-            }
-        },
-        "node_modules/multicast-dns-service-types": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
-            "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
-            "dev": true
-        },
-        "node_modules/mute-stream": {
-            "version": "0.0.8",
-            "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
-            "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
-            "dev": true
-        },
-        "node_modules/nan": {
-            "version": "2.16.0",
-            "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz",
-            "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA=="
-        },
-        "node_modules/nanoid": {
-            "version": "2.1.11",
-            "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz",
-            "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA=="
-        },
-        "node_modules/nanomatch": {
-            "version": "1.2.13",
-            "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
-            "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
-            "dependencies": {
-                "arr-diff": "^4.0.0",
-                "array-unique": "^0.3.2",
-                "define-property": "^2.0.2",
-                "extend-shallow": "^3.0.2",
-                "fragment-cache": "^0.2.1",
-                "is-windows": "^1.0.2",
-                "kind-of": "^6.0.2",
-                "object.pick": "^1.3.0",
-                "regex-not": "^1.0.0",
-                "snapdragon": "^0.8.1",
-                "to-regex": "^3.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/napi-build-utils": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
-            "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="
-        },
-        "node_modules/native-or-bluebird": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.2.0.tgz",
-            "integrity": "sha1-OcR7/Xgl0fuf+tMiEK4l2q3xAck=",
-            "deprecated": "'native-or-bluebird' is deprecated. Please use 'any-promise' instead."
-        },
-        "node_modules/natural-compare": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
-            "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
-            "dev": true
-        },
-        "node_modules/negotiator": {
-            "version": "0.6.3",
-            "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
-            "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/neo-async": {
-            "version": "2.6.2",
-            "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
-            "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
-        },
-        "node_modules/next-tick": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
-            "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
-        },
-        "node_modules/nextafter": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/nextafter/-/nextafter-1.0.0.tgz",
-            "integrity": "sha1-t9d7U1MQ4+CX5gJauwqQNHfsGjo=",
-            "dependencies": {
-                "double-bits": "^1.1.0"
-            }
-        },
-        "node_modules/nice-try": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
-            "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
-            "dev": true
-        },
-        "node_modules/no-case": {
-            "version": "3.0.4",
-            "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
-            "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
-            "dependencies": {
-                "lower-case": "^2.0.2",
-                "tslib": "^2.0.3"
-            }
-        },
-        "node_modules/node-abi": {
-            "version": "2.30.1",
-            "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz",
-            "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==",
-            "dependencies": {
-                "semver": "^5.4.1"
-            }
-        },
-        "node_modules/node-ensure": {
-            "version": "0.0.0",
-            "resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz",
-            "integrity": "sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc="
-        },
-        "node_modules/node-environment-flags": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz",
-            "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==",
-            "dependencies": {
-                "object.getownpropertydescriptors": "^2.0.3",
-                "semver": "^5.7.0"
-            }
-        },
-        "node_modules/node-fetch": {
-            "version": "1.7.3",
-            "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
-            "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
-            "dependencies": {
-                "encoding": "^0.1.11",
-                "is-stream": "^1.0.1"
-            }
-        },
-        "node_modules/node-forge": {
-            "version": "0.10.0",
-            "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
-            "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==",
-            "engines": {
-                "node": ">= 6.0.0"
-            }
-        },
-        "node_modules/node-gyp": {
-            "version": "3.8.0",
-            "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
-            "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
-            "dependencies": {
-                "fstream": "^1.0.0",
-                "glob": "^7.0.3",
-                "graceful-fs": "^4.1.2",
-                "mkdirp": "^0.5.0",
-                "nopt": "2 || 3",
-                "npmlog": "0 || 1 || 2 || 3 || 4",
-                "osenv": "0",
-                "request": "^2.87.0",
-                "rimraf": "2",
-                "semver": "~5.3.0",
-                "tar": "^2.0.0",
-                "which": "1"
-            },
-            "bin": {
-                "node-gyp": "bin/node-gyp.js"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/node-gyp/node_modules/ansi-regex": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-            "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/node-gyp/node_modules/aproba": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-            "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
-        },
-        "node_modules/node-gyp/node_modules/are-we-there-yet": {
-            "version": "1.1.7",
-            "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
-            "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
-            "dependencies": {
-                "delegates": "^1.0.0",
-                "readable-stream": "^2.0.6"
-            }
-        },
-        "node_modules/node-gyp/node_modules/gauge": {
-            "version": "2.7.4",
-            "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
-            "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==",
-            "dependencies": {
-                "aproba": "^1.0.3",
-                "console-control-strings": "^1.0.0",
-                "has-unicode": "^2.0.0",
-                "object-assign": "^4.1.0",
-                "signal-exit": "^3.0.0",
-                "string-width": "^1.0.1",
-                "strip-ansi": "^3.0.1",
-                "wide-align": "^1.1.0"
-            }
-        },
-        "node_modules/node-gyp/node_modules/is-fullwidth-code-point": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
-            "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==",
-            "dependencies": {
-                "number-is-nan": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/node-gyp/node_modules/nopt": {
-            "version": "3.0.6",
-            "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
-            "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
-            "dependencies": {
-                "abbrev": "1"
-            },
-            "bin": {
-                "nopt": "bin/nopt.js"
-            }
-        },
-        "node_modules/node-gyp/node_modules/npmlog": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
-            "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
-            "dependencies": {
-                "are-we-there-yet": "~1.1.2",
-                "console-control-strings": "~1.1.0",
-                "gauge": "~2.7.3",
-                "set-blocking": "~2.0.0"
-            }
-        },
-        "node_modules/node-gyp/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/node-gyp/node_modules/rimraf": {
-            "version": "2.7.1",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-            "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            }
-        },
-        "node_modules/node-gyp/node_modules/semver": {
-            "version": "5.3.0",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
-            "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
-            "bin": {
-                "semver": "bin/semver"
-            }
-        },
-        "node_modules/node-gyp/node_modules/string-width": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
-            "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
-            "dependencies": {
-                "code-point-at": "^1.0.0",
-                "is-fullwidth-code-point": "^1.0.0",
-                "strip-ansi": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/node-gyp/node_modules/strip-ansi": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-            "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
-            "dependencies": {
-                "ansi-regex": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/node-gyp/node_modules/tar": {
-            "version": "2.2.2",
-            "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
-            "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
-            "deprecated": "This version of tar is no longer supported, and will not receive security updates. Please upgrade asap.",
-            "dependencies": {
-                "block-stream": "*",
-                "fstream": "^1.0.12",
-                "inherits": "2"
-            }
-        },
-        "node_modules/node-releases": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz",
-            "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q=="
-        },
-        "node_modules/node-sass": {
-            "version": "4.14.1",
-            "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz",
-            "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==",
-            "hasInstallScript": true,
-            "dependencies": {
-                "async-foreach": "^0.1.3",
-                "chalk": "^1.1.1",
-                "cross-spawn": "^3.0.0",
-                "gaze": "^1.0.0",
-                "get-stdin": "^4.0.1",
-                "glob": "^7.0.3",
-                "in-publish": "^2.0.0",
-                "lodash": "^4.17.15",
-                "meow": "^3.7.0",
-                "mkdirp": "^0.5.1",
-                "nan": "^2.13.2",
-                "node-gyp": "^3.8.0",
-                "npmlog": "^4.0.0",
-                "request": "^2.88.0",
-                "sass-graph": "2.2.5",
-                "stdout-stream": "^1.4.0",
-                "true-case-path": "^1.0.2"
-            },
-            "bin": {
-                "node-sass": "bin/node-sass"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/node-sass-tilde-importer": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/node-sass-tilde-importer/-/node-sass-tilde-importer-1.0.2.tgz",
-            "integrity": "sha512-Swcmr38Y7uB78itQeBm3mThjxBy9/Ah/ykPIaURY/L6Nec9AyRoL/jJ7ECfMR+oZeCTVQNxVMu/aHU+TLRVbdg==",
-            "dependencies": {
-                "find-parent-dir": "^0.3.0"
-            }
-        },
-        "node_modules/node-sass/node_modules/ansi-regex": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-            "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/node-sass/node_modules/ansi-styles": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-            "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/node-sass/node_modules/aproba": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-            "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
-        },
-        "node_modules/node-sass/node_modules/are-we-there-yet": {
-            "version": "1.1.7",
-            "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
-            "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
-            "dependencies": {
-                "delegates": "^1.0.0",
-                "readable-stream": "^2.0.6"
-            }
-        },
-        "node_modules/node-sass/node_modules/chalk": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-            "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-            "dependencies": {
-                "ansi-styles": "^2.2.1",
-                "escape-string-regexp": "^1.0.2",
-                "has-ansi": "^2.0.0",
-                "strip-ansi": "^3.0.0",
-                "supports-color": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/node-sass/node_modules/gauge": {
-            "version": "2.7.4",
-            "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
-            "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==",
-            "dependencies": {
-                "aproba": "^1.0.3",
-                "console-control-strings": "^1.0.0",
-                "has-unicode": "^2.0.0",
-                "object-assign": "^4.1.0",
-                "signal-exit": "^3.0.0",
-                "string-width": "^1.0.1",
-                "strip-ansi": "^3.0.1",
-                "wide-align": "^1.1.0"
-            }
-        },
-        "node_modules/node-sass/node_modules/get-stdin": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
-            "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/node-sass/node_modules/is-fullwidth-code-point": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
-            "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==",
-            "dependencies": {
-                "number-is-nan": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/node-sass/node_modules/npmlog": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
-            "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
-            "dependencies": {
-                "are-we-there-yet": "~1.1.2",
-                "console-control-strings": "~1.1.0",
-                "gauge": "~2.7.3",
-                "set-blocking": "~2.0.0"
-            }
-        },
-        "node_modules/node-sass/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/node-sass/node_modules/string-width": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
-            "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
-            "dependencies": {
-                "code-point-at": "^1.0.0",
-                "is-fullwidth-code-point": "^1.0.0",
-                "strip-ansi": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/node-sass/node_modules/strip-ansi": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-            "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
-            "dependencies": {
-                "ansi-regex": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/node-sass/node_modules/supports-color": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-            "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
-            "engines": {
-                "node": ">=0.8.0"
-            }
-        },
-        "node_modules/node-stream-zip": {
-            "version": "1.15.0",
-            "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz",
-            "integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==",
-            "engines": {
-                "node": ">=0.12.0"
-            },
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/antelle"
-            }
-        },
-        "node_modules/nodemailer": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-5.1.1.tgz",
-            "integrity": "sha512-hKGCoeNdFL2W7S76J/Oucbw0/qRlfG815tENdhzcqTpSjKgAN91mFOqU2lQUflRRxFM7iZvCyaFcAR9noc/CqQ==",
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/nodemon": {
-            "version": "1.19.4",
-            "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.19.4.tgz",
-            "integrity": "sha512-VGPaqQBNk193lrJFotBU8nvWZPqEZY2eIzymy2jjY0fJ9qIsxA0sxQ8ATPl0gZC645gijYEc1jtZvpS8QWzJGQ==",
-            "hasInstallScript": true,
-            "dependencies": {
-                "chokidar": "^2.1.8",
-                "debug": "^3.2.6",
-                "ignore-by-default": "^1.0.1",
-                "minimatch": "^3.0.4",
-                "pstree.remy": "^1.1.7",
-                "semver": "^5.7.1",
-                "supports-color": "^5.5.0",
-                "touch": "^3.1.0",
-                "undefsafe": "^2.0.2",
-                "update-notifier": "^2.5.0"
-            },
-            "bin": {
-                "nodemon": "bin/nodemon.js"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/noop-logger": {
-            "version": "0.1.1",
-            "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
-            "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI="
-        },
-        "node_modules/nopt": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
-            "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
-            "dependencies": {
-                "abbrev": "1"
-            },
-            "bin": {
-                "nopt": "bin/nopt.js"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/normalize-package-data": {
-            "version": "2.5.0",
-            "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
-            "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
-            "dependencies": {
-                "hosted-git-info": "^2.1.4",
-                "resolve": "^1.10.0",
-                "semver": "2 || 3 || 4 || 5",
-                "validate-npm-package-license": "^3.0.1"
-            }
-        },
-        "node_modules/normalize-path": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
-            "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/normalize-url": {
-            "version": "6.1.0",
-            "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
-            "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/normalize.css": {
-            "version": "8.0.1",
-            "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz",
-            "integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg=="
-        },
-        "node_modules/npm": {
-            "version": "6.14.18",
-            "resolved": "https://registry.npmjs.org/npm/-/npm-6.14.18.tgz",
-            "integrity": "sha512-p3SjqSchSuNQUqbJBgwdv0L3O6bKkaSfQrQzJsskNpNKLg0g37c5xTXFV0SqTlX9GWvoGxBELVJMRWq0J8oaLA==",
-            "bundleDependencies": [
-                "abbrev",
-                "ansicolors",
-                "ansistyles",
-                "aproba",
-                "archy",
-                "bin-links",
-                "bluebird",
-                "byte-size",
-                "cacache",
-                "call-limit",
-                "chownr",
-                "ci-info",
-                "cli-columns",
-                "cli-table3",
-                "cmd-shim",
-                "columnify",
-                "config-chain",
-                "debuglog",
-                "detect-indent",
-                "detect-newline",
-                "dezalgo",
-                "editor",
-                "figgy-pudding",
-                "find-npm-prefix",
-                "fs-vacuum",
-                "fs-write-stream-atomic",
-                "gentle-fs",
-                "glob",
-                "graceful-fs",
-                "has-unicode",
-                "hosted-git-info",
-                "iferr",
-                "imurmurhash",
-                "infer-owner",
-                "inflight",
-                "inherits",
-                "ini",
-                "init-package-json",
-                "is-cidr",
-                "json-parse-better-errors",
-                "JSONStream",
-                "lazy-property",
-                "libcipm",
-                "libnpm",
-                "libnpmaccess",
-                "libnpmhook",
-                "libnpmorg",
-                "libnpmsearch",
-                "libnpmteam",
-                "libnpx",
-                "lock-verify",
-                "lockfile",
-                "lodash._baseindexof",
-                "lodash._baseuniq",
-                "lodash._bindcallback",
-                "lodash._cacheindexof",
-                "lodash._createcache",
-                "lodash._getnative",
-                "lodash.clonedeep",
-                "lodash.restparam",
-                "lodash.union",
-                "lodash.uniq",
-                "lodash.without",
-                "lru-cache",
-                "meant",
-                "mississippi",
-                "mkdirp",
-                "move-concurrently",
-                "node-gyp",
-                "nopt",
-                "normalize-package-data",
-                "npm-audit-report",
-                "npm-cache-filename",
-                "npm-install-checks",
-                "npm-lifecycle",
-                "npm-package-arg",
-                "npm-packlist",
-                "npm-pick-manifest",
-                "npm-profile",
-                "npm-registry-fetch",
-                "npm-user-validate",
-                "npmlog",
-                "once",
-                "opener",
-                "osenv",
-                "pacote",
-                "path-is-inside",
-                "promise-inflight",
-                "qrcode-terminal",
-                "query-string",
-                "qw",
-                "read-cmd-shim",
-                "read-installed",
-                "read-package-json",
-                "read-package-tree",
-                "read",
-                "readable-stream",
-                "readdir-scoped-modules",
-                "request",
-                "retry",
-                "rimraf",
-                "safe-buffer",
-                "semver",
-                "sha",
-                "slide",
-                "sorted-object",
-                "sorted-union-stream",
-                "ssri",
-                "stringify-package",
-                "tar",
-                "text-table",
-                "tiny-relative-date",
-                "uid-number",
-                "umask",
-                "unique-filename",
-                "unpipe",
-                "update-notifier",
-                "uuid",
-                "validate-npm-package-license",
-                "validate-npm-package-name",
-                "which",
-                "worker-farm",
-                "write-file-atomic"
-            ],
-            "dependencies": {
-                "abbrev": "~1.1.1",
-                "ansicolors": "~0.3.2",
-                "ansistyles": "~0.1.3",
-                "aproba": "^2.0.0",
-                "archy": "~1.0.0",
-                "bin-links": "^1.1.8",
-                "bluebird": "^3.7.2",
-                "byte-size": "^5.0.1",
-                "cacache": "^12.0.4",
-                "call-limit": "^1.1.1",
-                "chownr": "^1.1.4",
-                "ci-info": "^2.0.0",
-                "cli-columns": "^3.1.2",
-                "cli-table3": "^0.5.1",
-                "cmd-shim": "^3.0.3",
-                "columnify": "~1.5.4",
-                "config-chain": "^1.1.13",
-                "debuglog": "*",
-                "detect-indent": "~5.0.0",
-                "detect-newline": "^2.1.0",
-                "dezalgo": "^1.0.4",
-                "editor": "~1.0.0",
-                "figgy-pudding": "^3.5.2",
-                "find-npm-prefix": "^1.0.2",
-                "fs-vacuum": "~1.2.10",
-                "fs-write-stream-atomic": "~1.0.10",
-                "gentle-fs": "^2.3.1",
-                "glob": "^7.2.3",
-                "graceful-fs": "^4.2.10",
-                "has-unicode": "~2.0.1",
-                "hosted-git-info": "^2.8.9",
-                "iferr": "^1.0.2",
-                "imurmurhash": "*",
-                "infer-owner": "^1.0.4",
-                "inflight": "~1.0.6",
-                "inherits": "^2.0.4",
-                "ini": "^1.3.8",
-                "init-package-json": "^1.10.3",
-                "is-cidr": "^3.1.1",
-                "json-parse-better-errors": "^1.0.2",
-                "JSONStream": "^1.3.5",
-                "lazy-property": "~1.0.0",
-                "libcipm": "^4.0.8",
-                "libnpm": "^3.0.1",
-                "libnpmaccess": "^3.0.2",
-                "libnpmhook": "^5.0.3",
-                "libnpmorg": "^1.0.1",
-                "libnpmsearch": "^2.0.2",
-                "libnpmteam": "^1.0.2",
-                "libnpx": "^10.2.4",
-                "lock-verify": "^2.2.2",
-                "lockfile": "^1.0.4",
-                "lodash._baseindexof": "*",
-                "lodash._baseuniq": "~4.6.0",
-                "lodash._bindcallback": "*",
-                "lodash._cacheindexof": "*",
-                "lodash._createcache": "*",
-                "lodash._getnative": "*",
-                "lodash.clonedeep": "~4.5.0",
-                "lodash.restparam": "*",
-                "lodash.union": "~4.6.0",
-                "lodash.uniq": "~4.5.0",
-                "lodash.without": "~4.4.0",
-                "lru-cache": "^5.1.1",
-                "meant": "^1.0.3",
-                "mississippi": "^3.0.0",
-                "mkdirp": "^0.5.6",
-                "move-concurrently": "^1.0.1",
-                "node-gyp": "^5.1.1",
-                "nopt": "^4.0.3",
-                "normalize-package-data": "^2.5.0",
-                "npm-audit-report": "^1.3.3",
-                "npm-cache-filename": "~1.0.2",
-                "npm-install-checks": "^3.0.2",
-                "npm-lifecycle": "^3.1.5",
-                "npm-package-arg": "^6.1.1",
-                "npm-packlist": "^1.4.8",
-                "npm-pick-manifest": "^3.0.2",
-                "npm-profile": "^4.0.4",
-                "npm-registry-fetch": "^4.0.7",
-                "npm-user-validate": "^1.0.1",
-                "npmlog": "~4.1.2",
-                "once": "~1.4.0",
-                "opener": "^1.5.2",
-                "osenv": "^0.1.5",
-                "pacote": "^9.5.12",
-                "path-is-inside": "~1.0.2",
-                "promise-inflight": "~1.0.1",
-                "qrcode-terminal": "^0.12.0",
-                "query-string": "^6.14.1",
-                "qw": "^1.0.2",
-                "read": "~1.0.7",
-                "read-cmd-shim": "^1.0.5",
-                "read-installed": "~4.0.3",
-                "read-package-json": "^2.1.2",
-                "read-package-tree": "^5.3.1",
-                "readable-stream": "^3.6.0",
-                "readdir-scoped-modules": "^1.1.0",
-                "request": "^2.88.2",
-                "retry": "^0.12.0",
-                "rimraf": "^2.7.1",
-                "safe-buffer": "^5.2.1",
-                "semver": "^5.7.1",
-                "sha": "^3.0.0",
-                "slide": "~1.1.6",
-                "sorted-object": "~2.0.1",
-                "sorted-union-stream": "~2.1.3",
-                "ssri": "^6.0.2",
-                "stringify-package": "^1.0.1",
-                "tar": "^4.4.19",
-                "text-table": "~0.2.0",
-                "tiny-relative-date": "^1.3.0",
-                "uid-number": "0.0.6",
-                "umask": "~1.1.0",
-                "unique-filename": "^1.1.1",
-                "unpipe": "~1.0.0",
-                "update-notifier": "^2.5.0",
-                "uuid": "^3.4.0",
-                "validate-npm-package-license": "^3.0.4",
-                "validate-npm-package-name": "~3.0.0",
-                "which": "^1.3.1",
-                "worker-farm": "^1.7.0",
-                "write-file-atomic": "^2.4.3"
-            },
-            "bin": {
-                "npm": "bin/npm-cli.js",
-                "npx": "bin/npx-cli.js"
-            },
-            "engines": {
-                "node": "6 >=6.2.0 || 8 || >=9.3.0"
-            }
-        },
-        "node_modules/npm-run-path": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
-            "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
-            "dependencies": {
-                "path-key": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/@iarna/cli": {
-            "version": "2.1.0",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "glob": "^7.1.2",
-                "signal-exit": "^3.0.2"
-            }
-        },
-        "node_modules/npm/node_modules/abbrev": {
-            "version": "1.1.1",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/agent-base": {
-            "version": "4.3.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "es6-promisify": "^5.0.0"
-            },
-            "engines": {
-                "node": ">= 4.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/agentkeepalive": {
-            "version": "3.5.2",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "humanize-ms": "^1.2.1"
-            },
-            "engines": {
-                "node": ">= 4.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/ansi-align": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "string-width": "^2.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/ansi-regex": {
-            "version": "2.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/ansi-styles": {
-            "version": "3.2.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "color-convert": "^1.9.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/ansicolors": {
-            "version": "0.3.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/ansistyles": {
-            "version": "0.1.3",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/aproba": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/archy": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/are-we-there-yet": {
-            "version": "1.1.4",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "delegates": "^1.0.0",
-                "readable-stream": "^2.0.6"
-            }
-        },
-        "node_modules/npm/node_modules/are-we-there-yet/node_modules/readable-stream": {
-            "version": "2.3.6",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/are-we-there-yet/node_modules/readable-stream/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/are-we-there-yet/node_modules/string_decoder": {
-            "version": "1.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "safe-buffer": "~5.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/are-we-there-yet/node_modules/string_decoder/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/asap": {
-            "version": "2.0.6",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/asn1": {
-            "version": "0.2.6",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "safer-buffer": "~2.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/assert-plus": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.8"
-            }
-        },
-        "node_modules/npm/node_modules/asynckit": {
-            "version": "0.4.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/aws-sign2": {
-            "version": "0.7.0",
-            "inBundle": true,
-            "license": "Apache-2.0",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/npm/node_modules/aws4": {
-            "version": "1.11.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/balanced-match": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/bcrypt-pbkdf": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "BSD-3-Clause",
-            "dependencies": {
-                "tweetnacl": "^0.14.3"
-            }
-        },
-        "node_modules/npm/node_modules/bin-links": {
-            "version": "1.1.8",
-            "inBundle": true,
-            "license": "Artistic-2.0",
-            "dependencies": {
-                "bluebird": "^3.5.3",
-                "cmd-shim": "^3.0.0",
-                "gentle-fs": "^2.3.0",
-                "graceful-fs": "^4.1.15",
-                "npm-normalize-package-bin": "^1.0.0",
-                "write-file-atomic": "^2.3.0"
-            }
-        },
-        "node_modules/npm/node_modules/bluebird": {
-            "version": "3.7.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/boxen": {
-            "version": "1.3.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "ansi-align": "^2.0.0",
-                "camelcase": "^4.0.0",
-                "chalk": "^2.0.1",
-                "cli-boxes": "^1.0.0",
-                "string-width": "^2.0.0",
-                "term-size": "^1.2.0",
-                "widest-line": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/brace-expansion": {
-            "version": "1.1.11",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "balanced-match": "^1.0.0",
-                "concat-map": "0.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/buffer-from": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/builtins": {
-            "version": "1.0.3",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/byline": {
-            "version": "5.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/byte-size": {
-            "version": "5.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/cacache": {
-            "version": "12.0.4",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "bluebird": "^3.5.5",
-                "chownr": "^1.1.1",
-                "figgy-pudding": "^3.5.1",
-                "glob": "^7.1.4",
-                "graceful-fs": "^4.1.15",
-                "infer-owner": "^1.0.3",
-                "lru-cache": "^5.1.1",
-                "mississippi": "^3.0.0",
-                "mkdirp": "^0.5.1",
-                "move-concurrently": "^1.0.1",
-                "promise-inflight": "^1.0.1",
-                "rimraf": "^2.6.3",
-                "ssri": "^6.0.1",
-                "unique-filename": "^1.1.1",
-                "y18n": "^4.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/call-limit": {
-            "version": "1.1.1",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/camelcase": {
-            "version": "4.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/capture-stack-trace": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/caseless": {
-            "version": "0.12.0",
-            "inBundle": true,
-            "license": "Apache-2.0"
-        },
-        "node_modules/npm/node_modules/chalk": {
-            "version": "2.4.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "ansi-styles": "^3.2.1",
-                "escape-string-regexp": "^1.0.5",
-                "supports-color": "^5.3.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/chownr": {
-            "version": "1.1.4",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/ci-info": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/cidr-regex": {
-            "version": "2.0.10",
-            "inBundle": true,
-            "license": "BSD-2-Clause",
-            "dependencies": {
-                "ip-regex": "^2.1.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/cli-boxes": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/cli-columns": {
-            "version": "3.1.2",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "string-width": "^2.0.0",
-                "strip-ansi": "^3.0.1"
-            },
-            "engines": {
-                "node": ">= 4"
-            }
-        },
-        "node_modules/npm/node_modules/cli-table3": {
-            "version": "0.5.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "object-assign": "^4.1.0",
-                "string-width": "^2.1.1"
-            },
-            "engines": {
-                "node": ">=6"
-            },
-            "optionalDependencies": {
-                "colors": "^1.1.2"
-            }
-        },
-        "node_modules/npm/node_modules/cliui": {
-            "version": "5.0.0",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "string-width": "^3.1.0",
-                "strip-ansi": "^5.2.0",
-                "wrap-ansi": "^5.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/cliui/node_modules/ansi-regex": {
-            "version": "4.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/cliui/node_modules/is-fullwidth-code-point": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/cliui/node_modules/string-width": {
-            "version": "3.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "emoji-regex": "^7.0.1",
-                "is-fullwidth-code-point": "^2.0.0",
-                "strip-ansi": "^5.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/cliui/node_modules/strip-ansi": {
-            "version": "5.2.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "ansi-regex": "^4.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/clone": {
-            "version": "1.0.4",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.8"
-            }
-        },
-        "node_modules/npm/node_modules/cmd-shim": {
-            "version": "3.0.3",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "graceful-fs": "^4.1.2",
-                "mkdirp": "~0.5.0"
-            }
-        },
-        "node_modules/npm/node_modules/code-point-at": {
-            "version": "1.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/color-convert": {
-            "version": "1.9.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "color-name": "^1.1.1"
-            }
-        },
-        "node_modules/npm/node_modules/color-name": {
-            "version": "1.1.3",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/colors": {
-            "version": "1.3.3",
-            "inBundle": true,
-            "license": "MIT",
-            "optional": true,
-            "engines": {
-                "node": ">=0.1.90"
-            }
-        },
-        "node_modules/npm/node_modules/columnify": {
-            "version": "1.5.4",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "strip-ansi": "^3.0.0",
-                "wcwidth": "^1.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/combined-stream": {
-            "version": "1.0.8",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "delayed-stream": "~1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/npm/node_modules/concat-map": {
-            "version": "0.0.1",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/concat-stream": {
-            "version": "1.6.2",
-            "engines": [
-                "node >= 0.8"
-            ],
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "buffer-from": "^1.0.0",
-                "inherits": "^2.0.3",
-                "readable-stream": "^2.2.2",
-                "typedarray": "^0.0.6"
-            }
-        },
-        "node_modules/npm/node_modules/concat-stream/node_modules/readable-stream": {
-            "version": "2.3.6",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/concat-stream/node_modules/readable-stream/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/concat-stream/node_modules/string_decoder": {
-            "version": "1.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "safe-buffer": "~5.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/concat-stream/node_modules/string_decoder/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/config-chain": {
-            "version": "1.1.13",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "ini": "^1.3.4",
-                "proto-list": "~1.2.1"
-            }
-        },
-        "node_modules/npm/node_modules/configstore": {
-            "version": "3.1.5",
-            "inBundle": true,
-            "license": "BSD-2-Clause",
-            "dependencies": {
-                "dot-prop": "^4.2.1",
-                "graceful-fs": "^4.1.2",
-                "make-dir": "^1.0.0",
-                "unique-string": "^1.0.0",
-                "write-file-atomic": "^2.0.0",
-                "xdg-basedir": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/console-control-strings": {
-            "version": "1.1.0",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/copy-concurrently": {
-            "version": "1.0.5",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "aproba": "^1.1.1",
-                "fs-write-stream-atomic": "^1.0.8",
-                "iferr": "^0.1.5",
-                "mkdirp": "^0.5.1",
-                "rimraf": "^2.5.4",
-                "run-queue": "^1.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/copy-concurrently/node_modules/aproba": {
-            "version": "1.2.0",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/copy-concurrently/node_modules/iferr": {
-            "version": "0.1.5",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/core-util-is": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/create-error-class": {
-            "version": "3.0.2",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "capture-stack-trace": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/cross-spawn": {
-            "version": "5.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "lru-cache": "^4.0.1",
-                "shebang-command": "^1.2.0",
-                "which": "^1.2.9"
-            }
-        },
-        "node_modules/npm/node_modules/cross-spawn/node_modules/lru-cache": {
-            "version": "4.1.5",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "pseudomap": "^1.0.2",
-                "yallist": "^2.1.2"
-            }
-        },
-        "node_modules/npm/node_modules/cross-spawn/node_modules/yallist": {
-            "version": "2.1.2",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/crypto-random-string": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/cyclist": {
-            "version": "0.2.2",
-            "inBundle": true
-        },
-        "node_modules/npm/node_modules/dashdash": {
-            "version": "1.14.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "assert-plus": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10"
-            }
-        },
-        "node_modules/npm/node_modules/debug": {
-            "version": "3.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/debug/node_modules/ms": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/debuglog": {
-            "version": "1.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/npm/node_modules/decamelize": {
-            "version": "1.2.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/decode-uri-component": {
-            "version": "0.2.2",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10"
-            }
-        },
-        "node_modules/npm/node_modules/deep-extend": {
-            "version": "0.6.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/defaults": {
-            "version": "1.0.3",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "clone": "^1.0.2"
-            }
-        },
-        "node_modules/npm/node_modules/define-properties": {
-            "version": "1.1.3",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "object-keys": "^1.0.12"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/npm/node_modules/delayed-stream": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/npm/node_modules/delegates": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/detect-indent": {
-            "version": "5.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/detect-newline": {
-            "version": "2.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/dezalgo": {
-            "version": "1.0.4",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "asap": "^2.0.0",
-                "wrappy": "1"
-            }
-        },
-        "node_modules/npm/node_modules/dot-prop": {
-            "version": "4.2.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "is-obj": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/dotenv": {
-            "version": "5.0.1",
-            "inBundle": true,
-            "license": "BSD-2-Clause",
-            "engines": {
-                "node": ">=4.6.0"
-            }
-        },
-        "node_modules/npm/node_modules/duplexer3": {
-            "version": "0.1.4",
-            "inBundle": true,
-            "license": "BSD-3-Clause"
-        },
-        "node_modules/npm/node_modules/duplexify": {
-            "version": "3.6.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "end-of-stream": "^1.0.0",
-                "inherits": "^2.0.1",
-                "readable-stream": "^2.0.0",
-                "stream-shift": "^1.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/duplexify/node_modules/readable-stream": {
-            "version": "2.3.6",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/duplexify/node_modules/readable-stream/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/duplexify/node_modules/string_decoder": {
-            "version": "1.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "safe-buffer": "~5.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/duplexify/node_modules/string_decoder/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/ecc-jsbn": {
-            "version": "0.1.2",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "jsbn": "~0.1.0",
-                "safer-buffer": "^2.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/editor": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/emoji-regex": {
-            "version": "7.0.3",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/encoding": {
-            "version": "0.1.12",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "iconv-lite": "~0.4.13"
-            }
-        },
-        "node_modules/npm/node_modules/end-of-stream": {
-            "version": "1.4.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "once": "^1.4.0"
-            }
-        },
-        "node_modules/npm/node_modules/env-paths": {
-            "version": "2.2.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/err-code": {
-            "version": "1.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/errno": {
-            "version": "0.1.7",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "prr": "~1.0.1"
-            },
-            "bin": {
-                "errno": "cli.js"
-            }
-        },
-        "node_modules/npm/node_modules/es-abstract": {
-            "version": "1.12.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "es-to-primitive": "^1.1.1",
-                "function-bind": "^1.1.1",
-                "has": "^1.0.1",
-                "is-callable": "^1.1.3",
-                "is-regex": "^1.0.4"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/npm/node_modules/es-to-primitive": {
-            "version": "1.2.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "is-callable": "^1.1.4",
-                "is-date-object": "^1.0.1",
-                "is-symbol": "^1.0.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/npm/node_modules/es6-promise": {
-            "version": "4.2.8",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/es6-promisify": {
-            "version": "5.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "es6-promise": "^4.0.3"
-            }
-        },
-        "node_modules/npm/node_modules/escape-string-regexp": {
-            "version": "1.0.5",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.8.0"
-            }
-        },
-        "node_modules/npm/node_modules/execa": {
-            "version": "0.7.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "cross-spawn": "^5.0.1",
-                "get-stream": "^3.0.0",
-                "is-stream": "^1.1.0",
-                "npm-run-path": "^2.0.0",
-                "p-finally": "^1.0.0",
-                "signal-exit": "^3.0.0",
-                "strip-eof": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/execa/node_modules/get-stream": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/extend": {
-            "version": "3.0.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/extsprintf": {
-            "version": "1.3.0",
-            "engines": [
-                "node >=0.6.0"
-            ],
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/fast-json-stable-stringify": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/figgy-pudding": {
-            "version": "3.5.2",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/filter-obj": {
-            "version": "1.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/find-npm-prefix": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/flush-write-stream": {
-            "version": "1.0.3",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "inherits": "^2.0.1",
-                "readable-stream": "^2.0.4"
-            }
-        },
-        "node_modules/npm/node_modules/flush-write-stream/node_modules/readable-stream": {
-            "version": "2.3.6",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/flush-write-stream/node_modules/readable-stream/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/flush-write-stream/node_modules/string_decoder": {
-            "version": "1.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "safe-buffer": "~5.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/flush-write-stream/node_modules/string_decoder/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/forever-agent": {
-            "version": "0.6.1",
-            "inBundle": true,
-            "license": "Apache-2.0",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/npm/node_modules/form-data": {
-            "version": "2.3.3",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "asynckit": "^0.4.0",
-                "combined-stream": "^1.0.6",
-                "mime-types": "^2.1.12"
-            },
-            "engines": {
-                "node": ">= 0.12"
-            }
-        },
-        "node_modules/npm/node_modules/from2": {
-            "version": "2.3.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "inherits": "^2.0.1",
-                "readable-stream": "^2.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/from2/node_modules/readable-stream": {
-            "version": "2.3.6",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/from2/node_modules/readable-stream/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/from2/node_modules/string_decoder": {
-            "version": "1.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "safe-buffer": "~5.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/from2/node_modules/string_decoder/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/fs-minipass": {
-            "version": "1.2.7",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "minipass": "^2.6.0"
-            }
-        },
-        "node_modules/npm/node_modules/fs-minipass/node_modules/minipass": {
-            "version": "2.9.0",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "safe-buffer": "^5.1.2",
-                "yallist": "^3.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/fs-vacuum": {
-            "version": "1.2.10",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "graceful-fs": "^4.1.2",
-                "path-is-inside": "^1.0.1",
-                "rimraf": "^2.5.2"
-            }
-        },
-        "node_modules/npm/node_modules/fs-write-stream-atomic": {
-            "version": "1.0.10",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "graceful-fs": "^4.1.2",
-                "iferr": "^0.1.5",
-                "imurmurhash": "^0.1.4",
-                "readable-stream": "1 || 2"
-            }
-        },
-        "node_modules/npm/node_modules/fs-write-stream-atomic/node_modules/iferr": {
-            "version": "0.1.5",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/fs-write-stream-atomic/node_modules/readable-stream": {
-            "version": "2.3.6",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/fs-write-stream-atomic/node_modules/readable-stream/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/fs-write-stream-atomic/node_modules/string_decoder": {
-            "version": "1.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "safe-buffer": "~5.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/fs-write-stream-atomic/node_modules/string_decoder/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/fs.realpath": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/function-bind": {
-            "version": "1.1.1",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/gauge": {
-            "version": "2.7.4",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "aproba": "^1.0.3",
-                "console-control-strings": "^1.0.0",
-                "has-unicode": "^2.0.0",
-                "object-assign": "^4.1.0",
-                "signal-exit": "^3.0.0",
-                "string-width": "^1.0.1",
-                "strip-ansi": "^3.0.1",
-                "wide-align": "^1.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/gauge/node_modules/aproba": {
-            "version": "1.2.0",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/gauge/node_modules/string-width": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "code-point-at": "^1.0.0",
-                "is-fullwidth-code-point": "^1.0.0",
-                "strip-ansi": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/genfun": {
-            "version": "5.0.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/gentle-fs": {
-            "version": "2.3.1",
-            "inBundle": true,
-            "license": "Artistic-2.0",
-            "dependencies": {
-                "aproba": "^1.1.2",
-                "chownr": "^1.1.2",
-                "cmd-shim": "^3.0.3",
-                "fs-vacuum": "^1.2.10",
-                "graceful-fs": "^4.1.11",
-                "iferr": "^0.1.5",
-                "infer-owner": "^1.0.4",
-                "mkdirp": "^0.5.1",
-                "path-is-inside": "^1.0.2",
-                "read-cmd-shim": "^1.0.1",
-                "slide": "^1.1.6"
-            }
-        },
-        "node_modules/npm/node_modules/gentle-fs/node_modules/aproba": {
-            "version": "1.2.0",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/gentle-fs/node_modules/iferr": {
-            "version": "0.1.5",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/get-caller-file": {
-            "version": "2.0.5",
-            "inBundle": true,
-            "license": "ISC",
-            "engines": {
-                "node": "6.* || 8.* || >= 10.*"
-            }
-        },
-        "node_modules/npm/node_modules/get-stream": {
-            "version": "4.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "pump": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/getpass": {
-            "version": "0.1.7",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "assert-plus": "^1.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/glob": {
-            "version": "7.2.3",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "fs.realpath": "^1.0.0",
-                "inflight": "^1.0.4",
-                "inherits": "2",
-                "minimatch": "^3.1.1",
-                "once": "^1.3.0",
-                "path-is-absolute": "^1.0.0"
-            },
-            "engines": {
-                "node": "*"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/isaacs"
-            }
-        },
-        "node_modules/npm/node_modules/glob/node_modules/minimatch": {
-            "version": "3.1.2",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "brace-expansion": "^1.1.7"
-            },
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/npm/node_modules/global-dirs": {
-            "version": "0.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "ini": "^1.3.4"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/got": {
-            "version": "6.7.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "create-error-class": "^3.0.0",
-                "duplexer3": "^0.1.4",
-                "get-stream": "^3.0.0",
-                "is-redirect": "^1.0.0",
-                "is-retry-allowed": "^1.0.0",
-                "is-stream": "^1.0.0",
-                "lowercase-keys": "^1.0.0",
-                "safe-buffer": "^5.0.1",
-                "timed-out": "^4.0.0",
-                "unzip-response": "^2.0.1",
-                "url-parse-lax": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/got/node_modules/get-stream": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/graceful-fs": {
-            "version": "4.2.10",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/har-schema": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "ISC",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/har-validator": {
-            "version": "5.1.5",
-            "deprecated": "this library is no longer supported",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "ajv": "^6.12.3",
-                "har-schema": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/har-validator/node_modules/ajv": {
-            "version": "6.12.6",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "fast-deep-equal": "^3.1.1",
-                "fast-json-stable-stringify": "^2.0.0",
-                "json-schema-traverse": "^0.4.1",
-                "uri-js": "^4.2.2"
-            },
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/epoberezkin"
-            }
-        },
-        "node_modules/npm/node_modules/har-validator/node_modules/fast-deep-equal": {
-            "version": "3.1.3",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/har-validator/node_modules/json-schema-traverse": {
-            "version": "0.4.1",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/has": {
-            "version": "1.0.3",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "function-bind": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4.0"
-            }
-        },
-        "node_modules/npm/node_modules/has-flag": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/has-symbols": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/npm/node_modules/has-unicode": {
-            "version": "2.0.1",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/hosted-git-info": {
-            "version": "2.8.9",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/http-cache-semantics": {
-            "version": "3.8.1",
-            "inBundle": true,
-            "license": "BSD-2-Clause"
-        },
-        "node_modules/npm/node_modules/http-proxy-agent": {
-            "version": "2.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "agent-base": "4",
-                "debug": "3.1.0"
-            },
-            "engines": {
-                "node": ">= 4.5.0"
-            }
-        },
-        "node_modules/npm/node_modules/http-signature": {
-            "version": "1.2.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "assert-plus": "^1.0.0",
-                "jsprim": "^1.2.2",
-                "sshpk": "^1.7.0"
-            },
-            "engines": {
-                "node": ">=0.8",
-                "npm": ">=1.3.7"
-            }
-        },
-        "node_modules/npm/node_modules/https-proxy-agent": {
-            "version": "2.2.4",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "agent-base": "^4.3.0",
-                "debug": "^3.1.0"
-            },
-            "engines": {
-                "node": ">= 4.5.0"
-            }
-        },
-        "node_modules/npm/node_modules/humanize-ms": {
-            "version": "1.2.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "ms": "^2.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/iconv-lite": {
-            "version": "0.4.23",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "safer-buffer": ">= 2.1.2 < 3"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/iferr": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/ignore-walk": {
-            "version": "3.0.3",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "minimatch": "^3.0.4"
-            }
-        },
-        "node_modules/npm/node_modules/import-lazy": {
-            "version": "2.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/imurmurhash": {
-            "version": "0.1.4",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.8.19"
-            }
-        },
-        "node_modules/npm/node_modules/infer-owner": {
-            "version": "1.0.4",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/inflight": {
-            "version": "1.0.6",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "once": "^1.3.0",
-                "wrappy": "1"
-            }
-        },
-        "node_modules/npm/node_modules/inherits": {
-            "version": "2.0.4",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/ini": {
-            "version": "1.3.8",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/init-package-json": {
-            "version": "1.10.3",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "glob": "^7.1.1",
-                "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0",
-                "promzard": "^0.3.0",
-                "read": "~1.0.1",
-                "read-package-json": "1 || 2",
-                "semver": "2.x || 3.x || 4 || 5",
-                "validate-npm-package-license": "^3.0.1",
-                "validate-npm-package-name": "^3.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/ip": {
-            "version": "1.1.5",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/ip-regex": {
-            "version": "2.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/is-callable": {
-            "version": "1.1.4",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/npm/node_modules/is-ci": {
-            "version": "1.2.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "ci-info": "^1.5.0"
-            },
-            "bin": {
-                "is-ci": "bin.js"
-            }
-        },
-        "node_modules/npm/node_modules/is-ci/node_modules/ci-info": {
-            "version": "1.6.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/is-cidr": {
-            "version": "3.1.1",
-            "inBundle": true,
-            "license": "BSD-2-Clause",
-            "dependencies": {
-                "cidr-regex": "^2.0.10"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/is-date-object": {
-            "version": "1.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/npm/node_modules/is-fullwidth-code-point": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "number-is-nan": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/is-installed-globally": {
-            "version": "0.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "global-dirs": "^0.1.0",
-                "is-path-inside": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/is-npm": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/is-obj": {
-            "version": "1.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/is-path-inside": {
-            "version": "1.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "path-is-inside": "^1.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/is-redirect": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/is-regex": {
-            "version": "1.0.4",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "has": "^1.0.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/npm/node_modules/is-retry-allowed": {
-            "version": "1.2.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/is-stream": {
-            "version": "1.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/is-symbol": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "has-symbols": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/npm/node_modules/is-typedarray": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/isarray": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/isexe": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/isstream": {
-            "version": "0.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/jsbn": {
-            "version": "0.1.1",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/json-parse-better-errors": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/json-parse-even-better-errors": {
-            "version": "2.3.1",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/json-schema": {
-            "version": "0.4.0",
-            "inBundle": true,
-            "license": "(AFL-2.1 OR BSD-3-Clause)"
-        },
-        "node_modules/npm/node_modules/json-stringify-safe": {
-            "version": "5.0.1",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/jsonparse": {
-            "version": "1.3.1",
-            "engines": [
-                "node >= 0.2.0"
-            ],
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/JSONStream": {
-            "version": "1.3.5",
-            "inBundle": true,
-            "license": "(MIT OR Apache-2.0)",
-            "dependencies": {
-                "jsonparse": "^1.2.0",
-                "through": ">=2.2.7 <3"
-            },
-            "bin": {
-                "JSONStream": "bin.js"
-            },
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/npm/node_modules/jsprim": {
-            "version": "1.4.2",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "assert-plus": "1.0.0",
-                "extsprintf": "1.3.0",
-                "json-schema": "0.4.0",
-                "verror": "1.10.0"
-            },
-            "engines": {
-                "node": ">=0.6.0"
-            }
-        },
-        "node_modules/npm/node_modules/latest-version": {
-            "version": "3.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "package-json": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/lazy-property": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/libcipm": {
-            "version": "4.0.8",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "bin-links": "^1.1.2",
-                "bluebird": "^3.5.1",
-                "figgy-pudding": "^3.5.1",
-                "find-npm-prefix": "^1.0.2",
-                "graceful-fs": "^4.1.11",
-                "ini": "^1.3.5",
-                "lock-verify": "^2.1.0",
-                "mkdirp": "^0.5.1",
-                "npm-lifecycle": "^3.0.0",
-                "npm-logical-tree": "^1.2.1",
-                "npm-package-arg": "^6.1.0",
-                "pacote": "^9.1.0",
-                "read-package-json": "^2.0.13",
-                "rimraf": "^2.6.2",
-                "worker-farm": "^1.6.0"
-            }
-        },
-        "node_modules/npm/node_modules/libnpm": {
-            "version": "3.0.1",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "bin-links": "^1.1.2",
-                "bluebird": "^3.5.3",
-                "find-npm-prefix": "^1.0.2",
-                "libnpmaccess": "^3.0.2",
-                "libnpmconfig": "^1.2.1",
-                "libnpmhook": "^5.0.3",
-                "libnpmorg": "^1.0.1",
-                "libnpmpublish": "^1.1.2",
-                "libnpmsearch": "^2.0.2",
-                "libnpmteam": "^1.0.2",
-                "lock-verify": "^2.0.2",
-                "npm-lifecycle": "^3.0.0",
-                "npm-logical-tree": "^1.2.1",
-                "npm-package-arg": "^6.1.0",
-                "npm-profile": "^4.0.2",
-                "npm-registry-fetch": "^4.0.0",
-                "npmlog": "^4.1.2",
-                "pacote": "^9.5.3",
-                "read-package-json": "^2.0.13",
-                "stringify-package": "^1.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/libnpmaccess": {
-            "version": "3.0.2",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "aproba": "^2.0.0",
-                "get-stream": "^4.0.0",
-                "npm-package-arg": "^6.1.0",
-                "npm-registry-fetch": "^4.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/libnpmconfig": {
-            "version": "1.2.1",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "figgy-pudding": "^3.5.1",
-                "find-up": "^3.0.0",
-                "ini": "^1.3.5"
-            }
-        },
-        "node_modules/npm/node_modules/libnpmconfig/node_modules/find-up": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "locate-path": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/libnpmconfig/node_modules/locate-path": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "p-locate": "^3.0.0",
-                "path-exists": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/libnpmconfig/node_modules/p-limit": {
-            "version": "2.2.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "p-try": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/libnpmconfig/node_modules/p-locate": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "p-limit": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/libnpmconfig/node_modules/p-try": {
-            "version": "2.2.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/libnpmhook": {
-            "version": "5.0.3",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "aproba": "^2.0.0",
-                "figgy-pudding": "^3.4.1",
-                "get-stream": "^4.0.0",
-                "npm-registry-fetch": "^4.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/libnpmorg": {
-            "version": "1.0.1",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "aproba": "^2.0.0",
-                "figgy-pudding": "^3.4.1",
-                "get-stream": "^4.0.0",
-                "npm-registry-fetch": "^4.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/libnpmpublish": {
-            "version": "1.1.2",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "aproba": "^2.0.0",
-                "figgy-pudding": "^3.5.1",
-                "get-stream": "^4.0.0",
-                "lodash.clonedeep": "^4.5.0",
-                "normalize-package-data": "^2.4.0",
-                "npm-package-arg": "^6.1.0",
-                "npm-registry-fetch": "^4.0.0",
-                "semver": "^5.5.1",
-                "ssri": "^6.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/libnpmsearch": {
-            "version": "2.0.2",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "figgy-pudding": "^3.5.1",
-                "get-stream": "^4.0.0",
-                "npm-registry-fetch": "^4.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/libnpmteam": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "aproba": "^2.0.0",
-                "figgy-pudding": "^3.4.1",
-                "get-stream": "^4.0.0",
-                "npm-registry-fetch": "^4.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/libnpx": {
-            "version": "10.2.4",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "dotenv": "^5.0.1",
-                "npm-package-arg": "^6.0.0",
-                "rimraf": "^2.6.2",
-                "safe-buffer": "^5.1.0",
-                "update-notifier": "^2.3.0",
-                "which": "^1.3.0",
-                "y18n": "^4.0.0",
-                "yargs": "^14.2.3"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/lock-verify": {
-            "version": "2.2.2",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "@iarna/cli": "^2.1.0",
-                "npm-package-arg": "^6.1.0",
-                "semver": "^5.4.1"
-            },
-            "bin": {
-                "lock-verify": "cli.js"
-            }
-        },
-        "node_modules/npm/node_modules/lockfile": {
-            "version": "1.0.4",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "signal-exit": "^3.0.2"
-            }
-        },
-        "node_modules/npm/node_modules/lodash._baseindexof": {
-            "version": "3.1.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/lodash._baseuniq": {
-            "version": "4.6.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "lodash._createset": "~4.0.0",
-                "lodash._root": "~3.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/lodash._bindcallback": {
-            "version": "3.0.1",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/lodash._cacheindexof": {
-            "version": "3.0.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/lodash._createcache": {
-            "version": "3.1.2",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "lodash._getnative": "^3.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/lodash._createset": {
-            "version": "4.0.3",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/lodash._getnative": {
-            "version": "3.9.1",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/lodash._root": {
-            "version": "3.0.1",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/lodash.clonedeep": {
-            "version": "4.5.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/lodash.restparam": {
-            "version": "3.6.1",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/lodash.union": {
-            "version": "4.6.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/lodash.uniq": {
-            "version": "4.5.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/lodash.without": {
-            "version": "4.4.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/lowercase-keys": {
-            "version": "1.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/lru-cache": {
-            "version": "5.1.1",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "yallist": "^3.0.2"
-            }
-        },
-        "node_modules/npm/node_modules/make-dir": {
-            "version": "1.3.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "pify": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/make-fetch-happen": {
-            "version": "5.0.2",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "agentkeepalive": "^3.4.1",
-                "cacache": "^12.0.0",
-                "http-cache-semantics": "^3.8.1",
-                "http-proxy-agent": "^2.1.0",
-                "https-proxy-agent": "^2.2.3",
-                "lru-cache": "^5.1.1",
-                "mississippi": "^3.0.0",
-                "node-fetch-npm": "^2.0.2",
-                "promise-retry": "^1.1.1",
-                "socks-proxy-agent": "^4.0.0",
-                "ssri": "^6.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/meant": {
-            "version": "1.0.3",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/mime-db": {
-            "version": "1.35.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/npm/node_modules/mime-types": {
-            "version": "2.1.19",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "mime-db": "~1.35.0"
-            },
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/npm/node_modules/minimatch": {
-            "version": "3.1.2",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "brace-expansion": "^1.1.7"
-            },
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/npm/node_modules/minimist": {
-            "version": "1.2.6",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/minizlib": {
-            "version": "1.3.3",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "minipass": "^2.9.0"
-            }
-        },
-        "node_modules/npm/node_modules/minizlib/node_modules/minipass": {
-            "version": "2.9.0",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "safe-buffer": "^5.1.2",
-                "yallist": "^3.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/mississippi": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "BSD-2-Clause",
-            "dependencies": {
-                "concat-stream": "^1.5.0",
-                "duplexify": "^3.4.2",
-                "end-of-stream": "^1.1.0",
-                "flush-write-stream": "^1.0.0",
-                "from2": "^2.1.0",
-                "parallel-transform": "^1.1.0",
-                "pump": "^3.0.0",
-                "pumpify": "^1.3.3",
-                "stream-each": "^1.1.0",
-                "through2": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/mkdirp": {
-            "version": "0.5.6",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "minimist": "^1.2.6"
-            },
-            "bin": {
-                "mkdirp": "bin/cmd.js"
-            }
-        },
-        "node_modules/npm/node_modules/move-concurrently": {
-            "version": "1.0.1",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "aproba": "^1.1.1",
-                "copy-concurrently": "^1.0.0",
-                "fs-write-stream-atomic": "^1.0.8",
-                "mkdirp": "^0.5.1",
-                "rimraf": "^2.5.4",
-                "run-queue": "^1.0.3"
-            }
-        },
-        "node_modules/npm/node_modules/move-concurrently/node_modules/aproba": {
-            "version": "1.2.0",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/ms": {
-            "version": "2.1.1",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/mute-stream": {
-            "version": "0.0.7",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/node-fetch-npm": {
-            "version": "2.0.2",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "encoding": "^0.1.11",
-                "json-parse-better-errors": "^1.0.0",
-                "safe-buffer": "^5.1.1"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/node-gyp": {
-            "version": "5.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "env-paths": "^2.2.0",
-                "glob": "^7.1.4",
-                "graceful-fs": "^4.2.2",
-                "mkdirp": "^0.5.1",
-                "nopt": "^4.0.1",
-                "npmlog": "^4.1.2",
-                "request": "^2.88.0",
-                "rimraf": "^2.6.3",
-                "semver": "^5.7.1",
-                "tar": "^4.4.12",
-                "which": "^1.3.1"
-            },
-            "bin": {
-                "node-gyp": "bin/node-gyp.js"
-            },
-            "engines": {
-                "node": ">= 6.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/nopt": {
-            "version": "4.0.3",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "abbrev": "1",
-                "osenv": "^0.1.4"
-            },
-            "bin": {
-                "nopt": "bin/nopt.js"
-            }
-        },
-        "node_modules/npm/node_modules/normalize-package-data": {
-            "version": "2.5.0",
-            "inBundle": true,
-            "license": "BSD-2-Clause",
-            "dependencies": {
-                "hosted-git-info": "^2.1.4",
-                "resolve": "^1.10.0",
-                "semver": "2 || 3 || 4 || 5",
-                "validate-npm-package-license": "^3.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/normalize-package-data/node_modules/resolve": {
-            "version": "1.10.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "path-parse": "^1.0.6"
-            }
-        },
-        "node_modules/npm/node_modules/npm-audit-report": {
-            "version": "1.3.3",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "cli-table3": "^0.5.0",
-                "console-control-strings": "^1.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/npm-bundled": {
-            "version": "1.1.1",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "npm-normalize-package-bin": "^1.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/npm-cache-filename": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/npm-install-checks": {
-            "version": "3.0.2",
-            "inBundle": true,
-            "license": "BSD-2-Clause",
-            "dependencies": {
-                "semver": "^2.3.0 || 3.x || 4 || 5"
-            }
-        },
-        "node_modules/npm/node_modules/npm-lifecycle": {
-            "version": "3.1.5",
-            "inBundle": true,
-            "license": "Artistic-2.0",
-            "dependencies": {
-                "byline": "^5.0.0",
-                "graceful-fs": "^4.1.15",
-                "node-gyp": "^5.0.2",
-                "resolve-from": "^4.0.0",
-                "slide": "^1.1.6",
-                "uid-number": "0.0.6",
-                "umask": "^1.1.0",
-                "which": "^1.3.1"
-            }
-        },
-        "node_modules/npm/node_modules/npm-logical-tree": {
-            "version": "1.2.1",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/npm-normalize-package-bin": {
-            "version": "1.0.1",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/npm-package-arg": {
-            "version": "6.1.1",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "hosted-git-info": "^2.7.1",
-                "osenv": "^0.1.5",
-                "semver": "^5.6.0",
-                "validate-npm-package-name": "^3.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/npm-packlist": {
-            "version": "1.4.8",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "ignore-walk": "^3.0.1",
-                "npm-bundled": "^1.0.1",
-                "npm-normalize-package-bin": "^1.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/npm-pick-manifest": {
-            "version": "3.0.2",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "figgy-pudding": "^3.5.1",
-                "npm-package-arg": "^6.0.0",
-                "semver": "^5.4.1"
-            }
-        },
-        "node_modules/npm/node_modules/npm-profile": {
-            "version": "4.0.4",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "aproba": "^1.1.2 || 2",
-                "figgy-pudding": "^3.4.1",
-                "npm-registry-fetch": "^4.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/npm-registry-fetch": {
-            "version": "4.0.7",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "bluebird": "^3.5.1",
-                "figgy-pudding": "^3.4.1",
-                "JSONStream": "^1.3.4",
-                "lru-cache": "^5.1.1",
-                "make-fetch-happen": "^5.0.0",
-                "npm-package-arg": "^6.1.0",
-                "safe-buffer": "^5.2.0"
-            }
-        },
-        "node_modules/npm/node_modules/npm-registry-fetch/node_modules/safe-buffer": {
-            "version": "5.2.1",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ],
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/npm-run-path": {
-            "version": "2.0.2",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "path-key": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/npm-user-validate": {
-            "version": "1.0.1",
-            "inBundle": true,
-            "license": "BSD-2-Clause"
-        },
-        "node_modules/npm/node_modules/npmlog": {
-            "version": "4.1.2",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "are-we-there-yet": "~1.1.2",
-                "console-control-strings": "~1.1.0",
-                "gauge": "~2.7.3",
-                "set-blocking": "~2.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/number-is-nan": {
-            "version": "1.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/oauth-sign": {
-            "version": "0.9.0",
-            "inBundle": true,
-            "license": "Apache-2.0",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/npm/node_modules/object-assign": {
-            "version": "4.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/object-keys": {
-            "version": "1.0.12",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/npm/node_modules/object.getownpropertydescriptors": {
-            "version": "2.0.3",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "define-properties": "^1.1.2",
-                "es-abstract": "^1.5.1"
-            },
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/npm/node_modules/once": {
-            "version": "1.4.0",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "wrappy": "1"
-            }
-        },
-        "node_modules/npm/node_modules/opener": {
-            "version": "1.5.2",
-            "inBundle": true,
-            "license": "(WTFPL OR MIT)",
-            "bin": {
-                "opener": "bin/opener-bin.js"
-            }
-        },
-        "node_modules/npm/node_modules/os-homedir": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/os-tmpdir": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/osenv": {
-            "version": "0.1.5",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "os-homedir": "^1.0.0",
-                "os-tmpdir": "^1.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/p-finally": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/package-json": {
-            "version": "4.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "got": "^6.7.1",
-                "registry-auth-token": "^3.0.1",
-                "registry-url": "^3.0.3",
-                "semver": "^5.1.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/pacote": {
-            "version": "9.5.12",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "bluebird": "^3.5.3",
-                "cacache": "^12.0.2",
-                "chownr": "^1.1.2",
-                "figgy-pudding": "^3.5.1",
-                "get-stream": "^4.1.0",
-                "glob": "^7.1.3",
-                "infer-owner": "^1.0.4",
-                "lru-cache": "^5.1.1",
-                "make-fetch-happen": "^5.0.0",
-                "minimatch": "^3.0.4",
-                "minipass": "^2.3.5",
-                "mississippi": "^3.0.0",
-                "mkdirp": "^0.5.1",
-                "normalize-package-data": "^2.4.0",
-                "npm-normalize-package-bin": "^1.0.0",
-                "npm-package-arg": "^6.1.0",
-                "npm-packlist": "^1.1.12",
-                "npm-pick-manifest": "^3.0.0",
-                "npm-registry-fetch": "^4.0.0",
-                "osenv": "^0.1.5",
-                "promise-inflight": "^1.0.1",
-                "promise-retry": "^1.1.1",
-                "protoduck": "^5.0.1",
-                "rimraf": "^2.6.2",
-                "safe-buffer": "^5.1.2",
-                "semver": "^5.6.0",
-                "ssri": "^6.0.1",
-                "tar": "^4.4.10",
-                "unique-filename": "^1.1.1",
-                "which": "^1.3.1"
-            }
-        },
-        "node_modules/npm/node_modules/pacote/node_modules/minipass": {
-            "version": "2.9.0",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "safe-buffer": "^5.1.2",
-                "yallist": "^3.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/parallel-transform": {
-            "version": "1.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "cyclist": "~0.2.2",
-                "inherits": "^2.0.3",
-                "readable-stream": "^2.1.5"
-            }
-        },
-        "node_modules/npm/node_modules/parallel-transform/node_modules/readable-stream": {
-            "version": "2.3.6",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/parallel-transform/node_modules/readable-stream/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/parallel-transform/node_modules/string_decoder": {
-            "version": "1.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "safe-buffer": "~5.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/parallel-transform/node_modules/string_decoder/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/path-exists": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/path-is-absolute": {
-            "version": "1.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/path-is-inside": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "(WTFPL OR MIT)"
-        },
-        "node_modules/npm/node_modules/path-key": {
-            "version": "2.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/path-parse": {
-            "version": "1.0.7",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/performance-now": {
-            "version": "2.1.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/pify": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/prepend-http": {
-            "version": "1.0.4",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/process-nextick-args": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/promise-inflight": {
-            "version": "1.0.1",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/promise-retry": {
-            "version": "1.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "err-code": "^1.0.0",
-                "retry": "^0.10.0"
-            },
-            "engines": {
-                "node": ">=0.12"
-            }
-        },
-        "node_modules/npm/node_modules/promise-retry/node_modules/retry": {
-            "version": "0.10.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/npm/node_modules/promzard": {
-            "version": "0.3.0",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "read": "1"
-            }
-        },
-        "node_modules/npm/node_modules/proto-list": {
-            "version": "1.2.4",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/protoduck": {
-            "version": "5.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "genfun": "^5.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/prr": {
-            "version": "1.0.1",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/pseudomap": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/psl": {
-            "version": "1.9.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/pump": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "end-of-stream": "^1.1.0",
-                "once": "^1.3.1"
-            }
-        },
-        "node_modules/npm/node_modules/pumpify": {
-            "version": "1.5.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "duplexify": "^3.6.0",
-                "inherits": "^2.0.3",
-                "pump": "^2.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/pumpify/node_modules/pump": {
-            "version": "2.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "end-of-stream": "^1.1.0",
-                "once": "^1.3.1"
-            }
-        },
-        "node_modules/npm/node_modules/qrcode-terminal": {
-            "version": "0.12.0",
-            "inBundle": true,
-            "bin": {
-                "qrcode-terminal": "bin/qrcode-terminal.js"
-            }
-        },
-        "node_modules/npm/node_modules/qs": {
-            "version": "6.5.3",
-            "inBundle": true,
-            "license": "BSD-3-Clause",
-            "engines": {
-                "node": ">=0.6"
-            }
-        },
-        "node_modules/npm/node_modules/query-string": {
-            "version": "6.14.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "decode-uri-component": "^0.2.0",
-                "filter-obj": "^1.1.0",
-                "split-on-first": "^1.0.0",
-                "strict-uri-encode": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/npm/node_modules/qw": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/rc": {
-            "version": "1.2.8",
-            "inBundle": true,
-            "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
-            "dependencies": {
-                "deep-extend": "^0.6.0",
-                "ini": "~1.3.0",
-                "minimist": "^1.2.0",
-                "strip-json-comments": "~2.0.1"
-            },
-            "bin": {
-                "rc": "cli.js"
-            }
-        },
-        "node_modules/npm/node_modules/read": {
-            "version": "1.0.7",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "mute-stream": "~0.0.4"
-            },
-            "engines": {
-                "node": ">=0.8"
-            }
-        },
-        "node_modules/npm/node_modules/read-cmd-shim": {
-            "version": "1.0.5",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "graceful-fs": "^4.1.2"
-            }
-        },
-        "node_modules/npm/node_modules/read-installed": {
-            "version": "4.0.3",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "debuglog": "^1.0.1",
-                "read-package-json": "^2.0.0",
-                "readdir-scoped-modules": "^1.0.0",
-                "semver": "2 || 3 || 4 || 5",
-                "slide": "~1.1.3",
-                "util-extend": "^1.0.1"
-            },
-            "optionalDependencies": {
-                "graceful-fs": "^4.1.2"
-            }
-        },
-        "node_modules/npm/node_modules/read-package-json": {
-            "version": "2.1.2",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "glob": "^7.1.1",
-                "json-parse-even-better-errors": "^2.3.0",
-                "normalize-package-data": "^2.0.0",
-                "npm-normalize-package-bin": "^1.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/read-package-tree": {
-            "version": "5.3.1",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "read-package-json": "^2.0.0",
-                "readdir-scoped-modules": "^1.0.0",
-                "util-promisify": "^2.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/readable-stream": {
-            "version": "3.6.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "inherits": "^2.0.3",
-                "string_decoder": "^1.1.1",
-                "util-deprecate": "^1.0.1"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/npm/node_modules/readdir-scoped-modules": {
-            "version": "1.1.0",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "debuglog": "^1.0.1",
-                "dezalgo": "^1.0.0",
-                "graceful-fs": "^4.1.2",
-                "once": "^1.3.0"
-            }
-        },
-        "node_modules/npm/node_modules/registry-auth-token": {
-            "version": "3.4.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "rc": "^1.1.6",
-                "safe-buffer": "^5.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/registry-url": {
-            "version": "3.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "rc": "^1.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/request": {
-            "version": "2.88.2",
-            "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
-            "inBundle": true,
-            "license": "Apache-2.0",
-            "dependencies": {
-                "aws-sign2": "~0.7.0",
-                "aws4": "^1.8.0",
-                "caseless": "~0.12.0",
-                "combined-stream": "~1.0.6",
-                "extend": "~3.0.2",
-                "forever-agent": "~0.6.1",
-                "form-data": "~2.3.2",
-                "har-validator": "~5.1.3",
-                "http-signature": "~1.2.0",
-                "is-typedarray": "~1.0.0",
-                "isstream": "~0.1.2",
-                "json-stringify-safe": "~5.0.1",
-                "mime-types": "~2.1.19",
-                "oauth-sign": "~0.9.0",
-                "performance-now": "^2.1.0",
-                "qs": "~6.5.2",
-                "safe-buffer": "^5.1.2",
-                "tough-cookie": "~2.5.0",
-                "tunnel-agent": "^0.6.0",
-                "uuid": "^3.3.2"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/npm/node_modules/require-directory": {
-            "version": "2.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/require-main-filename": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/resolve-from": {
-            "version": "4.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/retry": {
-            "version": "0.12.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">= 4"
-            }
-        },
-        "node_modules/npm/node_modules/rimraf": {
-            "version": "2.7.1",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            }
-        },
-        "node_modules/npm/node_modules/run-queue": {
-            "version": "1.0.3",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "aproba": "^1.1.1"
-            }
-        },
-        "node_modules/npm/node_modules/run-queue/node_modules/aproba": {
-            "version": "1.2.0",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/safe-buffer": {
-            "version": "5.2.1",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ],
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/safer-buffer": {
-            "version": "2.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/semver": {
-            "version": "5.7.1",
-            "inBundle": true,
-            "license": "ISC",
-            "bin": {
-                "semver": "bin/semver"
-            }
-        },
-        "node_modules/npm/node_modules/semver-diff": {
-            "version": "2.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "semver": "^5.0.3"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/set-blocking": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/sha": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "(BSD-2-Clause OR MIT)",
-            "dependencies": {
-                "graceful-fs": "^4.1.2"
-            }
-        },
-        "node_modules/npm/node_modules/shebang-command": {
-            "version": "1.2.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "shebang-regex": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/shebang-regex": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/signal-exit": {
-            "version": "3.0.2",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/slide": {
-            "version": "1.1.6",
-            "inBundle": true,
-            "license": "ISC",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/npm/node_modules/smart-buffer": {
-            "version": "4.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">= 6.0.0",
-                "npm": ">= 3.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/socks": {
-            "version": "2.3.3",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "ip": "1.1.5",
-                "smart-buffer": "^4.1.0"
-            },
-            "engines": {
-                "node": ">= 6.0.0",
-                "npm": ">= 3.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/socks-proxy-agent": {
-            "version": "4.0.2",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "agent-base": "~4.2.1",
-                "socks": "~2.3.2"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/npm/node_modules/socks-proxy-agent/node_modules/agent-base": {
-            "version": "4.2.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "es6-promisify": "^5.0.0"
-            },
-            "engines": {
-                "node": ">= 4.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/sorted-object": {
-            "version": "2.0.1",
-            "inBundle": true,
-            "license": "(WTFPL OR MIT)"
-        },
-        "node_modules/npm/node_modules/sorted-union-stream": {
-            "version": "2.1.3",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "from2": "^1.3.0",
-                "stream-iterate": "^1.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/sorted-union-stream/node_modules/from2": {
-            "version": "1.3.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "inherits": "~2.0.1",
-                "readable-stream": "~1.1.10"
-            }
-        },
-        "node_modules/npm/node_modules/sorted-union-stream/node_modules/isarray": {
-            "version": "0.0.1",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/sorted-union-stream/node_modules/readable-stream": {
-            "version": "1.1.14",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.1",
-                "isarray": "0.0.1",
-                "string_decoder": "~0.10.x"
-            }
-        },
-        "node_modules/npm/node_modules/sorted-union-stream/node_modules/string_decoder": {
-            "version": "0.10.31",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/spdx-correct": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "Apache-2.0",
-            "dependencies": {
-                "spdx-expression-parse": "^3.0.0",
-                "spdx-license-ids": "^3.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/spdx-exceptions": {
-            "version": "2.1.0",
-            "inBundle": true,
-            "license": "CC-BY-3.0"
-        },
-        "node_modules/npm/node_modules/spdx-expression-parse": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "spdx-exceptions": "^2.1.0",
-                "spdx-license-ids": "^3.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/spdx-license-ids": {
-            "version": "3.0.5",
-            "inBundle": true,
-            "license": "CC0-1.0"
-        },
-        "node_modules/npm/node_modules/split-on-first": {
-            "version": "1.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/sshpk": {
-            "version": "1.17.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "asn1": "~0.2.3",
-                "assert-plus": "^1.0.0",
-                "bcrypt-pbkdf": "^1.0.0",
-                "dashdash": "^1.12.0",
-                "ecc-jsbn": "~0.1.1",
-                "getpass": "^0.1.1",
-                "jsbn": "~0.1.0",
-                "safer-buffer": "^2.0.2",
-                "tweetnacl": "~0.14.0"
-            },
-            "bin": {
-                "sshpk-conv": "bin/sshpk-conv",
-                "sshpk-sign": "bin/sshpk-sign",
-                "sshpk-verify": "bin/sshpk-verify"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/ssri": {
-            "version": "6.0.2",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "figgy-pudding": "^3.5.1"
-            }
-        },
-        "node_modules/npm/node_modules/stream-each": {
-            "version": "1.2.2",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "end-of-stream": "^1.1.0",
-                "stream-shift": "^1.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/stream-iterate": {
-            "version": "1.2.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "readable-stream": "^2.1.5",
-                "stream-shift": "^1.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/stream-iterate/node_modules/readable-stream": {
-            "version": "2.3.6",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/stream-iterate/node_modules/readable-stream/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/stream-iterate/node_modules/string_decoder": {
-            "version": "1.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "safe-buffer": "~5.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/stream-iterate/node_modules/string_decoder/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/stream-shift": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/strict-uri-encode": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/string_decoder": {
-            "version": "1.3.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "safe-buffer": "~5.2.0"
-            }
-        },
-        "node_modules/npm/node_modules/string_decoder/node_modules/safe-buffer": {
-            "version": "5.2.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/string-width": {
-            "version": "2.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "is-fullwidth-code-point": "^2.0.0",
-                "strip-ansi": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/string-width/node_modules/ansi-regex": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/string-width/node_modules/is-fullwidth-code-point": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/string-width/node_modules/strip-ansi": {
-            "version": "4.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "ansi-regex": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/stringify-package": {
-            "version": "1.0.1",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/strip-ansi": {
-            "version": "3.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "ansi-regex": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/strip-eof": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/strip-json-comments": {
-            "version": "2.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/supports-color": {
-            "version": "5.4.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "has-flag": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/tar": {
-            "version": "4.4.19",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "chownr": "^1.1.4",
-                "fs-minipass": "^1.2.7",
-                "minipass": "^2.9.0",
-                "minizlib": "^1.3.3",
-                "mkdirp": "^0.5.5",
-                "safe-buffer": "^5.2.1",
-                "yallist": "^3.1.1"
-            },
-            "engines": {
-                "node": ">=4.5"
-            }
-        },
-        "node_modules/npm/node_modules/tar/node_modules/minipass": {
-            "version": "2.9.0",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "safe-buffer": "^5.1.2",
-                "yallist": "^3.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/tar/node_modules/safe-buffer": {
-            "version": "5.2.1",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ],
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/tar/node_modules/yallist": {
-            "version": "3.1.1",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/term-size": {
-            "version": "1.2.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "execa": "^0.7.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/text-table": {
-            "version": "0.2.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/through": {
-            "version": "2.3.8",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/through2": {
-            "version": "2.0.3",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "readable-stream": "^2.1.5",
-                "xtend": "~4.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/through2/node_modules/readable-stream": {
-            "version": "2.3.6",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/through2/node_modules/readable-stream/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/through2/node_modules/string_decoder": {
-            "version": "1.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "safe-buffer": "~5.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/through2/node_modules/string_decoder/node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/timed-out": {
-            "version": "4.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/tiny-relative-date": {
-            "version": "1.3.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/tough-cookie": {
-            "version": "2.5.0",
-            "inBundle": true,
-            "license": "BSD-3-Clause",
-            "dependencies": {
-                "psl": "^1.1.28",
-                "punycode": "^2.1.1"
-            },
-            "engines": {
-                "node": ">=0.8"
-            }
-        },
-        "node_modules/npm/node_modules/tough-cookie/node_modules/punycode": {
-            "version": "2.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/tunnel-agent": {
-            "version": "0.6.0",
-            "inBundle": true,
-            "license": "Apache-2.0",
-            "dependencies": {
-                "safe-buffer": "^5.0.1"
-            },
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/npm/node_modules/tweetnacl": {
-            "version": "0.14.5",
-            "inBundle": true,
-            "license": "Unlicense"
-        },
-        "node_modules/npm/node_modules/typedarray": {
-            "version": "0.0.6",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/uid-number": {
-            "version": "0.0.6",
-            "inBundle": true,
-            "license": "ISC",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/npm/node_modules/umask": {
-            "version": "1.1.0",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/unique-filename": {
-            "version": "1.1.1",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "unique-slug": "^2.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/unique-slug": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "imurmurhash": "^0.1.4"
-            }
-        },
-        "node_modules/npm/node_modules/unique-string": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "crypto-random-string": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/unpipe": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/npm/node_modules/unzip-response": {
-            "version": "2.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/update-notifier": {
-            "version": "2.5.0",
-            "inBundle": true,
-            "license": "BSD-2-Clause",
-            "dependencies": {
-                "boxen": "^1.2.1",
-                "chalk": "^2.0.1",
-                "configstore": "^3.0.0",
-                "import-lazy": "^2.1.0",
-                "is-ci": "^1.0.10",
-                "is-installed-globally": "^0.1.0",
-                "is-npm": "^1.0.0",
-                "latest-version": "^3.0.0",
-                "semver-diff": "^2.0.0",
-                "xdg-basedir": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/uri-js": {
-            "version": "4.4.1",
-            "inBundle": true,
-            "license": "BSD-2-Clause",
-            "dependencies": {
-                "punycode": "^2.1.0"
-            }
-        },
-        "node_modules/npm/node_modules/uri-js/node_modules/punycode": {
-            "version": "2.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/url-parse-lax": {
-            "version": "1.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "prepend-http": "^1.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/util-deprecate": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/util-extend": {
-            "version": "1.0.3",
-            "inBundle": true,
-            "license": "MIT"
-        },
-        "node_modules/npm/node_modules/util-promisify": {
-            "version": "2.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "object.getownpropertydescriptors": "^2.0.3"
-            }
-        },
-        "node_modules/npm/node_modules/uuid": {
-            "version": "3.4.0",
-            "deprecated": "Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.",
-            "inBundle": true,
-            "license": "MIT",
-            "bin": {
-                "uuid": "bin/uuid"
-            }
-        },
-        "node_modules/npm/node_modules/validate-npm-package-license": {
-            "version": "3.0.4",
-            "inBundle": true,
-            "license": "Apache-2.0",
-            "dependencies": {
-                "spdx-correct": "^3.0.0",
-                "spdx-expression-parse": "^3.0.0"
-            }
-        },
-        "node_modules/npm/node_modules/validate-npm-package-name": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "builtins": "^1.0.3"
-            }
-        },
-        "node_modules/npm/node_modules/verror": {
-            "version": "1.10.0",
-            "engines": [
-                "node >=0.6.0"
-            ],
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "assert-plus": "^1.0.0",
-                "core-util-is": "1.0.2",
-                "extsprintf": "^1.2.0"
-            }
-        },
-        "node_modules/npm/node_modules/wcwidth": {
-            "version": "1.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "defaults": "^1.0.3"
-            }
-        },
-        "node_modules/npm/node_modules/which": {
-            "version": "1.3.1",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "isexe": "^2.0.0"
-            },
-            "bin": {
-                "which": "bin/which"
-            }
-        },
-        "node_modules/npm/node_modules/which-module": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/wide-align": {
-            "version": "1.1.2",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "string-width": "^1.0.2"
-            }
-        },
-        "node_modules/npm/node_modules/wide-align/node_modules/string-width": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "code-point-at": "^1.0.0",
-                "is-fullwidth-code-point": "^1.0.0",
-                "strip-ansi": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/npm/node_modules/widest-line": {
-            "version": "2.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "string-width": "^2.1.1"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/worker-farm": {
-            "version": "1.7.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "errno": "~0.1.7"
-            }
-        },
-        "node_modules/npm/node_modules/wrap-ansi": {
-            "version": "5.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "ansi-styles": "^3.2.0",
-                "string-width": "^3.0.0",
-                "strip-ansi": "^5.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": {
-            "version": "4.1.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": {
-            "version": "3.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "emoji-regex": "^7.0.1",
-                "is-fullwidth-code-point": "^2.0.0",
-                "strip-ansi": "^5.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": {
-            "version": "5.2.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "ansi-regex": "^4.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/wrappy": {
-            "version": "1.0.2",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/write-file-atomic": {
-            "version": "2.4.3",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "graceful-fs": "^4.1.11",
-                "imurmurhash": "^0.1.4",
-                "signal-exit": "^3.0.2"
-            }
-        },
-        "node_modules/npm/node_modules/xdg-basedir": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/xtend": {
-            "version": "4.0.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.4"
-            }
-        },
-        "node_modules/npm/node_modules/y18n": {
-            "version": "4.0.1",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/yallist": {
-            "version": "3.0.3",
-            "inBundle": true,
-            "license": "ISC"
-        },
-        "node_modules/npm/node_modules/yargs": {
-            "version": "14.2.3",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "cliui": "^5.0.0",
-                "decamelize": "^1.2.0",
-                "find-up": "^3.0.0",
-                "get-caller-file": "^2.0.1",
-                "require-directory": "^2.1.1",
-                "require-main-filename": "^2.0.0",
-                "set-blocking": "^2.0.0",
-                "string-width": "^3.0.0",
-                "which-module": "^2.0.0",
-                "y18n": "^4.0.0",
-                "yargs-parser": "^15.0.1"
-            }
-        },
-        "node_modules/npm/node_modules/yargs-parser": {
-            "version": "15.0.1",
-            "inBundle": true,
-            "license": "ISC",
-            "dependencies": {
-                "camelcase": "^5.0.0",
-                "decamelize": "^1.2.0"
-            }
-        },
-        "node_modules/npm/node_modules/yargs-parser/node_modules/camelcase": {
-            "version": "5.3.1",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/yargs/node_modules/ansi-regex": {
-            "version": "4.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/yargs/node_modules/find-up": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "locate-path": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/yargs/node_modules/is-fullwidth-code-point": {
-            "version": "2.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/npm/node_modules/yargs/node_modules/locate-path": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "p-locate": "^3.0.0",
-                "path-exists": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/yargs/node_modules/p-limit": {
-            "version": "2.3.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "p-try": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/npm/node_modules/yargs/node_modules/p-locate": {
-            "version": "3.0.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "p-limit": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/yargs/node_modules/p-try": {
-            "version": "2.2.0",
-            "inBundle": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/yargs/node_modules/string-width": {
-            "version": "3.1.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "emoji-regex": "^7.0.1",
-                "is-fullwidth-code-point": "^2.0.0",
-                "strip-ansi": "^5.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npm/node_modules/yargs/node_modules/strip-ansi": {
-            "version": "5.2.0",
-            "inBundle": true,
-            "license": "MIT",
-            "dependencies": {
-                "ansi-regex": "^4.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/npmlog": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
-            "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
-            "dependencies": {
-                "are-we-there-yet": "^2.0.0",
-                "console-control-strings": "^1.1.0",
-                "gauge": "^3.0.0",
-                "set-blocking": "^2.0.0"
-            }
-        },
-        "node_modules/nth-check": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
-            "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
-            "dependencies": {
-                "boolbase": "^1.0.0"
-            },
-            "funding": {
-                "url": "https://github.com/fb55/nth-check?sponsor=1"
-            }
-        },
-        "node_modules/number-is-nan": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
-            "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/nwsapi": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz",
-            "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==",
-            "dev": true
-        },
-        "node_modules/oauth": {
-            "version": "0.9.15",
-            "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz",
-            "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE="
-        },
-        "node_modules/oauth-sign": {
-            "version": "0.9.0",
-            "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
-            "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/object-assign": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-            "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/object-copy": {
-            "version": "0.1.0",
-            "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
-            "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
-            "dependencies": {
-                "copy-descriptor": "^0.1.0",
-                "define-property": "^0.2.5",
-                "kind-of": "^3.0.3"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/object-copy/node_modules/define-property": {
-            "version": "0.2.5",
-            "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-            "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-            "dependencies": {
-                "is-descriptor": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/object-copy/node_modules/is-buffer": {
-            "version": "1.1.6",
-            "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-            "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
-        },
-        "node_modules/object-copy/node_modules/kind-of": {
-            "version": "3.2.2",
-            "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-            "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-            "dependencies": {
-                "is-buffer": "^1.1.5"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/object-inspect": {
-            "version": "1.12.2",
-            "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
-            "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/object-is": {
-            "version": "1.1.5",
-            "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
-            "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.3"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/object-keys": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
-            "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/object-to-arguments": {
-            "version": "0.0.8",
-            "resolved": "https://registry.npmjs.org/object-to-arguments/-/object-to-arguments-0.0.8.tgz",
-            "integrity": "sha512-BfWfuAwuhdH1bhMG5EG90WE/eckkBhBvnke8eSEkCDXoLE9Jk5JwYGTbCx1ehGwV48HvBkn62VukPBdlMUOY9w==",
-            "dependencies": {
-                "inspect-parameters-declaration": "0.0.10",
-                "magicli": "0.0.5",
-                "split-skip": "0.0.2",
-                "stringify-parameters": "0.0.4",
-                "unpack-string": "0.0.2"
-            },
-            "bin": {
-                "object-to-arguments": "bin/cli.js"
-            }
-        },
-        "node_modules/object-to-arguments/node_modules/commander": {
-            "version": "2.20.3",
-            "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-            "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
-        },
-        "node_modules/object-to-arguments/node_modules/inspect-parameters-declaration": {
-            "version": "0.0.10",
-            "resolved": "https://registry.npmjs.org/inspect-parameters-declaration/-/inspect-parameters-declaration-0.0.10.tgz",
-            "integrity": "sha512-L8/Bvt9iDXQTZ63xY5/MAyvzz+FagR/qGh1kIXvUpsno3AAE0Z95d6QO51zrcMGaEGpwh/57idfMxTxbvRmytg==",
-            "dependencies": {
-                "magicli": "0.0.5",
-                "split-skip": "0.0.2",
-                "stringify-parameters": "0.0.4",
-                "unpack-string": "0.0.2"
-            },
-            "bin": {
-                "inspect-parameters-declaration": "bin/cli.js"
-            }
-        },
-        "node_modules/object-to-arguments/node_modules/magicli": {
-            "version": "0.0.5",
-            "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-            "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
-            "dependencies": {
-                "commander": "^2.9.0",
-                "get-stdin": "^5.0.1",
-                "inspect-function": "^0.2.1",
-                "pipe-functions": "^1.2.0"
-            }
-        },
-        "node_modules/object-visit": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
-            "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
-            "dependencies": {
-                "isobject": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/object.assign": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
-            "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
-            "dependencies": {
-                "define-properties": "^1.1.2",
-                "function-bind": "^1.1.1",
-                "has-symbols": "^1.0.0",
-                "object-keys": "^1.0.11"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/object.entries": {
-            "version": "1.1.5",
-            "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz",
-            "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.19.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/object.fromentries": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz",
-            "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.19.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/object.getownpropertydescriptors": {
-            "version": "2.1.4",
-            "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.4.tgz",
-            "integrity": "sha512-sccv3L/pMModT6dJAYF3fzGMVcb38ysQ0tEE6ixv2yXJDtEIPph268OlAdJj5/qZMZDq2g/jqvwppt36uS/uQQ==",
-            "dependencies": {
-                "array.prototype.reduce": "^1.0.4",
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.4",
-                "es-abstract": "^1.20.1"
-            },
-            "engines": {
-                "node": ">= 0.8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/object.hasown": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz",
-            "integrity": "sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==",
-            "dev": true,
-            "dependencies": {
-                "define-properties": "^1.1.4",
-                "es-abstract": "^1.19.5"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/object.pick": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
-            "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
-            "dependencies": {
-                "isobject": "^3.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/object.values": {
-            "version": "1.1.5",
-            "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz",
-            "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.19.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/obuf": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
-            "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
-            "dev": true
-        },
-        "node_modules/on-finished": {
-            "version": "2.4.1",
-            "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
-            "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
-            "dependencies": {
-                "ee-first": "1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/on-headers": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
-            "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/once": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-            "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
-            "dependencies": {
-                "wrappy": "1"
-            }
-        },
-        "node_modules/onetime": {
-            "version": "5.1.2",
-            "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
-            "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
-            "dev": true,
-            "dependencies": {
-                "mimic-fn": "^2.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/opentype.js": {
-            "version": "1.3.4",
-            "resolved": "https://registry.npmjs.org/opentype.js/-/opentype.js-1.3.4.tgz",
-            "integrity": "sha512-d2JE9RP/6uagpQAVtJoF0pJJA/fgai89Cc50Yp0EJHk+eLp6QQ7gBoblsnubRULNY132I0J1QKMJ+JTbMqz4sw==",
-            "dependencies": {
-                "string.prototype.codepointat": "^0.2.1",
-                "tiny-inflate": "^1.0.3"
-            },
-            "bin": {
-                "ot": "bin/ot"
-            },
-            "engines": {
-                "node": ">= 8.0.0"
-            }
-        },
-        "node_modules/opn": {
-            "version": "5.5.0",
-            "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz",
-            "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==",
-            "dev": true,
-            "dependencies": {
-                "is-wsl": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/optional-require": {
-            "version": "1.1.8",
-            "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz",
-            "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==",
-            "dependencies": {
-                "require-at": "^1.0.6"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/optionator": {
-            "version": "0.8.3",
-            "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
-            "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
-            "dev": true,
-            "dependencies": {
-                "deep-is": "~0.1.3",
-                "fast-levenshtein": "~2.0.6",
-                "levn": "~0.3.0",
-                "prelude-ls": "~1.1.2",
-                "type-check": "~0.3.2",
-                "word-wrap": "~1.2.3"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/orderedmap": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.0.0.tgz",
-            "integrity": "sha512-buf4PoAMlh45b8a8gsGy/X6w279TSqkyAS0C0wdTSJwFSU+ljQFJON5I8NfjLHoCXwpSROIo2wr0g33T+kQshQ=="
-        },
-        "node_modules/os-homedir": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
-            "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/os-tmpdir": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
-            "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/osenv": {
-            "version": "0.1.5",
-            "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
-            "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
-            "dependencies": {
-                "os-homedir": "^1.0.0",
-                "os-tmpdir": "^1.0.0"
-            }
-        },
-        "node_modules/p-cancelable": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz",
-            "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==",
-            "engines": {
-                "node": ">=12.20"
-            }
-        },
-        "node_modules/p-debounce": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/p-debounce/-/p-debounce-1.0.0.tgz",
-            "integrity": "sha1-y38svu/YegnrqGHhErZ1J+Yh4v0=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/p-finally": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
-            "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/p-limit": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
-            "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
-            "dependencies": {
-                "p-try": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/p-locate": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
-            "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
-            "dependencies": {
-                "p-limit": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/p-map": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
-            "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/p-retry": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz",
-            "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==",
-            "dev": true,
-            "dependencies": {
-                "retry": "^0.12.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/p-try": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
-            "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/package-json": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz",
-            "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=",
-            "dependencies": {
-                "got": "^6.7.1",
-                "registry-auth-token": "^3.0.1",
-                "registry-url": "^3.0.3",
-                "semver": "^5.1.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/package-json/node_modules/get-stream": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
-            "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/package-json/node_modules/got": {
-            "version": "6.7.1",
-            "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
-            "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
-            "dependencies": {
-                "create-error-class": "^3.0.0",
-                "duplexer3": "^0.1.4",
-                "get-stream": "^3.0.0",
-                "is-redirect": "^1.0.0",
-                "is-retry-allowed": "^1.0.0",
-                "is-stream": "^1.0.0",
-                "lowercase-keys": "^1.0.0",
-                "safe-buffer": "^5.0.1",
-                "timed-out": "^4.0.0",
-                "unzip-response": "^2.0.1",
-                "url-parse-lax": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/package-json/node_modules/lowercase-keys": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
-            "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/pako": {
-            "version": "1.0.11",
-            "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
-            "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
-        },
-        "node_modules/parallel-transform": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz",
-            "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==",
-            "dev": true,
-            "dependencies": {
-                "cyclist": "^1.0.1",
-                "inherits": "^2.0.3",
-                "readable-stream": "^2.1.5"
-            }
-        },
-        "node_modules/parallel-transform/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dev": true,
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/param-case": {
-            "version": "3.0.4",
-            "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
-            "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
-            "dependencies": {
-                "dot-case": "^3.0.4",
-                "tslib": "^2.0.3"
-            }
-        },
-        "node_modules/parent-module": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
-            "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
-            "dependencies": {
-                "callsites": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/parse-json": {
-            "version": "5.2.0",
-            "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
-            "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
-            "dependencies": {
-                "@babel/code-frame": "^7.0.0",
-                "error-ex": "^1.3.1",
-                "json-parse-even-better-errors": "^2.3.0",
-                "lines-and-columns": "^1.1.6"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/parse5": {
-            "version": "5.1.0",
-            "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz",
-            "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
-            "dev": true
-        },
-        "node_modules/parseqs": {
-            "version": "0.0.6",
-            "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
-            "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w=="
-        },
-        "node_modules/parseuri": {
-            "version": "0.0.6",
-            "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz",
-            "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow=="
-        },
-        "node_modules/parseurl": {
-            "version": "1.3.3",
-            "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
-            "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/pascal-case": {
-            "version": "3.1.2",
-            "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
-            "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
-            "dependencies": {
-                "no-case": "^3.0.4",
-                "tslib": "^2.0.3"
-            }
-        },
-        "node_modules/pascalcase": {
-            "version": "0.1.1",
-            "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
-            "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/passport": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz",
-            "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==",
-            "dependencies": {
-                "passport-strategy": "1.x.x",
-                "pause": "0.0.1"
-            },
-            "engines": {
-                "node": ">= 0.4.0"
-            }
-        },
-        "node_modules/passport-google-oauth20": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz",
-            "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==",
-            "dependencies": {
-                "passport-oauth2": "1.x.x"
-            },
-            "engines": {
-                "node": ">= 0.4.0"
-            }
-        },
-        "node_modules/passport-local": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
-            "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=",
-            "dependencies": {
-                "passport-strategy": "1.x.x"
-            },
-            "engines": {
-                "node": ">= 0.4.0"
-            }
-        },
-        "node_modules/passport-oauth2": {
-            "version": "1.6.1",
-            "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.6.1.tgz",
-            "integrity": "sha512-ZbV43Hq9d/SBSYQ22GOiglFsjsD1YY/qdiptA+8ej+9C1dL1TVB+mBE5kDH/D4AJo50+2i8f4bx0vg4/yDDZCQ==",
-            "dependencies": {
-                "base64url": "3.x.x",
-                "oauth": "0.9.x",
-                "passport-strategy": "1.x.x",
-                "uid2": "0.0.x",
-                "utils-merge": "1.x.x"
-            },
-            "engines": {
-                "node": ">= 0.4.0"
-            },
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/jaredhanson"
-            }
-        },
-        "node_modules/passport-strategy": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
-            "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=",
-            "engines": {
-                "node": ">= 0.4.0"
-            }
-        },
-        "node_modules/path-browserify": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
-            "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="
-        },
-        "node_modules/path-dirname": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
-            "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="
-        },
-        "node_modules/path-exists": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
-            "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/path-is-absolute": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-            "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/path-is-inside": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
-            "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="
-        },
-        "node_modules/path-key": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
-            "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/path-parse": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
-            "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
-        },
-        "node_modules/path-to-regexp": {
-            "version": "0.1.7",
-            "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
-            "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
-        },
-        "node_modules/path-type": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
-            "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/pathval": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
-            "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/pause": {
-            "version": "0.0.1",
-            "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
-            "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10="
-        },
-        "node_modules/pdf-parse": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/pdf-parse/-/pdf-parse-1.1.1.tgz",
-            "integrity": "sha512-v6ZJ/efsBpGrGGknjtq9J/oC8tZWq0KWL5vQrk2GlzLEQPUDB1ex+13Rmidl1neNN358Jn9EHZw5y07FFtaC7A==",
-            "dependencies": {
-                "debug": "^3.1.0",
-                "node-ensure": "^0.0.0"
-            },
-            "engines": {
-                "node": ">=6.8.1"
-            }
-        },
-        "node_modules/pdfjs": {
-            "version": "2.4.7",
-            "resolved": "https://registry.npmjs.org/pdfjs/-/pdfjs-2.4.7.tgz",
-            "integrity": "sha512-qGGZiQ7cz7nDgRgNSMm0qsZ4QPlAvZr+kWwB78hZzClojtfqGbGUT/gwzf8S2nniwvLMB56boBTTIppQohTJUA==",
-            "dependencies": {
-                "@rkusa/linebreak": "^1.0.0",
-                "opentype.js": "^1.3.3",
-                "pako": "^2.0.3",
-                "readable-stream": "^3.6.0",
-                "unorm": "^1.6.0",
-                "uuid": "^8.3.1"
-            },
-            "engines": {
-                "node": ">=7"
-            }
-        },
-        "node_modules/pdfjs-dist": {
-            "version": "2.14.305",
-            "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.14.305.tgz",
-            "integrity": "sha512-5f7i25J1dKIBczhgfxEgNxfYNIxXEdxqo6Qb4ehY7Ja+p6AI4uUmk/OcVGXfRGm2ys5iaJJhJUwBFwv6Jl/Qww==",
-            "dependencies": {
-                "dommatrix": "^1.0.1",
-                "web-streams-polyfill": "^3.2.1"
-            },
-            "peerDependencies": {
-                "worker-loader": "^3.0.8"
-            },
-            "peerDependenciesMeta": {
-                "worker-loader": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/pdfjs/node_modules/pako": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/pako/-/pako-2.0.4.tgz",
-            "integrity": "sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg=="
-        },
-        "node_modules/pdfjs/node_modules/uuid": {
-            "version": "8.3.2",
-            "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
-            "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
-            "bin": {
-                "uuid": "dist/bin/uuid"
-            }
-        },
-        "node_modules/pend": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
-            "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
-        },
-        "node_modules/perfect-scrollbar": {
-            "version": "1.5.5",
-            "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz",
-            "integrity": "sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g=="
-        },
-        "node_modules/performance-now": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
-            "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
-        },
-        "node_modules/picocolors": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
-            "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
-        },
-        "node_modules/picomatch": {
-            "version": "2.3.1",
-            "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
-            "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-            "engines": {
-                "node": ">=8.6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/jonschlinkert"
-            }
-        },
-        "node_modules/pify": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-            "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/pinkie": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
-            "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/pinkie-promise": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
-            "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
-            "dependencies": {
-                "pinkie": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/pipe-functions": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/pipe-functions/-/pipe-functions-1.3.0.tgz",
-            "integrity": "sha512-6Rtbp7criZRwedlvWbUYxqlqJoAlMvYHo2UcRWq79xZ54vZcaNHpVBOcWkX3ErT2aUA69tv+uiv4zKJbhD/Wgg=="
-        },
-        "node_modules/pkg-dir": {
-            "version": "4.2.0",
-            "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
-            "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
-            "dependencies": {
-                "find-up": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/pkg-dir/node_modules/find-up": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
-            "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
-            "dependencies": {
-                "locate-path": "^5.0.0",
-                "path-exists": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/pkg-dir/node_modules/locate-path": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
-            "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
-            "dependencies": {
-                "p-locate": "^4.1.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/pkg-dir/node_modules/p-locate": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
-            "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
-            "dependencies": {
-                "p-limit": "^2.2.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/pkg-dir/node_modules/path-exists": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
-            "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/please-upgrade-node": {
-            "version": "3.2.0",
-            "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz",
-            "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==",
-            "dependencies": {
-                "semver-compare": "^1.0.0"
-            }
-        },
-        "node_modules/plist": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/plist/-/plist-1.2.0.tgz",
-            "integrity": "sha1-CEtQk93JJQbiWfh0uNmxr7jHlZM=",
-            "dependencies": {
-                "base64-js": "0.0.8",
-                "util-deprecate": "1.0.2",
-                "xmlbuilder": "4.0.0",
-                "xmldom": "0.1.x"
-            }
-        },
-        "node_modules/plist/node_modules/base64-js": {
-            "version": "0.0.8",
-            "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
-            "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=",
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/pn": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz",
-            "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==",
-            "dev": true
-        },
-        "node_modules/popper.js": {
-            "version": "1.16.1-lts",
-            "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz",
-            "integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA=="
-        },
-        "node_modules/portfinder": {
-            "version": "1.0.28",
-            "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
-            "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==",
-            "dev": true,
-            "dependencies": {
-                "async": "^2.6.2",
-                "debug": "^3.1.1",
-                "mkdirp": "^0.5.5"
-            },
-            "engines": {
-                "node": ">= 0.12.0"
-            }
-        },
-        "node_modules/portfinder/node_modules/mkdirp": {
-            "version": "0.5.6",
-            "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
-            "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
-            "dev": true,
-            "dependencies": {
-                "minimist": "^1.2.6"
-            },
-            "bin": {
-                "mkdirp": "bin/cmd.js"
-            }
-        },
-        "node_modules/posix-character-classes": {
-            "version": "0.1.1",
-            "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
-            "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/postcss": {
-            "version": "7.0.39",
-            "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
-            "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
-            "dev": true,
-            "dependencies": {
-                "picocolors": "^0.2.1",
-                "source-map": "^0.6.1"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/postcss/"
-            }
-        },
-        "node_modules/postcss-modules-extract-imports": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz",
-            "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==",
-            "dev": true,
-            "dependencies": {
-                "postcss": "^7.0.5"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/postcss-modules-local-by-default": {
-            "version": "2.0.6",
-            "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz",
-            "integrity": "sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA==",
-            "dev": true,
-            "dependencies": {
-                "postcss": "^7.0.6",
-                "postcss-selector-parser": "^6.0.0",
-                "postcss-value-parser": "^3.3.1"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/postcss-modules-scope": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz",
-            "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==",
-            "dev": true,
-            "dependencies": {
-                "postcss": "^7.0.6",
-                "postcss-selector-parser": "^6.0.0"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/postcss-modules-values": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz",
-            "integrity": "sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w==",
-            "dev": true,
-            "dependencies": {
-                "icss-replace-symbols": "^1.1.0",
-                "postcss": "^7.0.6"
-            }
-        },
-        "node_modules/postcss-selector-parser": {
-            "version": "6.0.10",
-            "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
-            "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
-            "dev": true,
-            "dependencies": {
-                "cssesc": "^3.0.0",
-                "util-deprecate": "^1.0.2"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/postcss-value-parser": {
-            "version": "3.3.1",
-            "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
-            "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="
-        },
-        "node_modules/postcss/node_modules/picocolors": {
-            "version": "0.2.1",
-            "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
-            "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
-            "dev": true
-        },
-        "node_modules/postcss/node_modules/source-map": {
-            "version": "0.6.1",
-            "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-            "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/prebuild-install": {
-            "version": "5.3.6",
-            "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz",
-            "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==",
-            "dependencies": {
-                "detect-libc": "^1.0.3",
-                "expand-template": "^2.0.3",
-                "github-from-package": "0.0.0",
-                "minimist": "^1.2.3",
-                "mkdirp-classic": "^0.5.3",
-                "napi-build-utils": "^1.0.1",
-                "node-abi": "^2.7.0",
-                "noop-logger": "^0.1.1",
-                "npmlog": "^4.0.1",
-                "pump": "^3.0.0",
-                "rc": "^1.2.7",
-                "simple-get": "^3.0.3",
-                "tar-fs": "^2.0.0",
-                "tunnel-agent": "^0.6.0",
-                "which-pm-runs": "^1.0.0"
-            },
-            "bin": {
-                "prebuild-install": "bin.js"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/prebuild-install/node_modules/ansi-regex": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-            "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/prebuild-install/node_modules/aproba": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-            "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
-        },
-        "node_modules/prebuild-install/node_modules/are-we-there-yet": {
-            "version": "1.1.7",
-            "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
-            "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
-            "dependencies": {
-                "delegates": "^1.0.0",
-                "readable-stream": "^2.0.6"
-            }
-        },
-        "node_modules/prebuild-install/node_modules/detect-libc": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
-            "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
-            "bin": {
-                "detect-libc": "bin/detect-libc.js"
-            },
-            "engines": {
-                "node": ">=0.10"
-            }
-        },
-        "node_modules/prebuild-install/node_modules/gauge": {
-            "version": "2.7.4",
-            "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
-            "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==",
-            "dependencies": {
-                "aproba": "^1.0.3",
-                "console-control-strings": "^1.0.0",
-                "has-unicode": "^2.0.0",
-                "object-assign": "^4.1.0",
-                "signal-exit": "^3.0.0",
-                "string-width": "^1.0.1",
-                "strip-ansi": "^3.0.1",
-                "wide-align": "^1.1.0"
-            }
-        },
-        "node_modules/prebuild-install/node_modules/is-fullwidth-code-point": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
-            "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==",
-            "dependencies": {
-                "number-is-nan": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/prebuild-install/node_modules/npmlog": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
-            "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
-            "dependencies": {
-                "are-we-there-yet": "~1.1.2",
-                "console-control-strings": "~1.1.0",
-                "gauge": "~2.7.3",
-                "set-blocking": "~2.0.0"
-            }
-        },
-        "node_modules/prebuild-install/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/prebuild-install/node_modules/string-width": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
-            "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
-            "dependencies": {
-                "code-point-at": "^1.0.0",
-                "is-fullwidth-code-point": "^1.0.0",
-                "strip-ansi": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/prebuild-install/node_modules/strip-ansi": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-            "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
-            "dependencies": {
-                "ansi-regex": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/prelude-ls": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
-            "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
-            "dev": true,
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/prepend-http": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
-            "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/prettier": {
-            "version": "2.7.1",
-            "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
-            "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
-            "dev": true,
-            "bin": {
-                "prettier": "bin-prettier.js"
-            },
-            "engines": {
-                "node": ">=10.13.0"
-            },
-            "funding": {
-                "url": "https://github.com/prettier/prettier?sponsor=1"
-            }
-        },
-        "node_modules/prettier-linter-helpers": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
-            "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
-            "dev": true,
-            "dependencies": {
-                "fast-diff": "^1.1.2"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/pretty-error": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz",
-            "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==",
-            "dependencies": {
-                "lodash": "^4.17.20",
-                "renderkid": "^3.0.0"
-            }
-        },
-        "node_modules/probe-image-size": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/probe-image-size/-/probe-image-size-4.1.1.tgz",
-            "integrity": "sha512-42LqKZqTLxH/UvAZ2/cKhAsR4G/Y6B7i7fI2qtQu9hRBK4YjS6gqO+QRtwTjvojUx4+/+JuOMzLoFyRecT9qRw==",
-            "dependencies": {
-                "any-promise": "^1.3.0",
-                "deepmerge": "^4.0.0",
-                "inherits": "^2.0.3",
-                "next-tick": "^1.0.0",
-                "request": "^2.83.0",
-                "stream-parser": "~0.3.1"
-            }
-        },
-        "node_modules/probe-image-size/node_modules/deepmerge": {
-            "version": "4.2.2",
-            "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
-            "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/process": {
-            "version": "0.11.10",
-            "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
-            "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
-            "engines": {
-                "node": ">= 0.6.0"
-            }
-        },
-        "node_modules/process-nextick-args": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
-            "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
-        },
-        "node_modules/progress": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
-            "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/promise": {
-            "version": "7.3.1",
-            "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
-            "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
-            "dependencies": {
-                "asap": "~2.0.3"
-            }
-        },
-        "node_modules/promise-inflight": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
-            "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
-            "dev": true
-        },
-        "node_modules/prop-types": {
-            "version": "15.8.1",
-            "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
-            "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
-            "dependencies": {
-                "loose-envify": "^1.4.0",
-                "object-assign": "^4.1.1",
-                "react-is": "^16.13.1"
-            }
-        },
-        "node_modules/property-information": {
-            "version": "6.1.1",
-            "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.1.1.tgz",
-            "integrity": "sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w==",
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/wooorm"
-            }
-        },
-        "node_modules/prosemirror-commands": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.3.0.tgz",
-            "integrity": "sha512-BwBbZ5OAScPcm0x7H8SPbqjuEJnCU2RJT9LDyOiiIl/3NbL1nJZI4SFNHwU2e/tRr2Xe7JsptpzseqvZvToLBQ==",
-            "dependencies": {
-                "prosemirror-model": "^1.0.0",
-                "prosemirror-state": "^1.0.0",
-                "prosemirror-transform": "^1.0.0"
-            }
-        },
-        "node_modules/prosemirror-dev-tools": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/prosemirror-dev-tools/-/prosemirror-dev-tools-3.1.0.tgz",
-            "integrity": "sha512-ghuxb6QD3WWl3EE8OK1O3P67OKjbTxt5mvagAUK6xd0kS7SBysSS4KE+HiNPxC8r812EEFFJ2S6asIs9i7rvkQ==",
-            "dependencies": {
-                "@babel/runtime": "^7.0.0",
-                "@emotion/css": "^11.1.3",
-                "@emotion/react": "^11.4.0",
-                "@emotion/styled": "^11.3.0",
-                "html": "^1.0.0",
-                "jsondiffpatch": "^0.4.1",
-                "nanoid": "^2.1.11",
-                "prop-types": "^15.7.2",
-                "prosemirror-model": ">=1.0.0",
-                "prosemirror-state": ">=1.0.0",
-                "react-dock": "^0.2.4",
-                "react-json-tree": "^0.11.2",
-                "unstated": "^2.1.1"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "peerDependencies": {
-                "react": ">=16.8.0",
-                "react-dom": ">=16.8.0"
-            }
-        },
-        "node_modules/prosemirror-find-replace": {
-            "version": "0.9.0",
-            "resolved": "https://registry.npmjs.org/prosemirror-find-replace/-/prosemirror-find-replace-0.9.0.tgz",
-            "integrity": "sha1-QgsENNF5xdBJD44hSNhVGpVJY4I=",
-            "peerDependencies": {
-                "prosemirror": ">= 0.7.0"
-            }
-        },
-        "node_modules/prosemirror-history": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.3.0.tgz",
-            "integrity": "sha512-qo/9Wn4B/Bq89/YD+eNWFbAytu6dmIM85EhID+fz9Jcl9+DfGEo8TTSrRhP15+fFEoaPqpHSxlvSzSEbmlxlUA==",
-            "dependencies": {
-                "prosemirror-state": "^1.2.2",
-                "prosemirror-transform": "^1.0.0",
-                "rope-sequence": "^1.3.0"
-            }
-        },
-        "node_modules/prosemirror-inputrules": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.2.0.tgz",
-            "integrity": "sha512-eAW/M/NTSSzpCOxfR8Abw6OagdG0MiDAiWHQMQveIsZtoKVYzm0AflSPq/ymqJd56/Su1YPbwy9lM13wgHOFmQ==",
-            "dependencies": {
-                "prosemirror-state": "^1.0.0",
-                "prosemirror-transform": "^1.0.0"
-            }
-        },
-        "node_modules/prosemirror-keymap": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.0.tgz",
-            "integrity": "sha512-TdSfu+YyLDd54ufN/ZeD1VtBRYpgZnTPnnbY+4R08DDgs84KrIPEPbJL8t1Lm2dkljFx6xeBE26YWH3aIzkPKg==",
-            "dependencies": {
-                "prosemirror-state": "^1.0.0",
-                "w3c-keyname": "^2.2.0"
-            }
-        },
-        "node_modules/prosemirror-model": {
-            "version": "1.18.1",
-            "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.18.1.tgz",
-            "integrity": "sha512-IxSVBKAEMjD7s3n8cgtwMlxAXZrC7Mlag7zYsAKDndAqnDScvSmp/UdnRTV/B33lTCVU3CCm7dyAn/rVVD0mcw==",
-            "dependencies": {
-                "orderedmap": "^2.0.0"
-            }
-        },
-        "node_modules/prosemirror-schema-list": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.2.0.tgz",
-            "integrity": "sha512-8PT/9xOx1HHdC7fDNNfhQ50Z8Mzu7nKyA1KCDltSpcZVZIbB0k7KtsHrnXyuIhbLlScoymBiLZ00c5MH6wdFsA==",
-            "dependencies": {
-                "prosemirror-model": "^1.0.0",
-                "prosemirror-state": "^1.0.0",
-                "prosemirror-transform": "^1.0.0"
-            }
-        },
-        "node_modules/prosemirror-state": {
-            "version": "1.4.1",
-            "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.1.tgz",
-            "integrity": "sha512-U/LBDW2gNmVa07sz/D229XigSdDQ5CLFwVB1Vb32MJbAHHhWe/6pOc721faI17tqw4pZ49i1xfY/jEZ9tbIhPg==",
-            "dependencies": {
-                "prosemirror-model": "^1.0.0",
-                "prosemirror-transform": "^1.0.0"
-            }
-        },
-        "node_modules/prosemirror-transform": {
-            "version": "1.6.0",
-            "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.6.0.tgz",
-            "integrity": "sha512-MAp7AjsjEGEqQY0sSMufNIUuEyB1ZR9Fqlm8dTwwWwpEJRv/plsKjWXBbx52q3Ml8MtaMcd7ic14zAHVB3WaMw==",
-            "dependencies": {
-                "prosemirror-model": "^1.0.0"
-            }
-        },
-        "node_modules/prosemirror-view": {
-            "version": "1.26.5",
-            "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.26.5.tgz",
-            "integrity": "sha512-SO+AX6WwdbJZHVvuloXI0qfO+YJAnZAat8qrYwfiqTQwL/FewLUnr0m3EXZ6a60hQs8/Q/lzeJXiFR/dOPaaKQ==",
-            "dependencies": {
-                "prosemirror-model": "^1.16.0",
-                "prosemirror-state": "^1.0.0",
-                "prosemirror-transform": "^1.1.0"
-            }
-        },
-        "node_modules/proxy-addr": {
-            "version": "2.0.7",
-            "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
-            "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
-            "dependencies": {
-                "forwarded": "0.2.0",
-                "ipaddr.js": "1.9.1"
-            },
-            "engines": {
-                "node": ">= 0.10"
-            }
-        },
-        "node_modules/proxy-from-env": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
-            "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
-        },
-        "node_modules/prr": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
-            "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
-            "dev": true
-        },
-        "node_modules/pseudomap": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
-            "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
-        },
-        "node_modules/psl": {
-            "version": "1.8.0",
-            "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
-            "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
-        },
-        "node_modules/pstree.remy": {
-            "version": "1.1.8",
-            "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
-            "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w=="
-        },
-        "node_modules/pug": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.4.tgz",
-            "integrity": "sha512-XhoaDlvi6NIzL49nu094R2NA6P37ijtgMDuWE+ofekDChvfKnzFal60bhSdiy8y2PBO6fmz3oMEIcfpBVRUdvw==",
-            "dependencies": {
-                "pug-code-gen": "^2.0.2",
-                "pug-filters": "^3.1.1",
-                "pug-lexer": "^4.1.0",
-                "pug-linker": "^3.0.6",
-                "pug-load": "^2.0.12",
-                "pug-parser": "^5.0.1",
-                "pug-runtime": "^2.0.5",
-                "pug-strip-comments": "^1.0.4"
-            }
-        },
-        "node_modules/pug-attrs": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.4.tgz",
-            "integrity": "sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ==",
-            "dependencies": {
-                "constantinople": "^3.0.1",
-                "js-stringify": "^1.0.1",
-                "pug-runtime": "^2.0.5"
-            }
-        },
-        "node_modules/pug-code-gen": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.3.tgz",
-            "integrity": "sha512-r9sezXdDuZJfW9J91TN/2LFbiqDhmltTFmGpHTsGdrNGp3p4SxAjjXEfnuK2e4ywYsRIVP0NeLbSAMHUcaX1EA==",
-            "dependencies": {
-                "constantinople": "^3.1.2",
-                "doctypes": "^1.1.0",
-                "js-stringify": "^1.0.1",
-                "pug-attrs": "^2.0.4",
-                "pug-error": "^1.3.3",
-                "pug-runtime": "^2.0.5",
-                "void-elements": "^2.0.1",
-                "with": "^5.0.0"
-            }
-        },
-        "node_modules/pug-error": {
-            "version": "1.3.3",
-            "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.3.tgz",
-            "integrity": "sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ=="
-        },
-        "node_modules/pug-filters": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-3.1.1.tgz",
-            "integrity": "sha512-lFfjNyGEyVWC4BwX0WyvkoWLapI5xHSM3xZJFUhx4JM4XyyRdO8Aucc6pCygnqV2uSgJFaJWW3Ft1wCWSoQkQg==",
-            "dependencies": {
-                "clean-css": "^4.1.11",
-                "constantinople": "^3.0.1",
-                "jstransformer": "1.0.0",
-                "pug-error": "^1.3.3",
-                "pug-walk": "^1.1.8",
-                "resolve": "^1.1.6",
-                "uglify-js": "^2.6.1"
-            }
-        },
-        "node_modules/pug-filters/node_modules/clean-css": {
-            "version": "4.2.4",
-            "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz",
-            "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==",
-            "dependencies": {
-                "source-map": "~0.6.0"
-            },
-            "engines": {
-                "node": ">= 4.0"
-            }
-        },
-        "node_modules/pug-filters/node_modules/source-map": {
-            "version": "0.6.1",
-            "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-            "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/pug-lexer": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-4.1.0.tgz",
-            "integrity": "sha512-i55yzEBtjm0mlplW4LoANq7k3S8gDdfC6+LThGEvsK4FuobcKfDAwt6V4jKPH9RtiE3a2Akfg5UpafZ1OksaPA==",
-            "dependencies": {
-                "character-parser": "^2.1.1",
-                "is-expression": "^3.0.0",
-                "pug-error": "^1.3.3"
-            }
-        },
-        "node_modules/pug-linker": {
-            "version": "3.0.6",
-            "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.6.tgz",
-            "integrity": "sha512-bagfuHttfQOpANGy1Y6NJ+0mNb7dD2MswFG2ZKj22s8g0wVsojpRlqveEQHmgXXcfROB2RT6oqbPYr9EN2ZWzg==",
-            "dependencies": {
-                "pug-error": "^1.3.3",
-                "pug-walk": "^1.1.8"
-            }
-        },
-        "node_modules/pug-load": {
-            "version": "2.0.12",
-            "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.12.tgz",
-            "integrity": "sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg==",
-            "dependencies": {
-                "object-assign": "^4.1.0",
-                "pug-walk": "^1.1.8"
-            }
-        },
-        "node_modules/pug-parser": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-5.0.1.tgz",
-            "integrity": "sha512-nGHqK+w07p5/PsPIyzkTQfzlYfuqoiGjaoqHv1LjOv2ZLXmGX1O+4Vcvps+P4LhxZ3drYSljjq4b+Naid126wA==",
-            "dependencies": {
-                "pug-error": "^1.3.3",
-                "token-stream": "0.0.1"
-            }
-        },
-        "node_modules/pug-runtime": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.5.tgz",
-            "integrity": "sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw=="
-        },
-        "node_modules/pug-strip-comments": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.4.tgz",
-            "integrity": "sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw==",
-            "dependencies": {
-                "pug-error": "^1.3.3"
-            }
-        },
-        "node_modules/pug-walk": {
-            "version": "1.1.8",
-            "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.8.tgz",
-            "integrity": "sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA=="
-        },
-        "node_modules/pump": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
-            "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
-            "dependencies": {
-                "end-of-stream": "^1.1.0",
-                "once": "^1.3.1"
-            }
-        },
-        "node_modules/pumpify": {
-            "version": "1.5.1",
-            "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
-            "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
-            "dev": true,
-            "dependencies": {
-                "duplexify": "^3.6.0",
-                "inherits": "^2.0.3",
-                "pump": "^2.0.0"
-            }
-        },
-        "node_modules/pumpify/node_modules/pump": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
-            "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
-            "dev": true,
-            "dependencies": {
-                "end-of-stream": "^1.1.0",
-                "once": "^1.3.1"
-            }
-        },
-        "node_modules/punycode": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
-            "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/puppeteer": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-3.3.0.tgz",
-            "integrity": "sha512-23zNqRltZ1PPoK28uRefWJ/zKb5Jhnzbbwbpcna2o5+QMn17F0khq5s1bdH3vPlyj+J36pubccR8wiNA/VE0Vw==",
-            "deprecated": "< 18.1.0 is no longer supported",
-            "hasInstallScript": true,
-            "dependencies": {
-                "debug": "^4.1.0",
-                "extract-zip": "^2.0.0",
-                "https-proxy-agent": "^4.0.0",
-                "mime": "^2.0.3",
-                "progress": "^2.0.1",
-                "proxy-from-env": "^1.0.0",
-                "rimraf": "^3.0.2",
-                "tar-fs": "^2.0.0",
-                "unbzip2-stream": "^1.3.3",
-                "ws": "^7.2.3"
-            },
-            "engines": {
-                "node": ">=10.18.1"
-            }
-        },
-        "node_modules/puppeteer/node_modules/agent-base": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz",
-            "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==",
-            "engines": {
-                "node": ">= 6.0.0"
-            }
-        },
-        "node_modules/puppeteer/node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/puppeteer/node_modules/https-proxy-agent": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz",
-            "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==",
-            "dependencies": {
-                "agent-base": "5",
-                "debug": "4"
-            },
-            "engines": {
-                "node": ">= 6.0.0"
-            }
-        },
-        "node_modules/puppeteer/node_modules/mime": {
-            "version": "2.6.0",
-            "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
-            "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
-            "bin": {
-                "mime": "cli.js"
-            },
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/puppeteer/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
-        },
-        "node_modules/pure-color": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz",
-            "integrity": "sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4="
-        },
-        "node_modules/q": {
-            "version": "1.5.1",
-            "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
-            "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=",
-            "engines": {
-                "node": ">=0.6.0",
-                "teleport": ">=0.2.0"
-            }
-        },
-        "node_modules/qs": {
-            "version": "6.5.3",
-            "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
-            "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
-            "engines": {
-                "node": ">=0.6"
-            }
-        },
-        "node_modules/query-string": {
-            "version": "6.14.1",
-            "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz",
-            "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==",
-            "dependencies": {
-                "decode-uri-component": "^0.2.0",
-                "filter-obj": "^1.1.0",
-                "split-on-first": "^1.0.0",
-                "strict-uri-encode": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/querystring": {
-            "version": "0.2.0",
-            "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
-            "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
-            "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
-            "dev": true,
-            "engines": {
-                "node": ">=0.4.x"
-            }
-        },
-        "node_modules/querystringify": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
-            "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
-            "dev": true
-        },
-        "node_modules/quick-lru": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
-            "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/raf-schd": {
-            "version": "4.0.3",
-            "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz",
-            "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ=="
-        },
-        "node_modules/random-bytes": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
-            "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/randombytes": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
-            "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
-            "dependencies": {
-                "safe-buffer": "^5.1.0"
-            }
-        },
-        "node_modules/range-parser": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
-            "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/raw-body": {
-            "version": "2.5.1",
-            "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
-            "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
-            "dependencies": {
-                "bytes": "3.1.2",
-                "http-errors": "2.0.0",
-                "iconv-lite": "0.4.24",
-                "unpipe": "1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/raw-body/node_modules/iconv-lite": {
-            "version": "0.4.24",
-            "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
-            "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
-            "dependencies": {
-                "safer-buffer": ">= 2.1.2 < 3"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/raw-loader": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-1.0.0.tgz",
-            "integrity": "sha512-Uqy5AqELpytJTRxYT4fhltcKPj0TyaEpzJDcGz7DFJi+pQOOi3GjR/DOdxTkTsF+NzhnldIoG6TORaBlInUuqA==",
-            "dependencies": {
-                "loader-utils": "^1.1.0",
-                "schema-utils": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 6.9.0"
-            },
-            "peerDependencies": {
-                "webpack": "^4.3.0"
-            }
-        },
-        "node_modules/rc": {
-            "version": "1.2.8",
-            "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
-            "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
-            "dependencies": {
-                "deep-extend": "^0.6.0",
-                "ini": "~1.3.0",
-                "minimist": "^1.2.0",
-                "strip-json-comments": "~2.0.1"
-            },
-            "bin": {
-                "rc": "cli.js"
-            }
-        },
-        "node_modules/rc-switch": {
-            "version": "1.9.2",
-            "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-1.9.2.tgz",
-            "integrity": "sha512-qaK7mY4FLDKy99Hq3A1tf8CcqfzKtHp9LPX8WTnZ0MzdHCTneSARb1XD7Eqeu8BactasYGsi2bF9p18Q+/5JEw==",
-            "dependencies": {
-                "classnames": "^2.2.1",
-                "prop-types": "^15.5.6",
-                "react-lifecycles-compat": "^3.0.4"
-            },
-            "peerDependencies": {
-                "react": "^16.0.0",
-                "react-dom": "^16.0.0"
-            }
-        },
-        "node_modules/react": {
-            "version": "18.2.0",
-            "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
-            "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
-            "dependencies": {
-                "loose-envify": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/react-audio-waveform": {
-            "version": "0.0.5",
-            "resolved": "https://registry.npmjs.org/react-audio-waveform/-/react-audio-waveform-0.0.5.tgz",
-            "integrity": "sha512-4dJwhl+LQRuywzmmjuhWT5GueT3Ai2ZhB+loVxg0sRdhplyDp96xAu10/V/+J25Cl7YqNtl2DWSxvSoI/i6l6w==",
-            "peerDependencies": {
-                "react": "^15.5.4",
-                "react-dom": "^15.4.1"
-            }
-        },
-        "node_modules/react-autosuggest": {
-            "version": "9.4.3",
-            "resolved": "https://registry.npmjs.org/react-autosuggest/-/react-autosuggest-9.4.3.tgz",
-            "integrity": "sha512-wFbp5QpgFQRfw9cwKvcgLR8theikOUkv8PFsuLYqI2PUgVlx186Cz8MYt5bLxculi+jxGGUUVt+h0esaBZZouw==",
-            "dependencies": {
-                "prop-types": "^15.5.10",
-                "react-autowhatever": "^10.1.2",
-                "shallow-equal": "^1.0.0"
-            },
-            "peerDependencies": {
-                "react": ">=0.14.7"
-            }
-        },
-        "node_modules/react-autowhatever": {
-            "version": "10.2.1",
-            "resolved": "https://registry.npmjs.org/react-autowhatever/-/react-autowhatever-10.2.1.tgz",
-            "integrity": "sha512-5gQyoETyBH6GmuW1N1J81CuoAV+Djeg66DEo03xiZOl3WOwJHBP5LisKUvCGOakjrXU4M3hcIvCIqMBYGUmqOA==",
-            "dependencies": {
-                "prop-types": "^15.5.8",
-                "react-themeable": "^1.1.0",
-                "section-iterator": "^2.0.0"
-            },
-            "peerDependencies": {
-                "react": ">=0.14.7"
-            }
-        },
-        "node_modules/react-base16-styling": {
-            "version": "0.5.3",
-            "resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.5.3.tgz",
-            "integrity": "sha1-OFjyTpxN2MvT9wLz901YHKKRcmk=",
-            "dependencies": {
-                "base16": "^1.0.0",
-                "lodash.curry": "^4.0.1",
-                "lodash.flow": "^3.3.0",
-                "pure-color": "^1.2.0"
-            }
-        },
-        "node_modules/react-beautiful-dnd": {
-            "version": "13.1.0",
-            "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz",
-            "integrity": "sha512-aGvblPZTJowOWUNiwd6tNfEpgkX5OxmpqxHKNW/4VmvZTNTbeiq7bA3bn5T+QSF2uibXB0D1DmJsb1aC/+3cUA==",
-            "dependencies": {
-                "@babel/runtime": "^7.9.2",
-                "css-box-model": "^1.2.0",
-                "memoize-one": "^5.1.1",
-                "raf-schd": "^4.0.2",
-                "react-redux": "^7.2.0",
-                "redux": "^4.0.4",
-                "use-memo-one": "^1.1.1"
-            },
-            "peerDependencies": {
-                "react": "^16.8.5 || ^17.0.0",
-                "react-dom": "^16.8.5 || ^17.0.0"
-            }
-        },
-        "node_modules/react-color": {
-            "version": "2.19.3",
-            "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz",
-            "integrity": "sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==",
-            "dependencies": {
-                "@icons/material": "^0.2.4",
-                "lodash": "^4.17.15",
-                "lodash-es": "^4.17.15",
-                "material-colors": "^1.2.1",
-                "prop-types": "^15.5.10",
-                "reactcss": "^1.2.0",
-                "tinycolor2": "^1.4.1"
-            },
-            "peerDependencies": {
-                "react": "*"
-            }
-        },
-        "node_modules/react-compound-slider": {
-            "version": "2.5.0",
-            "resolved": "https://registry.npmjs.org/react-compound-slider/-/react-compound-slider-2.5.0.tgz",
-            "integrity": "sha512-T84FtSI0bkQPmH5GaaHbL+2McOyIR6M5sqS80dqw/bHc5r2UKLYY64BWTbsL+XO0jlx7REuJJnZUBqo4eSRl7g==",
-            "dependencies": {
-                "@babel/runtime": "^7.7.7",
-                "d3-array": "^1.2.4",
-                "prop-types": "^15.7.2",
-                "warning": "^3.0.0"
-            },
-            "peerDependencies": {
-                "react": "^16.3.0"
-            }
-        },
-        "node_modules/react-compound-slider/node_modules/d3-array": {
-            "version": "1.2.4",
-            "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
-            "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
-        },
-        "node_modules/react-datepicker": {
-            "version": "3.8.0",
-            "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-3.8.0.tgz",
-            "integrity": "sha512-iFVNEp8DJoX5yEvEiciM7sJKmLGrvE70U38KhpG13XrulNSijeHw1RZkhd/0UmuXR71dcZB/kdfjiidifstZjw==",
-            "dependencies": {
-                "classnames": "^2.2.6",
-                "date-fns": "^2.0.1",
-                "prop-types": "^15.7.2",
-                "react-onclickoutside": "^6.10.0",
-                "react-popper": "^1.3.8"
-            },
-            "peerDependencies": {
-                "react": "^16.9.0 || ^17",
-                "react-dom": "^16.9.0 || ^17"
-            }
-        },
-        "node_modules/react-dock": {
-            "version": "0.2.4",
-            "resolved": "https://registry.npmjs.org/react-dock/-/react-dock-0.2.4.tgz",
-            "integrity": "sha1-5yfcdVCztzEWY13LnA4E0Lev4Xw=",
-            "dependencies": {
-                "lodash.debounce": "^3.1.1",
-                "prop-types": "^15.5.8"
-            },
-            "peerDependencies": {
-                "babel-runtime": "^6.3.13",
-                "react": ">=0.13.0"
-            }
-        },
-        "node_modules/react-dom": {
-            "version": "18.2.0",
-            "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
-            "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
-            "dependencies": {
-                "loose-envify": "^1.1.0",
-                "scheduler": "^0.23.0"
-            },
-            "peerDependencies": {
-                "react": "^18.2.0"
-            }
-        },
-        "node_modules/react-dom/node_modules/scheduler": {
-            "version": "0.23.0",
-            "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
-            "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
-            "dependencies": {
-                "loose-envify": "^1.1.0"
-            }
-        },
-        "node_modules/react-draggable": {
-            "version": "4.4.5",
-            "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.5.tgz",
-            "integrity": "sha512-OMHzJdyJbYTZo4uQE393fHcqqPYsEtkjfMgvCHr6rejT+Ezn4OZbNyGH50vv+SunC1RMvwOTSWkEODQLzw1M9g==",
-            "dependencies": {
-                "clsx": "^1.1.1",
-                "prop-types": "^15.8.1"
-            },
-            "peerDependencies": {
-                "react": ">= 16.3.0",
-                "react-dom": ">= 16.3.0"
-            }
-        },
-        "node_modules/react-event-listener": {
-            "version": "0.6.6",
-            "resolved": "https://registry.npmjs.org/react-event-listener/-/react-event-listener-0.6.6.tgz",
-            "integrity": "sha512-+hCNqfy7o9wvO6UgjqFmBzARJS7qrNoda0VqzvOuioEpoEXKutiKuv92dSz6kP7rYLmyHPyYNLesi5t/aH1gfw==",
-            "dependencies": {
-                "@babel/runtime": "^7.2.0",
-                "prop-types": "^15.6.0",
-                "warning": "^4.0.1"
-            },
-            "peerDependencies": {
-                "react": "^16.3.0"
-            }
-        },
-        "node_modules/react-event-listener/node_modules/warning": {
-            "version": "4.0.3",
-            "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
-            "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
-            "dependencies": {
-                "loose-envify": "^1.0.0"
-            }
-        },
-        "node_modules/react-grid-layout": {
-            "version": "1.3.4",
-            "resolved": "https://registry.npmjs.org/react-grid-layout/-/react-grid-layout-1.3.4.tgz",
-            "integrity": "sha512-sB3rNhorW77HUdOjB4JkelZTdJGQKuXLl3gNg+BI8gJkTScspL1myfZzW/EM0dLEn+1eH+xW+wNqk0oIM9o7cw==",
-            "dependencies": {
-                "clsx": "^1.1.1",
-                "lodash.isequal": "^4.0.0",
-                "prop-types": "^15.8.1",
-                "react-draggable": "^4.0.0",
-                "react-resizable": "^3.0.4"
-            },
-            "peerDependencies": {
-                "react": ">= 16.3.0",
-                "react-dom": ">= 16.3.0"
-            }
-        },
-        "node_modules/react-grid-layout/node_modules/react-resizable": {
-            "version": "3.0.4",
-            "resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-3.0.4.tgz",
-            "integrity": "sha512-StnwmiESiamNzdRHbSSvA65b0ZQJ7eVQpPusrSmcpyGKzC0gojhtO62xxH6YOBmepk9dQTBi9yxidL3W4s3EBA==",
-            "dependencies": {
-                "prop-types": "15.x",
-                "react-draggable": "^4.0.3"
-            },
-            "peerDependencies": {
-                "react": ">= 16.3"
-            }
-        },
-        "node_modules/react-icons": {
-            "version": "4.4.0",
-            "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.4.0.tgz",
-            "integrity": "sha512-fSbvHeVYo/B5/L4VhB7sBA1i2tS8MkT0Hb9t2H1AVPkwGfVHLJCqyr2Py9dKMxsyM63Eng1GkdZfbWj+Fmv8Rg==",
-            "peerDependencies": {
-                "react": "*"
-            }
-        },
-        "node_modules/react-input-autosize": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-3.0.0.tgz",
-            "integrity": "sha512-nL9uS7jEs/zu8sqwFE5MAPx6pPkNAriACQ2rGLlqmKr2sPGtN7TXTyDdQt4lbNXVx7Uzadb40x8qotIuru6Rhg==",
-            "dependencies": {
-                "prop-types": "^15.5.8"
-            },
-            "peerDependencies": {
-                "react": "^16.3.0 || ^17.0.0"
-            }
-        },
-        "node_modules/react-is": {
-            "version": "16.13.1",
-            "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
-            "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
-        },
-        "node_modules/react-json-tree": {
-            "version": "0.11.2",
-            "resolved": "https://registry.npmjs.org/react-json-tree/-/react-json-tree-0.11.2.tgz",
-            "integrity": "sha512-aYhUPj1y5jR3ZQ+G3N7aL8FbTyO03iLwnVvvEikLcNFqNTyabdljo9xDftZndUBFyyyL0aK3qGO9+8EilILHUw==",
-            "dependencies": {
-                "babel-runtime": "^6.6.1",
-                "prop-types": "^15.5.8",
-                "react-base16-styling": "^0.5.1"
-            },
-            "peerDependencies": {
-                "react": "^15.0.0 || ^16.0.0",
-                "react-dom": "^15.0.0 || ^16.0.0"
-            }
-        },
-        "node_modules/react-jsx-parser": {
-            "version": "1.29.0",
-            "resolved": "https://registry.npmjs.org/react-jsx-parser/-/react-jsx-parser-1.29.0.tgz",
-            "integrity": "sha512-u0svZd0UsPffRrIK0sTbox54jhEbTmg6ED9ob5FQahp1DeOpd2Rq+KiSTIFNYkZUL+WZi4Ntia/Oj5T4lDJafQ==",
-            "hasInstallScript": true,
-            "dependencies": {
-                "@types/jsdom": "^16.2.6",
-                "acorn": "^8.0.5",
-                "acorn-jsx": "^5.3.1",
-                "browserslist": "^4.14.5",
-                "core-js": "^3.8.3"
-            },
-            "optionalDependencies": {
-                "@types/react": "^17.0.1",
-                "@types/react-dom": "^17.0.0"
-            },
-            "peerDependencies": {
-                "react": ">=17",
-                "react-dom": ">=17"
-            }
-        },
-        "node_modules/react-jsx-parser/node_modules/@types/react": {
-            "version": "17.0.45",
-            "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.45.tgz",
-            "integrity": "sha512-YfhQ22Lah2e3CHPsb93tRwIGNiSwkuz1/blk4e6QrWS0jQzCSNbGLtOEYhPg02W0yGTTmpajp7dCTbBAMN3qsg==",
-            "optional": true,
-            "dependencies": {
-                "@types/prop-types": "*",
-                "@types/scheduler": "*",
-                "csstype": "^3.0.2"
-            }
-        },
-        "node_modules/react-jsx-parser/node_modules/@types/react-dom": {
-            "version": "17.0.17",
-            "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.17.tgz",
-            "integrity": "sha512-VjnqEmqGnasQKV0CWLevqMTXBYG9GbwuE6x3VetERLh0cq2LTptFE73MrQi2S7GkKXCf2GgwItB/melLnxfnsg==",
-            "optional": true,
-            "dependencies": {
-                "@types/react": "^17"
-            }
-        },
-        "node_modules/react-jsx-parser/node_modules/core-js": {
-            "version": "3.22.8",
-            "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.8.tgz",
-            "integrity": "sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA==",
-            "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
-            "hasInstallScript": true,
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/core-js"
-            }
-        },
-        "node_modules/react-jsx-parser/node_modules/csstype": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-            "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==",
-            "optional": true
-        },
-        "node_modules/react-lifecycles-compat": {
-            "version": "3.0.4",
-            "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
-            "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
-        },
-        "node_modules/react-loading": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/react-loading/-/react-loading-2.0.3.tgz",
-            "integrity": "sha512-Vdqy79zq+bpeWJqC+xjltUjuGApyoItPgL0vgVfcJHhqwU7bAMKzysfGW/ADu6i0z0JiOCRJjo+IkFNkRNbA3A==",
-            "peerDependencies": {
-                "prop-types": "^15.6.0",
-                "react": ">=0.14.0"
-            }
-        },
-        "node_modules/react-markdown": {
-            "version": "8.0.3",
-            "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.3.tgz",
-            "integrity": "sha512-We36SfqaKoVNpN1QqsZwWSv/OZt5J15LNgTLWynwAN5b265hrQrsjMtlRNwUvS+YyR3yDM8HpTNc4pK9H/Gc0A==",
-            "dependencies": {
-                "@types/hast": "^2.0.0",
-                "@types/prop-types": "^15.0.0",
-                "@types/unist": "^2.0.0",
-                "comma-separated-tokens": "^2.0.0",
-                "hast-util-whitespace": "^2.0.0",
-                "prop-types": "^15.0.0",
-                "property-information": "^6.0.0",
-                "react-is": "^18.0.0",
-                "remark-parse": "^10.0.0",
-                "remark-rehype": "^10.0.0",
-                "space-separated-tokens": "^2.0.0",
-                "style-to-object": "^0.3.0",
-                "unified": "^10.0.0",
-                "unist-util-visit": "^4.0.0",
-                "vfile": "^5.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            },
-            "peerDependencies": {
-                "@types/react": ">=16",
-                "react": ">=16"
-            }
-        },
-        "node_modules/react-markdown/node_modules/react-is": {
-            "version": "18.2.0",
-            "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
-            "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
-        },
-        "node_modules/react-measure": {
-            "version": "2.5.2",
-            "resolved": "https://registry.npmjs.org/react-measure/-/react-measure-2.5.2.tgz",
-            "integrity": "sha512-M+rpbTLWJ3FD6FXvYV6YEGvQ5tMayQ3fGrZhRPHrE9bVlBYfDCLuDcgNttYfk8IqfOI03jz6cbpqMRTUclQnaA==",
-            "dependencies": {
-                "@babel/runtime": "^7.2.0",
-                "get-node-dimensions": "^1.2.1",
-                "prop-types": "^15.6.2",
-                "resize-observer-polyfill": "^1.5.0"
-            },
-            "peerDependencies": {
-                "react": ">0.13.0",
-                "react-dom": ">0.13.0"
-            }
-        },
-        "node_modules/react-merge-refs": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/react-merge-refs/-/react-merge-refs-1.1.0.tgz",
-            "integrity": "sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ==",
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/gregberge"
-            }
-        },
-        "node_modules/react-onclickoutside": {
-            "version": "6.12.2",
-            "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.12.2.tgz",
-            "integrity": "sha512-NMXGa223OnsrGVp5dJHkuKxQ4czdLmXSp5jSV9OqiCky9LOpPATn3vLldc+q5fK3gKbEHvr7J1u0yhBh/xYkpA==",
-            "funding": {
-                "type": "individual",
-                "url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md"
-            },
-            "peerDependencies": {
-                "react": "^15.5.x || ^16.x || ^17.x || ^18.x",
-                "react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x"
-            }
-        },
-        "node_modules/react-popper": {
-            "version": "1.3.11",
-            "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.11.tgz",
-            "integrity": "sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg==",
-            "dependencies": {
-                "@babel/runtime": "^7.1.2",
-                "@hypnosphi/create-react-context": "^0.3.1",
-                "deep-equal": "^1.1.1",
-                "popper.js": "^1.14.4",
-                "prop-types": "^15.6.1",
-                "typed-styles": "^0.0.7",
-                "warning": "^4.0.2"
-            },
-            "peerDependencies": {
-                "react": "0.14.x || ^15.0.0 || ^16.0.0 || ^17.0.0"
-            }
-        },
-        "node_modules/react-popper/node_modules/popper.js": {
-            "version": "1.16.1",
-            "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
-            "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
-            "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1",
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/popperjs"
-            }
-        },
-        "node_modules/react-popper/node_modules/warning": {
-            "version": "4.0.3",
-            "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
-            "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
-            "dependencies": {
-                "loose-envify": "^1.0.0"
-            }
-        },
-        "node_modules/react-reconciler": {
-            "version": "0.26.2",
-            "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.26.2.tgz",
-            "integrity": "sha512-nK6kgY28HwrMNwDnMui3dvm3rCFjZrcGiuwLc5COUipBK5hWHLOxMJhSnSomirqWwjPBJKV1QcbkI0VJr7Gl1Q==",
-            "dependencies": {
-                "loose-envify": "^1.1.0",
-                "object-assign": "^4.1.1",
-                "scheduler": "^0.20.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            },
-            "peerDependencies": {
-                "react": "^17.0.2"
-            }
-        },
-        "node_modules/react-redux": {
-            "version": "7.2.8",
-            "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.8.tgz",
-            "integrity": "sha512-6+uDjhs3PSIclqoCk0kd6iX74gzrGc3W5zcAjbrFgEdIjRSQObdIwfx80unTkVUYvbQ95Y8Av3OvFHq1w5EOUw==",
-            "dependencies": {
-                "@babel/runtime": "^7.15.4",
-                "@types/react-redux": "^7.1.20",
-                "hoist-non-react-statics": "^3.3.2",
-                "loose-envify": "^1.4.0",
-                "prop-types": "^15.7.2",
-                "react-is": "^17.0.2"
-            },
-            "peerDependencies": {
-                "react": "^16.8.3 || ^17 || ^18"
-            },
-            "peerDependenciesMeta": {
-                "react-dom": {
-                    "optional": true
-                },
-                "react-native": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/react-redux/node_modules/react-is": {
-            "version": "17.0.2",
-            "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
-            "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
-        },
-        "node_modules/react-refresh-typescript": {
-            "version": "2.0.7",
-            "resolved": "https://registry.npmjs.org/react-refresh-typescript/-/react-refresh-typescript-2.0.7.tgz",
-            "integrity": "sha512-KbuW57FauO11e6a9gU836sCm3M3z0b2+J2qPhUudg0QplOfz0eAF3gMeshcUC/ChfNLJCK1SZxvYmUtRxiZE5A==",
-            "peerDependencies": {
-                "react-refresh": "0.10.x || 0.11.x || 0.12.x || 0.13.x || 0.14.x",
-                "typescript": "^4"
-            }
-        },
-        "node_modules/react-resizable": {
-            "version": "1.11.1",
-            "resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-1.11.1.tgz",
-            "integrity": "sha512-S70gbLaAYqjuAd49utRHibtHLrHXInh7GuOR+6OO6RO6uleQfuBnWmZjRABfqNEx3C3Z6VPLg0/0uOYFrkfu9Q==",
-            "dependencies": {
-                "prop-types": "15.x",
-                "react-draggable": "^4.0.3"
-            },
-            "peerDependencies": {
-                "react": "0.14.x || 15.x || 16.x || 17.x",
-                "react-dom": "0.14.x || 15.x || 16.x || 17.x"
-            }
-        },
-        "node_modules/react-resizable-rotatable-draggable": {
-            "version": "0.2.0",
-            "resolved": "https://registry.npmjs.org/react-resizable-rotatable-draggable/-/react-resizable-rotatable-draggable-0.2.0.tgz",
-            "integrity": "sha512-F8TPx3z7/AcmRViySbYV3LpUWXFpHlGAmKmNcYMgPlS+h1eYFazRG3xYS8Z6e48hWY1EcCny/YNrwRNUrap8CQ==",
-            "engines": {
-                "node": ">=8",
-                "npm": ">=6"
-            },
-            "peerDependencies": {
-                "prop-types": "^15",
-                "react": "^16",
-                "styled-components": "^4"
-            }
-        },
-        "node_modules/react-reveal": {
-            "version": "1.2.2",
-            "resolved": "https://registry.npmjs.org/react-reveal/-/react-reveal-1.2.2.tgz",
-            "integrity": "sha512-JCv3fAoU6Z+Lcd8U48bwzm4pMZ79qsedSXYwpwt6lJNtj/v5nKJYZZbw3yhaQPPgYePo3Y0NOCoYOq/jcsisuw==",
-            "dependencies": {
-                "prop-types": "^15.5.10"
-            },
-            "peerDependencies": {
-                "react": "^15.3.0 || ^16.0.0"
-            }
-        },
-        "node_modules/react-select": {
-            "version": "3.2.0",
-            "resolved": "https://registry.npmjs.org/react-select/-/react-select-3.2.0.tgz",
-            "integrity": "sha512-B/q3TnCZXEKItO0fFN/I0tWOX3WJvi/X2wtdffmwSQVRwg5BpValScTO1vdic9AxlUgmeSzib2hAZAwIUQUZGQ==",
-            "dependencies": {
-                "@babel/runtime": "^7.4.4",
-                "@emotion/cache": "^10.0.9",
-                "@emotion/core": "^10.0.9",
-                "@emotion/css": "^10.0.9",
-                "memoize-one": "^5.0.0",
-                "prop-types": "^15.6.0",
-                "react-input-autosize": "^3.0.0",
-                "react-transition-group": "^4.3.0"
-            },
-            "peerDependencies": {
-                "react": "^16.8.0 || ^17.0.0",
-                "react-dom": "^16.8.0 || ^17.0.0"
-            }
-        },
-        "node_modules/react-select/node_modules/@emotion/css": {
-            "version": "10.0.27",
-            "resolved": "https://registry.npmjs.org/@emotion/css/-/css-10.0.27.tgz",
-            "integrity": "sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw==",
-            "dependencies": {
-                "@emotion/serialize": "^0.11.15",
-                "@emotion/utils": "0.11.3",
-                "babel-plugin-emotion": "^10.0.27"
-            }
-        },
-        "node_modules/react-select/node_modules/csstype": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-            "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
-        },
-        "node_modules/react-select/node_modules/dom-helpers": {
-            "version": "5.2.1",
-            "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
-            "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
-            "dependencies": {
-                "@babel/runtime": "^7.8.7",
-                "csstype": "^3.0.2"
-            }
-        },
-        "node_modules/react-select/node_modules/react-transition-group": {
-            "version": "4.4.2",
-            "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz",
-            "integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==",
-            "dependencies": {
-                "@babel/runtime": "^7.5.5",
-                "dom-helpers": "^5.0.1",
-                "loose-envify": "^1.4.0",
-                "prop-types": "^15.6.2"
-            },
-            "peerDependencies": {
-                "react": ">=16.6.0",
-                "react-dom": ">=16.6.0"
-            }
-        },
-        "node_modules/react-table": {
-            "version": "6.11.5",
-            "resolved": "https://registry.npmjs.org/react-table/-/react-table-6.11.5.tgz",
-            "integrity": "sha512-LM+AS9v//7Y7lAlgTWW/cW6Sn5VOb3EsSkKQfQTzOW8FngB1FUskLLNEVkAYsTX9LjOWR3QlGjykJqCE6eXT/g==",
-            "dependencies": {
-                "@types/react-table": "^6.8.5",
-                "classnames": "^2.2.5",
-                "react-is": "^16.8.1"
-            },
-            "peerDependencies": {
-                "prop-types": "^15.7.0",
-                "react": "^16.x.x",
-                "react-dom": "^16.x.x"
-            }
-        },
-        "node_modules/react-table/node_modules/@types/react-table": {
-            "version": "6.8.9",
-            "resolved": "https://registry.npmjs.org/@types/react-table/-/react-table-6.8.9.tgz",
-            "integrity": "sha512-fVQXjy/EYDbgraScgjDONA291McKqGrw0R0NeK639fx2bS4T19TnXMjg3FjOPlkI3qYTQtFTPADlRYysaQIMpA==",
-            "dependencies": {
-                "@types/react": "*"
-            }
-        },
-        "node_modules/react-themeable": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/react-themeable/-/react-themeable-1.1.0.tgz",
-            "integrity": "sha1-fURm3ZsrX6dQWHJ4JenxUro3mg4=",
-            "dependencies": {
-                "object-assign": "^3.0.0"
-            }
-        },
-        "node_modules/react-themeable/node_modules/object-assign": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
-            "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/react-three-fiber": {
-            "version": "0.0.0-deprecated",
-            "resolved": "https://registry.npmjs.org/react-three-fiber/-/react-three-fiber-0.0.0-deprecated.tgz",
-            "integrity": "sha512-EblIqTAsIpkYeM8bZtC4lcpTE0A2zCEGipFB52RgcQq/q+0oryrk7Sxt+sqhIjUu6xMNEVywV8dr74lz5yWO6A=="
-        },
-        "node_modules/react-transition-group": {
-            "version": "4.4.2",
-            "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz",
-            "integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==",
-            "dependencies": {
-                "@babel/runtime": "^7.5.5",
-                "dom-helpers": "^5.0.1",
-                "loose-envify": "^1.4.0",
-                "prop-types": "^15.6.2"
-            },
-            "peerDependencies": {
-                "react": ">=16.6.0",
-                "react-dom": ">=16.6.0"
-            }
-        },
-        "node_modules/react-transition-group/node_modules/csstype": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-            "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
-        },
-        "node_modules/react-transition-group/node_modules/dom-helpers": {
-            "version": "5.2.1",
-            "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
-            "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
-            "dependencies": {
-                "@babel/runtime": "^7.8.7",
-                "csstype": "^3.0.2"
-            }
-        },
-        "node_modules/react-use-measure": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.1.tgz",
-            "integrity": "sha512-nocZhN26cproIiIduswYpV5y5lQpSQS1y/4KuvUCjSKmw7ZWIS/+g3aFnX3WdBkyuGUtTLif3UTqnLLhbDoQig==",
-            "dependencies": {
-                "debounce": "^1.2.1"
-            },
-            "peerDependencies": {
-                "react": ">=16.13",
-                "react-dom": ">=16.13"
-            }
-        },
-        "node_modules/reactcss": {
-            "version": "1.2.3",
-            "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz",
-            "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==",
-            "dependencies": {
-                "lodash": "^4.0.1"
-            }
-        },
-        "node_modules/read-pkg": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
-            "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
-            "dependencies": {
-                "load-json-file": "^1.0.0",
-                "normalize-package-data": "^2.3.2",
-                "path-type": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/read-pkg-up": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
-            "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
-            "dependencies": {
-                "find-up": "^1.0.0",
-                "read-pkg": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/read-pkg-up/node_modules/find-up": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
-            "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
-            "dependencies": {
-                "path-exists": "^2.0.0",
-                "pinkie-promise": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/read-pkg-up/node_modules/path-exists": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
-            "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
-            "dependencies": {
-                "pinkie-promise": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/read-pkg/node_modules/path-type": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
-            "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
-            "dependencies": {
-                "graceful-fs": "^4.1.2",
-                "pify": "^2.0.0",
-                "pinkie-promise": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/readable-stream": {
-            "version": "3.6.0",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
-            "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
-            "dependencies": {
-                "inherits": "^2.0.3",
-                "string_decoder": "^1.1.1",
-                "util-deprecate": "^1.0.1"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/readdirp": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
-            "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
-            "dependencies": {
-                "graceful-fs": "^4.1.11",
-                "micromatch": "^3.1.10",
-                "readable-stream": "^2.0.2"
-            },
-            "engines": {
-                "node": ">=0.10"
-            }
-        },
-        "node_modules/readdirp/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/readline": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz",
-            "integrity": "sha1-xYDXfvLPyHUrEySYBg3JeTp6wBw="
-        },
-        "node_modules/rechoir": {
-            "version": "0.6.2",
-            "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
-            "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
-            "dependencies": {
-                "resolve": "^1.1.6"
-            },
-            "engines": {
-                "node": ">= 0.10"
-            }
-        },
-        "node_modules/recompose": {
-            "version": "0.26.0",
-            "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.26.0.tgz",
-            "integrity": "sha512-KwOu6ztO0mN5vy3+zDcc45lgnaUoaQse/a5yLVqtzTK13czSWnFGmXbQVmnoMgDkI5POd1EwIKSbjU1V7xdZog==",
-            "dependencies": {
-                "change-emitter": "^0.1.2",
-                "fbjs": "^0.8.1",
-                "hoist-non-react-statics": "^2.3.1",
-                "symbol-observable": "^1.0.4"
-            },
-            "peerDependencies": {
-                "react": "^0.14.0 || ^15.0.0 || ^16.0.0"
-            }
-        },
-        "node_modules/recompose/node_modules/hoist-non-react-statics": {
-            "version": "2.5.5",
-            "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
-            "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
-        },
-        "node_modules/redent": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
-            "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
-            "dependencies": {
-                "indent-string": "^2.1.0",
-                "strip-indent": "^1.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/reduce-flatten": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz",
-            "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/redux": {
-            "version": "4.2.0",
-            "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz",
-            "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==",
-            "dependencies": {
-                "@babel/runtime": "^7.9.2"
-            }
-        },
-        "node_modules/regenerator-runtime": {
-            "version": "0.13.9",
-            "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
-            "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
-        },
-        "node_modules/regex-not": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
-            "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
-            "dependencies": {
-                "extend-shallow": "^3.0.2",
-                "safe-regex": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/regexp-clone": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz",
-            "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw=="
-        },
-        "node_modules/regexp.prototype.flags": {
-            "version": "1.4.3",
-            "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
-            "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.3",
-                "functions-have-names": "^1.2.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/regexpp": {
-            "version": "3.2.0",
-            "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
-            "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/mysticatea"
-            }
-        },
-        "node_modules/registry-auth-token": {
-            "version": "3.4.0",
-            "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz",
-            "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==",
-            "dependencies": {
-                "rc": "^1.1.6",
-                "safe-buffer": "^5.0.1"
-            }
-        },
-        "node_modules/registry-url": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz",
-            "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=",
-            "dependencies": {
-                "rc": "^1.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/rehype-raw": {
-            "version": "6.1.1",
-            "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-6.1.1.tgz",
-            "integrity": "sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==",
-            "dependencies": {
-                "@types/hast": "^2.0.0",
-                "hast-util-raw": "^7.2.0",
-                "unified": "^10.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/relateurl": {
-            "version": "0.2.7",
-            "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
-            "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
-            "engines": {
-                "node": ">= 0.10"
-            }
-        },
-        "node_modules/remark-gfm": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz",
-            "integrity": "sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==",
-            "dependencies": {
-                "@types/mdast": "^3.0.0",
-                "mdast-util-gfm": "^2.0.0",
-                "micromark-extension-gfm": "^2.0.0",
-                "unified": "^10.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/remark-parse": {
-            "version": "10.0.1",
-            "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.1.tgz",
-            "integrity": "sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw==",
-            "dependencies": {
-                "@types/mdast": "^3.0.0",
-                "mdast-util-from-markdown": "^1.0.0",
-                "unified": "^10.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/remark-rehype": {
-            "version": "10.1.0",
-            "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-10.1.0.tgz",
-            "integrity": "sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==",
-            "dependencies": {
-                "@types/hast": "^2.0.0",
-                "@types/mdast": "^3.0.0",
-                "mdast-util-to-hast": "^12.1.0",
-                "unified": "^10.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/remove-trailing-separator": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
-            "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
-        },
-        "node_modules/renderkid": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz",
-            "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==",
-            "dependencies": {
-                "css-select": "^4.1.3",
-                "dom-converter": "^0.2.0",
-                "htmlparser2": "^6.1.0",
-                "lodash": "^4.17.21",
-                "strip-ansi": "^6.0.1"
-            }
-        },
-        "node_modules/renderkid/node_modules/ansi-regex": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/renderkid/node_modules/dom-serializer": {
-            "version": "1.4.1",
-            "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
-            "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
-            "dependencies": {
-                "domelementtype": "^2.0.1",
-                "domhandler": "^4.2.0",
-                "entities": "^2.0.0"
-            },
-            "funding": {
-                "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
-            }
-        },
-        "node_modules/renderkid/node_modules/domelementtype": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
-            "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/fb55"
-                }
-            ]
-        },
-        "node_modules/renderkid/node_modules/domhandler": {
-            "version": "4.3.1",
-            "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
-            "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
-            "dependencies": {
-                "domelementtype": "^2.2.0"
-            },
-            "engines": {
-                "node": ">= 4"
-            },
-            "funding": {
-                "url": "https://github.com/fb55/domhandler?sponsor=1"
-            }
-        },
-        "node_modules/renderkid/node_modules/domutils": {
-            "version": "2.8.0",
-            "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
-            "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
-            "dependencies": {
-                "dom-serializer": "^1.0.1",
-                "domelementtype": "^2.2.0",
-                "domhandler": "^4.2.0"
-            },
-            "funding": {
-                "url": "https://github.com/fb55/domutils?sponsor=1"
-            }
-        },
-        "node_modules/renderkid/node_modules/entities": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
-            "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
-            "funding": {
-                "url": "https://github.com/fb55/entities?sponsor=1"
-            }
-        },
-        "node_modules/renderkid/node_modules/htmlparser2": {
-            "version": "6.1.0",
-            "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
-            "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
-            "funding": [
-                "https://github.com/fb55/htmlparser2?sponsor=1",
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/fb55"
-                }
-            ],
-            "dependencies": {
-                "domelementtype": "^2.0.1",
-                "domhandler": "^4.0.0",
-                "domutils": "^2.5.2",
-                "entities": "^2.0.0"
-            }
-        },
-        "node_modules/renderkid/node_modules/strip-ansi": {
-            "version": "6.0.1",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-            "dependencies": {
-                "ansi-regex": "^5.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/repeat-element": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz",
-            "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/repeat-string": {
-            "version": "1.6.1",
-            "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
-            "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
-            "engines": {
-                "node": ">=0.10"
-            }
-        },
-        "node_modules/repeating": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
-            "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
-            "dependencies": {
-                "is-finite": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/request": {
-            "version": "2.88.2",
-            "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
-            "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
-            "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
-            "dependencies": {
-                "aws-sign2": "~0.7.0",
-                "aws4": "^1.8.0",
-                "caseless": "~0.12.0",
-                "combined-stream": "~1.0.6",
-                "extend": "~3.0.2",
-                "forever-agent": "~0.6.1",
-                "form-data": "~2.3.2",
-                "har-validator": "~5.1.3",
-                "http-signature": "~1.2.0",
-                "is-typedarray": "~1.0.0",
-                "isstream": "~0.1.2",
-                "json-stringify-safe": "~5.0.1",
-                "mime-types": "~2.1.19",
-                "oauth-sign": "~0.9.0",
-                "performance-now": "^2.1.0",
-                "qs": "~6.5.2",
-                "safe-buffer": "^5.1.2",
-                "tough-cookie": "~2.5.0",
-                "tunnel-agent": "^0.6.0",
-                "uuid": "^3.3.2"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/request-promise": {
-            "version": "4.2.6",
-            "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz",
-            "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==",
-            "deprecated": "request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142",
-            "dependencies": {
-                "bluebird": "^3.5.0",
-                "request-promise-core": "1.1.4",
-                "stealthy-require": "^1.1.1",
-                "tough-cookie": "^2.3.3"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            },
-            "peerDependencies": {
-                "request": "^2.34"
-            }
-        },
-        "node_modules/request-promise-core": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
-            "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
-            "dependencies": {
-                "lodash": "^4.17.19"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            },
-            "peerDependencies": {
-                "request": "^2.34"
-            }
-        },
-        "node_modules/request-promise-native": {
-            "version": "1.0.9",
-            "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz",
-            "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==",
-            "deprecated": "request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142",
-            "dev": true,
-            "dependencies": {
-                "request-promise-core": "1.1.4",
-                "stealthy-require": "^1.1.1",
-                "tough-cookie": "^2.3.3"
-            },
-            "engines": {
-                "node": ">=0.12.0"
-            },
-            "peerDependencies": {
-                "request": "^2.34"
-            }
-        },
-        "node_modules/request-promise-native/node_modules/tough-cookie": {
-            "version": "2.5.0",
-            "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
-            "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
-            "dev": true,
-            "dependencies": {
-                "psl": "^1.1.28",
-                "punycode": "^2.1.1"
-            },
-            "engines": {
-                "node": ">=0.8"
-            }
-        },
-        "node_modules/request-promise/node_modules/tough-cookie": {
-            "version": "2.5.0",
-            "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
-            "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
-            "dependencies": {
-                "psl": "^1.1.28",
-                "punycode": "^2.1.1"
-            },
-            "engines": {
-                "node": ">=0.8"
-            }
-        },
-        "node_modules/request/node_modules/tough-cookie": {
-            "version": "2.5.0",
-            "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
-            "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
-            "dependencies": {
-                "psl": "^1.1.28",
-                "punycode": "^2.1.1"
-            },
-            "engines": {
-                "node": ">=0.8"
-            }
-        },
-        "node_modules/require_optional": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
-            "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
-            "dependencies": {
-                "resolve-from": "^2.0.0",
-                "semver": "^5.1.0"
-            }
-        },
-        "node_modules/require_optional/node_modules/resolve-from": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
-            "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/require-at": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz",
-            "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/require-directory": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
-            "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/require-from-string": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
-            "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/require-main-filename": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
-            "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
-        },
-        "node_modules/require-package-name": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz",
-            "integrity": "sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk="
-        },
-        "node_modules/requires-port": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
-            "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
-            "dev": true
-        },
-        "node_modules/resize-observer-polyfill": {
-            "version": "1.5.1",
-            "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
-            "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
-        },
-        "node_modules/resolve": {
-            "version": "1.22.0",
-            "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
-            "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
-            "dependencies": {
-                "is-core-module": "^2.8.1",
-                "path-parse": "^1.0.7",
-                "supports-preserve-symlinks-flag": "^1.0.0"
-            },
-            "bin": {
-                "resolve": "bin/resolve"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/resolve-alpn": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
-            "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="
-        },
-        "node_modules/resolve-cwd": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
-            "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
-            "dependencies": {
-                "resolve-from": "^5.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/resolve-cwd/node_modules/resolve-from": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
-            "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/resolve-from": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
-            "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/resolve-url": {
-            "version": "0.2.1",
-            "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
-            "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
-            "deprecated": "https://github.com/lydell/resolve-url#deprecated"
-        },
-        "node_modules/responselike": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz",
-            "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==",
-            "dependencies": {
-                "lowercase-keys": "^2.0.0"
-            }
-        },
-        "node_modules/responselike/node_modules/lowercase-keys": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
-            "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/restore-cursor": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
-            "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
-            "dev": true,
-            "dependencies": {
-                "onetime": "^5.1.0",
-                "signal-exit": "^3.0.2"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/ret": {
-            "version": "0.1.15",
-            "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
-            "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
-            "engines": {
-                "node": ">=0.12"
-            }
-        },
-        "node_modules/retry": {
-            "version": "0.12.0",
-            "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
-            "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
-            "dev": true,
-            "engines": {
-                "node": ">= 4"
-            }
-        },
-        "node_modules/reveal.js": {
-            "version": "4.3.1",
-            "resolved": "https://registry.npmjs.org/reveal.js/-/reveal.js-4.3.1.tgz",
-            "integrity": "sha512-1kyEnWeUkaCdBdX//XXq9dtBK95ppvIlSwlHelrP8/wrX6LcsYp4HT9WTFoFEOUBfVqkm8C2aHQ367o+UKfcxw==",
-            "engines": {
-                "node": ">=10.0.0"
-            }
-        },
-        "node_modules/right-align": {
-            "version": "0.1.3",
-            "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
-            "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
-            "dependencies": {
-                "align-text": "^0.1.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/rimraf": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-            "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/isaacs"
-            }
-        },
-        "node_modules/rope-sequence": {
-            "version": "1.3.3",
-            "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.3.tgz",
-            "integrity": "sha512-85aZYCxweiD5J8yTEbw+E6A27zSnLPNDL0WfPdw3YYodq7WjnTKo0q4dtyQ2gz23iPT8Q9CUyJtAaUNcTxRf5Q=="
-        },
-        "node_modules/rtcpeerconnection-shim": {
-            "version": "1.2.15",
-            "resolved": "https://registry.npmjs.org/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.15.tgz",
-            "integrity": "sha512-C6DxhXt7bssQ1nHb154lqeL0SXz5Dx4RczXZu2Aa/L1NJFnEVDxFwCBo3fqtuljhHIGceg5JKBV4XJ0gW5JKyw==",
-            "dependencies": {
-                "sdp": "^2.6.0"
-            },
-            "engines": {
-                "node": ">=6.0.0",
-                "npm": ">=3.10.0"
-            }
-        },
-        "node_modules/run-async": {
-            "version": "2.4.1",
-            "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
-            "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.12.0"
-            }
-        },
-        "node_modules/run-queue": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
-            "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
-            "dev": true,
-            "dependencies": {
-                "aproba": "^1.1.1"
-            }
-        },
-        "node_modules/run-queue/node_modules/aproba": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-            "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
-            "dev": true
-        },
-        "node_modules/rxjs": {
-            "version": "6.6.7",
-            "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
-            "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
-            "dev": true,
-            "dependencies": {
-                "tslib": "^1.9.0"
-            },
-            "engines": {
-                "npm": ">=2.0.0"
-            }
-        },
-        "node_modules/rxjs/node_modules/tslib": {
-            "version": "1.14.1",
-            "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-            "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
-            "dev": true
-        },
-        "node_modules/sade": {
-            "version": "1.8.1",
-            "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
-            "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
-            "dependencies": {
-                "mri": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-            "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
-        },
-        "node_modules/safe-regex": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
-            "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
-            "dependencies": {
-                "ret": "~0.1.10"
-            }
-        },
-        "node_modules/safer-buffer": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-            "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
-        },
-        "node_modules/saslprep": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
-            "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
-            "optional": true,
-            "dependencies": {
-                "sparse-bitfield": "^3.0.3"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/sass-graph": {
-            "version": "2.2.5",
-            "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz",
-            "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==",
-            "dependencies": {
-                "glob": "^7.0.0",
-                "lodash": "^4.0.0",
-                "scss-tokenizer": "^0.2.3",
-                "yargs": "^13.3.2"
-            },
-            "bin": {
-                "sassgraph": "bin/sassgraph"
-            }
-        },
-        "node_modules/sass-loader": {
-            "version": "7.3.1",
-            "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.3.1.tgz",
-            "integrity": "sha512-tuU7+zm0pTCynKYHpdqaPpe+MMTQ76I9TPZ7i4/5dZsigE350shQWe5EZNl5dBidM49TPET75tNqRbcsUZWeNA==",
-            "dev": true,
-            "dependencies": {
-                "clone-deep": "^4.0.1",
-                "loader-utils": "^1.0.1",
-                "neo-async": "^2.5.0",
-                "pify": "^4.0.1",
-                "semver": "^6.3.0"
-            },
-            "engines": {
-                "node": ">= 6.9.0"
-            },
-            "peerDependencies": {
-                "webpack": "^3.0.0 || ^4.0.0"
-            }
-        },
-        "node_modules/sass-loader/node_modules/pify": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
-            "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/sass-loader/node_modules/semver": {
-            "version": "6.3.0",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-            "dev": true,
-            "bin": {
-                "semver": "bin/semver.js"
-            }
-        },
-        "node_modules/saxes": {
-            "version": "3.1.11",
-            "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz",
-            "integrity": "sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==",
-            "dev": true,
-            "dependencies": {
-                "xmlchars": "^2.1.1"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/scheduler": {
-            "version": "0.20.2",
-            "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
-            "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
-            "dependencies": {
-                "loose-envify": "^1.1.0",
-                "object-assign": "^4.1.1"
-            }
-        },
-        "node_modules/schema-utils": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
-            "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
-            "dependencies": {
-                "ajv": "^6.1.0",
-                "ajv-errors": "^1.0.0",
-                "ajv-keywords": "^3.1.0"
-            },
-            "engines": {
-                "node": ">= 4"
-            }
-        },
-        "node_modules/scss-loader": {
-            "version": "0.0.1",
-            "resolved": "https://registry.npmjs.org/scss-loader/-/scss-loader-0.0.1.tgz",
-            "integrity": "sha1-6uAXueDzjBKlMtslwiC5Avs05nE=",
-            "dev": true
-        },
-        "node_modules/scss-tokenizer": {
-            "version": "0.2.3",
-            "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
-            "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
-            "dependencies": {
-                "js-base64": "^2.1.8",
-                "source-map": "^0.4.2"
-            }
-        },
-        "node_modules/scss-tokenizer/node_modules/source-map": {
-            "version": "0.4.4",
-            "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
-            "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
-            "dependencies": {
-                "amdefine": ">=0.0.4"
-            },
-            "engines": {
-                "node": ">=0.8.0"
-            }
-        },
-        "node_modules/sdp": {
-            "version": "2.12.0",
-            "resolved": "https://registry.npmjs.org/sdp/-/sdp-2.12.0.tgz",
-            "integrity": "sha512-jhXqQAQVM+8Xj5EjJGVweuEzgtGWb3tmEEpl3CLP3cStInSbVHSg0QWOGQzNq8pSID4JkpeV2mPqlMDLrm0/Vw=="
-        },
-        "node_modules/section-iterator": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/section-iterator/-/section-iterator-2.0.0.tgz",
-            "integrity": "sha1-v0RNev7rlK1Dw5rS+yYVFifMuio="
-        },
-        "node_modules/select": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
-            "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
-        },
-        "node_modules/select-hose": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
-            "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
-            "dev": true
-        },
-        "node_modules/selfsigned": {
-            "version": "1.10.14",
-            "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.14.tgz",
-            "integrity": "sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==",
-            "dev": true,
-            "dependencies": {
-                "node-forge": "^0.10.0"
-            }
-        },
-        "node_modules/semver": {
-            "version": "5.7.1",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-            "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-            "bin": {
-                "semver": "bin/semver"
-            }
-        },
-        "node_modules/semver-compare": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
-            "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w="
-        },
-        "node_modules/semver-diff": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz",
-            "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=",
-            "dependencies": {
-                "semver": "^5.0.3"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/send": {
-            "version": "0.18.0",
-            "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
-            "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
-            "dependencies": {
-                "debug": "2.6.9",
-                "depd": "2.0.0",
-                "destroy": "1.2.0",
-                "encodeurl": "~1.0.2",
-                "escape-html": "~1.0.3",
-                "etag": "~1.8.1",
-                "fresh": "0.5.2",
-                "http-errors": "2.0.0",
-                "mime": "1.6.0",
-                "ms": "2.1.3",
-                "on-finished": "2.4.1",
-                "range-parser": "~1.2.1",
-                "statuses": "2.0.1"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/send/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/send/node_modules/debug/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
-        },
-        "node_modules/send/node_modules/ms": {
-            "version": "2.1.3",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-            "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
-        },
-        "node_modules/serialize-javascript": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
-            "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
-            "dependencies": {
-                "randombytes": "^2.1.0"
-            }
-        },
-        "node_modules/serializr": {
-            "version": "1.5.4",
-            "resolved": "https://registry.npmjs.org/serializr/-/serializr-1.5.4.tgz",
-            "integrity": "sha512-ImLlkNfNSSv9d7Ah1j/yrPk1FHbRC1zkD7URcgx/8M1eYHGUxGf/Ig/d8ML04ifqN7QesyYKsfLYA4xjAVAR/g=="
-        },
-        "node_modules/serve-index": {
-            "version": "1.9.1",
-            "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
-            "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
-            "dev": true,
-            "dependencies": {
-                "accepts": "~1.3.4",
-                "batch": "0.6.1",
-                "debug": "2.6.9",
-                "escape-html": "~1.0.3",
-                "http-errors": "~1.6.2",
-                "mime-types": "~2.1.17",
-                "parseurl": "~1.3.2"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/serve-index/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "dev": true,
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/serve-index/node_modules/depd": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
-            "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
-            "dev": true,
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/serve-index/node_modules/http-errors": {
-            "version": "1.6.3",
-            "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
-            "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
-            "dev": true,
-            "dependencies": {
-                "depd": "~1.1.2",
-                "inherits": "2.0.3",
-                "setprototypeof": "1.1.0",
-                "statuses": ">= 1.4.0 < 2"
-            },
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/serve-index/node_modules/inherits": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
-            "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
-            "dev": true
-        },
-        "node_modules/serve-index/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
-            "dev": true
-        },
-        "node_modules/serve-index/node_modules/setprototypeof": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
-            "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
-            "dev": true
-        },
-        "node_modules/serve-index/node_modules/statuses": {
-            "version": "1.5.0",
-            "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
-            "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
-            "dev": true,
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/serve-static": {
-            "version": "1.15.0",
-            "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
-            "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
-            "dependencies": {
-                "encodeurl": "~1.0.2",
-                "escape-html": "~1.0.3",
-                "parseurl": "~1.3.3",
-                "send": "0.18.0"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/set-blocking": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
-            "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
-        },
-        "node_modules/set-value": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
-            "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
-            "dependencies": {
-                "extend-shallow": "^2.0.1",
-                "is-extendable": "^0.1.1",
-                "is-plain-object": "^2.0.3",
-                "split-string": "^3.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/set-value/node_modules/extend-shallow": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-            "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-            "dependencies": {
-                "is-extendable": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/setimmediate": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
-            "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
-        },
-        "node_modules/setprototypeof": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
-            "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
-        },
-        "node_modules/shallow-clone": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
-            "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
-            "dependencies": {
-                "kind-of": "^6.0.2"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/shallow-equal": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz",
-            "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA=="
-        },
-        "node_modules/sharp": {
-            "version": "0.23.4",
-            "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.23.4.tgz",
-            "integrity": "sha512-fJMagt6cT0UDy9XCsgyLi0eiwWWhQRxbwGmqQT6sY8Av4s0SVsT/deg8fobBQCTDU5iXRgz0rAeXoE2LBZ8g+Q==",
-            "hasInstallScript": true,
-            "dependencies": {
-                "color": "^3.1.2",
-                "detect-libc": "^1.0.3",
-                "nan": "^2.14.0",
-                "npmlog": "^4.1.2",
-                "prebuild-install": "^5.3.3",
-                "semver": "^6.3.0",
-                "simple-get": "^3.1.0",
-                "tar": "^5.0.5",
-                "tunnel-agent": "^0.6.0"
-            },
-            "engines": {
-                "node": ">=8.5.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/libvips"
-            }
-        },
-        "node_modules/sharp/node_modules/ansi-regex": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-            "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/sharp/node_modules/aproba": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-            "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
-        },
-        "node_modules/sharp/node_modules/are-we-there-yet": {
-            "version": "1.1.7",
-            "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
-            "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
-            "dependencies": {
-                "delegates": "^1.0.0",
-                "readable-stream": "^2.0.6"
-            }
-        },
-        "node_modules/sharp/node_modules/chownr": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
-            "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
-        },
-        "node_modules/sharp/node_modules/detect-libc": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
-            "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
-            "bin": {
-                "detect-libc": "bin/detect-libc.js"
-            },
-            "engines": {
-                "node": ">=0.10"
-            }
-        },
-        "node_modules/sharp/node_modules/gauge": {
-            "version": "2.7.4",
-            "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
-            "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==",
-            "dependencies": {
-                "aproba": "^1.0.3",
-                "console-control-strings": "^1.0.0",
-                "has-unicode": "^2.0.0",
-                "object-assign": "^4.1.0",
-                "signal-exit": "^3.0.0",
-                "string-width": "^1.0.1",
-                "strip-ansi": "^3.0.1",
-                "wide-align": "^1.1.0"
-            }
-        },
-        "node_modules/sharp/node_modules/is-fullwidth-code-point": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
-            "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==",
-            "dependencies": {
-                "number-is-nan": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/sharp/node_modules/mkdirp": {
-            "version": "0.5.6",
-            "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
-            "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
-            "dependencies": {
-                "minimist": "^1.2.6"
-            },
-            "bin": {
-                "mkdirp": "bin/cmd.js"
-            }
-        },
-        "node_modules/sharp/node_modules/npmlog": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
-            "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
-            "dependencies": {
-                "are-we-there-yet": "~1.1.2",
-                "console-control-strings": "~1.1.0",
-                "gauge": "~2.7.3",
-                "set-blocking": "~2.0.0"
-            }
-        },
-        "node_modules/sharp/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/sharp/node_modules/semver": {
-            "version": "6.3.0",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-            "bin": {
-                "semver": "bin/semver.js"
-            }
-        },
-        "node_modules/sharp/node_modules/string-width": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
-            "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
-            "dependencies": {
-                "code-point-at": "^1.0.0",
-                "is-fullwidth-code-point": "^1.0.0",
-                "strip-ansi": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/sharp/node_modules/strip-ansi": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-            "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
-            "dependencies": {
-                "ansi-regex": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/sharp/node_modules/tar": {
-            "version": "5.0.11",
-            "resolved": "https://registry.npmjs.org/tar/-/tar-5.0.11.tgz",
-            "integrity": "sha512-E6q48d5y4XSCD+Xmwc0yc8lXuyDK38E0FB8N4S/drQRtXOMUhfhDxbB0xr2KKDhNfO51CFmoa6Oz00nAkWsjnA==",
-            "dependencies": {
-                "chownr": "^1.1.4",
-                "fs-minipass": "^2.1.0",
-                "minipass": "^3.1.3",
-                "minizlib": "^2.1.2",
-                "mkdirp": "^0.5.5",
-                "yallist": "^4.0.0"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/shebang-command": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
-            "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
-            "dependencies": {
-                "shebang-regex": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/shebang-regex": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
-            "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/shelljs": {
-            "version": "0.8.5",
-            "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
-            "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
-            "dependencies": {
-                "glob": "^7.0.0",
-                "interpret": "^1.0.0",
-                "rechoir": "^0.6.2"
-            },
-            "bin": {
-                "shjs": "bin/shjs"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/side-channel": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
-            "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
-            "dependencies": {
-                "call-bind": "^1.0.0",
-                "get-intrinsic": "^1.0.2",
-                "object-inspect": "^1.9.0"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/sift": {
-            "version": "13.5.2",
-            "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz",
-            "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA=="
-        },
-        "node_modules/signal-exit": {
-            "version": "3.0.7",
-            "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
-            "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
-        },
-        "node_modules/simple-assign": {
-            "version": "0.1.0",
-            "resolved": "https://registry.npmjs.org/simple-assign/-/simple-assign-0.1.0.tgz",
-            "integrity": "sha1-F/0wZqXz13OPUDIbsPFMooHMS6o="
-        },
-        "node_modules/simple-concat": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
-            "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ]
-        },
-        "node_modules/simple-get": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
-            "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
-            "dependencies": {
-                "decompress-response": "^4.2.0",
-                "once": "^1.3.1",
-                "simple-concat": "^1.0.0"
-            }
-        },
-        "node_modules/simple-swizzle": {
-            "version": "0.2.2",
-            "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
-            "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
-            "dependencies": {
-                "is-arrayish": "^0.3.1"
-            }
-        },
-        "node_modules/simple-swizzle/node_modules/is-arrayish": {
-            "version": "0.3.2",
-            "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
-            "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
-        },
-        "node_modules/slash": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
-            "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/slice-ansi": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
-            "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
-            "dev": true,
-            "dependencies": {
-                "ansi-styles": "^3.2.0",
-                "astral-regex": "^1.0.0",
-                "is-fullwidth-code-point": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/sliced": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
-            "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E="
-        },
-        "node_modules/snapdragon": {
-            "version": "0.8.2",
-            "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
-            "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
-            "dependencies": {
-                "base": "^0.11.1",
-                "debug": "^2.2.0",
-                "define-property": "^0.2.5",
-                "extend-shallow": "^2.0.1",
-                "map-cache": "^0.2.2",
-                "source-map": "^0.5.6",
-                "source-map-resolve": "^0.5.0",
-                "use": "^3.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/snapdragon-node": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
-            "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
-            "dependencies": {
-                "define-property": "^1.0.0",
-                "isobject": "^3.0.0",
-                "snapdragon-util": "^3.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/snapdragon-node/node_modules/define-property": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-            "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
-            "dependencies": {
-                "is-descriptor": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-            "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-            "dependencies": {
-                "kind-of": "^6.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/snapdragon-node/node_modules/is-data-descriptor": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-            "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-            "dependencies": {
-                "kind-of": "^6.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/snapdragon-node/node_modules/is-descriptor": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-            "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-            "dependencies": {
-                "is-accessor-descriptor": "^1.0.0",
-                "is-data-descriptor": "^1.0.0",
-                "kind-of": "^6.0.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/snapdragon-util": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
-            "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
-            "dependencies": {
-                "kind-of": "^3.2.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/snapdragon-util/node_modules/is-buffer": {
-            "version": "1.1.6",
-            "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-            "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
-        },
-        "node_modules/snapdragon-util/node_modules/kind-of": {
-            "version": "3.2.2",
-            "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-            "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-            "dependencies": {
-                "is-buffer": "^1.1.5"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/snapdragon/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/snapdragon/node_modules/define-property": {
-            "version": "0.2.5",
-            "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-            "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-            "dependencies": {
-                "is-descriptor": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/snapdragon/node_modules/extend-shallow": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-            "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-            "dependencies": {
-                "is-extendable": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/snapdragon/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
-        },
-        "node_modules/socket.io": {
-            "version": "2.5.0",
-            "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.5.0.tgz",
-            "integrity": "sha512-gGunfS0od3VpwDBpGwVkzSZx6Aqo9uOcf1afJj2cKnKFAoyl16fvhpsUhmUFd4Ldbvl5JvRQed6eQw6oQp6n8w==",
-            "dependencies": {
-                "debug": "~4.1.0",
-                "engine.io": "~3.6.0",
-                "has-binary2": "~1.0.2",
-                "socket.io-adapter": "~1.1.0",
-                "socket.io-client": "2.5.0",
-                "socket.io-parser": "~3.4.0"
-            }
-        },
-        "node_modules/socket.io-adapter": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz",
-            "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g=="
-        },
-        "node_modules/socket.io-client": {
-            "version": "2.5.0",
-            "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.5.0.tgz",
-            "integrity": "sha512-lOO9clmdgssDykiOmVQQitwBAF3I6mYcQAo7hQ7AM6Ny5X7fp8hIJ3HcQs3Rjz4SoggoxA1OgrQyY8EgTbcPYw==",
-            "dependencies": {
-                "backo2": "1.0.2",
-                "component-bind": "1.0.0",
-                "component-emitter": "~1.3.0",
-                "debug": "~3.1.0",
-                "engine.io-client": "~3.5.0",
-                "has-binary2": "~1.0.2",
-                "indexof": "0.0.1",
-                "parseqs": "0.0.6",
-                "parseuri": "0.0.6",
-                "socket.io-parser": "~3.3.0",
-                "to-array": "0.1.4"
-            }
-        },
-        "node_modules/socket.io-client/node_modules/debug": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-            "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/socket.io-client/node_modules/isarray": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
-            "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ=="
-        },
-        "node_modules/socket.io-client/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
-        },
-        "node_modules/socket.io-client/node_modules/socket.io-parser": {
-            "version": "3.3.2",
-            "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.2.tgz",
-            "integrity": "sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg==",
-            "dependencies": {
-                "component-emitter": "~1.3.0",
-                "debug": "~3.1.0",
-                "isarray": "2.0.1"
-            }
-        },
-        "node_modules/socket.io-parser": {
-            "version": "3.4.1",
-            "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz",
-            "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==",
-            "dependencies": {
-                "component-emitter": "1.2.1",
-                "debug": "~4.1.0",
-                "isarray": "2.0.1"
-            }
-        },
-        "node_modules/socket.io-parser/node_modules/component-emitter": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
-            "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
-        },
-        "node_modules/socket.io-parser/node_modules/debug": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-            "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
-            "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
-            "dependencies": {
-                "ms": "^2.1.1"
-            }
-        },
-        "node_modules/socket.io-parser/node_modules/isarray": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
-            "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
-        },
-        "node_modules/socket.io/node_modules/debug": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-            "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
-            "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
-            "dependencies": {
-                "ms": "^2.1.1"
-            }
-        },
-        "node_modules/sockjs": {
-            "version": "0.3.24",
-            "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
-            "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==",
-            "dev": true,
-            "dependencies": {
-                "faye-websocket": "^0.11.3",
-                "uuid": "^8.3.2",
-                "websocket-driver": "^0.7.4"
-            }
-        },
-        "node_modules/sockjs-client": {
-            "version": "1.6.1",
-            "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.6.1.tgz",
-            "integrity": "sha512-2g0tjOR+fRs0amxENLi/q5TiJTqY+WXFOzb5UwXndlK6TO3U/mirZznpx6w34HVMoc3g7cY24yC/ZMIYnDlfkw==",
-            "dev": true,
-            "dependencies": {
-                "debug": "^3.2.7",
-                "eventsource": "^2.0.2",
-                "faye-websocket": "^0.11.4",
-                "inherits": "^2.0.4",
-                "url-parse": "^1.5.10"
-            },
-            "engines": {
-                "node": ">=12"
-            },
-            "funding": {
-                "url": "https://tidelift.com/funding/github/npm/sockjs-client"
-            }
-        },
-        "node_modules/sockjs-client/node_modules/debug": {
-            "version": "3.2.7",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
-            "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
-            "dev": true,
-            "dependencies": {
-                "ms": "^2.1.1"
-            }
-        },
-        "node_modules/sockjs/node_modules/uuid": {
-            "version": "8.3.2",
-            "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
-            "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
-            "dev": true,
-            "bin": {
-                "uuid": "dist/bin/uuid"
-            }
-        },
-        "node_modules/solr-node": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/solr-node/-/solr-node-1.2.1.tgz",
-            "integrity": "sha512-DN3+FSBgpJEgGTNddzS8tNb+ILSn5MLcsWf15G9rGxi/sROHbpcevdRSVx6s5/nz56c/5AnBTBZWak7IXWX97A==",
-            "dependencies": {
-                "@log4js-node/log4js-api": "^1.0.2",
-                "node-fetch": "^2.3.0",
-                "underscore": "^1.8.3"
-            },
-            "engines": {
-                "node": ">= 0.12.0"
-            }
-        },
-        "node_modules/solr-node/node_modules/node-fetch": {
-            "version": "2.6.7",
-            "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
-            "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
-            "dependencies": {
-                "whatwg-url": "^5.0.0"
-            },
-            "engines": {
-                "node": "4.x || >=6.0.0"
-            },
-            "peerDependencies": {
-                "encoding": "^0.1.0"
-            },
-            "peerDependenciesMeta": {
-                "encoding": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/source-map": {
-            "version": "0.5.7",
-            "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-            "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/source-map-resolve": {
-            "version": "0.5.3",
-            "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
-            "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
-            "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated",
-            "dependencies": {
-                "atob": "^2.1.2",
-                "decode-uri-component": "^0.2.0",
-                "resolve-url": "^0.2.1",
-                "source-map-url": "^0.4.0",
-                "urix": "^0.1.0"
-            }
-        },
-        "node_modules/source-map-support": {
-            "version": "0.5.21",
-            "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
-            "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
-            "dependencies": {
-                "buffer-from": "^1.0.0",
-                "source-map": "^0.6.0"
-            }
-        },
-        "node_modules/source-map-support/node_modules/source-map": {
-            "version": "0.6.1",
-            "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-            "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/source-map-url": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz",
-            "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==",
-            "deprecated": "See https://github.com/lydell/source-map-url#deprecated"
-        },
-        "node_modules/space-separated-tokens": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.1.tgz",
-            "integrity": "sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw==",
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/wooorm"
-            }
-        },
-        "node_modules/sparse-bitfield": {
-            "version": "3.0.3",
-            "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
-            "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
-            "optional": true,
-            "dependencies": {
-                "memory-pager": "^1.0.2"
-            }
-        },
-        "node_modules/spdx-correct": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
-            "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
-            "dependencies": {
-                "spdx-expression-parse": "^3.0.0",
-                "spdx-license-ids": "^3.0.0"
-            }
-        },
-        "node_modules/spdx-exceptions": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
-            "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A=="
-        },
-        "node_modules/spdx-expression-parse": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
-            "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
-            "dependencies": {
-                "spdx-exceptions": "^2.1.0",
-                "spdx-license-ids": "^3.0.0"
-            }
-        },
-        "node_modules/spdx-license-ids": {
-            "version": "3.0.11",
-            "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz",
-            "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g=="
-        },
-        "node_modules/spdy": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",
-            "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==",
-            "dev": true,
-            "dependencies": {
-                "debug": "^4.1.0",
-                "handle-thing": "^2.0.0",
-                "http-deceiver": "^1.2.7",
-                "select-hose": "^2.0.0",
-                "spdy-transport": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/spdy-transport": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz",
-            "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==",
-            "dev": true,
-            "dependencies": {
-                "debug": "^4.1.0",
-                "detect-node": "^2.0.4",
-                "hpack.js": "^2.1.6",
-                "obuf": "^1.1.2",
-                "readable-stream": "^3.0.6",
-                "wbuf": "^1.7.3"
-            }
-        },
-        "node_modules/spdy-transport/node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dev": true,
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/spdy-transport/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-            "dev": true
-        },
-        "node_modules/spdy/node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dev": true,
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/spdy/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-            "dev": true
-        },
-        "node_modules/split-on-first": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
-            "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/split-skip": {
-            "version": "0.0.2",
-            "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.2.tgz",
-            "integrity": "sha1-2J2Iu9L3Pka1FYqjcKVhIk6A1GE="
-        },
-        "node_modules/split-string": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
-            "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
-            "dependencies": {
-                "extend-shallow": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/sprintf-js": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
-            "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
-        },
-        "node_modules/sshpk": {
-            "version": "1.17.0",
-            "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
-            "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
-            "dependencies": {
-                "asn1": "~0.2.3",
-                "assert-plus": "^1.0.0",
-                "bcrypt-pbkdf": "^1.0.0",
-                "dashdash": "^1.12.0",
-                "ecc-jsbn": "~0.1.1",
-                "getpass": "^0.1.1",
-                "jsbn": "~0.1.0",
-                "safer-buffer": "^2.0.2",
-                "tweetnacl": "~0.14.0"
-            },
-            "bin": {
-                "sshpk-conv": "bin/sshpk-conv",
-                "sshpk-sign": "bin/sshpk-sign",
-                "sshpk-verify": "bin/sshpk-verify"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/ssri": {
-            "version": "5.3.0",
-            "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz",
-            "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==",
-            "dev": true,
-            "dependencies": {
-                "safe-buffer": "^5.1.1"
-            }
-        },
-        "node_modules/standard-error": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/standard-error/-/standard-error-1.1.0.tgz",
-            "integrity": "sha1-I+UWj6HAggGJ5YEnAaeQWFENDTQ="
-        },
-        "node_modules/standard-http-error": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/standard-http-error/-/standard-http-error-2.0.1.tgz",
-            "integrity": "sha1-+K6RcuPO+cs40ucIShkl9Xp8NL0=",
-            "dependencies": {
-                "standard-error": ">= 1.1.0 < 2"
-            }
-        },
-        "node_modules/static-extend": {
-            "version": "0.1.2",
-            "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
-            "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
-            "dependencies": {
-                "define-property": "^0.2.5",
-                "object-copy": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/static-extend/node_modules/define-property": {
-            "version": "0.2.5",
-            "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-            "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-            "dependencies": {
-                "is-descriptor": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/statuses": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
-            "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/stdout-stream": {
-            "version": "1.4.1",
-            "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz",
-            "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==",
-            "dependencies": {
-                "readable-stream": "^2.0.1"
-            }
-        },
-        "node_modules/stdout-stream/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/stealthy-require": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
-            "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/stream-browserify": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz",
-            "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==",
-            "dependencies": {
-                "inherits": "~2.0.4",
-                "readable-stream": "^3.5.0"
-            }
-        },
-        "node_modules/stream-each": {
-            "version": "1.2.3",
-            "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
-            "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==",
-            "dev": true,
-            "dependencies": {
-                "end-of-stream": "^1.1.0",
-                "stream-shift": "^1.0.0"
-            }
-        },
-        "node_modules/stream-parser": {
-            "version": "0.3.1",
-            "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz",
-            "integrity": "sha1-FhhUhpRCACGhGC/wrxkRwSl2F3M=",
-            "dependencies": {
-                "debug": "2"
-            }
-        },
-        "node_modules/stream-parser/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/stream-parser/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
-        },
-        "node_modules/stream-shift": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
-            "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
-            "dev": true
-        },
-        "node_modules/strict-uri-encode": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
-            "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/string_decoder": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-            "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-            "dependencies": {
-                "safe-buffer": "~5.1.0"
-            }
-        },
-        "node_modules/string-width": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
-            "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
-            "dependencies": {
-                "is-fullwidth-code-point": "^2.0.0",
-                "strip-ansi": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/string.prototype.codepointat": {
-            "version": "0.2.1",
-            "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz",
-            "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg=="
-        },
-        "node_modules/string.prototype.matchall": {
-            "version": "4.0.7",
-            "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz",
-            "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.3",
-                "es-abstract": "^1.19.1",
-                "get-intrinsic": "^1.1.1",
-                "has-symbols": "^1.0.3",
-                "internal-slot": "^1.0.3",
-                "regexp.prototype.flags": "^1.4.1",
-                "side-channel": "^1.0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/string.prototype.trimend": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz",
-            "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.4",
-                "es-abstract": "^1.19.5"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/string.prototype.trimstart": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz",
-            "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.4",
-                "es-abstract": "^1.19.5"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/stringify-parameters": {
-            "version": "0.0.4",
-            "resolved": "https://registry.npmjs.org/stringify-parameters/-/stringify-parameters-0.0.4.tgz",
-            "integrity": "sha512-H3L90ERn5UPtkpO8eugnKcLgpIVlvTyUTrcLGm607AV5JDH6z0GymtNLr3gjGlP6I6NB/mxNX9QpY6jEQGLPdQ==",
-            "dependencies": {
-                "magicli": "0.0.5",
-                "unpack-string": "0.0.2"
-            },
-            "bin": {
-                "stringify-parameters": "bin/cli.js"
-            }
-        },
-        "node_modules/stringify-parameters/node_modules/commander": {
-            "version": "2.20.3",
-            "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-            "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
-        },
-        "node_modules/stringify-parameters/node_modules/magicli": {
-            "version": "0.0.5",
-            "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-            "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
-            "dependencies": {
-                "commander": "^2.9.0",
-                "get-stdin": "^5.0.1",
-                "inspect-function": "^0.2.1",
-                "pipe-functions": "^1.2.0"
-            }
-        },
-        "node_modules/strip-ansi": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
-            "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
-            "dependencies": {
-                "ansi-regex": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/strip-bom": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
-            "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
-            "dependencies": {
-                "is-utf8": "^0.2.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/strip-eof": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
-            "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/strip-indent": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
-            "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
-            "dependencies": {
-                "get-stdin": "^4.0.1"
-            },
-            "bin": {
-                "strip-indent": "cli.js"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/strip-indent/node_modules/get-stdin": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
-            "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/strip-json-comments": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
-            "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/style-loader": {
-            "version": "0.23.1",
-            "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz",
-            "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==",
-            "dev": true,
-            "dependencies": {
-                "loader-utils": "^1.1.0",
-                "schema-utils": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.12.0"
-            }
-        },
-        "node_modules/style-to-object": {
-            "version": "0.3.0",
-            "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz",
-            "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==",
-            "dependencies": {
-                "inline-style-parser": "0.1.1"
-            }
-        },
-        "node_modules/styled-components": {
-            "version": "4.4.1",
-            "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-4.4.1.tgz",
-            "integrity": "sha512-RNqj14kYzw++6Sr38n7197xG33ipEOktGElty4I70IKzQF1jzaD1U4xQ+Ny/i03UUhHlC5NWEO+d8olRCDji6g==",
-            "hasInstallScript": true,
-            "dependencies": {
-                "@babel/helper-module-imports": "^7.0.0",
-                "@babel/traverse": "^7.0.0",
-                "@emotion/is-prop-valid": "^0.8.1",
-                "@emotion/unitless": "^0.7.0",
-                "babel-plugin-styled-components": ">= 1",
-                "css-to-react-native": "^2.2.2",
-                "memoize-one": "^5.0.0",
-                "merge-anything": "^2.2.4",
-                "prop-types": "^15.5.4",
-                "react-is": "^16.6.0",
-                "stylis": "^3.5.0",
-                "stylis-rule-sheet": "^0.0.10",
-                "supports-color": "^5.5.0"
-            },
-            "peerDependencies": {
-                "react": ">= 16.3.0",
-                "react-dom": ">= 16.3.0"
-            }
-        },
-        "node_modules/styled-components/node_modules/@emotion/is-prop-valid": {
-            "version": "0.8.8",
-            "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
-            "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
-            "dependencies": {
-                "@emotion/memoize": "0.7.4"
-            }
-        },
-        "node_modules/styled-components/node_modules/stylis": {
-            "version": "3.5.4",
-            "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz",
-            "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q=="
-        },
-        "node_modules/stylis": {
-            "version": "4.0.13",
-            "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
-            "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
-        },
-        "node_modules/stylis-rule-sheet": {
-            "version": "0.0.10",
-            "resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz",
-            "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==",
-            "peerDependencies": {
-                "stylis": "^3.5.0"
-            }
-        },
-        "node_modules/supercluster": {
-            "version": "7.1.5",
-            "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.1.5.tgz",
-            "integrity": "sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==",
-            "dependencies": {
-                "kdbush": "^3.0.0"
-            }
-        },
-        "node_modules/supports-color": {
-            "version": "5.5.0",
-            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-            "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-            "dependencies": {
-                "has-flag": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/supports-preserve-symlinks-flag": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
-            "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/symbol-observable": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
-            "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/symbol-tree": {
-            "version": "3.2.4",
-            "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
-            "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
-            "dev": true
-        },
-        "node_modules/table": {
-            "version": "5.4.6",
-            "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
-            "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
-            "dev": true,
-            "dependencies": {
-                "ajv": "^6.10.2",
-                "lodash": "^4.17.14",
-                "slice-ansi": "^2.1.0",
-                "string-width": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/table-layout": {
-            "version": "0.4.5",
-            "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz",
-            "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==",
-            "dependencies": {
-                "array-back": "^2.0.0",
-                "deep-extend": "~0.6.0",
-                "lodash.padend": "^4.6.1",
-                "typical": "^2.6.1",
-                "wordwrapjs": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/table/node_modules/ansi-regex": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
-            "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/table/node_modules/string-width": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-            "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
-            "dev": true,
-            "dependencies": {
-                "emoji-regex": "^7.0.1",
-                "is-fullwidth-code-point": "^2.0.0",
-                "strip-ansi": "^5.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/table/node_modules/strip-ansi": {
-            "version": "5.2.0",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-            "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
-            "dev": true,
-            "dependencies": {
-                "ansi-regex": "^4.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/tapable": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
-            "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/tar": {
-            "version": "6.1.11",
-            "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
-            "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
-            "dependencies": {
-                "chownr": "^2.0.0",
-                "fs-minipass": "^2.0.0",
-                "minipass": "^3.0.0",
-                "minizlib": "^2.1.1",
-                "mkdirp": "^1.0.3",
-                "yallist": "^4.0.0"
-            },
-            "engines": {
-                "node": ">= 10"
-            }
-        },
-        "node_modules/tar-fs": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
-            "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
-            "dependencies": {
-                "chownr": "^1.1.1",
-                "mkdirp-classic": "^0.5.2",
-                "pump": "^3.0.0",
-                "tar-stream": "^2.1.4"
-            }
-        },
-        "node_modules/tar-fs/node_modules/chownr": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
-            "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
-        },
-        "node_modules/tar-stream": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
-            "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
-            "dependencies": {
-                "bl": "^4.0.3",
-                "end-of-stream": "^1.4.1",
-                "fs-constants": "^1.0.0",
-                "inherits": "^2.0.3",
-                "readable-stream": "^3.1.1"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/tar/node_modules/mkdirp": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
-            "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
-            "bin": {
-                "mkdirp": "bin/cmd.js"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/temp-dir": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz",
-            "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/tempy": {
-            "version": "0.2.1",
-            "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.2.1.tgz",
-            "integrity": "sha512-LB83o9bfZGrntdqPuRdanIVCPReam9SOZKW0fOy5I9X3A854GGWi0tjCqoXEk84XIEYBc/x9Hq3EFop/H5wJaw==",
-            "dependencies": {
-                "temp-dir": "^1.0.0",
-                "unique-string": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/term-size": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
-            "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=",
-            "dependencies": {
-                "execa": "^0.7.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/terser": {
-            "version": "5.14.0",
-            "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.0.tgz",
-            "integrity": "sha512-JC6qfIEkPBd9j1SMO3Pfn+A6w2kQV54tv+ABQLgZr7dA3k/DL/OBoYSWxzVpZev3J+bUHXfr55L8Mox7AaNo6g==",
-            "dependencies": {
-                "@jridgewell/source-map": "^0.3.2",
-                "acorn": "^8.5.0",
-                "commander": "^2.20.0",
-                "source-map-support": "~0.5.20"
-            },
-            "bin": {
-                "terser": "bin/terser"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/terser-webpack-plugin": {
-            "version": "5.3.3",
-            "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz",
-            "integrity": "sha512-Fx60G5HNYknNTNQnzQ1VePRuu89ZVYWfjRAeT5rITuCY/1b08s49e5kSQwHDirKZWuoKOBRFS98EUUoZ9kLEwQ==",
-            "dependencies": {
-                "@jridgewell/trace-mapping": "^0.3.7",
-                "jest-worker": "^27.4.5",
-                "schema-utils": "^3.1.1",
-                "serialize-javascript": "^6.0.0",
-                "terser": "^5.7.2"
-            },
-            "engines": {
-                "node": ">= 10.13.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/webpack"
-            },
-            "peerDependencies": {
-                "webpack": "^5.1.0"
-            },
-            "peerDependenciesMeta": {
-                "@swc/core": {
-                    "optional": true
-                },
-                "esbuild": {
-                    "optional": true
-                },
-                "uglify-js": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/terser-webpack-plugin/node_modules/schema-utils": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
-            "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
-            "dependencies": {
-                "@types/json-schema": "^7.0.8",
-                "ajv": "^6.12.5",
-                "ajv-keywords": "^3.5.2"
-            },
-            "engines": {
-                "node": ">= 10.13.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/webpack"
-            }
-        },
-        "node_modules/terser/node_modules/commander": {
-            "version": "2.20.3",
-            "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-            "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
-        },
-        "node_modules/text-table": {
-            "version": "0.2.0",
-            "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
-            "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
-            "dev": true
-        },
-        "node_modules/textarea-caret": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/textarea-caret/-/textarea-caret-3.1.0.tgz",
-            "integrity": "sha512-cXAvzO9pP5CGa6NKx0WYHl+8CHKZs8byMkt3PCJBCmq2a34YA9pO1NrQET5pzeqnBjBdToF5No4rrmkDUgQC2Q=="
-        },
-        "node_modules/three": {
-            "version": "0.127.0",
-            "resolved": "https://registry.npmjs.org/three/-/three-0.127.0.tgz",
-            "integrity": "sha512-wtgrn+mhYUbobxT7QN3GPdu3SRpSBQvwY6uOzLChWS7QE//f7paDU/+wlzbg+ngeIvBBqjBHSRuywTh8A99Jng=="
-        },
-        "node_modules/through": {
-            "version": "2.3.8",
-            "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
-            "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
-        },
-        "node_modules/through2": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
-            "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
-            "dev": true,
-            "dependencies": {
-                "readable-stream": "~2.3.6",
-                "xtend": "~4.0.1"
-            }
-        },
-        "node_modules/through2/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dev": true,
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/thunky": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
-            "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
-            "dev": true
-        },
-        "node_modules/timed-out": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
-            "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/tiny-emitter": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
-            "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
-        },
-        "node_modules/tiny-inflate": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
-            "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="
-        },
-        "node_modules/tiny-invariant": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz",
-            "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg=="
-        },
-        "node_modules/tiny-warning": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
-            "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
-        },
-        "node_modules/tinycolor2": {
-            "version": "1.4.2",
-            "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz",
-            "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==",
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/tmp": {
-            "version": "0.0.33",
-            "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
-            "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
-            "dev": true,
-            "dependencies": {
-                "os-tmpdir": "~1.0.2"
-            },
-            "engines": {
-                "node": ">=0.6.0"
-            }
-        },
-        "node_modules/to-array": {
-            "version": "0.1.4",
-            "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
-            "integrity": "sha512-LhVdShQD/4Mk4zXNroIQZJC+Ap3zgLcDuwEdcmLv9CCO73NWockQDwyUnW/m8VX/EElfL6FcYx7EeutN4HJA6A=="
-        },
-        "node_modules/to-fast-properties": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
-            "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/to-object-path": {
-            "version": "0.3.0",
-            "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
-            "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
-            "dependencies": {
-                "kind-of": "^3.0.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/to-object-path/node_modules/is-buffer": {
-            "version": "1.1.6",
-            "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-            "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
-        },
-        "node_modules/to-object-path/node_modules/kind-of": {
-            "version": "3.2.2",
-            "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-            "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-            "dependencies": {
-                "is-buffer": "^1.1.5"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/to-regex": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
-            "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
-            "dependencies": {
-                "define-property": "^2.0.2",
-                "extend-shallow": "^3.0.2",
-                "regex-not": "^1.0.2",
-                "safe-regex": "^1.1.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/to-regex-range": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
-            "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
-            "dependencies": {
-                "is-number": "^3.0.0",
-                "repeat-string": "^1.6.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/toidentifier": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
-            "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
-            "engines": {
-                "node": ">=0.6"
-            }
-        },
-        "node_modules/token-stream": {
-            "version": "0.0.1",
-            "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz",
-            "integrity": "sha1-zu78cXp2xDFvEm0LnbqlXX598Bo="
-        },
-        "node_modules/touch": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
-            "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
-            "dependencies": {
-                "nopt": "~1.0.10"
-            },
-            "bin": {
-                "nodetouch": "bin/nodetouch.js"
-            }
-        },
-        "node_modules/touch/node_modules/nopt": {
-            "version": "1.0.10",
-            "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
-            "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
-            "dependencies": {
-                "abbrev": "1"
-            },
-            "bin": {
-                "nopt": "bin/nopt.js"
-            },
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/tough-cookie": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
-            "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==",
-            "dependencies": {
-                "psl": "^1.1.33",
-                "punycode": "^2.1.1",
-                "universalify": "^0.1.2"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/tr46": {
-            "version": "0.0.3",
-            "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
-            "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
-        },
-        "node_modules/translate-google-api": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/translate-google-api/-/translate-google-api-1.0.4.tgz",
-            "integrity": "sha512-KVXmo4+64/H1vIbnzf2zNiJ2JLeEB3jrEnNRP2EFNAGNqna/5bmw/Cps3pCHu0n3BzTOoWh9u6wFvrRYdzQ6Iw==",
-            "dependencies": {
-                "axios": "^0.20.0"
-            }
-        },
-        "node_modules/translate-google-api/node_modules/axios": {
-            "version": "0.20.0",
-            "resolved": "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz",
-            "integrity": "sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==",
-            "deprecated": "Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410",
-            "dependencies": {
-                "follow-redirects": "^1.10.0"
-            }
-        },
-        "node_modules/translate-google-api/node_modules/follow-redirects": {
-            "version": "1.15.1",
-            "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
-            "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
-            "funding": [
-                {
-                    "type": "individual",
-                    "url": "https://github.com/sponsors/RubenVerborgh"
-                }
-            ],
-            "engines": {
-                "node": ">=4.0"
-            },
-            "peerDependenciesMeta": {
-                "debug": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/traverse-chain": {
-            "version": "0.1.0",
-            "resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz",
-            "integrity": "sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE="
-        },
-        "node_modules/tree-kill": {
-            "version": "1.2.2",
-            "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
-            "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
-            "dev": true,
-            "bin": {
-                "tree-kill": "cli.js"
-            }
-        },
-        "node_modules/trim-lines": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
-            "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/wooorm"
-            }
-        },
-        "node_modules/trim-newlines": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
-            "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/trough": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz",
-            "integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==",
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/wooorm"
-            }
-        },
-        "node_modules/true-case-path": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz",
-            "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==",
-            "dependencies": {
-                "glob": "^7.1.2"
-            }
-        },
-        "node_modules/tryit": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz",
-            "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics="
-        },
-        "node_modules/ts-loader": {
-            "version": "5.4.5",
-            "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.5.tgz",
-            "integrity": "sha512-XYsjfnRQCBum9AMRZpk2rTYSVpdZBpZK+kDh0TeT3kxmQNBDVIeUjdPjY5RZry4eIAb8XHc4gYSUiUWPYvzSRw==",
-            "dev": true,
-            "dependencies": {
-                "chalk": "^2.3.0",
-                "enhanced-resolve": "^4.0.0",
-                "loader-utils": "^1.0.2",
-                "micromatch": "^3.1.4",
-                "semver": "^5.0.1"
-            },
-            "engines": {
-                "node": ">=6.11.5"
-            },
-            "peerDependencies": {
-                "typescript": "*"
-            }
-        },
-        "node_modules/ts-loader/node_modules/enhanced-resolve": {
-            "version": "4.5.0",
-            "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz",
-            "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==",
-            "dev": true,
-            "dependencies": {
-                "graceful-fs": "^4.1.2",
-                "memory-fs": "^0.5.0",
-                "tapable": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/ts-loader/node_modules/tapable": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
-            "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/ts-node": {
-            "version": "10.9.1",
-            "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
-            "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
-            "dev": true,
-            "dependencies": {
-                "@cspotcode/source-map-support": "^0.8.0",
-                "@tsconfig/node10": "^1.0.7",
-                "@tsconfig/node12": "^1.0.7",
-                "@tsconfig/node14": "^1.0.0",
-                "@tsconfig/node16": "^1.0.2",
-                "acorn": "^8.4.1",
-                "acorn-walk": "^8.1.1",
-                "arg": "^4.1.0",
-                "create-require": "^1.1.0",
-                "diff": "^4.0.1",
-                "make-error": "^1.1.1",
-                "v8-compile-cache-lib": "^3.0.1",
-                "yn": "3.1.1"
-            },
-            "bin": {
-                "ts-node": "dist/bin.js",
-                "ts-node-cwd": "dist/bin-cwd.js",
-                "ts-node-esm": "dist/bin-esm.js",
-                "ts-node-script": "dist/bin-script.js",
-                "ts-node-transpile-only": "dist/bin-transpile.js",
-                "ts-script": "dist/bin-script-deprecated.js"
-            },
-            "peerDependencies": {
-                "@swc/core": ">=1.2.50",
-                "@swc/wasm": ">=1.2.50",
-                "@types/node": "*",
-                "typescript": ">=2.7"
-            },
-            "peerDependenciesMeta": {
-                "@swc/core": {
-                    "optional": true
-                },
-                "@swc/wasm": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/ts-node-dev": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz",
-            "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==",
-            "dev": true,
-            "dependencies": {
-                "chokidar": "^3.5.1",
-                "dynamic-dedupe": "^0.3.0",
-                "minimist": "^1.2.6",
-                "mkdirp": "^1.0.4",
-                "resolve": "^1.0.0",
-                "rimraf": "^2.6.1",
-                "source-map-support": "^0.5.12",
-                "tree-kill": "^1.2.2",
-                "ts-node": "^10.4.0",
-                "tsconfig": "^7.0.0"
-            },
-            "bin": {
-                "ts-node-dev": "lib/bin.js",
-                "tsnd": "lib/bin.js"
-            },
-            "engines": {
-                "node": ">=0.8.0"
-            },
-            "peerDependencies": {
-                "node-notifier": "*",
-                "typescript": "*"
-            },
-            "peerDependenciesMeta": {
-                "node-notifier": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/ts-node-dev/node_modules/anymatch": {
-            "version": "3.1.3",
-            "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
-            "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
-            "dev": true,
-            "dependencies": {
-                "normalize-path": "^3.0.0",
-                "picomatch": "^2.0.4"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/ts-node-dev/node_modules/binary-extensions": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
-            "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/ts-node-dev/node_modules/braces": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-            "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
-            "dev": true,
-            "dependencies": {
-                "fill-range": "^7.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/ts-node-dev/node_modules/chokidar": {
-            "version": "3.5.3",
-            "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
-            "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
-            "dev": true,
-            "funding": [
-                {
-                    "type": "individual",
-                    "url": "https://paulmillr.com/funding/"
-                }
-            ],
-            "dependencies": {
-                "anymatch": "~3.1.2",
-                "braces": "~3.0.2",
-                "glob-parent": "~5.1.2",
-                "is-binary-path": "~2.1.0",
-                "is-glob": "~4.0.1",
-                "normalize-path": "~3.0.0",
-                "readdirp": "~3.6.0"
-            },
-            "engines": {
-                "node": ">= 8.10.0"
-            },
-            "optionalDependencies": {
-                "fsevents": "~2.3.2"
-            }
-        },
-        "node_modules/ts-node-dev/node_modules/fill-range": {
-            "version": "7.0.1",
-            "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-            "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
-            "dev": true,
-            "dependencies": {
-                "to-regex-range": "^5.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/ts-node-dev/node_modules/fsevents": {
-            "version": "2.3.2",
-            "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
-            "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
-            "dev": true,
-            "hasInstallScript": true,
-            "optional": true,
-            "os": [
-                "darwin"
-            ],
-            "engines": {
-                "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
-            }
-        },
-        "node_modules/ts-node-dev/node_modules/glob-parent": {
-            "version": "5.1.2",
-            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-            "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-            "dev": true,
-            "dependencies": {
-                "is-glob": "^4.0.1"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/ts-node-dev/node_modules/is-binary-path": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
-            "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
-            "dev": true,
-            "dependencies": {
-                "binary-extensions": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/ts-node-dev/node_modules/is-number": {
-            "version": "7.0.0",
-            "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
-            "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.12.0"
-            }
-        },
-        "node_modules/ts-node-dev/node_modules/mkdirp": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
-            "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
-            "dev": true,
-            "bin": {
-                "mkdirp": "bin/cmd.js"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/ts-node-dev/node_modules/readdirp": {
-            "version": "3.6.0",
-            "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
-            "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-            "dev": true,
-            "dependencies": {
-                "picomatch": "^2.2.1"
-            },
-            "engines": {
-                "node": ">=8.10.0"
-            }
-        },
-        "node_modules/ts-node-dev/node_modules/rimraf": {
-            "version": "2.7.1",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-            "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-            "dev": true,
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            }
-        },
-        "node_modules/ts-node-dev/node_modules/to-regex-range": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-            "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-            "dev": true,
-            "dependencies": {
-                "is-number": "^7.0.0"
-            },
-            "engines": {
-                "node": ">=8.0"
-            }
-        },
-        "node_modules/ts-node/node_modules/acorn-walk": {
-            "version": "8.2.0",
-            "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
-            "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/ts-node/node_modules/diff": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
-            "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.3.1"
-            }
-        },
-        "node_modules/tsconfig": {
-            "version": "7.0.0",
-            "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
-            "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
-            "dev": true,
-            "dependencies": {
-                "@types/strip-bom": "^3.0.0",
-                "@types/strip-json-comments": "0.0.30",
-                "strip-bom": "^3.0.0",
-                "strip-json-comments": "^2.0.0"
-            }
-        },
-        "node_modules/tsconfig-paths": {
-            "version": "3.14.1",
-            "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
-            "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==",
-            "dev": true,
-            "dependencies": {
-                "@types/json5": "^0.0.29",
-                "json5": "^1.0.1",
-                "minimist": "^1.2.6",
-                "strip-bom": "^3.0.0"
-            }
-        },
-        "node_modules/tsconfig-paths/node_modules/strip-bom": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
-            "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/tsconfig/node_modules/strip-bom": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
-            "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/tslib": {
-            "version": "2.4.0",
-            "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
-            "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
-        },
-        "node_modules/tslint": {
-            "version": "5.20.1",
-            "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz",
-            "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==",
-            "dev": true,
-            "dependencies": {
-                "@babel/code-frame": "^7.0.0",
-                "builtin-modules": "^1.1.1",
-                "chalk": "^2.3.0",
-                "commander": "^2.12.1",
-                "diff": "^4.0.1",
-                "glob": "^7.1.1",
-                "js-yaml": "^3.13.1",
-                "minimatch": "^3.0.4",
-                "mkdirp": "^0.5.1",
-                "resolve": "^1.3.2",
-                "semver": "^5.3.0",
-                "tslib": "^1.8.0",
-                "tsutils": "^2.29.0"
-            },
-            "bin": {
-                "tslint": "bin/tslint"
-            },
-            "engines": {
-                "node": ">=4.8.0"
-            },
-            "peerDependencies": {
-                "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev"
-            }
-        },
-        "node_modules/tslint-loader": {
-            "version": "3.6.0",
-            "resolved": "https://registry.npmjs.org/tslint-loader/-/tslint-loader-3.6.0.tgz",
-            "integrity": "sha512-Me9Qf/87BOfCY8uJJw+J7VMF4U8WiMXKLhKKKugMydF0xMhMOt9wo2mjYTNhwbF9H7SHh8PAIwRG8roisTNekQ==",
-            "deprecated": "TSLint is deprecated. As such migrate from tslint-loader to eslint-loader.",
-            "dev": true,
-            "dependencies": {
-                "loader-utils": "^1.0.2",
-                "mkdirp": "^0.5.1",
-                "object-assign": "^4.1.1",
-                "rimraf": "^2.4.4",
-                "semver": "^5.3.0"
-            },
-            "peerDependencies": {
-                "tslint": ">=4.0.0"
-            }
-        },
-        "node_modules/tslint-loader/node_modules/rimraf": {
-            "version": "2.7.1",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-            "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-            "dev": true,
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            }
-        },
-        "node_modules/tslint/node_modules/builtin-modules": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
-            "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/tslint/node_modules/commander": {
-            "version": "2.20.3",
-            "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-            "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
-            "dev": true
-        },
-        "node_modules/tslint/node_modules/diff": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
-            "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.3.1"
-            }
-        },
-        "node_modules/tslint/node_modules/tslib": {
-            "version": "1.14.1",
-            "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-            "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
-            "dev": true
-        },
-        "node_modules/tsscmp": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
-            "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==",
-            "engines": {
-                "node": ">=0.6.x"
-            }
-        },
-        "node_modules/tsutils": {
-            "version": "2.29.0",
-            "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
-            "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
-            "dev": true,
-            "dependencies": {
-                "tslib": "^1.8.1"
-            },
-            "peerDependencies": {
-                "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev"
-            }
-        },
-        "node_modules/tsutils/node_modules/tslib": {
-            "version": "1.14.1",
-            "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-            "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
-            "dev": true
-        },
-        "node_modules/tunnel-agent": {
-            "version": "0.6.0",
-            "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
-            "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
-            "dependencies": {
-                "safe-buffer": "^5.0.1"
-            },
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/tweetnacl": {
-            "version": "0.14.5",
-            "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
-            "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
-        },
-        "node_modules/type-check": {
-            "version": "0.3.2",
-            "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
-            "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
-            "dev": true,
-            "dependencies": {
-                "prelude-ls": "~1.1.2"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/type-detect": {
-            "version": "4.0.8",
-            "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
-            "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/type-fest": {
-            "version": "0.20.2",
-            "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
-            "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/type-is": {
-            "version": "1.6.18",
-            "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
-            "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
-            "dependencies": {
-                "media-typer": "0.3.0",
-                "mime-types": "~2.1.24"
-            },
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/typed-styles": {
-            "version": "0.0.7",
-            "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz",
-            "integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q=="
-        },
-        "node_modules/typedarray": {
-            "version": "0.0.6",
-            "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
-            "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
-        },
-        "node_modules/typescript": {
-            "version": "4.7.4",
-            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
-            "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
-            "bin": {
-                "tsc": "bin/tsc",
-                "tsserver": "bin/tsserver"
-            },
-            "engines": {
-                "node": ">=4.2.0"
-            }
-        },
-        "node_modules/typescript-collections": {
-            "version": "1.3.3",
-            "resolved": "https://registry.npmjs.org/typescript-collections/-/typescript-collections-1.3.3.tgz",
-            "integrity": "sha512-7sI4e/bZijOzyURng88oOFZCISQPTHozfE2sUu5AviFYk5QV7fYGb6YiDl+vKjF/pICA354JImBImL9XJWUvdQ=="
-        },
-        "node_modules/typescript-language-server": {
-            "version": "0.4.0",
-            "resolved": "https://registry.npmjs.org/typescript-language-server/-/typescript-language-server-0.4.0.tgz",
-            "integrity": "sha512-K8jNOmDFn+QfrCh8ujby2pGDs5rpjYZQn+zvQnf42rxG4IHbfw5CHoMvbGkWPK/J5Gw8/l5K3i03kVZC2IBElg==",
-            "dependencies": {
-                "command-exists": "1.2.6",
-                "commander": "^2.11.0",
-                "fs-extra": "^7.0.0",
-                "p-debounce": "^1.0.0",
-                "tempy": "^0.2.1",
-                "vscode-languageserver": "^5.3.0-next",
-                "vscode-uri": "^1.0.5"
-            },
-            "bin": {
-                "typescript-language-server": "lib/cli.js"
-            }
-        },
-        "node_modules/typescript-language-server/node_modules/commander": {
-            "version": "2.20.3",
-            "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-            "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
-        },
-        "node_modules/typescript-language-server/node_modules/fs-extra": {
-            "version": "7.0.1",
-            "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
-            "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
-            "dependencies": {
-                "graceful-fs": "^4.1.2",
-                "jsonfile": "^4.0.0",
-                "universalify": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=6 <7 || >=8"
-            }
-        },
-        "node_modules/typescript-language-server/node_modules/jsonfile": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
-            "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
-            "optionalDependencies": {
-                "graceful-fs": "^4.1.6"
-            }
-        },
-        "node_modules/typical": {
-            "version": "2.6.1",
-            "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz",
-            "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0="
-        },
-        "node_modules/ua-parser-js": {
-            "version": "0.7.31",
-            "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz",
-            "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==",
-            "funding": [
-                {
-                    "type": "opencollective",
-                    "url": "https://opencollective.com/ua-parser-js"
-                },
-                {
-                    "type": "paypal",
-                    "url": "https://paypal.me/faisalman"
-                }
-            ],
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/uglify-js": {
-            "version": "2.8.29",
-            "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
-            "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
-            "dependencies": {
-                "source-map": "~0.5.1",
-                "yargs": "~3.10.0"
-            },
-            "bin": {
-                "uglifyjs": "bin/uglifyjs"
-            },
-            "engines": {
-                "node": ">=0.8.0"
-            },
-            "optionalDependencies": {
-                "uglify-to-browserify": "~1.0.0"
-            }
-        },
-        "node_modules/uglify-js/node_modules/camelcase": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
-            "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/uglify-js/node_modules/cliui": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
-            "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
-            "dependencies": {
-                "center-align": "^0.1.1",
-                "right-align": "^0.1.1",
-                "wordwrap": "0.0.2"
-            }
-        },
-        "node_modules/uglify-js/node_modules/yargs": {
-            "version": "3.10.0",
-            "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
-            "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
-            "dependencies": {
-                "camelcase": "^1.0.2",
-                "cliui": "^2.1.0",
-                "decamelize": "^1.0.0",
-                "window-size": "0.1.0"
-            }
-        },
-        "node_modules/uglify-to-browserify": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
-            "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
-            "optional": true
-        },
-        "node_modules/uid-safe": {
-            "version": "2.1.5",
-            "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
-            "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
-            "dependencies": {
-                "random-bytes": "~1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/uid2": {
-            "version": "0.0.4",
-            "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz",
-            "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA=="
-        },
-        "node_modules/unbox-primitive": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
-            "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "has-bigints": "^1.0.2",
-                "has-symbols": "^1.0.3",
-                "which-boxed-primitive": "^1.0.2"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/unbzip2-stream": {
-            "version": "1.4.3",
-            "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
-            "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
-            "dependencies": {
-                "buffer": "^5.2.1",
-                "through": "^2.3.8"
-            }
-        },
-        "node_modules/undefsafe": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
-            "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA=="
-        },
-        "node_modules/underscore": {
-            "version": "1.13.4",
-            "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.4.tgz",
-            "integrity": "sha512-BQFnUDuAQ4Yf/cYY5LNrK9NCJFKriaRbD9uR1fTeXnBeoa97W0i41qkZfGO9pSo8I5KzjAcSY2XYtdf0oKd7KQ=="
-        },
-        "node_modules/unicode-trie": {
-            "version": "0.3.1",
-            "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-0.3.1.tgz",
-            "integrity": "sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU=",
-            "dependencies": {
-                "pako": "^0.2.5",
-                "tiny-inflate": "^1.0.0"
-            }
-        },
-        "node_modules/unicode-trie/node_modules/pako": {
-            "version": "0.2.9",
-            "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
-            "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU="
-        },
-        "node_modules/unified": {
-            "version": "10.1.2",
-            "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz",
-            "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==",
-            "dependencies": {
-                "@types/unist": "^2.0.0",
-                "bail": "^2.0.0",
-                "extend": "^3.0.0",
-                "is-buffer": "^2.0.0",
-                "is-plain-obj": "^4.0.0",
-                "trough": "^2.0.0",
-                "vfile": "^5.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/union-value": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
-            "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
-            "dependencies": {
-                "arr-union": "^3.1.0",
-                "get-value": "^2.0.6",
-                "is-extendable": "^0.1.1",
-                "set-value": "^2.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/unique-filename": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
-            "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
-            "dev": true,
-            "dependencies": {
-                "unique-slug": "^2.0.0"
-            }
-        },
-        "node_modules/unique-slug": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
-            "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
-            "dev": true,
-            "dependencies": {
-                "imurmurhash": "^0.1.4"
-            }
-        },
-        "node_modules/unique-string": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",
-            "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=",
-            "dependencies": {
-                "crypto-random-string": "^1.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/unist-builder": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-3.0.0.tgz",
-            "integrity": "sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ==",
-            "dependencies": {
-                "@types/unist": "^2.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/unist-util-generated": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.0.tgz",
-            "integrity": "sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw==",
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/unist-util-is": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.1.1.tgz",
-            "integrity": "sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==",
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/unist-util-position": {
-            "version": "4.0.3",
-            "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.3.tgz",
-            "integrity": "sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ==",
-            "dependencies": {
-                "@types/unist": "^2.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/unist-util-stringify-position": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.2.tgz",
-            "integrity": "sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg==",
-            "dependencies": {
-                "@types/unist": "^2.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/unist-util-visit": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.0.tgz",
-            "integrity": "sha512-n7lyhFKJfVZ9MnKtqbsqkQEk5P1KShj0+//V7mAcoI6bpbUjh3C/OG8HVD+pBihfh6Ovl01m8dkcv9HNqYajmQ==",
-            "dependencies": {
-                "@types/unist": "^2.0.0",
-                "unist-util-is": "^5.0.0",
-                "unist-util-visit-parents": "^5.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/unist-util-visit-parents": {
-            "version": "5.1.0",
-            "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.0.tgz",
-            "integrity": "sha512-y+QVLcY5eR/YVpqDsLf/xh9R3Q2Y4HxkZTp7ViLDU6WtJCEcPmRzW1gpdWDCDIqIlhuPDXOgttqPlykrHYDekg==",
-            "dependencies": {
-                "@types/unist": "^2.0.0",
-                "unist-util-is": "^5.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/universal-user-agent": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
-            "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
-        },
-        "node_modules/universalify": {
-            "version": "0.1.2",
-            "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
-            "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
-            "engines": {
-                "node": ">= 4.0.0"
-            }
-        },
-        "node_modules/unorm": {
-            "version": "1.6.0",
-            "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz",
-            "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==",
-            "engines": {
-                "node": ">= 0.4.0"
-            }
-        },
-        "node_modules/unpack-string": {
-            "version": "0.0.2",
-            "resolved": "https://registry.npmjs.org/unpack-string/-/unpack-string-0.0.2.tgz",
-            "integrity": "sha1-MC7PCCOLATm9Q0pNf9Z83zPKJ10="
-        },
-        "node_modules/unpipe": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
-            "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/unset-value": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
-            "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
-            "dependencies": {
-                "has-value": "^0.3.1",
-                "isobject": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/unset-value/node_modules/has-value": {
-            "version": "0.3.1",
-            "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
-            "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
-            "dependencies": {
-                "get-value": "^2.0.3",
-                "has-values": "^0.1.4",
-                "isobject": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/unset-value/node_modules/has-value/node_modules/isobject": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
-            "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
-            "dependencies": {
-                "isarray": "1.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/unset-value/node_modules/has-values": {
-            "version": "0.1.4",
-            "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
-            "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/unstated": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/unstated/-/unstated-2.1.1.tgz",
-            "integrity": "sha512-fORlTWMZxq7NuMJDxyIrrYIZKN7wEWYQ9SiaJfIRcSpsowr6Ph/JIfK2tgtXLW614JfPG/t5q9eEIhXRCf55xg==",
-            "dependencies": {
-                "create-react-context": "^0.1.5"
-            },
-            "peerDependencies": {
-                "react": "^15.0.0 || ^16.0.0"
-            }
-        },
-        "node_modules/unstated/node_modules/create-react-context": {
-            "version": "0.1.6",
-            "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.1.6.tgz",
-            "integrity": "sha512-eCnYYEUEc5i32LHwpE/W7NlddOB9oHwsPaWtWzYtflNkkwa3IfindIcoXdVWs12zCbwaMCavKNu84EXogVIWHw==",
-            "peerDependencies": {
-                "prop-types": "^15.0.0",
-                "react": "^14.0.0 || ^15.0.0 || ^16.0.0"
-            }
-        },
-        "node_modules/unzip-response": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz",
-            "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/upath": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
-            "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
-            "engines": {
-                "node": ">=4",
-                "yarn": "*"
-            }
-        },
-        "node_modules/update-notifier": {
-            "version": "2.5.0",
-            "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz",
-            "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==",
-            "dependencies": {
-                "boxen": "^1.2.1",
-                "chalk": "^2.0.1",
-                "configstore": "^3.0.0",
-                "import-lazy": "^2.1.0",
-                "is-ci": "^1.0.10",
-                "is-installed-globally": "^0.1.0",
-                "is-npm": "^1.0.0",
-                "latest-version": "^3.0.0",
-                "semver-diff": "^2.0.0",
-                "xdg-basedir": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/uri-js": {
-            "version": "4.4.1",
-            "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
-            "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
-            "dependencies": {
-                "punycode": "^2.1.0"
-            }
-        },
-        "node_modules/urix": {
-            "version": "0.1.0",
-            "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
-            "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
-            "deprecated": "Please see https://github.com/lydell/urix#deprecated"
-        },
-        "node_modules/url": {
-            "version": "0.11.0",
-            "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
-            "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
-            "dev": true,
-            "dependencies": {
-                "punycode": "1.3.2",
-                "querystring": "0.2.0"
-            }
-        },
-        "node_modules/url-loader": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz",
-            "integrity": "sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==",
-            "dependencies": {
-                "loader-utils": "^1.1.0",
-                "mime": "^2.0.3",
-                "schema-utils": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 6.9.0"
-            },
-            "peerDependencies": {
-                "webpack": "^3.0.0 || ^4.0.0"
-            }
-        },
-        "node_modules/url-loader/node_modules/mime": {
-            "version": "2.6.0",
-            "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
-            "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
-            "bin": {
-                "mime": "cli.js"
-            },
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/url-parse": {
-            "version": "1.5.10",
-            "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
-            "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
-            "dev": true,
-            "dependencies": {
-                "querystringify": "^2.1.1",
-                "requires-port": "^1.0.0"
-            }
-        },
-        "node_modules/url-parse-lax": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
-            "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
-            "dependencies": {
-                "prepend-http": "^1.0.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/url-template": {
-            "version": "2.0.8",
-            "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz",
-            "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE="
-        },
-        "node_modules/url/node_modules/punycode": {
-            "version": "1.3.2",
-            "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
-            "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
-            "dev": true
-        },
-        "node_modules/use": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
-            "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/use-asset": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/use-asset/-/use-asset-1.0.4.tgz",
-            "integrity": "sha512-7/hqDrWa0iMnCoET9W1T07EmD4Eg/Wmoj/X8TGBc++ECRK4m5yTsjP4O6s0yagbxfqIOuUkIxe2/sA+VR2GxZA==",
-            "dependencies": {
-                "fast-deep-equal": "^3.1.3"
-            },
-            "peerDependencies": {
-                "react": ">=17.0"
-            }
-        },
-        "node_modules/use-memo-one": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz",
-            "integrity": "sha512-u2qFKtxLsia/r8qG0ZKkbytbztzRb317XCkT7yP8wxL0tZ/CzK2G+WWie5vWvpyeP7+YoPIwbJoIHJ4Ba4k0oQ==",
-            "peerDependencies": {
-                "react": "^16.8.0 || ^17.0.0"
-            }
-        },
-        "node_modules/util": {
-            "version": "0.12.4",
-            "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz",
-            "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==",
-            "dependencies": {
-                "inherits": "^2.0.3",
-                "is-arguments": "^1.0.4",
-                "is-generator-function": "^1.0.7",
-                "is-typed-array": "^1.1.3",
-                "safe-buffer": "^5.1.2",
-                "which-typed-array": "^1.1.2"
-            }
-        },
-        "node_modules/util-deprecate": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-            "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
-        },
-        "node_modules/utila": {
-            "version": "0.4.0",
-            "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
-            "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw="
-        },
-        "node_modules/utility-types": {
-            "version": "3.10.0",
-            "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz",
-            "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==",
-            "engines": {
-                "node": ">= 4"
-            }
-        },
-        "node_modules/utils-merge": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
-            "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
-            "engines": {
-                "node": ">= 0.4.0"
-            }
-        },
-        "node_modules/uuid": {
-            "version": "3.4.0",
-            "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
-            "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
-            "deprecated": "Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.",
-            "bin": {
-                "uuid": "bin/uuid"
-            }
-        },
-        "node_modules/uuid-js": {
-            "version": "0.7.5",
-            "resolved": "https://registry.npmjs.org/uuid-js/-/uuid-js-0.7.5.tgz",
-            "integrity": "sha1-bIhtAqU9LUDc8l2RoXC0p7JblNA=",
-            "engines": {
-                "node": ">= 0.4.0"
-            }
-        },
-        "node_modules/uvu": {
-            "version": "0.5.6",
-            "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz",
-            "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==",
-            "dependencies": {
-                "dequal": "^2.0.0",
-                "diff": "^5.0.0",
-                "kleur": "^4.0.3",
-                "sade": "^1.7.3"
-            },
-            "bin": {
-                "uvu": "bin.js"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/uvu/node_modules/diff": {
-            "version": "5.1.0",
-            "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz",
-            "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==",
-            "engines": {
-                "node": ">=0.3.1"
-            }
-        },
-        "node_modules/v8-compile-cache": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
-            "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
-            "dev": true
-        },
-        "node_modules/v8-compile-cache-lib": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
-            "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
-            "dev": true
-        },
-        "node_modules/valid-url": {
-            "version": "1.0.9",
-            "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz",
-            "integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA="
-        },
-        "node_modules/validate-npm-package-license": {
-            "version": "3.0.4",
-            "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
-            "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
-            "dependencies": {
-                "spdx-correct": "^3.0.0",
-                "spdx-expression-parse": "^3.0.0"
-            }
-        },
-        "node_modules/validator": {
-            "version": "10.11.0",
-            "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
-            "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==",
-            "engines": {
-                "node": ">= 0.10"
-            }
-        },
-        "node_modules/vary": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
-            "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/verror": {
-            "version": "1.10.0",
-            "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
-            "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
-            "engines": [
-                "node >=0.6.0"
-            ],
-            "dependencies": {
-                "assert-plus": "^1.0.0",
-                "core-util-is": "1.0.2",
-                "extsprintf": "^1.2.0"
-            }
-        },
-        "node_modules/verror/node_modules/core-util-is": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-            "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="
-        },
-        "node_modules/vfile": {
-            "version": "5.3.4",
-            "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.4.tgz",
-            "integrity": "sha512-KI+7cnst03KbEyN1+JE504zF5bJBZa+J+CrevLeyIMq0aPU681I2rQ5p4PlnQ6exFtWiUrg26QUdFMnAKR6PIw==",
-            "dependencies": {
-                "@types/unist": "^2.0.0",
-                "is-buffer": "^2.0.0",
-                "unist-util-stringify-position": "^3.0.0",
-                "vfile-message": "^3.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/vfile-location": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.0.1.tgz",
-            "integrity": "sha512-JDxPlTbZrZCQXogGheBHjbRWjESSPEak770XwWPfw5mTc1v1nWGLB/apzZxsx8a0SJVfF8HK8ql8RD308vXRUw==",
-            "dependencies": {
-                "@types/unist": "^2.0.0",
-                "vfile": "^5.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/vfile-message": {
-            "version": "3.1.2",
-            "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.2.tgz",
-            "integrity": "sha512-QjSNP6Yxzyycd4SVOtmKKyTsSvClqBPJcd00Z0zuPj3hOIjg0rUPG6DbFGPvUKRgYyaIWLPKpuEclcuvb3H8qA==",
-            "dependencies": {
-                "@types/unist": "^2.0.0",
-                "unist-util-stringify-position": "^3.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/unified"
-            }
-        },
-        "node_modules/void-elements": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
-            "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/vscode-jsonrpc": {
-            "version": "8.0.1",
-            "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.1.tgz",
-            "integrity": "sha512-N/WKvghIajmEvXpatSzvTvOIz61ZSmOSa4BRA4pTLi+1+jozquQKP/MkaylP9iB68k73Oua1feLQvH3xQuigiQ==",
-            "engines": {
-                "node": ">=14.0.0"
-            }
-        },
-        "node_modules/vscode-languageserver": {
-            "version": "5.3.0-next.10",
-            "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-5.3.0-next.10.tgz",
-            "integrity": "sha512-QL7Fe1FT6PdLtVzwJeZ78pTic4eZbzLRy7yAQgPb9xalqqgZESR0+yDZPwJrM3E7PzOmwHBceYcJR54eQZ7Kng==",
-            "dependencies": {
-                "vscode-languageserver-protocol": "^3.15.0-next.8",
-                "vscode-textbuffer": "^1.0.0"
-            },
-            "bin": {
-                "installServerIntoExtension": "bin/installServerIntoExtension"
-            }
-        },
-        "node_modules/vscode-languageserver-protocol": {
-            "version": "3.17.1",
-            "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.1.tgz",
-            "integrity": "sha512-BNlAYgQoYwlSgDLJhSG+DeA8G1JyECqRzM2YO6tMmMji3Ad9Mw6AW7vnZMti90qlAKb0LqAlJfSVGEdqMMNzKg==",
-            "dependencies": {
-                "vscode-jsonrpc": "8.0.1",
-                "vscode-languageserver-types": "3.17.1"
-            }
-        },
-        "node_modules/vscode-languageserver-types": {
-            "version": "3.17.1",
-            "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.1.tgz",
-            "integrity": "sha512-K3HqVRPElLZVVPtMeKlsyL9aK0GxGQpvtAUTfX4k7+iJ4mc1M+JM+zQwkgGy2LzY0f0IAafe8MKqIkJrxfGGjQ=="
-        },
-        "node_modules/vscode-textbuffer": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/vscode-textbuffer/-/vscode-textbuffer-1.0.0.tgz",
-            "integrity": "sha512-zPaHo4urgpwsm+PrJWfNakolRpryNja18SUip/qIIsfhuEqEIPEXMxHOlFPjvDC4JgTaimkncNW7UMXRJTY6ow==",
-            "deprecated": "This package has been renamed to @vscode/textbuffer, please update to the new name"
-        },
-        "node_modules/vscode-uri": {
-            "version": "1.0.8",
-            "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz",
-            "integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ=="
-        },
-        "node_modules/vue-template-compiler": {
-            "version": "2.6.14",
-            "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz",
-            "integrity": "sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g==",
-            "dependencies": {
-                "de-indent": "^1.0.2",
-                "he": "^1.1.0"
-            }
-        },
-        "node_modules/w3c-hr-time": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
-            "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==",
-            "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.",
-            "dev": true,
-            "dependencies": {
-                "browser-process-hrtime": "^1.0.0"
-            }
-        },
-        "node_modules/w3c-keyname": {
-            "version": "2.2.4",
-            "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz",
-            "integrity": "sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw=="
-        },
-        "node_modules/w3c-xmlserializer": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz",
-            "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==",
-            "dev": true,
-            "dependencies": {
-                "domexception": "^1.0.1",
-                "webidl-conversions": "^4.0.2",
-                "xml-name-validator": "^3.0.0"
-            }
-        },
-        "node_modules/w3c-xmlserializer/node_modules/webidl-conversions": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
-            "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
-            "dev": true
-        },
-        "node_modules/walkdir": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.4.1.tgz",
-            "integrity": "sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ==",
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/warning": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
-            "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=",
-            "dependencies": {
-                "loose-envify": "^1.0.0"
-            }
-        },
-        "node_modules/watchpack": {
-            "version": "2.4.0",
-            "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
-            "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
-            "dependencies": {
-                "glob-to-regexp": "^0.4.1",
-                "graceful-fs": "^4.1.2"
-            },
-            "engines": {
-                "node": ">=10.13.0"
-            }
-        },
-        "node_modules/wbuf": {
-            "version": "1.7.3",
-            "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
-            "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
-            "dev": true,
-            "dependencies": {
-                "minimalistic-assert": "^1.0.0"
-            }
-        },
-        "node_modules/web-namespaces": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
-            "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==",
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/wooorm"
-            }
-        },
-        "node_modules/web-request": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/web-request/-/web-request-1.0.7.tgz",
-            "integrity": "sha1-twxCs81FV3noLbaIYlOySR8r1Wk=",
-            "dependencies": {
-                "request": "^2.69.0"
-            }
-        },
-        "node_modules/web-streams-polyfill": {
-            "version": "3.2.1",
-            "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
-            "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/webidl-conversions": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
-            "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
-        },
-        "node_modules/webpack": {
-            "version": "5.73.0",
-            "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz",
-            "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==",
-            "dependencies": {
-                "@types/eslint-scope": "^3.7.3",
-                "@types/estree": "^0.0.51",
-                "@webassemblyjs/ast": "1.11.1",
-                "@webassemblyjs/wasm-edit": "1.11.1",
-                "@webassemblyjs/wasm-parser": "1.11.1",
-                "acorn": "^8.4.1",
-                "acorn-import-assertions": "^1.7.6",
-                "browserslist": "^4.14.5",
-                "chrome-trace-event": "^1.0.2",
-                "enhanced-resolve": "^5.9.3",
-                "es-module-lexer": "^0.9.0",
-                "eslint-scope": "5.1.1",
-                "events": "^3.2.0",
-                "glob-to-regexp": "^0.4.1",
-                "graceful-fs": "^4.2.9",
-                "json-parse-even-better-errors": "^2.3.1",
-                "loader-runner": "^4.2.0",
-                "mime-types": "^2.1.27",
-                "neo-async": "^2.6.2",
-                "schema-utils": "^3.1.0",
-                "tapable": "^2.1.1",
-                "terser-webpack-plugin": "^5.1.3",
-                "watchpack": "^2.3.1",
-                "webpack-sources": "^3.2.3"
-            },
-            "bin": {
-                "webpack": "bin/webpack.js"
-            },
-            "engines": {
-                "node": ">=10.13.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/webpack"
-            },
-            "peerDependenciesMeta": {
-                "webpack-cli": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/webpack-cli": {
-            "version": "4.10.0",
-            "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz",
-            "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==",
-            "dependencies": {
-                "@discoveryjs/json-ext": "^0.5.0",
-                "@webpack-cli/configtest": "^1.2.0",
-                "@webpack-cli/info": "^1.5.0",
-                "@webpack-cli/serve": "^1.7.0",
-                "colorette": "^2.0.14",
-                "commander": "^7.0.0",
-                "cross-spawn": "^7.0.3",
-                "fastest-levenshtein": "^1.0.12",
-                "import-local": "^3.0.2",
-                "interpret": "^2.2.0",
-                "rechoir": "^0.7.0",
-                "webpack-merge": "^5.7.3"
-            },
-            "bin": {
-                "webpack-cli": "bin/cli.js"
-            },
-            "engines": {
-                "node": ">=10.13.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/webpack"
-            },
-            "peerDependencies": {
-                "webpack": "4.x.x || 5.x.x"
-            },
-            "peerDependenciesMeta": {
-                "@webpack-cli/generators": {
-                    "optional": true
-                },
-                "@webpack-cli/migrate": {
-                    "optional": true
-                },
-                "webpack-bundle-analyzer": {
-                    "optional": true
-                },
-                "webpack-dev-server": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/webpack-cli/node_modules/commander": {
-            "version": "7.2.0",
-            "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
-            "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
-            "engines": {
-                "node": ">= 10"
-            }
-        },
-        "node_modules/webpack-cli/node_modules/cross-spawn": {
-            "version": "7.0.3",
-            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-            "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
-            "dependencies": {
-                "path-key": "^3.1.0",
-                "shebang-command": "^2.0.0",
-                "which": "^2.0.1"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/webpack-cli/node_modules/interpret": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz",
-            "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==",
-            "engines": {
-                "node": ">= 0.10"
-            }
-        },
-        "node_modules/webpack-cli/node_modules/path-key": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
-            "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/webpack-cli/node_modules/rechoir": {
-            "version": "0.7.1",
-            "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
-            "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==",
-            "dependencies": {
-                "resolve": "^1.9.0"
-            },
-            "engines": {
-                "node": ">= 0.10"
-            }
-        },
-        "node_modules/webpack-cli/node_modules/shebang-command": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
-            "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
-            "dependencies": {
-                "shebang-regex": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/webpack-cli/node_modules/shebang-regex": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
-            "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/webpack-cli/node_modules/which": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
-            "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
-            "dependencies": {
-                "isexe": "^2.0.0"
-            },
-            "bin": {
-                "node-which": "bin/node-which"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/webpack-dev-middleware": {
-            "version": "5.3.3",
-            "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz",
-            "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==",
-            "dependencies": {
-                "colorette": "^2.0.10",
-                "memfs": "^3.4.3",
-                "mime-types": "^2.1.31",
-                "range-parser": "^1.2.1",
-                "schema-utils": "^4.0.0"
-            },
-            "engines": {
-                "node": ">= 12.13.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/webpack"
-            },
-            "peerDependencies": {
-                "webpack": "^4.0.0 || ^5.0.0"
-            }
-        },
-        "node_modules/webpack-dev-middleware/node_modules/ajv": {
-            "version": "8.11.0",
-            "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
-            "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
-            "dependencies": {
-                "fast-deep-equal": "^3.1.1",
-                "json-schema-traverse": "^1.0.0",
-                "require-from-string": "^2.0.2",
-                "uri-js": "^4.2.2"
-            },
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/epoberezkin"
-            }
-        },
-        "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": {
-            "version": "5.1.0",
-            "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
-            "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
-            "dependencies": {
-                "fast-deep-equal": "^3.1.3"
-            },
-            "peerDependencies": {
-                "ajv": "^8.8.2"
-            }
-        },
-        "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
-            "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
-        },
-        "node_modules/webpack-dev-middleware/node_modules/schema-utils": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz",
-            "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==",
-            "dependencies": {
-                "@types/json-schema": "^7.0.9",
-                "ajv": "^8.8.0",
-                "ajv-formats": "^2.1.1",
-                "ajv-keywords": "^5.0.0"
-            },
-            "engines": {
-                "node": ">= 12.13.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/webpack"
-            }
-        },
-        "node_modules/webpack-dev-server": {
-            "version": "3.11.3",
-            "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz",
-            "integrity": "sha512-3x31rjbEQWKMNzacUZRE6wXvUFuGpH7vr0lIEbYpMAG9BOxi0928QU1BBswOAP3kg3H1O4hiS+sq4YyAn6ANnA==",
-            "dev": true,
-            "dependencies": {
-                "ansi-html-community": "0.0.8",
-                "bonjour": "^3.5.0",
-                "chokidar": "^2.1.8",
-                "compression": "^1.7.4",
-                "connect-history-api-fallback": "^1.6.0",
-                "debug": "^4.1.1",
-                "del": "^4.1.1",
-                "express": "^4.17.1",
-                "html-entities": "^1.3.1",
-                "http-proxy-middleware": "0.19.1",
-                "import-local": "^2.0.0",
-                "internal-ip": "^4.3.0",
-                "ip": "^1.1.5",
-                "is-absolute-url": "^3.0.3",
-                "killable": "^1.0.1",
-                "loglevel": "^1.6.8",
-                "opn": "^5.5.0",
-                "p-retry": "^3.0.1",
-                "portfinder": "^1.0.26",
-                "schema-utils": "^1.0.0",
-                "selfsigned": "^1.10.8",
-                "semver": "^6.3.0",
-                "serve-index": "^1.9.1",
-                "sockjs": "^0.3.21",
-                "sockjs-client": "^1.5.0",
-                "spdy": "^4.0.2",
-                "strip-ansi": "^3.0.1",
-                "supports-color": "^6.1.0",
-                "url": "^0.11.0",
-                "webpack-dev-middleware": "^3.7.2",
-                "webpack-log": "^2.0.0",
-                "ws": "^6.2.1",
-                "yargs": "^13.3.2"
-            },
-            "bin": {
-                "webpack-dev-server": "bin/webpack-dev-server.js"
-            },
-            "engines": {
-                "node": ">= 6.11.5"
-            },
-            "peerDependencies": {
-                "webpack": "^4.0.0 || ^5.0.0"
-            },
-            "peerDependenciesMeta": {
-                "webpack-cli": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/webpack-dev-server/node_modules/ansi-regex": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-            "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/webpack-dev-server/node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dev": true,
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/webpack-dev-server/node_modules/import-local": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
-            "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
-            "dev": true,
-            "dependencies": {
-                "pkg-dir": "^3.0.0",
-                "resolve-cwd": "^2.0.0"
-            },
-            "bin": {
-                "import-local-fixture": "fixtures/cli.js"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/webpack-dev-server/node_modules/memory-fs": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
-            "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
-            "dev": true,
-            "dependencies": {
-                "errno": "^0.1.3",
-                "readable-stream": "^2.0.1"
-            }
-        },
-        "node_modules/webpack-dev-server/node_modules/mime": {
-            "version": "2.6.0",
-            "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
-            "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
-            "dev": true,
-            "bin": {
-                "mime": "cli.js"
-            },
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/webpack-dev-server/node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-            "dev": true
-        },
-        "node_modules/webpack-dev-server/node_modules/pkg-dir": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
-            "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
-            "dev": true,
-            "dependencies": {
-                "find-up": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/webpack-dev-server/node_modules/readable-stream": {
-            "version": "2.3.7",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-            "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-            "dev": true,
-            "dependencies": {
-                "core-util-is": "~1.0.0",
-                "inherits": "~2.0.3",
-                "isarray": "~1.0.0",
-                "process-nextick-args": "~2.0.0",
-                "safe-buffer": "~5.1.1",
-                "string_decoder": "~1.1.1",
-                "util-deprecate": "~1.0.1"
-            }
-        },
-        "node_modules/webpack-dev-server/node_modules/resolve-cwd": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
-            "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
-            "dev": true,
-            "dependencies": {
-                "resolve-from": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/webpack-dev-server/node_modules/resolve-from": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
-            "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/webpack-dev-server/node_modules/semver": {
-            "version": "6.3.0",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
-            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
-            "dev": true,
-            "bin": {
-                "semver": "bin/semver.js"
-            }
-        },
-        "node_modules/webpack-dev-server/node_modules/strip-ansi": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-            "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
-            "dev": true,
-            "dependencies": {
-                "ansi-regex": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/webpack-dev-server/node_modules/supports-color": {
-            "version": "6.1.0",
-            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
-            "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
-            "dev": true,
-            "dependencies": {
-                "has-flag": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/webpack-dev-server/node_modules/webpack-dev-middleware": {
-            "version": "3.7.3",
-            "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz",
-            "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==",
-            "dev": true,
-            "dependencies": {
-                "memory-fs": "^0.4.1",
-                "mime": "^2.4.4",
-                "mkdirp": "^0.5.1",
-                "range-parser": "^1.2.1",
-                "webpack-log": "^2.0.0"
-            },
-            "engines": {
-                "node": ">= 6"
-            },
-            "peerDependencies": {
-                "webpack": "^4.0.0 || ^5.0.0"
-            }
-        },
-        "node_modules/webpack-dev-server/node_modules/webpack-log": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz",
-            "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==",
-            "dev": true,
-            "dependencies": {
-                "ansi-colors": "^3.0.0",
-                "uuid": "^3.3.2"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/webpack-dev-server/node_modules/ws": {
-            "version": "6.2.2",
-            "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
-            "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
-            "dev": true,
-            "dependencies": {
-                "async-limiter": "~1.0.0"
-            }
-        },
-        "node_modules/webpack-hot-middleware": {
-            "version": "2.25.1",
-            "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.25.1.tgz",
-            "integrity": "sha512-Koh0KyU/RPYwel/khxbsDz9ibDivmUbrRuKSSQvW42KSDdO4w23WI3SkHpSUKHE76LrFnnM/L7JCrpBwu8AXYw==",
-            "dev": true,
-            "dependencies": {
-                "ansi-html-community": "0.0.8",
-                "html-entities": "^2.1.0",
-                "querystring": "^0.2.0",
-                "strip-ansi": "^6.0.0"
-            }
-        },
-        "node_modules/webpack-hot-middleware/node_modules/ansi-regex": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/webpack-hot-middleware/node_modules/html-entities": {
-            "version": "2.3.3",
-            "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz",
-            "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==",
-            "dev": true
-        },
-        "node_modules/webpack-hot-middleware/node_modules/strip-ansi": {
-            "version": "6.0.1",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-            "dev": true,
-            "dependencies": {
-                "ansi-regex": "^5.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/webpack-log": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz",
-            "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==",
-            "dev": true,
-            "dependencies": {
-                "chalk": "^2.1.0",
-                "log-symbols": "^2.1.0",
-                "loglevelnext": "^1.0.1",
-                "uuid": "^3.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/webpack-merge": {
-            "version": "5.8.0",
-            "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz",
-            "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==",
-            "dependencies": {
-                "clone-deep": "^4.0.1",
-                "wildcard": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=10.0.0"
-            }
-        },
-        "node_modules/webpack-sources": {
-            "version": "3.2.3",
-            "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
-            "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
-            "engines": {
-                "node": ">=10.13.0"
-            }
-        },
-        "node_modules/webpack/node_modules/schema-utils": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
-            "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
-            "dependencies": {
-                "@types/json-schema": "^7.0.8",
-                "ajv": "^6.12.5",
-                "ajv-keywords": "^3.5.2"
-            },
-            "engines": {
-                "node": ">= 10.13.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/webpack"
-            }
-        },
-        "node_modules/webrtc-adapter": {
-            "version": "7.7.1",
-            "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-7.7.1.tgz",
-            "integrity": "sha512-TbrbBmiQBL9n0/5bvDdORc6ZfRY/Z7JnEj+EYOD1ghseZdpJ+nF2yx14k3LgQKc7JZnG7HAcL+zHnY25So9d7A==",
-            "dependencies": {
-                "rtcpeerconnection-shim": "^1.2.15",
-                "sdp": "^2.12.0"
-            },
-            "engines": {
-                "node": ">=6.0.0",
-                "npm": ">=3.10.0"
-            }
-        },
-        "node_modules/websocket-driver": {
-            "version": "0.7.4",
-            "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
-            "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
-            "dev": true,
-            "dependencies": {
-                "http-parser-js": ">=0.5.1",
-                "safe-buffer": ">=5.1.0",
-                "websocket-extensions": ">=0.1.1"
-            },
-            "engines": {
-                "node": ">=0.8.0"
-            }
-        },
-        "node_modules/websocket-extensions": {
-            "version": "0.1.4",
-            "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
-            "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.8.0"
-            }
-        },
-        "node_modules/whatwg-encoding": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz",
-            "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==",
-            "dev": true,
-            "dependencies": {
-                "iconv-lite": "0.4.24"
-            }
-        },
-        "node_modules/whatwg-encoding/node_modules/iconv-lite": {
-            "version": "0.4.24",
-            "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
-            "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
-            "dev": true,
-            "dependencies": {
-                "safer-buffer": ">= 2.1.2 < 3"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/whatwg-fetch": {
-            "version": "3.6.2",
-            "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz",
-            "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA=="
-        },
-        "node_modules/whatwg-mimetype": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz",
-            "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==",
-            "dev": true
-        },
-        "node_modules/whatwg-url": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
-            "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
-            "dependencies": {
-                "tr46": "~0.0.3",
-                "webidl-conversions": "^3.0.0"
-            }
-        },
-        "node_modules/when": {
-            "version": "3.7.8",
-            "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz",
-            "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I="
-        },
-        "node_modules/which": {
-            "version": "1.3.1",
-            "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-            "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
-            "dependencies": {
-                "isexe": "^2.0.0"
-            },
-            "bin": {
-                "which": "bin/which"
-            }
-        },
-        "node_modules/which-boxed-primitive": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
-            "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
-            "dependencies": {
-                "is-bigint": "^1.0.1",
-                "is-boolean-object": "^1.1.0",
-                "is-number-object": "^1.0.4",
-                "is-string": "^1.0.5",
-                "is-symbol": "^1.0.3"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/which-module": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
-            "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
-        },
-        "node_modules/which-pm-runs": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz",
-            "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/which-typed-array": {
-            "version": "1.1.8",
-            "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz",
-            "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==",
-            "dependencies": {
-                "available-typed-arrays": "^1.0.5",
-                "call-bind": "^1.0.2",
-                "es-abstract": "^1.20.0",
-                "for-each": "^0.3.3",
-                "has-tostringtag": "^1.0.0",
-                "is-typed-array": "^1.1.9"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/wide-align": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
-            "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
-            "dependencies": {
-                "string-width": "^1.0.2 || 2"
-            }
-        },
-        "node_modules/widest-line": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
-            "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==",
-            "dependencies": {
-                "string-width": "^2.1.1"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/wikijs": {
-            "version": "6.3.3",
-            "resolved": "https://registry.npmjs.org/wikijs/-/wikijs-6.3.3.tgz",
-            "integrity": "sha512-pYVaUuJyTd7VO2aNxbdN341zgio+QuGdc6HC3jyQqakyaLJdOD8Shj+bs7lnZnhv/wml2u+C+OME9YUkck06Cg==",
-            "dependencies": {
-                "cross-fetch": "^3.0.2",
-                "hyntax": "^1.1.9",
-                "infobox-parser": "3.6.2"
-            },
-            "engines": {
-                "node": ">=0.10.4"
-            },
-            "funding": {
-                "type": "individual",
-                "url": "https://www.buymeacoffee.com/2tmRKi9"
-            }
-        },
-        "node_modules/wildcard": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz",
-            "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw=="
-        },
-        "node_modules/window-size": {
-            "version": "0.1.0",
-            "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
-            "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/with": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz",
-            "integrity": "sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=",
-            "dependencies": {
-                "acorn": "^3.1.0",
-                "acorn-globals": "^3.0.0"
-            }
-        },
-        "node_modules/with/node_modules/acorn": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
-            "integrity": "sha512-OLUyIIZ7mF5oaAUT1w0TFqQS81q3saT46x8t7ukpPjMNk+nbs4ZHhs7ToV8EWnLYLepjETXd4XaCE4uxkMeqUw==",
-            "bin": {
-                "acorn": "bin/acorn"
-            },
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/word-wrap": {
-            "version": "1.2.3",
-            "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
-            "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/words-to-numbers": {
-            "version": "1.5.1",
-            "resolved": "https://registry.npmjs.org/words-to-numbers/-/words-to-numbers-1.5.1.tgz",
-            "integrity": "sha512-uvz7zSCKmmA7o5f5zp4Z5l24RQhy6HSNu10URhNxQWv1I82RsFaZX3qD07RLFUMJsCV38oAuaca13AvhO+9yGw==",
-            "dependencies": {
-                "babel-runtime": "6.x.x",
-                "clj-fuzzy": "^0.3.2",
-                "its-set": "^1.1.5"
-            }
-        },
-        "node_modules/wordwrap": {
-            "version": "0.0.2",
-            "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
-            "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/wordwrapjs": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz",
-            "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==",
-            "dependencies": {
-                "reduce-flatten": "^1.0.1",
-                "typical": "^2.6.1"
-            },
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
-        "node_modules/worker-rpc": {
-            "version": "0.1.1",
-            "resolved": "https://registry.npmjs.org/worker-rpc/-/worker-rpc-0.1.1.tgz",
-            "integrity": "sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg==",
-            "dev": true,
-            "dependencies": {
-                "microevent.ts": "~0.1.1"
-            }
-        },
-        "node_modules/wrap-ansi": {
-            "version": "5.1.0",
-            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
-            "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
-            "dependencies": {
-                "ansi-styles": "^3.2.0",
-                "string-width": "^3.0.0",
-                "strip-ansi": "^5.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/wrap-ansi/node_modules/ansi-regex": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
-            "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/wrap-ansi/node_modules/string-width": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-            "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
-            "dependencies": {
-                "emoji-regex": "^7.0.1",
-                "is-fullwidth-code-point": "^2.0.0",
-                "strip-ansi": "^5.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/wrap-ansi/node_modules/strip-ansi": {
-            "version": "5.2.0",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-            "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
-            "dependencies": {
-                "ansi-regex": "^4.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/wrappy": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-            "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
-        },
-        "node_modules/write": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
-            "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
-            "dev": true,
-            "dependencies": {
-                "mkdirp": "^0.5.1"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/write-file-atomic": {
-            "version": "2.4.3",
-            "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
-            "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
-            "dependencies": {
-                "graceful-fs": "^4.1.11",
-                "imurmurhash": "^0.1.4",
-                "signal-exit": "^3.0.2"
-            }
-        },
-        "node_modules/ws": {
-            "version": "7.5.8",
-            "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.8.tgz",
-            "integrity": "sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==",
-            "engines": {
-                "node": ">=8.3.0"
-            },
-            "peerDependencies": {
-                "bufferutil": "^4.0.1",
-                "utf-8-validate": "^5.0.2"
-            },
-            "peerDependenciesMeta": {
-                "bufferutil": {
-                    "optional": true
-                },
-                "utf-8-validate": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/xdg-basedir": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz",
-            "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/xml-name-validator": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
-            "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==",
-            "dev": true
-        },
-        "node_modules/xmlbuilder": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.0.0.tgz",
-            "integrity": "sha1-mLj2UcowqmJANvEn0RzGbce5B6M=",
-            "dependencies": {
-                "lodash": "^3.5.0"
-            },
-            "engines": {
-                "node": ">=0.8.0"
-            }
-        },
-        "node_modules/xmlbuilder/node_modules/lodash": {
-            "version": "3.10.1",
-            "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
-            "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
-        },
-        "node_modules/xmlchars": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
-            "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
-            "dev": true
-        },
-        "node_modules/xmldom": {
-            "version": "0.1.31",
-            "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz",
-            "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==",
-            "deprecated": "Deprecated due to CVE-2021-21366 resolved in 0.5.0",
-            "engines": {
-                "node": ">=0.1"
-            }
-        },
-        "node_modules/xmlhttprequest-ssl": {
-            "version": "1.6.3",
-            "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz",
-            "integrity": "sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==",
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/xoauth2": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/xoauth2/-/xoauth2-1.2.0.tgz",
-            "integrity": "sha1-8u76wRRyyXHqO8RuVU60sSMhRuU="
-        },
-        "node_modules/xregexp": {
-            "version": "4.4.1",
-            "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.4.1.tgz",
-            "integrity": "sha512-2u9HwfadaJaY9zHtRRnH6BY6CQVNQKkYm3oLtC9gJXXzfsbACg5X5e4EZZGVAH+YIfa+QA9lsFQTTe3HURF3ag==",
-            "dependencies": {
-                "@babel/runtime-corejs3": "^7.12.1"
-            }
-        },
-        "node_modules/xtend": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
-            "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.4"
-            }
-        },
-        "node_modules/y18n": {
-            "version": "4.0.3",
-            "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
-            "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
-        },
-        "node_modules/yallist": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
-        },
-        "node_modules/yaml": {
-            "version": "1.10.2",
-            "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
-            "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/yargs": {
-            "version": "13.3.2",
-            "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
-            "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
-            "dependencies": {
-                "cliui": "^5.0.0",
-                "find-up": "^3.0.0",
-                "get-caller-file": "^2.0.1",
-                "require-directory": "^2.1.1",
-                "require-main-filename": "^2.0.0",
-                "set-blocking": "^2.0.0",
-                "string-width": "^3.0.0",
-                "which-module": "^2.0.0",
-                "y18n": "^4.0.0",
-                "yargs-parser": "^13.1.2"
-            }
-        },
-        "node_modules/yargs-parser": {
-            "version": "13.1.2",
-            "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
-            "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
-            "dependencies": {
-                "camelcase": "^5.0.0",
-                "decamelize": "^1.2.0"
-            }
-        },
-        "node_modules/yargs-unparser": {
-            "version": "1.6.0",
-            "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz",
-            "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==",
-            "dependencies": {
-                "flat": "^4.1.0",
-                "lodash": "^4.17.15",
-                "yargs": "^13.3.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/yargs/node_modules/ansi-regex": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
-            "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/yargs/node_modules/string-width": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
-            "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
-            "dependencies": {
-                "emoji-regex": "^7.0.1",
-                "is-fullwidth-code-point": "^2.0.0",
-                "strip-ansi": "^5.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/yargs/node_modules/strip-ansi": {
-            "version": "5.2.0",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-            "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
-            "dependencies": {
-                "ansi-regex": "^4.1.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/yauzl": {
-            "version": "2.10.0",
-            "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
-            "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
-            "dependencies": {
-                "buffer-crc32": "~0.2.3",
-                "fd-slicer": "~1.1.0"
-            }
-        },
-        "node_modules/yeast": {
-            "version": "0.1.2",
-            "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
-            "integrity": "sha512-8HFIh676uyGYP6wP13R/j6OJ/1HwJ46snpvzE7aHAN3Ryqh2yX6Xox2B4CUmTwwOIzlG3Bs7ocsP5dZH/R1Qbg=="
-        },
-        "node_modules/yn": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
-            "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/zip-stream": {
-            "version": "2.1.3",
-            "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.1.3.tgz",
-            "integrity": "sha512-EkXc2JGcKhO5N5aZ7TmuNo45budRaFGHOmz24wtJR7znbNqDPmdZtUauKX6et8KAVseAMBOyWJqEpXcHTBsh7Q==",
-            "dependencies": {
-                "archiver-utils": "^2.1.0",
-                "compress-commons": "^2.1.1",
-                "readable-stream": "^3.4.0"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/zustand": {
-            "version": "3.7.2",
-            "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz",
-            "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==",
-            "engines": {
-                "node": ">=12.7.0"
-            },
-            "peerDependencies": {
-                "react": ">=16.8"
-            },
-            "peerDependenciesMeta": {
-                "react": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/zwitch": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.2.tgz",
-            "integrity": "sha512-JZxotl7SxAJH0j7dN4pxsTV6ZLXoLdGME+PsjkL/DaBrVryK9kTGq06GfKrwcSOqypP+fdXGoCHE36b99fWVoA==",
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/wooorm"
-            }
-        }
-    },
     "dependencies": {
         "@babel/code-frame": {
             "version": "7.16.7",
@@ -29767,11 +343,18 @@
             "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
         },
         "@emotion/is-prop-valid": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.1.2.tgz",
-            "integrity": "sha512-3QnhqeL+WW88YjYbQL5gUIkthuMw7a0NGbZ7wfFVk2kg/CK5w8w5FFa0RzWjyY1+sujN0NWbtSHH6OJmWHtJpQ==",
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz",
+            "integrity": "sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==",
             "requires": {
-                "@emotion/memoize": "^0.7.4"
+                "@emotion/memoize": "^0.8.0"
+            },
+            "dependencies": {
+                "@emotion/memoize": {
+                    "version": "0.8.0",
+                    "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz",
+                    "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="
+                }
             }
         },
         "@emotion/memoize": {
@@ -29780,57 +363,128 @@
             "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw=="
         },
         "@emotion/react": {
-            "version": "11.9.0",
-            "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.9.0.tgz",
-            "integrity": "sha512-lBVSF5d0ceKtfKCDQJveNAtkC7ayxpVlgOohLgXqRwqWr9bOf4TZAFFyIcNngnV6xK6X4x2ZeXq7vliHkoVkxQ==",
+            "version": "11.10.8",
+            "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.8.tgz",
+            "integrity": "sha512-ZfGfiABtJ1P1OXqOBsW08EgCDp5fK6C5I8hUJauc/VcJBGSzqAirMnFslhFWnZJ/w5HxPI36XbvMV0l4KZHl+w==",
             "requires": {
-                "@babel/runtime": "^7.13.10",
-                "@emotion/babel-plugin": "^11.7.1",
-                "@emotion/cache": "^11.7.1",
-                "@emotion/serialize": "^1.0.3",
-                "@emotion/utils": "^1.1.0",
-                "@emotion/weak-memoize": "^0.2.5",
+                "@babel/runtime": "^7.18.3",
+                "@emotion/babel-plugin": "^11.10.8",
+                "@emotion/cache": "^11.10.8",
+                "@emotion/serialize": "^1.1.1",
+                "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0",
+                "@emotion/utils": "^1.2.0",
+                "@emotion/weak-memoize": "^0.3.0",
                 "hoist-non-react-statics": "^3.3.1"
             },
             "dependencies": {
+                "@emotion/babel-plugin": {
+                    "version": "11.10.8",
+                    "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.8.tgz",
+                    "integrity": "sha512-gxNky50AJL3AlkbjvTARiwAqei6/tNUxDZPSKd+3jqWVM3AmdVTTdpjHorR/an/M0VJqdsuq5oGcFH+rjtyujQ==",
+                    "requires": {
+                        "@babel/helper-module-imports": "^7.16.7",
+                        "@babel/runtime": "^7.18.3",
+                        "@emotion/hash": "^0.9.0",
+                        "@emotion/memoize": "^0.8.0",
+                        "@emotion/serialize": "^1.1.1",
+                        "babel-plugin-macros": "^3.1.0",
+                        "convert-source-map": "^1.5.0",
+                        "escape-string-regexp": "^4.0.0",
+                        "find-root": "^1.1.0",
+                        "source-map": "^0.5.7",
+                        "stylis": "4.1.4"
+                    }
+                },
                 "@emotion/cache": {
-                    "version": "11.7.1",
-                    "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.7.1.tgz",
-                    "integrity": "sha512-r65Zy4Iljb8oyjtLeCuBH8Qjiy107dOYC6SJq7g7GV5UCQWMObY4SJDPGFjiiVpPrOJ2hmJOoBiYTC7hwx9E2A==",
+                    "version": "11.10.8",
+                    "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.8.tgz",
+                    "integrity": "sha512-5fyqGHi51LU95o7qQ/vD1jyvC4uCY5GcBT+UgP4LHdpO9jPDlXqhrRr9/wCKmfoAvh5G/F7aOh4MwQa+8uEqhA==",
                     "requires": {
-                        "@emotion/memoize": "^0.7.4",
-                        "@emotion/sheet": "^1.1.0",
-                        "@emotion/utils": "^1.0.0",
-                        "@emotion/weak-memoize": "^0.2.5",
-                        "stylis": "4.0.13"
+                        "@emotion/memoize": "^0.8.0",
+                        "@emotion/sheet": "^1.2.1",
+                        "@emotion/utils": "^1.2.0",
+                        "@emotion/weak-memoize": "^0.3.0",
+                        "stylis": "4.1.4"
                     }
                 },
+                "@emotion/hash": {
+                    "version": "0.9.0",
+                    "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz",
+                    "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ=="
+                },
+                "@emotion/memoize": {
+                    "version": "0.8.0",
+                    "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz",
+                    "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="
+                },
                 "@emotion/serialize": {
-                    "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.3.tgz",
-                    "integrity": "sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==",
+                    "version": "1.1.1",
+                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.1.tgz",
+                    "integrity": "sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==",
                     "requires": {
-                        "@emotion/hash": "^0.8.0",
-                        "@emotion/memoize": "^0.7.4",
-                        "@emotion/unitless": "^0.7.5",
-                        "@emotion/utils": "^1.0.0",
+                        "@emotion/hash": "^0.9.0",
+                        "@emotion/memoize": "^0.8.0",
+                        "@emotion/unitless": "^0.8.0",
+                        "@emotion/utils": "^1.2.0",
                         "csstype": "^3.0.2"
                     }
                 },
                 "@emotion/sheet": {
-                    "version": "1.1.0",
-                    "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.1.0.tgz",
-                    "integrity": "sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g=="
+                    "version": "1.2.1",
+                    "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.1.tgz",
+                    "integrity": "sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA=="
+                },
+                "@emotion/unitless": {
+                    "version": "0.8.0",
+                    "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz",
+                    "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw=="
                 },
                 "@emotion/utils": {
-                    "version": "1.1.0",
-                    "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.1.0.tgz",
-                    "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz",
+                    "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw=="
                 },
-                "csstype": {
+                "@emotion/weak-memoize": {
+                    "version": "0.3.0",
+                    "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz",
+                    "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg=="
+                },
+                "babel-plugin-macros": {
                     "version": "3.1.0",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
+                    "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
+                    "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
+                    "requires": {
+                        "@babel/runtime": "^7.12.5",
+                        "cosmiconfig": "^7.0.0",
+                        "resolve": "^1.19.0"
+                    }
+                },
+                "cosmiconfig": {
+                    "version": "7.1.0",
+                    "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
+                    "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
+                    "requires": {
+                        "@types/parse-json": "^4.0.0",
+                        "import-fresh": "^3.2.1",
+                        "parse-json": "^5.0.0",
+                        "path-type": "^4.0.0",
+                        "yaml": "^1.10.0"
+                    }
+                },
+                "csstype": {
+                    "version": "3.1.2",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
+                    "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
+                },
+                "escape-string-regexp": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+                    "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
+                },
+                "stylis": {
+                    "version": "4.1.4",
+                    "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.4.tgz",
+                    "integrity": "sha512-USf5pszRYwuE6hg9by0OkKChkQYEXfkeTtm0xKw+jqQhwyjCVLdYyMBK7R+n7dhzsblAWJnGxju4vxq5eH20GQ=="
                 }
             }
         },
@@ -29852,38 +506,104 @@
             "integrity": "sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA=="
         },
         "@emotion/styled": {
-            "version": "11.8.1",
-            "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.8.1.tgz",
-            "integrity": "sha512-OghEVAYBZMpEquHZwuelXcRjRJQOVayvbmNR0zr174NHdmMgrNkLC6TljKC5h9lZLkN5WGrdUcrKlOJ4phhoTQ==",
+            "version": "11.10.8",
+            "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.10.8.tgz",
+            "integrity": "sha512-gow0lF4Uw/QEdX2REMhI8v6wLOabPKJ+4HKNF0xdJ2DJdznN6fxaXpQOx6sNkyBhSUL558Rmcu1Lq/MYlVo4vw==",
             "requires": {
-                "@babel/runtime": "^7.13.10",
-                "@emotion/babel-plugin": "^11.7.1",
-                "@emotion/is-prop-valid": "^1.1.2",
-                "@emotion/serialize": "^1.0.2",
-                "@emotion/utils": "^1.1.0"
-            },
-            "dependencies": {
+                "@babel/runtime": "^7.18.3",
+                "@emotion/babel-plugin": "^11.10.8",
+                "@emotion/is-prop-valid": "^1.2.0",
+                "@emotion/serialize": "^1.1.1",
+                "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0",
+                "@emotion/utils": "^1.2.0"
+            },
+            "dependencies": {
+                "@emotion/babel-plugin": {
+                    "version": "11.10.8",
+                    "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.8.tgz",
+                    "integrity": "sha512-gxNky50AJL3AlkbjvTARiwAqei6/tNUxDZPSKd+3jqWVM3AmdVTTdpjHorR/an/M0VJqdsuq5oGcFH+rjtyujQ==",
+                    "requires": {
+                        "@babel/helper-module-imports": "^7.16.7",
+                        "@babel/runtime": "^7.18.3",
+                        "@emotion/hash": "^0.9.0",
+                        "@emotion/memoize": "^0.8.0",
+                        "@emotion/serialize": "^1.1.1",
+                        "babel-plugin-macros": "^3.1.0",
+                        "convert-source-map": "^1.5.0",
+                        "escape-string-regexp": "^4.0.0",
+                        "find-root": "^1.1.0",
+                        "source-map": "^0.5.7",
+                        "stylis": "4.1.4"
+                    }
+                },
+                "@emotion/hash": {
+                    "version": "0.9.0",
+                    "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz",
+                    "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ=="
+                },
+                "@emotion/memoize": {
+                    "version": "0.8.0",
+                    "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz",
+                    "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="
+                },
                 "@emotion/serialize": {
-                    "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.3.tgz",
-                    "integrity": "sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==",
+                    "version": "1.1.1",
+                    "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.1.tgz",
+                    "integrity": "sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==",
                     "requires": {
-                        "@emotion/hash": "^0.8.0",
-                        "@emotion/memoize": "^0.7.4",
-                        "@emotion/unitless": "^0.7.5",
-                        "@emotion/utils": "^1.0.0",
+                        "@emotion/hash": "^0.9.0",
+                        "@emotion/memoize": "^0.8.0",
+                        "@emotion/unitless": "^0.8.0",
+                        "@emotion/utils": "^1.2.0",
                         "csstype": "^3.0.2"
                     }
                 },
+                "@emotion/unitless": {
+                    "version": "0.8.0",
+                    "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz",
+                    "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw=="
+                },
                 "@emotion/utils": {
-                    "version": "1.1.0",
-                    "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.1.0.tgz",
-                    "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ=="
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz",
+                    "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw=="
                 },
-                "csstype": {
+                "babel-plugin-macros": {
                     "version": "3.1.0",
-                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-                    "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
+                    "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
+                    "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
+                    "requires": {
+                        "@babel/runtime": "^7.12.5",
+                        "cosmiconfig": "^7.0.0",
+                        "resolve": "^1.19.0"
+                    }
+                },
+                "cosmiconfig": {
+                    "version": "7.1.0",
+                    "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
+                    "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
+                    "requires": {
+                        "@types/parse-json": "^4.0.0",
+                        "import-fresh": "^3.2.1",
+                        "parse-json": "^5.0.0",
+                        "path-type": "^4.0.0",
+                        "yaml": "^1.10.0"
+                    }
+                },
+                "csstype": {
+                    "version": "3.1.2",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
+                    "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
+                },
+                "escape-string-regexp": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+                    "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
+                },
+                "stylis": {
+                    "version": "4.1.4",
+                    "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.4.tgz",
+                    "integrity": "sha512-USf5pszRYwuE6hg9by0OkKChkQYEXfkeTtm0xKw+jqQhwyjCVLdYyMBK7R+n7dhzsblAWJnGxju4vxq5eH20GQ=="
                 }
             }
         },
@@ -29897,6 +617,11 @@
             "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
             "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
         },
+        "@emotion/use-insertion-effect-with-fallbacks": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz",
+            "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A=="
+        },
         "@emotion/utils": {
             "version": "0.11.3",
             "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.11.3.tgz",
@@ -30192,8 +917,7 @@
         "@icons/material": {
             "version": "0.2.4",
             "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz",
-            "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==",
-            "requires": {}
+            "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw=="
         },
         "@jridgewell/gen-mapping": {
             "version": "0.3.1",
@@ -30346,31 +1070,337 @@
                 "prop-types": "^15.7.2"
             }
         },
-        "@material-ui/system": {
-            "version": "4.12.2",
-            "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.2.tgz",
-            "integrity": "sha512-6CSKu2MtmiJgcCGf6nBQpM8fLkuB9F55EKfbdTC80NND5wpTmKzwdhLYLH3zL4cLlK0gVaaltW7/wMuyTnN0Lw==",
+        "@material-ui/system": {
+            "version": "4.12.2",
+            "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.2.tgz",
+            "integrity": "sha512-6CSKu2MtmiJgcCGf6nBQpM8fLkuB9F55EKfbdTC80NND5wpTmKzwdhLYLH3zL4cLlK0gVaaltW7/wMuyTnN0Lw==",
+            "requires": {
+                "@babel/runtime": "^7.4.4",
+                "@material-ui/utils": "^4.11.3",
+                "csstype": "^2.5.2",
+                "prop-types": "^15.7.2"
+            }
+        },
+        "@material-ui/types": {
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz",
+            "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A=="
+        },
+        "@material-ui/utils": {
+            "version": "4.11.3",
+            "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.3.tgz",
+            "integrity": "sha512-ZuQPV4rBK/V1j2dIkSSEcH5uT6AaHuKWFfotADHsC0wVL1NLd2WkFCm4ZZbX33iO4ydl6V0GPngKm8HZQ2oujg==",
+            "requires": {
+                "@babel/runtime": "^7.4.4",
+                "prop-types": "^15.7.2",
+                "react-is": "^16.8.0 || ^17.0.0"
+            }
+        },
+        "@mui/base": {
+            "version": "5.0.0-alpha.127",
+            "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.127.tgz",
+            "integrity": "sha512-FoRQd0IOH9MnfyL5yXssyQRnC4vXI+1bwkU1idr+wNkP1ZfxE+JsThHcfl1dy5azLssVUGTtQFD9edQLdbyJog==",
+            "requires": {
+                "@babel/runtime": "^7.21.0",
+                "@emotion/is-prop-valid": "^1.2.0",
+                "@mui/types": "^7.2.4",
+                "@mui/utils": "^5.12.0",
+                "@popperjs/core": "^2.11.7",
+                "clsx": "^1.2.1",
+                "prop-types": "^15.8.1",
+                "react-is": "^18.2.0"
+            },
+            "dependencies": {
+                "@babel/runtime": {
+                    "version": "7.21.5",
+                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz",
+                    "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==",
+                    "requires": {
+                        "regenerator-runtime": "^0.13.11"
+                    }
+                },
+                "clsx": {
+                    "version": "1.2.1",
+                    "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
+                    "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg=="
+                },
+                "react-is": {
+                    "version": "18.2.0",
+                    "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+                    "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
+                },
+                "regenerator-runtime": {
+                    "version": "0.13.11",
+                    "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+                    "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+                }
+            }
+        },
+        "@mui/core-downloads-tracker": {
+            "version": "5.12.2",
+            "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.12.2.tgz",
+            "integrity": "sha512-Qn7dy8tql6T0hY6gTFPkpWlnqVVFGu5Z6QzEzUSzzmLZpfAx4kf8sFz0PHiB7gU5yrqcZF9picMx1shpRY/rXw=="
+        },
+        "@mui/icons-material": {
+            "version": "5.11.16",
+            "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.11.16.tgz",
+            "integrity": "sha512-oKkx9z9Kwg40NtcIajF9uOXhxiyTZrrm9nmIJ4UjkU2IdHpd4QVLbCc/5hZN/y0C6qzi2Zlxyr9TGddQx2vx2A==",
+            "requires": {
+                "@babel/runtime": "^7.21.0"
+            },
+            "dependencies": {
+                "@babel/runtime": {
+                    "version": "7.21.5",
+                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz",
+                    "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==",
+                    "requires": {
+                        "regenerator-runtime": "^0.13.11"
+                    }
+                },
+                "regenerator-runtime": {
+                    "version": "0.13.11",
+                    "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+                    "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+                }
+            }
+        },
+        "@mui/material": {
+            "version": "5.12.2",
+            "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.12.2.tgz",
+            "integrity": "sha512-XOVy6fVC0rI2dEwDq/1s4Te2hewTUe6lznzeVnruyATGkdmM06WnHqkZOoLVIWo9hWwAxpcgTDcAIVpFtt1nrw==",
+            "requires": {
+                "@babel/runtime": "^7.21.0",
+                "@mui/base": "5.0.0-alpha.127",
+                "@mui/core-downloads-tracker": "^5.12.2",
+                "@mui/system": "^5.12.1",
+                "@mui/types": "^7.2.4",
+                "@mui/utils": "^5.12.0",
+                "@types/react-transition-group": "^4.4.5",
+                "clsx": "^1.2.1",
+                "csstype": "^3.1.2",
+                "prop-types": "^15.8.1",
+                "react-is": "^18.2.0",
+                "react-transition-group": "^4.4.5"
+            },
+            "dependencies": {
+                "@babel/runtime": {
+                    "version": "7.21.5",
+                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz",
+                    "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==",
+                    "requires": {
+                        "regenerator-runtime": "^0.13.11"
+                    }
+                },
+                "clsx": {
+                    "version": "1.2.1",
+                    "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
+                    "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg=="
+                },
+                "csstype": {
+                    "version": "3.1.2",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
+                    "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
+                },
+                "dom-helpers": {
+                    "version": "5.2.1",
+                    "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+                    "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+                    "requires": {
+                        "@babel/runtime": "^7.8.7",
+                        "csstype": "^3.0.2"
+                    }
+                },
+                "react-is": {
+                    "version": "18.2.0",
+                    "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+                    "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
+                },
+                "react-transition-group": {
+                    "version": "4.4.5",
+                    "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+                    "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+                    "requires": {
+                        "@babel/runtime": "^7.5.5",
+                        "dom-helpers": "^5.0.1",
+                        "loose-envify": "^1.4.0",
+                        "prop-types": "^15.6.2"
+                    }
+                },
+                "regenerator-runtime": {
+                    "version": "0.13.11",
+                    "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+                    "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+                }
+            }
+        },
+        "@mui/private-theming": {
+            "version": "5.12.0",
+            "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.12.0.tgz",
+            "integrity": "sha512-w5dwMen1CUm1puAtubqxY9BIzrBxbOThsg2iWMvRJmWyJAPdf3Z583fPXpqeA2lhTW79uH2jajk5Ka4FuGlTPg==",
+            "requires": {
+                "@babel/runtime": "^7.21.0",
+                "@mui/utils": "^5.12.0",
+                "prop-types": "^15.8.1"
+            },
+            "dependencies": {
+                "@babel/runtime": {
+                    "version": "7.21.5",
+                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz",
+                    "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==",
+                    "requires": {
+                        "regenerator-runtime": "^0.13.11"
+                    }
+                },
+                "regenerator-runtime": {
+                    "version": "0.13.11",
+                    "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+                    "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+                }
+            }
+        },
+        "@mui/styled-engine": {
+            "version": "5.12.0",
+            "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.12.0.tgz",
+            "integrity": "sha512-frh8L7CRnvD0RDmIqEv6jFeKQUIXqW90BaZ6OrxJ2j4kIsiVLu29Gss4SbBvvrWwwatR72sBmC3w1aG4fjp9mQ==",
+            "requires": {
+                "@babel/runtime": "^7.21.0",
+                "@emotion/cache": "^11.10.7",
+                "csstype": "^3.1.2",
+                "prop-types": "^15.8.1"
+            },
+            "dependencies": {
+                "@babel/runtime": {
+                    "version": "7.21.5",
+                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz",
+                    "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==",
+                    "requires": {
+                        "regenerator-runtime": "^0.13.11"
+                    }
+                },
+                "@emotion/cache": {
+                    "version": "11.10.8",
+                    "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.8.tgz",
+                    "integrity": "sha512-5fyqGHi51LU95o7qQ/vD1jyvC4uCY5GcBT+UgP4LHdpO9jPDlXqhrRr9/wCKmfoAvh5G/F7aOh4MwQa+8uEqhA==",
+                    "requires": {
+                        "@emotion/memoize": "^0.8.0",
+                        "@emotion/sheet": "^1.2.1",
+                        "@emotion/utils": "^1.2.0",
+                        "@emotion/weak-memoize": "^0.3.0",
+                        "stylis": "4.1.4"
+                    }
+                },
+                "@emotion/memoize": {
+                    "version": "0.8.0",
+                    "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz",
+                    "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="
+                },
+                "@emotion/sheet": {
+                    "version": "1.2.1",
+                    "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.1.tgz",
+                    "integrity": "sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA=="
+                },
+                "@emotion/utils": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz",
+                    "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw=="
+                },
+                "@emotion/weak-memoize": {
+                    "version": "0.3.0",
+                    "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz",
+                    "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg=="
+                },
+                "csstype": {
+                    "version": "3.1.2",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
+                    "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
+                },
+                "regenerator-runtime": {
+                    "version": "0.13.11",
+                    "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+                    "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+                },
+                "stylis": {
+                    "version": "4.1.4",
+                    "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.4.tgz",
+                    "integrity": "sha512-USf5pszRYwuE6hg9by0OkKChkQYEXfkeTtm0xKw+jqQhwyjCVLdYyMBK7R+n7dhzsblAWJnGxju4vxq5eH20GQ=="
+                }
+            }
+        },
+        "@mui/system": {
+            "version": "5.12.1",
+            "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.12.1.tgz",
+            "integrity": "sha512-Po+sicdV3bbRYXdU29XZaHPZrW7HUYUqU1qCu77GCCEMbahC756YpeyefdIYuPMUg0OdO3gKIUfDISBrkjJL+w==",
             "requires": {
-                "@babel/runtime": "^7.4.4",
-                "@material-ui/utils": "^4.11.3",
-                "csstype": "^2.5.2",
-                "prop-types": "^15.7.2"
+                "@babel/runtime": "^7.21.0",
+                "@mui/private-theming": "^5.12.0",
+                "@mui/styled-engine": "^5.12.0",
+                "@mui/types": "^7.2.4",
+                "@mui/utils": "^5.12.0",
+                "clsx": "^1.2.1",
+                "csstype": "^3.1.2",
+                "prop-types": "^15.8.1"
+            },
+            "dependencies": {
+                "@babel/runtime": {
+                    "version": "7.21.5",
+                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz",
+                    "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==",
+                    "requires": {
+                        "regenerator-runtime": "^0.13.11"
+                    }
+                },
+                "clsx": {
+                    "version": "1.2.1",
+                    "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
+                    "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg=="
+                },
+                "csstype": {
+                    "version": "3.1.2",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
+                    "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
+                },
+                "regenerator-runtime": {
+                    "version": "0.13.11",
+                    "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+                    "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+                }
             }
         },
-        "@material-ui/types": {
-            "version": "5.1.0",
-            "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz",
-            "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==",
-            "requires": {}
+        "@mui/types": {
+            "version": "7.2.4",
+            "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.4.tgz",
+            "integrity": "sha512-LBcwa8rN84bKF+f5sDyku42w1NTxaPgPyYKODsh01U1fVstTClbUoSA96oyRBnSNyEiAVjKm6Gwx9vjR+xyqHA=="
         },
-        "@material-ui/utils": {
-            "version": "4.11.3",
-            "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.3.tgz",
-            "integrity": "sha512-ZuQPV4rBK/V1j2dIkSSEcH5uT6AaHuKWFfotADHsC0wVL1NLd2WkFCm4ZZbX33iO4ydl6V0GPngKm8HZQ2oujg==",
+        "@mui/utils": {
+            "version": "5.12.0",
+            "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.12.0.tgz",
+            "integrity": "sha512-RmQwgzF72p7Yr4+AAUO6j1v2uzt6wr7SWXn68KBsnfVpdOHyclCzH2lr/Xu6YOw9su4JRtdAIYfJFXsS6Cjkmw==",
             "requires": {
-                "@babel/runtime": "^7.4.4",
-                "prop-types": "^15.7.2",
-                "react-is": "^16.8.0 || ^17.0.0"
+                "@babel/runtime": "^7.21.0",
+                "@types/prop-types": "^15.7.5",
+                "@types/react-is": "^16.7.1 || ^17.0.0",
+                "prop-types": "^15.8.1",
+                "react-is": "^18.2.0"
+            },
+            "dependencies": {
+                "@babel/runtime": {
+                    "version": "7.21.5",
+                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz",
+                    "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==",
+                    "requires": {
+                        "regenerator-runtime": "^0.13.11"
+                    }
+                },
+                "react-is": {
+                    "version": "18.2.0",
+                    "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+                    "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
+                },
+                "regenerator-runtime": {
+                    "version": "0.13.11",
+                    "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+                    "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+                }
             }
         },
         "@octokit/auth-token": {
@@ -30473,6 +1503,11 @@
                 "@octokit/openapi-types": "^12.11.0"
             }
         },
+        "@popperjs/core": {
+            "version": "2.11.7",
+            "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz",
+            "integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw=="
+        },
         "@react-google-maps/api": {
             "version": "2.12.0",
             "resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-2.12.0.tgz",
@@ -30609,7 +1644,7 @@
         "@types/bcrypt-nodejs": {
             "version": "0.0.30",
             "resolved": "https://registry.npmjs.org/@types/bcrypt-nodejs/-/bcrypt-nodejs-0.0.30.tgz",
-            "integrity": "sha1-TN2WtJKTs5MhIuS34pVD415rrlg=",
+            "integrity": "sha512-gSWCu7EOXhcM0FYM8tanV0deaX1VM07sgBS8dSUmgnAQ5/3Xn6k+mWF+ZfE+c/OCW14IVnNdTOKcHgvL78oDFQ==",
             "dev": true
         },
         "@types/bezier-js": {
@@ -30810,6 +1845,7 @@
             "version": "8.4.3",
             "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.3.tgz",
             "integrity": "sha512-YP1S7YJRMPs+7KZKDb9G63n8YejIwW9BALq7a5j2+H4yl6iOv9CB29edho+cuFRrvmJbbaH2yiVChKLJVysDGw==",
+            "dev": true,
             "requires": {
                 "@types/estree": "*",
                 "@types/json-schema": "*"
@@ -30819,6 +1855,7 @@
             "version": "3.7.3",
             "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz",
             "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==",
+            "dev": true,
             "requires": {
                 "@types/eslint": "*",
                 "@types/estree": "*"
@@ -30827,7 +1864,8 @@
         "@types/estree": {
             "version": "0.0.51",
             "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz",
-            "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ=="
+            "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==",
+            "dev": true
         },
         "@types/events": {
             "version": "3.0.0",
@@ -31148,7 +2186,8 @@
         "@types/node": {
             "version": "10.17.60",
             "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz",
-            "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw=="
+            "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==",
+            "dev": true
         },
         "@types/nodemailer": {
             "version": "4.6.8",
@@ -31468,6 +2507,31 @@
                 "react-icons": "*"
             }
         },
+        "@types/react-is": {
+            "version": "17.0.4",
+            "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-17.0.4.tgz",
+            "integrity": "sha512-FLzd0K9pnaEvKz4D1vYxK9JmgQPiGk1lu23o1kqGsLeT0iPbRSF7b76+S5T9fD8aRa0B8bY7I/3DebEj+1ysBA==",
+            "requires": {
+                "@types/react": "^17"
+            },
+            "dependencies": {
+                "@types/react": {
+                    "version": "17.0.58",
+                    "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.58.tgz",
+                    "integrity": "sha512-c1GzVY97P0fGxwGxhYq989j4XwlcHQoto6wQISOC2v6wm3h0PORRWJFHlkRjfGsiG3y1609WdQ+J+tKxvrEd6A==",
+                    "requires": {
+                        "@types/prop-types": "*",
+                        "@types/scheduler": "*",
+                        "csstype": "^3.0.2"
+                    }
+                },
+                "csstype": {
+                    "version": "3.1.2",
+                    "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
+                    "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
+                }
+            }
+        },
         "@types/react-measure": {
             "version": "2.0.8",
             "resolved": "https://registry.npmjs.org/@types/react-measure/-/react-measure-2.0.8.tgz",
@@ -31710,7 +2774,7 @@
         "@types/strip-bom": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
-            "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=",
+            "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==",
             "dev": true
         },
         "@types/strip-json-comments": {
@@ -31746,7 +2810,7 @@
         "@types/typescript": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/@types/typescript/-/typescript-2.0.0.tgz",
-            "integrity": "sha1-xDNTnJi64oaCswfqp6D9IRW4PCg=",
+            "integrity": "sha512-WMEWfMISiJ2QKyk5/dSdgL0ZwP//PZj0jmDU0hMh51FmLq4WIYzjlngsUQZXejQL+QtkXJUOGjb3G3UCvgZuSQ==",
             "dev": true,
             "requires": {
                 "typescript": "*"
@@ -31889,6 +2953,7 @@
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz",
             "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==",
+            "dev": true,
             "requires": {
                 "@webassemblyjs/helper-numbers": "1.11.1",
                 "@webassemblyjs/helper-wasm-bytecode": "1.11.1"
@@ -31897,22 +2962,26 @@
         "@webassemblyjs/floating-point-hex-parser": {
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz",
-            "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ=="
+            "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==",
+            "dev": true
         },
         "@webassemblyjs/helper-api-error": {
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz",
-            "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg=="
+            "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==",
+            "dev": true
         },
         "@webassemblyjs/helper-buffer": {
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz",
-            "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA=="
+            "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==",
+            "dev": true
         },
         "@webassemblyjs/helper-numbers": {
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz",
             "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==",
+            "dev": true,
             "requires": {
                 "@webassemblyjs/floating-point-hex-parser": "1.11.1",
                 "@webassemblyjs/helper-api-error": "1.11.1",
@@ -31922,12 +2991,14 @@
         "@webassemblyjs/helper-wasm-bytecode": {
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz",
-            "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q=="
+            "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==",
+            "dev": true
         },
         "@webassemblyjs/helper-wasm-section": {
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz",
             "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==",
+            "dev": true,
             "requires": {
                 "@webassemblyjs/ast": "1.11.1",
                 "@webassemblyjs/helper-buffer": "1.11.1",
@@ -31939,6 +3010,7 @@
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz",
             "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==",
+            "dev": true,
             "requires": {
                 "@xtuc/ieee754": "^1.2.0"
             }
@@ -31947,6 +3019,7 @@
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz",
             "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==",
+            "dev": true,
             "requires": {
                 "@xtuc/long": "4.2.2"
             }
@@ -31954,12 +3027,14 @@
         "@webassemblyjs/utf8": {
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz",
-            "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ=="
+            "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==",
+            "dev": true
         },
         "@webassemblyjs/wasm-edit": {
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz",
             "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==",
+            "dev": true,
             "requires": {
                 "@webassemblyjs/ast": "1.11.1",
                 "@webassemblyjs/helper-buffer": "1.11.1",
@@ -31975,6 +3050,7 @@
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz",
             "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==",
+            "dev": true,
             "requires": {
                 "@webassemblyjs/ast": "1.11.1",
                 "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
@@ -31987,6 +3063,7 @@
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz",
             "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==",
+            "dev": true,
             "requires": {
                 "@webassemblyjs/ast": "1.11.1",
                 "@webassemblyjs/helper-buffer": "1.11.1",
@@ -31998,6 +3075,7 @@
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz",
             "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==",
+            "dev": true,
             "requires": {
                 "@webassemblyjs/ast": "1.11.1",
                 "@webassemblyjs/helper-api-error": "1.11.1",
@@ -32011,6 +3089,7 @@
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz",
             "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==",
+            "dev": true,
             "requires": {
                 "@webassemblyjs/ast": "1.11.1",
                 "@xtuc/long": "4.2.2"
@@ -32019,8 +3098,7 @@
         "@webpack-cli/configtest": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz",
-            "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==",
-            "requires": {}
+            "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg=="
         },
         "@webpack-cli/info": {
             "version": "1.5.0",
@@ -32033,8 +3111,7 @@
         "@webpack-cli/serve": {
             "version": "1.7.0",
             "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz",
-            "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==",
-            "requires": {}
+            "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q=="
         },
         "@webscopeio/react-textarea-autocomplete": {
             "version": "4.9.1",
@@ -32048,19 +3125,31 @@
                 "textarea-caret": {
                     "version": "3.0.2",
                     "resolved": "https://registry.npmjs.org/textarea-caret/-/textarea-caret-3.0.2.tgz",
-                    "integrity": "sha512-gRzeti2YS4did7UJnPQ47wrjD+vp+CJIe9zbsu0bJ987d8QVLvLNG9757rqiQTIy4hGIeFauTTJt5Xkn51UkXg=="
+                    "integrity": "sha1-82DEhpmqGr9xhoCkOjGoUGZcLK8="
                 }
             }
         },
         "@xtuc/ieee754": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
-            "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="
+            "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+            "dev": true
         },
         "@xtuc/long": {
             "version": "4.2.2",
             "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
-            "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
+            "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+            "dev": true
+        },
+        "Base64": {
+            "version": "0.2.1",
+            "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz",
+            "integrity": "sha512-reGEWshDmTDQDsCec/HduOO9Wyj6yMOupMfhIf3ugN1TDlK2NQW4DDJSqNNtp380SNcvRfXtO8HSCQot0d0SMw=="
+        },
+        "D": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/D/-/D-1.0.0.tgz",
+            "integrity": "sha512-nQvrCBu7K2pSSEtIM0EEF03FVjcczCXInMt3moLNFbjlWx6bZrX72uT6/1uAXDbnzGUAx9gTyDiQ+vrFi663oA=="
         },
         "abab": {
             "version": "2.0.6",
@@ -32098,7 +3187,7 @@
         "acorn-globals": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz",
-            "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=",
+            "integrity": "sha512-uWttZCk96+7itPxK8xCzY86PnxKTMrReKDqrHzv42VQY0K30PUO8WY13WMOuI+cOdX4EIdzdvQ8k6jkuGRFMYw==",
             "requires": {
                 "acorn": "^4.0.4"
             },
@@ -32106,7 +3195,7 @@
                 "acorn": {
                     "version": "4.0.13",
                     "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
-                    "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c="
+                    "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug=="
                 }
             }
         },
@@ -32114,13 +3203,12 @@
             "version": "1.8.0",
             "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
             "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
-            "requires": {}
+            "dev": true
         },
         "acorn-jsx": {
             "version": "5.3.2",
             "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
-            "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
-            "requires": {}
+            "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="
         },
         "acorn-walk": {
             "version": "6.2.0",
@@ -32136,7 +3224,7 @@
         "after": {
             "version": "0.8.2",
             "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
-            "integrity": "sha512-QbJ0NTQ/I9DI3uSJA4cbexiwQeRAfjPScqIbSjUDd9TOrcg6pTkdgziesOqxBMBzit8vFCTwrP27t13vFOORRA=="
+            "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8="
         },
         "agent-base": {
             "version": "6.0.2",
@@ -32175,8 +3263,7 @@
         "ajv-errors": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
-            "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
-            "requires": {}
+            "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ=="
         },
         "ajv-formats": {
             "version": "2.1.1",
@@ -32207,13 +3294,12 @@
         "ajv-keywords": {
             "version": "3.5.2",
             "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
-            "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
-            "requires": {}
+            "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ=="
         },
         "align-text": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
-            "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
+            "integrity": "sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==",
             "requires": {
                 "kind-of": "^3.0.2",
                 "longest": "^1.0.1",
@@ -32228,7 +3314,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -32238,12 +3324,12 @@
         "amdefine": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
-            "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
+            "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg=="
         },
         "ansi-align": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz",
-            "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=",
+            "integrity": "sha512-TdlOggdA/zURfMYa7ABC66j+oqfMew58KpJMbUlH3bcZP1b+cBHIHDDn5uH9INsxrHBPjsqM0tDB4jPTF/vgJA==",
             "requires": {
                 "string-width": "^2.0.0"
             }
@@ -32307,7 +3393,7 @@
         "any-promise": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
-            "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
+            "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
         },
         "anymatch": {
             "version": "2.0.0",
@@ -32321,7 +3407,7 @@
                 "normalize-path": {
                     "version": "2.1.1",
                     "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
-                    "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+                    "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==",
                     "requires": {
                         "remove-trailing-separator": "^1.0.1"
                     }
@@ -32416,7 +3502,7 @@
         "arr-diff": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
-            "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
+            "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA=="
         },
         "arr-flatten": {
             "version": "1.1.0",
@@ -32426,7 +3512,7 @@
         "arr-union": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
-            "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
+            "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q=="
         },
         "array-back": {
             "version": "2.0.0",
@@ -32517,18 +3603,18 @@
         "array-equal": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
-            "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
+            "integrity": "sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==",
             "dev": true
         },
         "array-find-index": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
-            "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E="
+            "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw=="
         },
         "array-flatten": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
-            "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+            "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
         },
         "array-includes": {
             "version": "3.1.5",
@@ -32546,7 +3632,7 @@
         "array-union": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
-            "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+            "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==",
             "dev": true,
             "requires": {
                 "array-uniq": "^1.0.1"
@@ -32555,13 +3641,13 @@
         "array-uniq": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
-            "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+            "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==",
             "dev": true
         },
         "array-unique": {
             "version": "0.3.2",
             "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
-            "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
+            "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ=="
         },
         "array.prototype.flat": {
             "version": "1.3.0",
@@ -32612,7 +3698,7 @@
         "asap": {
             "version": "2.0.6",
             "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
-            "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
+            "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
         },
         "asn1": {
             "version": "0.2.6",
@@ -32625,7 +3711,7 @@
         "assert-plus": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
-            "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+            "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="
         },
         "assertion-error": {
             "version": "1.1.0",
@@ -32635,7 +3721,7 @@
         "assign-symbols": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
-            "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
+            "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw=="
         },
         "ast-types-flow": {
             "version": "0.0.7",
@@ -32665,7 +3751,7 @@
         "async-foreach": {
             "version": "0.1.3",
             "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
-            "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI="
+            "integrity": "sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA=="
         },
         "async-limiter": {
             "version": "1.0.1",
@@ -32676,7 +3762,7 @@
         "asynckit": {
             "version": "0.4.0",
             "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-            "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+            "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
         },
         "atob": {
             "version": "2.1.2",
@@ -32726,7 +3812,7 @@
         "aws-sign2": {
             "version": "0.7.0",
             "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
-            "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
+            "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA=="
         },
         "aws4": {
             "version": "1.11.0",
@@ -32756,12 +3842,12 @@
         "babel": {
             "version": "6.23.0",
             "resolved": "https://registry.npmjs.org/babel/-/babel-6.23.0.tgz",
-            "integrity": "sha1-0NHn2APpdHZb7qMjLU4VPA77kPQ="
+            "integrity": "sha512-ZDcCaI8Vlct8PJ3DvmyqUz+5X2Ylz3ZuuItBe/74yXosk2dwyVo/aN7MCJ8HJzhnnJ+6yP4o+lDgG9MBe91DLA=="
         },
         "babel-code-frame": {
             "version": "6.26.0",
             "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
-            "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+            "integrity": "sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==",
             "dev": true,
             "requires": {
                 "chalk": "^1.1.3",
@@ -32772,19 +3858,19 @@
                 "ansi-regex": {
                     "version": "2.1.1",
                     "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+                    "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
                     "dev": true
                 },
                 "ansi-styles": {
                     "version": "2.2.1",
                     "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-                    "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+                    "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==",
                     "dev": true
                 },
                 "chalk": {
                     "version": "1.1.3",
                     "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-                    "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+                    "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
                     "dev": true,
                     "requires": {
                         "ansi-styles": "^2.2.1",
@@ -32797,7 +3883,7 @@
                 "js-tokens": {
                     "version": "3.0.2",
                     "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
-                    "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+                    "integrity": "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==",
                     "dev": true
                 },
                 "strip-ansi": {
@@ -32881,12 +3967,12 @@
         "babel-plugin-syntax-jsx": {
             "version": "6.18.0",
             "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
-            "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
+            "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw=="
         },
         "babel-runtime": {
             "version": "6.26.0",
             "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
-            "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+            "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
             "requires": {
                 "core-js": "^2.4.0",
                 "regenerator-runtime": "^0.11.0"
@@ -32907,7 +3993,7 @@
         "babel-types": {
             "version": "6.26.0",
             "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
-            "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+            "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==",
             "requires": {
                 "babel-runtime": "^6.26.0",
                 "esutils": "^2.0.2",
@@ -32930,7 +4016,7 @@
         "backo2": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
-            "integrity": "sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA=="
+            "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
         },
         "bail": {
             "version": "2.0.2",
@@ -32959,7 +4045,7 @@
                 "define-property": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-                    "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+                    "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
                     "requires": {
                         "is-descriptor": "^1.0.0"
                     }
@@ -32995,17 +4081,12 @@
         "base16": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz",
-            "integrity": "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA="
-        },
-        "Base64": {
-            "version": "0.2.1",
-            "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz",
-            "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg="
+            "integrity": "sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ=="
         },
         "base64-arraybuffer": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz",
-            "integrity": "sha512-a1eIFi4R9ySrbiMuyTGx5e92uRH5tQY6kArNcFaKBUleIoLjdjBg7Zxm3Mqm3Kmkf27HLR/1fnxX9q8GQ7Iavg=="
+            "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI="
         },
         "base64-js": {
             "version": "1.5.1",
@@ -33025,18 +4106,18 @@
         "batch": {
             "version": "0.6.1",
             "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
-            "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
+            "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
             "dev": true
         },
         "bcrypt-nodejs": {
             "version": "0.0.3",
             "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz",
-            "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs="
+            "integrity": "sha512-NmTbLm867btBHCBZ222FQXkQKzecB0KG6pTXFa6NeTVZaSnLfCsx7EK2PL3J+kX8xJThUquEBbhimRCKKZX9zA=="
         },
         "bcrypt-pbkdf": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
-            "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+            "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
             "requires": {
                 "tweetnacl": "^0.14.3"
             }
@@ -33049,7 +4130,7 @@
         "bezier-curve": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/bezier-curve/-/bezier-curve-1.0.0.tgz",
-            "integrity": "sha1-o9+v6rEqlMRicw1QeYxSqEBdc3k="
+            "integrity": "sha512-h6uZJ6qdFfswS1rIRericgouhTeiVi/MnH10OKtCu2IZzXa+ZcjaxRLHY4u/evRsJcxYbbiNkgWQj2Z4UIcpEQ=="
         },
         "bezier-js": {
             "version": "4.1.1",
@@ -33098,7 +4179,7 @@
         "block-stream": {
             "version": "0.0.9",
             "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
-            "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+            "integrity": "sha512-OorbnJVPII4DuUKbjARAe8u8EfqOmkEEaSFIyoQ7OjTHn6kafxWl0wLgoZ2rXaYd7MyLcDaU4TmhfxtwgcccMQ==",
             "requires": {
                 "inherits": "~2.0.0"
             }
@@ -33161,7 +4242,7 @@
         "bonjour": {
             "version": "3.5.0",
             "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
-            "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
+            "integrity": "sha512-RaVTblr+OnEli0r/ud8InrU7D+G0y6aJhlxaLa6Pwty4+xoxboF1BsUI45tujvRpbj9dQVoglChqonGAsjEBYg==",
             "dev": true,
             "requires": {
                 "array-flatten": "^2.1.0",
@@ -33183,13 +4264,12 @@
         "boolbase": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
-            "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
+            "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
         },
         "bootstrap": {
             "version": "4.6.1",
             "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.1.tgz",
-            "integrity": "sha512-0dj+VgI9Ecom+rvvpNZ4MUZJz8dcX7WCX+eTID9+/8HgOkv3dsRzi8BGeZJCQU6flWQVYxwTQnEZFrmJSEO7og==",
-            "requires": {}
+            "integrity": "sha512-0dj+VgI9Ecom+rvvpNZ4MUZJz8dcX7WCX+eTID9+/8HgOkv3dsRzi8BGeZJCQU6flWQVYxwTQnEZFrmJSEO7og=="
         },
         "bowser": {
             "version": "1.9.4",
@@ -33213,7 +4293,7 @@
                 "camelcase": {
                     "version": "4.1.0",
                     "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-                    "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+                    "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw=="
                 }
             }
         },
@@ -33246,7 +4326,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -33291,7 +4371,7 @@
         "browser-assert": {
             "version": "1.2.1",
             "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz",
-            "integrity": "sha1-mqpaKox0aFwq4Fv+Ru/WBvBowgA="
+            "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ=="
         },
         "browser-process-hrtime": {
             "version": "1.0.0",
@@ -33336,12 +4416,12 @@
         "buffer-crc32": {
             "version": "0.2.13",
             "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
-            "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
+            "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="
         },
         "buffer-equal-constant-time": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
-            "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
+            "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
         },
         "buffer-from": {
             "version": "1.1.2",
@@ -33357,12 +4437,12 @@
         "buffer-shims": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
-            "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E="
+            "integrity": "sha512-Zy8ZXMyxIT6RMTeY7OP/bDndfj6bwCan7SS98CEndS6deHwWPpseeHlwarNcBim+etXnF9HBc1non5JgDaJU1g=="
         },
         "built-in-math-eval": {
             "version": "0.3.0",
             "resolved": "https://registry.npmjs.org/built-in-math-eval/-/built-in-math-eval-0.3.0.tgz",
-            "integrity": "sha1-JA3CHLOJQ5WIxhxGDrAHZJfvxBw=",
+            "integrity": "sha512-5XD5cujru60ooKJ4sGZqoH5v2Xvgw7ezV54gJX/OnPkgDKoH3BnlMEi8xW6hl8xaEjxKHebgrsawroeZnGwIMA==",
             "requires": {
                 "math-codegen": "^0.3.5"
             }
@@ -33493,7 +4573,7 @@
         "caller-callsite": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
-            "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+            "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==",
             "requires": {
                 "callsites": "^2.0.0"
             },
@@ -33501,14 +4581,14 @@
                 "callsites": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
-                    "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA="
+                    "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ=="
                 }
             }
         },
         "caller-path": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
-            "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+            "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==",
             "requires": {
                 "caller-callsite": "^2.0.0"
             }
@@ -33535,7 +4615,7 @@
         "camelcase-keys": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
-            "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+            "integrity": "sha512-bA/Z/DERHKqoEOrp+qeGKw1QlvEQkGZSc0XaY6VnTxZr+Kv1G5zFwttpjv8qxZ/sBPT4nthwZaAcsAZTJlSKXQ==",
             "requires": {
                 "camelcase": "^2.0.0",
                 "map-obj": "^1.0.0"
@@ -33544,14 +4624,14 @@
                 "camelcase": {
                     "version": "2.1.1",
                     "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
-                    "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
+                    "integrity": "sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw=="
                 }
             }
         },
         "camelize": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
-            "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
+            "integrity": "sha512-W2lPwkBkMZwFlPCXhIlYgxu+7gC/NUlCtdK652DAJ1JdgV0sTrvuPFshNPrFa1TY2JOkLhgdeEBplB4ezEa+xg=="
         },
         "caniuse-lite": {
             "version": "1.0.30001351",
@@ -33576,7 +4656,7 @@
         "caseless": {
             "version": "0.12.0",
             "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
-            "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
+            "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
         },
         "ccount": {
             "version": "2.0.1",
@@ -33586,7 +4666,7 @@
         "center-align": {
             "version": "0.1.3",
             "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
-            "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
+            "integrity": "sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==",
             "requires": {
                 "align-text": "^0.1.3",
                 "lazy-cache": "^1.0.3"
@@ -33624,7 +4704,7 @@
         "change-emitter": {
             "version": "0.1.6",
             "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz",
-            "integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU="
+            "integrity": "sha512-YXzt1cQ4a2jqazhcuSWEOc1K2q8g9H6eWNsyZgi640LDzRWVQ2eDe+Y/kVdftH+vYdPF2rgDb3dLdpxE1jvAxw=="
         },
         "character-entities": {
             "version": "2.0.2",
@@ -33634,7 +4714,7 @@
         "character-parser": {
             "version": "2.2.0",
             "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz",
-            "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=",
+            "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==",
             "requires": {
                 "is-regex": "^1.0.3"
             }
@@ -33648,12 +4728,12 @@
         "check-error": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
-            "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
+            "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA=="
         },
         "child_process": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz",
-            "integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o="
+            "integrity": "sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g=="
         },
         "chokidar": {
             "version": "2.1.8",
@@ -33682,7 +4762,7 @@
         "chrome": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/chrome/-/chrome-0.1.0.tgz",
-            "integrity": "sha1-9h2beS/v6MGUxwVt3BAscmqGQyk=",
+            "integrity": "sha512-6KYl20U4Taj6YipylsWr2etUvp9AElJKfGNSBmyGTymYmancnOb041ZNadolEZi2nboLXH7jMSqUmm4kpuTzfg==",
             "requires": {
                 "exeq": "^2.2.0",
                 "plist": "^1.1.0"
@@ -33691,7 +4771,8 @@
         "chrome-trace-event": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
-            "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg=="
+            "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
+            "dev": true
         },
         "ci-info": {
             "version": "1.6.0",
@@ -33701,7 +4782,7 @@
         "clamp": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz",
-            "integrity": "sha1-ZqDmQBGBbjcZaCj9yMjBRzEshjQ="
+            "integrity": "sha512-kgMuFyE78OC6Dyu3Dy7vcx4uy97EIbVxJB/B0eJ3bUNAkwdNcxYzgKltnyADiYwsR7SEqkkUPsEUT//OVS6XMA=="
         },
         "class-transformer": {
             "version": "0.2.3",
@@ -33722,7 +4803,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -33752,7 +4833,7 @@
         "cli-boxes": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
-            "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM="
+            "integrity": "sha512-3Fo5wu8Ytle8q9iCzS4D2MWVL2X7JVWRiS1BnXbTFDhS9c/REkM9vd1AmabsoZoY5/dGi5TT9iKL8Kb6DeBRQg=="
         },
         "cli-cursor": {
             "version": "3.1.0",
@@ -33772,7 +4853,7 @@
         "clipboard": {
             "version": "1.7.1",
             "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-1.7.1.tgz",
-            "integrity": "sha1-Ng1taUbpmnof7zleQrqStem1oWs=",
+            "integrity": "sha512-smkaRaIQsrnKN1F3wd1/vY9Q+DeR4L8ZCXKeHCFC2j8RZuSBbuImcLdnIO4GTxmzJxQuDGNKkyfpGoPW7Ua5bQ==",
             "requires": {
                 "good-listener": "^1.2.2",
                 "select": "^1.1.2",
@@ -33797,7 +4878,7 @@
                 "camelcase": {
                     "version": "4.1.0",
                     "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-                    "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+                    "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw=="
                 },
                 "yargs-parser": {
                     "version": "7.0.0",
@@ -33847,7 +4928,7 @@
         "clj-fuzzy": {
             "version": "0.3.3",
             "resolved": "https://registry.npmjs.org/clj-fuzzy/-/clj-fuzzy-0.3.3.tgz",
-            "integrity": "sha1-seU0MJHFIC28UlMoY+HEp4RX8D0="
+            "integrity": "sha512-9cyh9A8+OphDZeKIG21MgyDHWDkWxTvagwvFLVjtdi6eToFENF7iDLlKwhHrnBQRSQwprKNhazG053nE/UgwfQ=="
         },
         "clone-deep": {
             "version": "4.0.1",
@@ -33862,7 +4943,7 @@
         "clone-response": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
-            "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
+            "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==",
             "requires": {
                 "mimic-response": "^1.0.0"
             },
@@ -33882,12 +4963,12 @@
         "code-point-at": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
-            "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+            "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA=="
         },
         "collection-visit": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
-            "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+            "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==",
             "requires": {
                 "map-visit": "^1.0.0",
                 "object-visit": "^1.0.0"
@@ -33913,7 +4994,7 @@
         "color-name": {
             "version": "1.1.3",
             "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-            "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+            "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
         },
         "color-string": {
             "version": "1.9.1",
@@ -33976,13 +5057,13 @@
         "commondir": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
-            "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+            "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
             "dev": true
         },
         "component-bind": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
-            "integrity": "sha512-WZveuKPeKAG9qY+FkYDeADzdHyTYdIboXS59ixDeRJL5ZhxpqUnxSOwop4FQjMsiYm3/Or8cegVbpAHNA7pHxw=="
+            "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E="
         },
         "component-emitter": {
             "version": "1.3.0",
@@ -33992,7 +5073,7 @@
         "component-inherit": {
             "version": "0.0.3",
             "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
-            "integrity": "sha512-w+LhYREhatpVqTESyGFg3NlP6Iu0kEKUHETY9GoZP/pQyW4mHFZuFWRUCIqVPZ36ueVLtoOEZaAqbCF2RDndaA=="
+            "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM="
         },
         "compress-brotli": {
             "version": "1.3.8",
@@ -34057,7 +5138,7 @@
                 "bytes": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
-                    "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
+                    "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
                     "dev": true
                 },
                 "debug": {
@@ -34072,7 +5153,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
                     "dev": true
                 }
             }
@@ -34080,7 +5161,7 @@
         "concat-map": {
             "version": "0.0.1",
             "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-            "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+            "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
         },
         "concat-stream": {
             "version": "1.6.2",
@@ -34146,7 +5227,7 @@
         "connect-flash": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz",
-            "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA="
+            "integrity": "sha512-2rcfELQt/ZMP+SM/pG8PyhJRaLKp+6Hk2IUBNkEit09X+vwn3QsAL3ZbYtxUn7NVPzbMTSLRDhqe0B/eh30RYA=="
         },
         "connect-history-api-fallback": {
             "version": "1.6.0",
@@ -34175,12 +5256,12 @@
                 "process-nextick-args": {
                     "version": "1.0.7",
                     "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
-                    "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
+                    "integrity": "sha512-yN0WQmuCX63LP/TMvAg31nvT6m4vDqJEiiv2CAZqWOGNWutc9DfDk1NPYYmKUFmaVM2UwDowH4u5AHWYP/jxKw=="
                 },
                 "readable-stream": {
                     "version": "2.2.7",
                     "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz",
-                    "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=",
+                    "integrity": "sha512-a6ibcfWFhgihuTw/chl+u3fB5ykBZFmnvpyZHebY0MCQE4vvYcsCLpCeaQ1BkH7HdJYavNSqF0WDLeo4IPHQaQ==",
                     "requires": {
                         "buffer-shims": "~1.0.0",
                         "core-util-is": "~1.0.0",
@@ -34204,7 +5285,7 @@
         "console-control-strings": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
-            "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
+            "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
         },
         "constantinople": {
             "version": "3.1.2",
@@ -34288,7 +5369,7 @@
         "cookie-signature": {
             "version": "1.0.6",
             "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
-            "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+            "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
         },
         "cookies": {
             "version": "0.8.0",
@@ -34333,7 +5414,7 @@
         "copy-descriptor": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
-            "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
+            "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw=="
         },
         "copy-webpack-plugin": {
             "version": "4.6.0",
@@ -34363,7 +5444,7 @@
                 "p-try": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
-                    "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+                    "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
                     "dev": true
                 },
                 "serialize-javascript": {
@@ -34377,7 +5458,7 @@
         "core-js": {
             "version": "1.2.7",
             "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
-            "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
+            "integrity": "sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA=="
         },
         "core-js-pure": {
             "version": "3.22.8",
@@ -34441,7 +5522,7 @@
         "create-error-class": {
             "version": "3.0.2",
             "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
-            "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=",
+            "integrity": "sha512-gYTKKexFO3kh200H1Nit76sRwRtOY32vQd3jpAQKpLtZqyNsSQNfI4N7o3eP2wUjV35pTWKRYqFUDBvUha/Pkw==",
             "requires": {
                 "capture-stack-trace": "^1.0.0"
             }
@@ -34506,7 +5587,7 @@
         "cross-spawn": {
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
-            "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
+            "integrity": "sha512-eZ+m1WNhSZutOa/uRblAc9Ut5MQfukFrFMtPSm3bZCA888NmMd5AWXWdgRZ80zd+pTk1P2JrGjg9pUPTvl2PWQ==",
             "requires": {
                 "lru-cache": "^4.0.1",
                 "which": "^1.2.9"
@@ -34536,7 +5617,7 @@
         "crypto-random-string": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
-            "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4="
+            "integrity": "sha512-GsVpkFPlycH7/fRR7Dhcmnoii54gV1nz7y4CWyeFS14N+JVBBhY+r8amRHE4BwSYal7BPTDp8isvAlCxyFt3Hg=="
         },
         "css-box-model": {
             "version": "1.2.1",
@@ -34549,7 +5630,7 @@
         "css-color-keywords": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
-            "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU="
+            "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg=="
         },
         "css-in-js-utils": {
             "version": "2.0.1",
@@ -34692,7 +5773,7 @@
         "currently-unhandled": {
             "version": "0.4.1",
             "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
-            "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+            "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==",
             "requires": {
                 "array-find-index": "^1.0.1"
             }
@@ -34700,19 +5781,14 @@
         "custom-event": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz",
-            "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg=="
+            "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU="
         },
         "cyclist": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
-            "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
+            "integrity": "sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A==",
             "dev": true
         },
-        "D": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/D/-/D-1.0.0.tgz",
-            "integrity": "sha512-nQvrCBu7K2pSSEtIM0EEF03FVjcczCXInMt3moLNFbjlWx6bZrX72uT6/1uAXDbnzGUAx9gTyDiQ+vrFi663oA=="
-        },
         "d3-array": {
             "version": "2.12.1",
             "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
@@ -34847,7 +5923,7 @@
         "dashdash": {
             "version": "1.14.1",
             "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
-            "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+            "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
             "requires": {
                 "assert-plus": "^1.0.0"
             }
@@ -34899,7 +5975,7 @@
         "de-indent": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
-            "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0="
+            "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg=="
         },
         "debounce": {
             "version": "1.2.1",
@@ -34917,7 +5993,7 @@
         "decamelize": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
-            "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+            "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="
         },
         "decode-named-character-reference": {
             "version": "1.0.2",
@@ -34930,7 +6006,7 @@
         "decode-uri-component": {
             "version": "0.2.0",
             "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
-            "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
+            "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og=="
         },
         "decompress-response": {
             "version": "4.2.1",
@@ -35095,7 +6171,7 @@
                 "globby": {
                     "version": "6.1.0",
                     "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
-                    "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
+                    "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==",
                     "dev": true,
                     "requires": {
                         "array-union": "^1.0.1",
@@ -35108,7 +6184,7 @@
                         "pify": {
                             "version": "2.3.0",
                             "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-                            "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+                            "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
                             "dev": true
                         }
                     }
@@ -35133,7 +6209,7 @@
         "delayed-stream": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-            "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+            "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
         },
         "delegate": {
             "version": "3.2.0",
@@ -35143,7 +6219,7 @@
         "delegates": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
-            "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
+            "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
         },
         "denque": {
             "version": "1.5.1",
@@ -35246,7 +6322,7 @@
                 "import-fresh": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
-                    "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
+                    "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==",
                     "requires": {
                         "caller-path": "^2.0.0",
                         "resolve-from": "^3.0.0"
@@ -35281,7 +6357,7 @@
                 "parse-json": {
                     "version": "4.0.0",
                     "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
-                    "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+                    "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
                     "requires": {
                         "error-ex": "^1.3.1",
                         "json-parse-better-errors": "^1.0.1"
@@ -35295,7 +6371,7 @@
                 "resolve-from": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
-                    "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
+                    "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw=="
                 },
                 "string-width": {
                     "version": "4.2.3",
@@ -35367,7 +6443,7 @@
         "deps-regex": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/deps-regex/-/deps-regex-0.1.4.tgz",
-            "integrity": "sha1-UYZnt2kUYKXn4KNBvnbrfOgJAYQ="
+            "integrity": "sha512-3tzwGYogSJi8HoG93R5x9NrdefZQOXgHgGih/7eivloOq6yC6O+yoFxZnkgP661twvfILONfoKRdF9GQOGx2RA=="
         },
         "dequal": {
             "version": "2.0.3",
@@ -35421,7 +6497,7 @@
                 "pify": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-                    "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+                    "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
                     "dev": true
                 }
             }
@@ -35429,7 +6505,7 @@
         "dns-equal": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
-            "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
+            "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==",
             "dev": true
         },
         "dns-packet": {
@@ -35445,7 +6521,7 @@
         "dns-txt": {
             "version": "2.0.2",
             "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
-            "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
+            "integrity": "sha512-Ix5PrWjphuSoUXV/Zv5gaFHjnaJtb02F2+Si3Ht9dyJ87+Z/lMmy+dpNHtTGraNK958ndXq2i+GLkWsWHcKaBQ==",
             "dev": true,
             "requires": {
                 "buffer-indexof": "^1.0.0"
@@ -35463,7 +6539,7 @@
         "doctypes": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz",
-            "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk="
+            "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ=="
         },
         "dom-converter": {
             "version": "0.2.0",
@@ -35572,12 +6648,12 @@
         "double-bits": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/double-bits/-/double-bits-1.1.1.tgz",
-            "integrity": "sha1-WKu6RUlNpND6Nrc60RoobJGEscY="
+            "integrity": "sha512-BCLEIBq0O/DWoA7BsCu/R+RP0ZXiowP8BhtJT3qeuuQEBpnS8LK/Wo6UTJQv6v8mK1fj8n90YziHLwGdM5whSg=="
         },
         "duplexer3": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
-            "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
+            "integrity": "sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA=="
         },
         "duplexify": {
             "version": "3.7.1",
@@ -35611,7 +6687,7 @@
         "dynamic-dedupe": {
             "version": "0.3.0",
             "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
-            "integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=",
+            "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==",
             "dev": true,
             "requires": {
                 "xtend": "^4.0.0"
@@ -35620,7 +6696,7 @@
         "ecc-jsbn": {
             "version": "0.1.2",
             "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
-            "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+            "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
             "requires": {
                 "jsbn": "~0.1.0",
                 "safer-buffer": "^2.1.0"
@@ -35637,7 +6713,7 @@
         "ee-first": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-            "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+            "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
         },
         "electron-to-chromium": {
             "version": "1.4.149",
@@ -35666,7 +6742,7 @@
         "encodeurl": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
-            "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+            "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
         },
         "encoding": {
             "version": "0.1.13",
@@ -35708,8 +6784,7 @@
                 "ws": {
                     "version": "7.4.6",
                     "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
-                    "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
-                    "requires": {}
+                    "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A=="
                 }
             }
         },
@@ -35742,13 +6817,12 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
                 },
                 "ws": {
                     "version": "7.4.6",
                     "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
-                    "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
-                    "requires": {}
+                    "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A=="
                 }
             }
         },
@@ -35768,6 +6842,7 @@
             "version": "5.9.3",
             "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz",
             "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==",
+            "dev": true,
             "requires": {
                 "graceful-fs": "^4.2.4",
                 "tapable": "^2.2.0"
@@ -35859,7 +6934,8 @@
         "es-module-lexer": {
             "version": "0.9.3",
             "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz",
-            "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ=="
+            "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==",
+            "dev": true
         },
         "es-shim-unscopables": {
             "version": "1.0.0",
@@ -35883,7 +6959,7 @@
         "es6-promise": {
             "version": "3.2.1",
             "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz",
-            "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q="
+            "integrity": "sha512-oj4jOSXvWglTsc3wrw86iom3LDPOx1nbipQk+jaG3dy+sMRM6ReSgVr/VlmBuF6lXUrflN9DCcQHeSbAwGUl4g=="
         },
         "es6-symbol": {
             "version": "3.1.3",
@@ -35891,7 +6967,6 @@
             "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
             "dev": true,
             "requires": {
-                "d": "^1.0.1",
                 "ext": "^1.1.2"
             }
         },
@@ -35903,12 +6978,12 @@
         "escape-html": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-            "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+            "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
         },
         "escape-string-regexp": {
             "version": "1.0.5",
             "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-            "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+            "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
         },
         "escodegen": {
             "version": "1.14.3",
@@ -36712,8 +7787,7 @@
             "version": "8.5.0",
             "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz",
             "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==",
-            "dev": true,
-            "requires": {}
+            "dev": true
         },
         "eslint-import-resolver-node": {
             "version": "0.3.6",
@@ -37030,8 +8104,7 @@
             "version": "4.6.0",
             "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
             "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
-            "dev": true,
-            "requires": {}
+            "dev": true
         },
         "eslint-rule-composer": {
             "version": "0.3.0",
@@ -37043,6 +8116,7 @@
             "version": "5.1.1",
             "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
             "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+            "dev": true,
             "requires": {
                 "esrecurse": "^4.3.0",
                 "estraverse": "^4.1.1"
@@ -37108,6 +8182,7 @@
             "version": "4.3.0",
             "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
             "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+            "dev": true,
             "requires": {
                 "estraverse": "^5.2.0"
             },
@@ -37115,14 +8190,16 @@
                 "estraverse": {
                     "version": "5.3.0",
                     "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-                    "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="
+                    "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+                    "dev": true
                 }
             }
         },
         "estraverse": {
             "version": "4.3.0",
             "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
-            "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="
+            "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+            "dev": true
         },
         "esutils": {
             "version": "2.0.3",
@@ -37132,7 +8209,7 @@
         "etag": {
             "version": "1.8.1",
             "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-            "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+            "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
         },
         "event-target-shim": {
             "version": "5.0.1",
@@ -37148,7 +8225,8 @@
         "events": {
             "version": "3.3.0",
             "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
-            "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="
+            "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+            "dev": true
         },
         "eventsource": {
             "version": "2.0.2",
@@ -37159,7 +8237,7 @@
         "execa": {
             "version": "0.7.0",
             "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
-            "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+            "integrity": "sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==",
             "requires": {
                 "cross-spawn": "^5.0.1",
                 "get-stream": "^3.0.0",
@@ -37173,7 +8251,7 @@
                 "cross-spawn": {
                     "version": "5.1.0",
                     "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
-                    "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+                    "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==",
                     "requires": {
                         "lru-cache": "^4.0.1",
                         "shebang-command": "^1.2.0",
@@ -37204,7 +8282,7 @@
         "exeq": {
             "version": "2.4.0",
             "resolved": "https://registry.npmjs.org/exeq/-/exeq-2.4.0.tgz",
-            "integrity": "sha1-Td8qaEZIxCeteZNJzzO9dTWPiEo=",
+            "integrity": "sha512-B648qbDS00nQZv9UQGLT5RbZm/5dNBX10F8oWeXcgpFHSLm1249u95t/3sn2wXdQjLhlF+edAECdshFtSr1K0Q==",
             "requires": {
                 "bluebird": "^3.0.3",
                 "native-or-bluebird": "^1.2.0"
@@ -37213,7 +8291,7 @@
         "exif": {
             "version": "0.6.0",
             "resolved": "https://registry.npmjs.org/exif/-/exif-0.6.0.tgz",
-            "integrity": "sha1-YKYmaAdlQst+T1cZnUrG830sX0o=",
+            "integrity": "sha512-gEwM4uanNMfLnDNKclZ7jPEA99E3rpy4ntoS6QW8u6murZjl1o8qRaPdMoC46Syg3d9/QaET0bYKhWlTwJCPgg==",
             "requires": {
                 "debug": "^2.2"
             },
@@ -37229,7 +8307,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 }
             }
         },
@@ -37241,7 +8319,7 @@
         "expand-brackets": {
             "version": "2.1.4",
             "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
-            "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+            "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==",
             "requires": {
                 "debug": "^2.3.3",
                 "define-property": "^0.2.5",
@@ -37263,7 +8341,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -37271,7 +8349,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -37279,7 +8357,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 }
             }
         },
@@ -37362,7 +8440,7 @@
         "express-flash": {
             "version": "0.0.2",
             "resolved": "https://registry.npmjs.org/express-flash/-/express-flash-0.0.2.tgz",
-            "integrity": "sha1-I9GovPP5DXB5KOSJ+Whp7K0KzaI=",
+            "integrity": "sha512-QVUR0ZZRCaa8+iPHoUQaQJrQWcQuK/Q+19M7IUIdIEtvwhrA/ifHT7y1CVJI41YfGiOQnbGtn3uvd2vOdgu58A==",
             "requires": {
                 "connect-flash": "0.1.x"
             }
@@ -37419,7 +8497,7 @@
         "expressjs": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/expressjs/-/expressjs-1.0.1.tgz",
-            "integrity": "sha1-IgMoRpoY31rWFeK3oM6ZXxf7ru8="
+            "integrity": "sha512-eFnQ5bMJxTZ29XwRJPV8ee/OURBBMS6Fm+b5rvMMEyz6u2IxPEh2SRzMZt9WvgnV+SMLmnzkALE1DnGG1HxJCw=="
         },
         "ext": {
             "version": "1.6.0",
@@ -37446,7 +8524,7 @@
         "extend-shallow": {
             "version": "3.0.2",
             "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
-            "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+            "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==",
             "requires": {
                 "assign-symbols": "^1.0.0",
                 "is-extendable": "^1.0.1"
@@ -37502,7 +8580,7 @@
                 "define-property": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-                    "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+                    "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
                     "requires": {
                         "is-descriptor": "^1.0.0"
                     }
@@ -37510,7 +8588,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -37580,7 +8658,7 @@
         "extsprintf": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
-            "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
+            "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g=="
         },
         "fast-deep-equal": {
             "version": "3.1.3",
@@ -37601,7 +8679,7 @@
         "fast-levenshtein": {
             "version": "2.0.6",
             "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-            "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+            "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
             "dev": true
         },
         "fast-text-encoding": {
@@ -37640,7 +8718,7 @@
         "fd-slicer": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
-            "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
+            "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
             "requires": {
                 "pend": "~1.2.0"
             }
@@ -37648,7 +8726,7 @@
         "ffmpeg": {
             "version": "0.0.4",
             "resolved": "https://registry.npmjs.org/ffmpeg/-/ffmpeg-0.0.4.tgz",
-            "integrity": "sha1-HEYN+OfaUSf2LO70v6BsWciWMMs=",
+            "integrity": "sha512-3TgWUJJlZGQn+crJFyhsO/oNeRRnGTy6GhgS98oUCIfZrOW5haPPV7DUfOm3xJcHr5q3TJpjk2GudPutrNisRA==",
             "requires": {
                 "when": ">= 0.0.1"
             }
@@ -37695,7 +8773,7 @@
         "fill-range": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
-            "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+            "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==",
             "requires": {
                 "extend-shallow": "^2.0.1",
                 "is-number": "^3.0.0",
@@ -37706,7 +8784,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -37716,7 +8794,7 @@
         "filter-obj": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
-            "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs="
+            "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ=="
         },
         "finalhandler": {
             "version": "1.2.0",
@@ -37750,7 +8828,7 @@
         "find": {
             "version": "0.1.7",
             "resolved": "https://registry.npmjs.org/find/-/find-0.1.7.tgz",
-            "integrity": "sha1-yGyHrxqxjyIrvjjeyGy8dg0Wpvs=",
+            "integrity": "sha512-jPrupTOe/pO//3a9Ty2o4NqQCp0L46UG+swUnfFtdmtQVN8pEltKpAqR7Nuf6vWn0GBXx5w+R1MyZzqwjEIqdA==",
             "requires": {
                 "traverse-chain": "~0.1.0"
             }
@@ -37758,7 +8836,7 @@
         "find-cache-dir": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
-            "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
+            "integrity": "sha512-46TFiBOzX7xq/PcSWfFwkyjpemdRnMe31UQF+os0y+1W3k95f6R4SEt02Hj4p3X0Mir9gfrkmOtshFidS0VPUg==",
             "dev": true,
             "requires": {
                 "commondir": "^1.0.1",
@@ -37894,13 +8972,12 @@
         "flexlayout-react": {
             "version": "0.3.11",
             "resolved": "https://registry.npmjs.org/flexlayout-react/-/flexlayout-react-0.3.11.tgz",
-            "integrity": "sha512-V+rEfyYJBqNk9oBgotPoXg8rmom4/ji9Mvr6f7T8sIJs83RuyK1D3oOrya2ydZIUCP2T6BIvj7rFTmRRkzpU8w==",
-            "requires": {}
+            "integrity": "sha512-V+rEfyYJBqNk9oBgotPoXg8rmom4/ji9Mvr6f7T8sIJs83RuyK1D3oOrya2ydZIUCP2T6BIvj7rFTmRRkzpU8w=="
         },
         "fluent-ffmpeg": {
             "version": "2.1.2",
             "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz",
-            "integrity": "sha1-yVLeIkD4EuvaCqgAbXd27irPfXQ=",
+            "integrity": "sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q==",
             "requires": {
                 "async": ">=0.2.9",
                 "which": "^1.1.1"
@@ -37967,7 +9044,7 @@
         "for-each-property": {
             "version": "0.0.4",
             "resolved": "https://registry.npmjs.org/for-each-property/-/for-each-property-0.0.4.tgz",
-            "integrity": "sha1-z6hXrsFCLh0Sb/CHhPz2Jim8g/Y=",
+            "integrity": "sha512-xYs28PM0CKXETFzuGC6ZooH0voZlsSDZwidJcy92flQJi3PK7i3gZx23xHXCPOaD4zmet3bDo+wS7E7SujrlCw==",
             "requires": {
                 "get-prototype-chain": "^1.0.1"
             }
@@ -37975,7 +9052,7 @@
         "for-each-property-deep": {
             "version": "0.0.3",
             "resolved": "https://registry.npmjs.org/for-each-property-deep/-/for-each-property-deep-0.0.3.tgz",
-            "integrity": "sha1-MTCaSvw4qcygbxsiP1PWSm0IP60=",
+            "integrity": "sha512-qzP8QkODWVVRPpWiBZacSbBl67cTTWoBfxMG0wE46AsS1yl7qv05sGN+dHvD4s4tnvl/goe6Sp4qBI+rlVBgNg==",
             "requires": {
                 "for-each-property": "0.0.4"
             }
@@ -37983,12 +9060,12 @@
         "for-in": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
-            "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
+            "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ=="
         },
         "forever-agent": {
             "version": "0.6.1",
             "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
-            "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+            "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw=="
         },
         "fork-ts-checker-webpack-plugin": {
             "version": "1.6.0",
@@ -38042,7 +9119,7 @@
         "fragment-cache": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
-            "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+            "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==",
             "requires": {
                 "map-cache": "^0.2.2"
             }
@@ -38050,12 +9127,12 @@
         "fresh": {
             "version": "0.5.2",
             "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
-            "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+            "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
         },
         "from2": {
             "version": "2.3.0",
             "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
-            "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+            "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==",
             "dev": true,
             "requires": {
                 "inherits": "^2.0.1",
@@ -38087,7 +9164,7 @@
         "fs-extra": {
             "version": "0.26.7",
             "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz",
-            "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=",
+            "integrity": "sha512-waKu+1KumRhYv8D8gMRCKJGAMI9pRnPuEb1mvgYD0f7wBscg+h6bW4FDTmEZhB9VKxvoTtxW+Y7bnIlB7zja6Q==",
             "requires": {
                 "graceful-fs": "^4.1.2",
                 "jsonfile": "^2.1.0",
@@ -38122,7 +9199,7 @@
         "fs-write-stream-atomic": {
             "version": "1.0.10",
             "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
-            "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+            "integrity": "sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==",
             "dev": true,
             "requires": {
                 "graceful-fs": "^4.1.2",
@@ -38151,7 +9228,7 @@
         "fs.realpath": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-            "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+            "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
         },
         "fsevents": {
             "version": "1.2.13",
@@ -38332,7 +9409,7 @@
         "get-func-name": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
-            "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE="
+            "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig=="
         },
         "get-intrinsic": {
             "version": "1.1.2",
@@ -38352,12 +9429,12 @@
         "get-prototype-chain": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/get-prototype-chain/-/get-prototype-chain-1.0.1.tgz",
-            "integrity": "sha1-oXGhFeoeSQbG7ThDofABwYUQQW8="
+            "integrity": "sha512-2m7WZ0jveIg/dAbCbpUxEToaJ8Dmti5EkgDP8YM3UpHUT6SAORjE2odP8XQGNVGXMHi8q8cCCoy3HTByTaTVTw=="
         },
         "get-stdin": {
             "version": "5.0.1",
             "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz",
-            "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="
+            "integrity": "sha512-jZV7n6jGE3Gt7fgSTJoz91Ak5MuTLwMwkoYdjxuJ/AmjIsE1UC03y/IWkZCQGEvVNS9qoRNwy5BCqxImv0FVeA=="
         },
         "get-stream": {
             "version": "6.0.1",
@@ -38376,12 +9453,12 @@
         "get-value": {
             "version": "2.0.6",
             "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
-            "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
+            "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA=="
         },
         "getpass": {
             "version": "0.1.7",
             "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
-            "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+            "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
             "requires": {
                 "assert-plus": "^1.0.0"
             }
@@ -38389,7 +9466,7 @@
         "github-from-package": {
             "version": "0.0.0",
             "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
-            "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4="
+            "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
         },
         "glob": {
             "version": "7.2.3",
@@ -38407,7 +9484,7 @@
         "glob-parent": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
-            "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+            "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==",
             "requires": {
                 "is-glob": "^3.1.0",
                 "path-dirname": "^1.0.0"
@@ -38416,7 +9493,7 @@
                 "is-glob": {
                     "version": "3.1.0",
                     "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
-                    "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+                    "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==",
                     "requires": {
                         "is-extglob": "^2.1.0"
                     }
@@ -38426,12 +9503,13 @@
         "glob-to-regexp": {
             "version": "0.4.1",
             "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
-            "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
+            "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+            "dev": true
         },
         "global-dirs": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
-            "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=",
+            "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==",
             "requires": {
                 "ini": "^1.3.4"
             }
@@ -38444,7 +9522,7 @@
         "globby": {
             "version": "7.1.1",
             "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
-            "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
+            "integrity": "sha512-yANWAN2DUcBtuus5Cpd+SKROzXHs2iVXFZt/Ykrfz6SAXqacLX25NZpltE+39ceMexYF4TtEadjuSTw8+3wX4g==",
             "dev": true,
             "requires": {
                 "array-union": "^1.0.1",
@@ -38458,7 +9536,7 @@
                 "pify": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
-                    "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+                    "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
                     "dev": true
                 }
             }
@@ -38499,7 +9577,7 @@
         "golden-layout": {
             "version": "1.5.9",
             "resolved": "https://registry.npmjs.org/golden-layout/-/golden-layout-1.5.9.tgz",
-            "integrity": "sha1-o5vB9qZ+b4hreXwBbdkk6UJrp38=",
+            "integrity": "sha512-iBXDQCXOTgUEQJo96zPbjDoy5bRIk9XW5l+q+pDgLnIyReqaa1aiQctNud4epsskyLt952BG521dew5Z1liSxA==",
             "requires": {
                 "jquery": "*"
             }
@@ -38507,7 +9585,7 @@
         "good-listener": {
             "version": "1.2.2",
             "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
-            "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
+            "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
             "requires": {
                 "delegate": "^3.1.2"
             }
@@ -38545,8 +9623,7 @@
         "google-maps-react": {
             "version": "2.0.6",
             "resolved": "https://registry.npmjs.org/google-maps-react/-/google-maps-react-2.0.6.tgz",
-            "integrity": "sha512-M8Eo9WndfQEfxcmm6yRq03qdJgw1x6rQmJ9DN+a+xPQ3K7yNDGkVDbinrf4/8vcox7nELbeopbm4bpefKewWfQ==",
-            "requires": {}
+            "integrity": "sha512-M8Eo9WndfQEfxcmm6yRq03qdJgw1x6rQmJ9DN+a+xPQ3K7yNDGkVDbinrf4/8vcox7nELbeopbm4bpefKewWfQ=="
         },
         "google-p12-pem": {
             "version": "2.0.5",
@@ -38675,7 +9752,7 @@
         "har-schema": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
-            "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
+            "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q=="
         },
         "har-validator": {
             "version": "5.1.5",
@@ -38697,7 +9774,7 @@
         "has-ansi": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
-            "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+            "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==",
             "requires": {
                 "ansi-regex": "^2.0.0"
             },
@@ -38705,7 +9782,7 @@
                 "ansi-regex": {
                     "version": "2.1.1",
                     "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+                    "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="
                 }
             }
         },
@@ -38725,19 +9802,19 @@
                 "isarray": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
-                    "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ=="
+                    "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
                 }
             }
         },
         "has-cors": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
-            "integrity": "sha512-g5VNKdkFuUuVCP9gYfDJHjK2nqdQJ7aDLTnycnc2+RvsOQbuLdF5pm7vuE5J76SEBIQjs4kQY/BWq74JUmjbXA=="
+            "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk="
         },
         "has-flag": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-            "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+            "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="
         },
         "has-property-descriptors": {
             "version": "1.0.0",
@@ -38763,12 +9840,12 @@
         "has-unicode": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
-            "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
+            "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
         },
         "has-value": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
-            "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+            "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==",
             "requires": {
                 "get-value": "^2.0.6",
                 "has-values": "^1.0.0",
@@ -38778,7 +9855,7 @@
         "has-values": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
-            "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+            "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==",
             "requires": {
                 "is-number": "^3.0.0",
                 "kind-of": "^4.0.0"
@@ -38792,7 +9869,7 @@
                 "kind-of": {
                     "version": "4.0.0",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
-                    "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+                    "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -38917,7 +9994,7 @@
         "hpack.js": {
             "version": "2.1.6",
             "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
-            "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
+            "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==",
             "dev": true,
             "requires": {
                 "inherits": "^2.0.1",
@@ -38946,7 +10023,7 @@
         "html": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/html/-/html-1.0.0.tgz",
-            "integrity": "sha1-pUT6nqVJK/s6LMqCEKEL57WvH2E=",
+            "integrity": "sha512-lw/7YsdKiP3kk5PnR1INY17iJuzdAtJewxr14ozKJWbbR97znovZ0mh+WEMZ8rjc3lgTK+ID/htTjuyGKB52Kw==",
             "requires": {
                 "concat-stream": "^1.4.7"
             }
@@ -39029,7 +10106,7 @@
         "http-browserify": {
             "version": "1.7.0",
             "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz",
-            "integrity": "sha1-M3la3nLfiKz7/TZ3PO/tp2RzWyA=",
+            "integrity": "sha512-Irf/LJXmE3cBzU1eaR4+NEX6bmVLqt1wkmDiA7kBwH7zmb0D8kBAXsDmQ88hhj/qv9iEZKlyGx/hrMcFi8sOHw==",
             "requires": {
                 "Base64": "~0.2.0",
                 "inherits": "~2.0.1"
@@ -39043,7 +10120,7 @@
         "http-deceiver": {
             "version": "1.2.7",
             "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
-            "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
+            "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==",
             "dev": true
         },
         "http-errors": {
@@ -39090,7 +10167,7 @@
         "http-signature": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
-            "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+            "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
             "requires": {
                 "assert-plus": "^1.0.0",
                 "jsprim": "^1.2.2",
@@ -39109,12 +10186,12 @@
         "https": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/https/-/https-1.0.0.tgz",
-            "integrity": "sha1-PDfHrhqO65ZpBKKtHpdaGUt+06Q="
+            "integrity": "sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg=="
         },
         "https-browserify": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
-            "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
+            "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg=="
         },
         "https-proxy-agent": {
             "version": "5.0.1",
@@ -39166,7 +10243,7 @@
         "icss-replace-symbols": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz",
-            "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=",
+            "integrity": "sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==",
             "dev": true
         },
         "icss-utils": {
@@ -39186,7 +10263,7 @@
         "iferr": {
             "version": "0.1.5",
             "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
-            "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
+            "integrity": "sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==",
             "dev": true
         },
         "ignore": {
@@ -39198,7 +10275,7 @@
         "ignore-by-default": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
-            "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk="
+            "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA=="
         },
         "iink-js": {
             "version": "1.5.4",
@@ -39242,9 +10319,9 @@
         "image-size-stream": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/image-size-stream/-/image-size-stream-1.1.0.tgz",
-            "integrity": "sha1-Ivou2mbG31AQh0bacUkmSy0l+Gs=",
+            "integrity": "sha512-N505B5FSy2Xf5l/Haef+99TwfJqTu40hnU560+rC0Cm6cxtwVz2yRFh9WpOk1YEjfv3dI0PgVYAH0hmXQmjDcw==",
             "requires": {
-                "image-size": "git+https://github.com/netroy/image-size#da2c863807a3e9602617bdd357b0de3ab4a064c1",
+                "image-size": "image-size@git+https://github.com/netroy/image-size#da2c863807a3e9602617bdd357b0de3ab4a064c1",
                 "readable-stream": "^1.0.33",
                 "tryit": "^1.0.1"
             },
@@ -39256,12 +10333,12 @@
                 "isarray": {
                     "version": "0.0.1",
                     "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
-                    "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+                    "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
                 },
                 "readable-stream": {
                     "version": "1.1.14",
                     "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
-                    "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+                    "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==",
                     "requires": {
                         "core-util-is": "~1.0.0",
                         "inherits": "~2.0.1",
@@ -39279,7 +10356,7 @@
         "immediate": {
             "version": "3.0.6",
             "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
-            "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
+            "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
         },
         "import-fresh": {
             "version": "3.3.0",
@@ -39293,7 +10370,7 @@
         "import-lazy": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
-            "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM="
+            "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A=="
         },
         "import-local": {
             "version": "3.1.0",
@@ -39307,7 +10384,7 @@
         "imurmurhash": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-            "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
+            "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="
         },
         "in-publish": {
             "version": "2.0.1",
@@ -39317,7 +10394,7 @@
         "indent-string": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
-            "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+            "integrity": "sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==",
             "requires": {
                 "repeating": "^2.0.0"
             }
@@ -39325,12 +10402,12 @@
         "indexof": {
             "version": "0.0.1",
             "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
-            "integrity": "sha512-i0G7hLJ1z0DE8dsqJa2rycj9dBmNKgXBvotXtZYXakU9oivfB9Uj2ZBC27qqef2U58/ZLwalxa1X/RDCdkHtVg=="
+            "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
         },
         "inflight": {
             "version": "1.0.6",
             "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-            "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+            "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
             "requires": {
                 "once": "^1.3.0",
                 "wrappy": "1"
@@ -39347,7 +10424,7 @@
                 "camelcase": {
                     "version": "4.1.0",
                     "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-                    "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+                    "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw=="
                 }
             }
         },
@@ -39369,7 +10446,7 @@
         "inline-style-prefixer": {
             "version": "3.0.8",
             "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-3.0.8.tgz",
-            "integrity": "sha1-hVG45bTVcyROZqNLBPfTIHaitTQ=",
+            "integrity": "sha512-ne8XIyyqkRaNJ1JfL1NYzNdCNxq+MCBQhC8NgOQlzNm2vv3XxlP0VSLQUbSRCF6KPEoveCVEpayHoHzcMyZsMQ==",
             "requires": {
                 "bowser": "^1.7.3",
                 "css-in-js-utils": "^2.0.0"
@@ -39488,7 +10565,7 @@
         "inspect-function": {
             "version": "0.2.2",
             "resolved": "https://registry.npmjs.org/inspect-function/-/inspect-function-0.2.2.tgz",
-            "integrity": "sha1-hdoMUli8TDMK4yg7Z0fgdZ2QpjU=",
+            "integrity": "sha512-becs5gzcHwPrlHawscYkyQ/ShiOiosrXPhA5RVZ3qyWH4aWdD52RnMfXq/dwQXciHwiieD8aIPwdIWYv6eL+sQ==",
             "requires": {
                 "split-skip": "0.0.1",
                 "unpack-string": "0.0.2"
@@ -39497,7 +10574,7 @@
                 "split-skip": {
                     "version": "0.0.1",
                     "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.1.tgz",
-                    "integrity": "sha1-gK2ONumOV2RUzDtmfB3SXYZejwA="
+                    "integrity": "sha512-7dkvq+gofI4M8zx4iZnEZ3O1s7FP4Y/iaIDHJh5RyWrs8idcPauFi2OZe3TBi36fLvR2j5z3kSzVtz6IhPdncQ=="
                 }
             }
         },
@@ -39520,7 +10597,7 @@
                 "magicli": {
                     "version": "0.0.5",
                     "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-                    "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
+                    "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
                     "requires": {
                         "commander": "^2.9.0",
                         "get-stdin": "^5.0.1",
@@ -39571,7 +10648,7 @@
                         "inspect-function": {
                             "version": "0.2.2",
                             "resolved": "https://registry.npmjs.org/inspect-function/-/inspect-function-0.2.2.tgz",
-                            "integrity": "sha1-hdoMUli8TDMK4yg7Z0fgdZ2QpjU=",
+                            "integrity": "sha512-becs5gzcHwPrlHawscYkyQ/ShiOiosrXPhA5RVZ3qyWH4aWdD52RnMfXq/dwQXciHwiieD8aIPwdIWYv6eL+sQ==",
                             "requires": {
                                 "split-skip": "0.0.1",
                                 "unpack-string": "0.0.2"
@@ -39580,14 +10657,14 @@
                                 "split-skip": {
                                     "version": "0.0.1",
                                     "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.1.tgz",
-                                    "integrity": "sha1-gK2ONumOV2RUzDtmfB3SXYZejwA="
+                                    "integrity": "sha512-7dkvq+gofI4M8zx4iZnEZ3O1s7FP4Y/iaIDHJh5RyWrs8idcPauFi2OZe3TBi36fLvR2j5z3kSzVtz6IhPdncQ=="
                                 }
                             }
                         },
                         "magicli": {
                             "version": "0.0.5",
                             "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-                            "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
+                            "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
                             "requires": {
                                 "commander": "^2.9.0",
                                 "get-stdin": "^5.0.1",
@@ -39598,14 +10675,14 @@
                         "split-skip": {
                             "version": "0.0.2",
                             "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.2.tgz",
-                            "integrity": "sha1-2J2Iu9L3Pka1FYqjcKVhIk6A1GE="
+                            "integrity": "sha512-weHOi8BolsDnGIwhhWHbA+wKSuSpvWwjRrdj8SdbIIis2vSwOE37CQP8x3EleuzxanUr3AK8BdUy4MkiOULPZg=="
                         }
                     }
                 },
                 "split-skip": {
                     "version": "0.0.1",
                     "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.1.tgz",
-                    "integrity": "sha1-gK2ONumOV2RUzDtmfB3SXYZejwA="
+                    "integrity": "sha512-7dkvq+gofI4M8zx4iZnEZ3O1s7FP4Y/iaIDHJh5RyWrs8idcPauFi2OZe3TBi36fLvR2j5z3kSzVtz6IhPdncQ=="
                 }
             }
         },
@@ -39676,7 +10753,7 @@
         "ip-regex": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
-            "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
+            "integrity": "sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==",
             "dev": true
         },
         "ipaddr.js": {
@@ -39693,7 +10770,7 @@
         "is-accessor-descriptor": {
             "version": "0.1.6",
             "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-            "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+            "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==",
             "requires": {
                 "kind-of": "^3.0.2"
             },
@@ -39706,7 +10783,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -39725,7 +10802,7 @@
         "is-arrayish": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
-            "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
+            "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
         },
         "is-bigint": {
             "version": "1.0.4",
@@ -39738,7 +10815,7 @@
         "is-binary-path": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
-            "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+            "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==",
             "requires": {
                 "binary-extensions": "^1.0.0"
             }
@@ -39781,7 +10858,7 @@
         "is-data-descriptor": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-            "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+            "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==",
             "requires": {
                 "kind-of": "^3.0.2"
             },
@@ -39794,7 +10871,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -39829,12 +10906,12 @@
         "is-directory": {
             "version": "0.3.1",
             "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
-            "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
+            "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw=="
         },
         "is-expression": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz",
-            "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=",
+            "integrity": "sha512-vyMeQMq+AiH5uUnoBfMTwf18tO3bM6k1QXBE9D6ueAAquEfCZe3AJPtud9g6qS0+4X8xA7ndpZiDyeb2l2qOBw==",
             "requires": {
                 "acorn": "~4.0.2",
                 "object-assign": "^4.0.1"
@@ -39843,7 +10920,7 @@
                 "acorn": {
                     "version": "4.0.13",
                     "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
-                    "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c="
+                    "integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug=="
                 }
             }
         },
@@ -39855,7 +10932,7 @@
         "is-extglob": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-            "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
+            "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
         },
         "is-finite": {
             "version": "1.1.0",
@@ -39865,7 +10942,7 @@
         "is-fullwidth-code-point": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-            "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+            "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w=="
         },
         "is-generator-function": {
             "version": "1.0.10",
@@ -39886,12 +10963,12 @@
         "is-in-browser": {
             "version": "1.1.3",
             "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz",
-            "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU="
+            "integrity": "sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g=="
         },
         "is-installed-globally": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
-            "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=",
+            "integrity": "sha512-ERNhMg+i/XgDwPIPF3u24qpajVreaiSuvpb1Uu0jugw7KKcxGyCX8cgp8P5fwTmAuXku6beDHHECdKArjlg7tw==",
             "requires": {
                 "global-dirs": "^0.1.0",
                 "is-path-inside": "^1.0.0"
@@ -39905,12 +10982,12 @@
         "is-npm": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
-            "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ="
+            "integrity": "sha512-9r39FIr3d+KD9SbX0sfMsHzb5PP3uimOiwr3YupUaUFG4W0l1U57Rx3utpttV7qz5U3jmrO5auUa04LU9pyHsg=="
         },
         "is-number": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
-            "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+            "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==",
             "requires": {
                 "kind-of": "^3.0.2"
             },
@@ -39923,7 +11000,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -39941,7 +11018,7 @@
         "is-obj": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
-            "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
+            "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg=="
         },
         "is-path-cwd": {
             "version": "2.2.0",
@@ -39972,7 +11049,7 @@
         "is-path-inside": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
-            "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+            "integrity": "sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g==",
             "requires": {
                 "path-is-inside": "^1.0.1"
             }
@@ -39998,7 +11075,7 @@
         "is-redirect": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
-            "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ="
+            "integrity": "sha512-cr/SlUEe5zOGmzvj9bUyC4LVvkNVAXu4GytXLNMr1pny+a65MpQ9IJzFHD5vi7FyJgb4qt27+eS3TuQnqB+RQw=="
         },
         "is-regex": {
             "version": "1.1.4",
@@ -40033,7 +11110,7 @@
         "is-stream": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
-            "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
+            "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="
         },
         "is-string": {
             "version": "1.0.7",
@@ -40066,7 +11143,7 @@
         "is-typedarray": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
-            "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+            "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
         },
         "is-url": {
             "version": "1.2.4",
@@ -40076,7 +11153,7 @@
         "is-utf8": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
-            "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI="
+            "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q=="
         },
         "is-weakref": {
             "version": "1.0.2",
@@ -40099,28 +11176,28 @@
         "is-wsl": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
-            "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
+            "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==",
             "dev": true
         },
         "isarray": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-            "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+            "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
         },
         "isexe": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-            "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+            "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
         },
         "isobject": {
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
-            "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+            "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="
         },
         "isomorphic-fetch": {
             "version": "2.2.1",
             "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
-            "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
+            "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==",
             "requires": {
                 "node-fetch": "^1.0.1",
                 "whatwg-fetch": ">=0.10.0"
@@ -40129,7 +11206,7 @@
         "isstream": {
             "version": "0.1.2",
             "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
-            "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+            "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
         },
         "its-set": {
             "version": "1.2.3",
@@ -40144,6 +11221,7 @@
             "version": "27.5.1",
             "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
             "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
+            "dev": true,
             "requires": {
                 "@types/node": "*",
                 "merge-stream": "^2.0.0",
@@ -40153,12 +11231,14 @@
                 "has-flag": {
                     "version": "4.0.0",
                     "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-                    "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+                    "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+                    "dev": true
                 },
                 "supports-color": {
                     "version": "8.1.1",
                     "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
                     "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+                    "dev": true,
                     "requires": {
                         "has-flag": "^4.0.0"
                     }
@@ -40183,7 +11263,7 @@
         "js-stringify": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz",
-            "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds="
+            "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g=="
         },
         "js-tokens": {
             "version": "4.0.0",
@@ -40202,7 +11282,7 @@
         "jsbn": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-            "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
+            "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
         },
         "jsdom": {
             "version": "15.2.1",
@@ -40322,7 +11402,7 @@
         "json-css": {
             "version": "1.5.6",
             "resolved": "https://registry.npmjs.org/json-css/-/json-css-1.5.6.tgz",
-            "integrity": "sha1-65ZPg0ouTqobwvaY/12wB6JsfAA="
+            "integrity": "sha512-B/0T0OxZH9tSb93tXV6VOYtXqrPz/Vgz2QrCT/4NXen8HGElYkYr9V+8IrSVTMj/ftxa8cG1kcu7f3iAMlaFlQ=="
         },
         "json-parse-better-errors": {
             "version": "1.0.2",
@@ -40353,7 +11433,7 @@
         "json-stringify-safe": {
             "version": "5.0.1",
             "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
-            "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+            "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
         },
         "json5": {
             "version": "1.0.1",
@@ -40375,7 +11455,7 @@
         "jsonfile": {
             "version": "2.4.0",
             "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
-            "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
+            "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==",
             "requires": {
                 "graceful-fs": "^4.1.6"
             }
@@ -40484,7 +11564,7 @@
         "jstransformer": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz",
-            "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=",
+            "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==",
             "requires": {
                 "is-promise": "^2.0.0",
                 "promise": "^7.0.1"
@@ -40606,7 +11686,7 @@
         "klaw": {
             "version": "1.3.1",
             "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
-            "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=",
+            "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==",
             "requires": {
                 "graceful-fs": "^4.1.9"
             }
@@ -40634,7 +11714,7 @@
         "latest-version": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
-            "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=",
+            "integrity": "sha512-Be1YRHWWlZaSsrz2U+VInk+tO0EwLIyV+23RhWLINJYwg/UIikxjlj3MhH37/6/EDCAusjajvMkMMUXRaMWl/w==",
             "requires": {
                 "package-json": "^4.0.0"
             }
@@ -40642,7 +11722,7 @@
         "lazy-cache": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
-            "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
+            "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ=="
         },
         "lazystream": {
             "version": "1.0.1",
@@ -40671,7 +11751,7 @@
         "levn": {
             "version": "0.3.0",
             "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
-            "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+            "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
             "dev": true,
             "requires": {
                 "prelude-ls": "~1.1.2",
@@ -40694,7 +11774,7 @@
         "load-json-file": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
-            "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+            "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==",
             "requires": {
                 "graceful-fs": "^4.1.2",
                 "parse-json": "^2.2.0",
@@ -40706,7 +11786,7 @@
                 "parse-json": {
                     "version": "2.2.0",
                     "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
-                    "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+                    "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==",
                     "requires": {
                         "error-ex": "^1.2.0"
                     }
@@ -40716,7 +11796,8 @@
         "loader-runner": {
             "version": "4.3.0",
             "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
-            "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg=="
+            "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
+            "dev": true
         },
         "loader-utils": {
             "version": "1.4.0",
@@ -40750,22 +11831,22 @@
         "lodash._getnative": {
             "version": "3.9.1",
             "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
-            "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U="
+            "integrity": "sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA=="
         },
         "lodash.chunk": {
             "version": "4.2.0",
             "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz",
-            "integrity": "sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw="
+            "integrity": "sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w=="
         },
         "lodash.curry": {
             "version": "4.1.1",
             "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz",
-            "integrity": "sha1-JI42By7ekGUB11lmIAqG2riyMXA="
+            "integrity": "sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA=="
         },
         "lodash.debounce": {
             "version": "3.1.1",
             "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-3.1.1.tgz",
-            "integrity": "sha1-gSIRw3ipTMKdWqTjNGzwv846ffU=",
+            "integrity": "sha512-lcmJwMpdPAtChA4hfiwxTtgFeNAaow701wWUgVUqeD0XJF7vMXIN+bu/2FJSGxT0NUbZy9g9VFrlOFfPjl+0Ew==",
             "requires": {
                 "lodash._getnative": "^3.0.0"
             }
@@ -40773,42 +11854,42 @@
         "lodash.defaults": {
             "version": "4.2.0",
             "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
-            "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
+            "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
         },
         "lodash.difference": {
             "version": "4.5.0",
             "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
-            "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw="
+            "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA=="
         },
         "lodash.flatten": {
             "version": "4.4.0",
             "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
-            "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8="
+            "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g=="
         },
         "lodash.flow": {
             "version": "3.5.0",
             "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz",
-            "integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o="
+            "integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw=="
         },
         "lodash.get": {
             "version": "4.4.2",
             "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
-            "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
+            "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ=="
         },
         "lodash.isequal": {
             "version": "4.5.0",
             "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
-            "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
+            "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
         },
         "lodash.isplainobject": {
             "version": "4.0.6",
             "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
-            "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
+            "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
         },
         "lodash.memoize": {
             "version": "4.1.2",
             "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
-            "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
+            "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="
         },
         "lodash.merge": {
             "version": "4.6.2",
@@ -40818,23 +11899,23 @@
         "lodash.padend": {
             "version": "4.6.1",
             "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz",
-            "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4="
+            "integrity": "sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw=="
         },
         "lodash.sortby": {
             "version": "4.7.0",
             "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
-            "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
+            "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==",
             "dev": true
         },
         "lodash.throttle": {
             "version": "4.1.1",
             "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
-            "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
+            "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="
         },
         "lodash.union": {
             "version": "4.6.0",
             "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
-            "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg="
+            "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw=="
         },
         "log-symbols": {
             "version": "2.2.0",
@@ -40862,7 +11943,7 @@
         "longest": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
-            "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
+            "integrity": "sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg=="
         },
         "longest-streak": {
             "version": "3.0.1",
@@ -40880,7 +11961,7 @@
         "loud-rejection": {
             "version": "1.6.0",
             "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
-            "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+            "integrity": "sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ==",
             "requires": {
                 "currently-unhandled": "^0.4.1",
                 "signal-exit": "^3.0.0"
@@ -40929,7 +12010,7 @@
                 "find-up": {
                     "version": "2.1.0",
                     "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
-                    "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+                    "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
                     "requires": {
                         "locate-path": "^2.0.0"
                     }
@@ -40937,7 +12018,7 @@
                 "locate-path": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
-                    "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+                    "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
                     "requires": {
                         "p-locate": "^2.0.0",
                         "path-exists": "^3.0.0"
@@ -40954,7 +12035,7 @@
                 "p-locate": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
-                    "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+                    "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
                     "requires": {
                         "p-limit": "^1.1.0"
                     }
@@ -40962,7 +12043,7 @@
                 "p-try": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
-                    "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
+                    "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww=="
                 }
             }
         },
@@ -40990,17 +12071,17 @@
         "map-cache": {
             "version": "0.2.2",
             "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
-            "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8="
+            "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg=="
         },
         "map-obj": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
-            "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0="
+            "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg=="
         },
         "map-visit": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
-            "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+            "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==",
             "requires": {
                 "object-visit": "^1.0.0"
             }
@@ -41050,7 +12131,7 @@
         "math-codegen": {
             "version": "0.3.5",
             "resolved": "https://registry.npmjs.org/math-codegen/-/math-codegen-0.3.5.tgz",
-            "integrity": "sha1-R5nuRnfe0Ud2bQA8ykt4ee3UDMo=",
+            "integrity": "sha512-SsFYMv33FxMKYxI1PBiaZT+8AeDITK+k/PKhbHNlOPHIz5FIPF4wy78yWqanN6luXdsXENUZgCIC6xH6bfUq1g==",
             "requires": {
                 "extend": "^3.0.0",
                 "mr-parser": "^0.2.1"
@@ -41059,7 +12140,7 @@
         "mathquill": {
             "version": "0.10.1-a",
             "resolved": "https://registry.npmjs.org/mathquill/-/mathquill-0.10.1-a.tgz",
-            "integrity": "sha512-snSAEwAtwdwBFSor+nVBnWWQtTw67kgAgKMyAIxuz4ZPboy0qkWZmd7BL3lfOXp/INihhRlU1PcfaAtDaRhmzA==",
+            "integrity": "sha1-vyylaQEAY6w0vNXVKa3Ag3zVPD8=",
             "requires": {
                 "jquery": "^1.12.3"
             },
@@ -41067,14 +12148,14 @@
                 "jquery": {
                     "version": "1.12.4",
                     "resolved": "https://registry.npmjs.org/jquery/-/jquery-1.12.4.tgz",
-                    "integrity": "sha512-UEVp7PPK9xXYSk8xqXCJrkXnKZtlgWkd2GsAQbMRFK6S/ePU2JN5G2Zum8hIVjzR3CpdfSqdqAzId/xd4TJHeg=="
+                    "integrity": "sha1-AeHfuikP5z3rp3zurLD5ui/sngw="
                 }
             }
         },
         "max-safe-integer": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/max-safe-integer/-/max-safe-integer-1.0.1.tgz",
-            "integrity": "sha1-84BgvixWPYwC5tSK85Ei/YO29BA="
+            "integrity": "sha512-CHZ/Nopqh46UtA0YvLclxj9F95qExLmTnMS5fnYlXvX4zj1RUOC3cPaGEOMhdPE8SSudSQ6wkQUJLA5E/WeL4A=="
         },
         "md5-file": {
             "version": "5.0.0",
@@ -41235,7 +12316,7 @@
         "media-typer": {
             "version": "0.3.0",
             "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
-            "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+            "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
         },
         "memfs": {
             "version": "3.4.4",
@@ -41286,12 +12367,12 @@
         "memorystream": {
             "version": "0.3.1",
             "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
-            "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI="
+            "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw=="
         },
         "meow": {
             "version": "3.7.0",
             "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
-            "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+            "integrity": "sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==",
             "requires": {
                 "camelcase-keys": "^2.0.0",
                 "decamelize": "^1.1.2",
@@ -41316,17 +12397,18 @@
         "merge-descriptors": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
-            "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+            "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
         },
         "merge-stream": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
-            "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
+            "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+            "dev": true
         },
         "methods": {
             "version": "1.1.2",
             "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
-            "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+            "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
         },
         "microevent.ts": {
             "version": "0.1.1",
@@ -41817,14 +12899,12 @@
         "mobx-react-devtools": {
             "version": "6.1.1",
             "resolved": "https://registry.npmjs.org/mobx-react-devtools/-/mobx-react-devtools-6.1.1.tgz",
-            "integrity": "sha512-nc5IXLdEUFLn3wZal65KF3/JFEFd+mbH4KTz/IG5BOPyw7jo8z29w/8qm7+wiCyqVfUIgJ1gL4+HVKmcXIOgqA==",
-            "requires": {}
+            "integrity": "sha512-nc5IXLdEUFLn3wZal65KF3/JFEFd+mbH4KTz/IG5BOPyw7jo8z29w/8qm7+wiCyqVfUIgJ1gL4+HVKmcXIOgqA=="
         },
         "mobx-utils": {
             "version": "5.6.2",
             "resolved": "https://registry.npmjs.org/mobx-utils/-/mobx-utils-5.6.2.tgz",
-            "integrity": "sha512-a/WlXyGkp6F12b01sTarENpxbmlRgPHFyR1Xv2bsSjQBm5dcOtd16ONb40/vOqck8L99NHpI+C9MXQ+SZ8f+yw==",
-            "requires": {}
+            "integrity": "sha512-a/WlXyGkp6F12b01sTarENpxbmlRgPHFyR1Xv2bsSjQBm5dcOtd16ONb40/vOqck8L99NHpI+C9MXQ+SZ8f+yw=="
         },
         "mocha": {
             "version": "5.2.0",
@@ -41877,7 +12957,7 @@
                 "he": {
                     "version": "1.1.1",
                     "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
-                    "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
+                    "integrity": "sha512-z/GDPjlRMNOa2XJiB4em8wJpuuBfrFOlYKTZxtpkdr1uPdibHI8rYA3MY0KDObpVyaes0e/aunid/t88ZI2EKA==",
                     "dev": true
                 },
                 "minimatch": {
@@ -41892,13 +12972,13 @@
                 "minimist": {
                     "version": "0.0.8",
                     "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
-                    "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+                    "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==",
                     "dev": true
                 },
                 "mkdirp": {
                     "version": "0.5.1",
                     "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
-                    "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+                    "integrity": "sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==",
                     "dev": true,
                     "requires": {
                         "minimist": "0.0.8"
@@ -41907,7 +12987,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
                     "dev": true
                 },
                 "supports-color": {
@@ -42026,13 +13106,12 @@
         "mongoose-legacy-pluralize": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz",
-            "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==",
-            "requires": {}
+            "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ=="
         },
         "move-concurrently": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
-            "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+            "integrity": "sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==",
             "dev": true,
             "requires": {
                 "aproba": "^1.1.1",
@@ -42093,14 +13172,14 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 }
             }
         },
         "mr-parser": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/mr-parser/-/mr-parser-0.2.1.tgz",
-            "integrity": "sha1-hhi5ukF+KOn0OaQcaVtVTq/u2Sc="
+            "integrity": "sha512-hug+mpbSSKnH13rFqy3zm+XiG+QTStiDAgMTHK355TIstQE0qBkBtSJsa5YHP94AuarVX9b/4dcebdTRZ9YiEw=="
         },
         "mri": {
             "version": "1.2.0",
@@ -42125,7 +13204,7 @@
         "multicast-dns-service-types": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
-            "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
+            "integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==",
             "dev": true
         },
         "mute-stream": {
@@ -42170,7 +13249,7 @@
         "native-or-bluebird": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.2.0.tgz",
-            "integrity": "sha1-OcR7/Xgl0fuf+tMiEK4l2q3xAck="
+            "integrity": "sha512-0SH8UubxDfe382eYiwmd12qxAbiWGzlGZv6CkMA+DPojWa/Y0oH4hE0lRtFfFgJmPQFyKXeB8XxPbZz6TvvKaQ=="
         },
         "natural-compare": {
             "version": "1.4.0",
@@ -42186,7 +13265,8 @@
         "neo-async": {
             "version": "2.6.2",
             "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
-            "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
+            "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+            "dev": true
         },
         "next-tick": {
             "version": "1.1.0",
@@ -42196,7 +13276,7 @@
         "nextafter": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/nextafter/-/nextafter-1.0.0.tgz",
-            "integrity": "sha1-t9d7U1MQ4+CX5gJauwqQNHfsGjo=",
+            "integrity": "sha512-7PO+A89Tll2rSEfyrjtqO0MaI37+nnxBdnQcPypfbEYYuGaJxWGCqaOwQX4a3GHNTS08l1kazuiLEWZniZjMUQ==",
             "requires": {
                 "double-bits": "^1.1.0"
             }
@@ -42227,7 +13307,7 @@
         "node-ensure": {
             "version": "0.0.0",
             "resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz",
-            "integrity": "sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc="
+            "integrity": "sha512-DRI60hzo2oKN1ma0ckc6nQWlHU69RH6xN0sjQTjMpChPfTYvKZdcQFfdYK2RWbJcKyUizSIy/l8OTGxMAM1QDw=="
         },
         "node-environment-flags": {
             "version": "1.0.5",
@@ -42316,7 +13396,7 @@
                 "nopt": {
                     "version": "3.0.6",
                     "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
-                    "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+                    "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==",
                     "requires": {
                         "abbrev": "1"
                     }
@@ -42357,7 +13437,7 @@
                 "semver": {
                     "version": "5.3.0",
                     "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
-                    "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
+                    "integrity": "sha512-mfmm3/H9+67MCVix1h+IXTpDwL6710LyHuk7+cWC9T1mE0qz4iHhh6r4hU2wrIT9iTsAAC2XQRvfblL028cpLw=="
                 },
                 "string-width": {
                     "version": "1.0.2",
@@ -42421,12 +13501,12 @@
                 "ansi-regex": {
                     "version": "2.1.1",
                     "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+                    "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="
                 },
                 "ansi-styles": {
                     "version": "2.2.1",
                     "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-                    "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+                    "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA=="
                 },
                 "aproba": {
                     "version": "1.2.0",
@@ -42445,7 +13525,7 @@
                 "chalk": {
                     "version": "1.1.3",
                     "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-                    "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+                    "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
                     "requires": {
                         "ansi-styles": "^2.2.1",
                         "escape-string-regexp": "^1.0.2",
@@ -42472,7 +13552,7 @@
                 "get-stdin": {
                     "version": "4.0.1",
                     "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
-                    "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="
+                    "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw=="
                 },
                 "is-fullwidth-code-point": {
                     "version": "1.0.0",
@@ -42570,7 +13650,7 @@
         "noop-logger": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
-            "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI="
+            "integrity": "sha512-6kM8CLXvuW5crTxsAtva2YLrRrDaiTIkIePWs9moLHqbFWT94WpNFjwS/5dfLfECg5i/lkmw3aoqVidxt23TEQ=="
         },
         "nopt": {
             "version": "5.0.0",
@@ -42611,6 +13691,7 @@
             "resolved": "https://registry.npmjs.org/npm/-/npm-6.14.18.tgz",
             "integrity": "sha512-p3SjqSchSuNQUqbJBgwdv0L3O6bKkaSfQrQzJsskNpNKLg0g37c5xTXFV0SqTlX9GWvoGxBELVJMRWq0J8oaLA==",
             "requires": {
+                "JSONStream": "^1.3.5",
                 "abbrev": "~1.1.1",
                 "ansicolors": "~0.3.2",
                 "ansistyles": "~0.1.3",
@@ -42651,7 +13732,6 @@
                 "init-package-json": "^1.10.3",
                 "is-cidr": "^3.1.1",
                 "json-parse-better-errors": "^1.0.2",
-                "JSONStream": "^1.3.5",
                 "lazy-property": "~1.0.0",
                 "libcipm": "^4.0.8",
                 "libnpm": "^3.0.1",
@@ -42744,6 +13824,14 @@
                         "signal-exit": "^3.0.2"
                     }
                 },
+                "JSONStream": {
+                    "version": "1.3.5",
+                    "bundled": true,
+                    "requires": {
+                        "jsonparse": "^1.2.0",
+                        "through": ">=2.2.7 <3"
+                    }
+                },
                 "abbrev": {
                     "version": "1.1.1",
                     "bundled": true
@@ -44080,14 +15168,6 @@
                     "version": "1.3.1",
                     "bundled": true
                 },
-                "JSONStream": {
-                    "version": "1.3.5",
-                    "bundled": true,
-                    "requires": {
-                        "jsonparse": "^1.2.0",
-                        "through": ">=2.2.7 <3"
-                    }
-                },
                 "jsprim": {
                     "version": "1.4.2",
                     "bundled": true,
@@ -44622,9 +15702,9 @@
                     "version": "4.0.7",
                     "bundled": true,
                     "requires": {
+                        "JSONStream": "^1.3.4",
                         "bluebird": "^3.5.1",
                         "figgy-pudding": "^3.4.1",
-                        "JSONStream": "^1.3.4",
                         "lru-cache": "^5.1.1",
                         "make-fetch-happen": "^5.0.0",
                         "npm-package-arg": "^6.1.0",
@@ -45323,19 +16403,6 @@
                     "version": "2.0.0",
                     "bundled": true
                 },
-                "string_decoder": {
-                    "version": "1.3.0",
-                    "bundled": true,
-                    "requires": {
-                        "safe-buffer": "~5.2.0"
-                    },
-                    "dependencies": {
-                        "safe-buffer": {
-                            "version": "5.2.0",
-                            "bundled": true
-                        }
-                    }
-                },
                 "string-width": {
                     "version": "2.1.1",
                     "bundled": true,
@@ -45361,6 +16428,19 @@
                         }
                     }
                 },
+                "string_decoder": {
+                    "version": "1.3.0",
+                    "bundled": true,
+                    "requires": {
+                        "safe-buffer": "~5.2.0"
+                    },
+                    "dependencies": {
+                        "safe-buffer": {
+                            "version": "5.2.0",
+                            "bundled": true
+                        }
+                    }
+                },
                 "stringify-package": {
                     "version": "1.0.1",
                     "bundled": true
@@ -45837,7 +16917,7 @@
         "npm-run-path": {
             "version": "2.0.2",
             "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
-            "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+            "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==",
             "requires": {
                 "path-key": "^2.0.0"
             }
@@ -45864,7 +16944,7 @@
         "number-is-nan": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
-            "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+            "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ=="
         },
         "nwsapi": {
             "version": "2.2.0",
@@ -45875,7 +16955,7 @@
         "oauth": {
             "version": "0.9.15",
             "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz",
-            "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE="
+            "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA=="
         },
         "oauth-sign": {
             "version": "0.9.0",
@@ -45885,12 +16965,12 @@
         "object-assign": {
             "version": "4.1.1",
             "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-            "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+            "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
         },
         "object-copy": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
-            "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+            "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==",
             "requires": {
                 "copy-descriptor": "^0.1.0",
                 "define-property": "^0.2.5",
@@ -45900,7 +16980,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -45913,7 +16993,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -45970,7 +17050,7 @@
                 "magicli": {
                     "version": "0.0.5",
                     "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-                    "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
+                    "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
                     "requires": {
                         "commander": "^2.9.0",
                         "get-stdin": "^5.0.1",
@@ -45983,7 +17063,7 @@
         "object-visit": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
-            "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+            "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==",
             "requires": {
                 "isobject": "^3.0.0"
             }
@@ -46045,7 +17125,7 @@
         "object.pick": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
-            "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+            "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==",
             "requires": {
                 "isobject": "^3.0.1"
             }
@@ -46083,7 +17163,7 @@
         "once": {
             "version": "1.4.0",
             "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-            "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+            "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
             "requires": {
                 "wrappy": "1"
             }
@@ -46145,12 +17225,12 @@
         "os-homedir": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
-            "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
+            "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ=="
         },
         "os-tmpdir": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
-            "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
+            "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="
         },
         "osenv": {
             "version": "0.1.5",
@@ -46169,12 +17249,12 @@
         "p-debounce": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/p-debounce/-/p-debounce-1.0.0.tgz",
-            "integrity": "sha1-y38svu/YegnrqGHhErZ1J+Yh4v0="
+            "integrity": "sha512-ttOxn4Yt0hzIsLLqKi/Ry9QRxW+UQKdoWHz7g99Ci57zPkqUU3kbWKAeHuv+HfRLe109acYLUY6kuVCOOqnt4g=="
         },
         "p-finally": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
-            "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
+            "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow=="
         },
         "p-limit": {
             "version": "2.3.0",
@@ -46215,7 +17295,7 @@
         "package-json": {
             "version": "4.0.1",
             "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz",
-            "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=",
+            "integrity": "sha512-q/R5GrMek0vzgoomq6rm9OX+3PQve8sLwTirmK30YB3Cu0Bbt9OX9M/SIUnroN5BGJkzwGsFwDaRGD9EwBOlCA==",
             "requires": {
                 "got": "^6.7.1",
                 "registry-auth-token": "^3.0.1",
@@ -46231,7 +17311,7 @@
                 "got": {
                     "version": "6.7.1",
                     "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
-                    "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
+                    "integrity": "sha512-Y/K3EDuiQN9rTZhBvPRWMLXIKdeD1Rj0nzunfoi0Yyn5WBEbzxXKU9Ub2X41oZBagVWOBU3MuDonFMgPWQFnwg==",
                     "requires": {
                         "create-error-class": "^3.0.0",
                         "duplexer3": "^0.1.4",
@@ -46347,7 +17427,7 @@
         "pascalcase": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
-            "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
+            "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw=="
         },
         "passport": {
             "version": "0.4.1",
@@ -46369,7 +17449,7 @@
         "passport-local": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
-            "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=",
+            "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==",
             "requires": {
                 "passport-strategy": "1.x.x"
             }
@@ -46389,7 +17469,7 @@
         "passport-strategy": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
-            "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ="
+            "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA=="
         },
         "path-browserify": {
             "version": "1.0.1",
@@ -46399,27 +17479,27 @@
         "path-dirname": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
-            "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="
+            "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q=="
         },
         "path-exists": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
-            "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
+            "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="
         },
         "path-is-absolute": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-            "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+            "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
         },
         "path-is-inside": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
-            "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="
+            "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w=="
         },
         "path-key": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
-            "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
+            "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="
         },
         "path-parse": {
             "version": "1.0.7",
@@ -46429,7 +17509,7 @@
         "path-to-regexp": {
             "version": "0.1.7",
             "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
-            "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+            "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
         },
         "path-type": {
             "version": "4.0.0",
@@ -46444,7 +17524,7 @@
         "pause": {
             "version": "0.0.1",
             "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
-            "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10="
+            "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg=="
         },
         "pdf-parse": {
             "version": "1.1.1",
@@ -46492,7 +17572,7 @@
         "pend": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
-            "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
+            "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="
         },
         "perfect-scrollbar": {
             "version": "1.5.5",
@@ -46502,7 +17582,7 @@
         "performance-now": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
-            "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
+            "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
         },
         "picocolors": {
             "version": "1.0.0",
@@ -46522,12 +17602,12 @@
         "pinkie": {
             "version": "2.0.4",
             "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
-            "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
+            "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg=="
         },
         "pinkie-promise": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
-            "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+            "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==",
             "requires": {
                 "pinkie": "^2.0.0"
             }
@@ -46588,7 +17668,7 @@
         "plist": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/plist/-/plist-1.2.0.tgz",
-            "integrity": "sha1-CEtQk93JJQbiWfh0uNmxr7jHlZM=",
+            "integrity": "sha512-dL9Xc2Aj3YyBnwvCNuHmFl2LWvQacm/HEAsoVwLiuu0POboMChETt5wexpU1P6F6MnibIucXlVsMFFgNUT2IyA==",
             "requires": {
                 "base64-js": "0.0.8",
                 "util-deprecate": "1.0.2",
@@ -46599,7 +17679,7 @@
                 "base64-js": {
                     "version": "0.0.8",
                     "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
-                    "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg="
+                    "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw=="
                 }
             }
         },
@@ -46639,7 +17719,7 @@
         "posix-character-classes": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
-            "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
+            "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg=="
         },
         "postcss": {
             "version": "7.0.39",
@@ -46837,13 +17917,13 @@
         "prelude-ls": {
             "version": "1.1.2",
             "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
-            "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+            "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
             "dev": true
         },
         "prepend-http": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
-            "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
+            "integrity": "sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg=="
         },
         "prettier": {
             "version": "2.7.1",
@@ -46892,7 +17972,7 @@
         "process": {
             "version": "0.11.10",
             "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
-            "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
+            "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="
         },
         "process-nextick-args": {
             "version": "2.0.1",
@@ -46915,7 +17995,7 @@
         "promise-inflight": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
-            "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
+            "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
             "dev": true
         },
         "prop-types": {
@@ -46966,8 +18046,7 @@
         "prosemirror-find-replace": {
             "version": "0.9.0",
             "resolved": "https://registry.npmjs.org/prosemirror-find-replace/-/prosemirror-find-replace-0.9.0.tgz",
-            "integrity": "sha1-QgsENNF5xdBJD44hSNhVGpVJY4I=",
-            "requires": {}
+            "integrity": "sha512-LfhQ/Zr0PkkJpCsr9vTJ5ZPYh49mSVVG+hHJ6djT+chlCW+t2ilSxBpBG+2IeE/I5nlbcvuLLAbxeI1g3pTCpA=="
         },
         "prosemirror-history": {
             "version": "1.3.0",
@@ -47059,13 +18138,13 @@
         "prr": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
-            "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
+            "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==",
             "dev": true
         },
         "pseudomap": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
-            "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
+            "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ=="
         },
         "psl": {
             "version": "1.8.0",
@@ -47297,12 +18376,12 @@
         "pure-color": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz",
-            "integrity": "sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4="
+            "integrity": "sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA=="
         },
         "q": {
             "version": "1.5.1",
             "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
-            "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc="
+            "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw=="
         },
         "qs": {
             "version": "6.5.3",
@@ -47323,7 +18402,7 @@
         "querystring": {
             "version": "0.2.0",
             "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
-            "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
+            "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==",
             "dev": true
         },
         "querystringify": {
@@ -47345,12 +18424,13 @@
         "random-bytes": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
-            "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
+            "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ=="
         },
         "randombytes": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
             "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+            "dev": true,
             "requires": {
                 "safe-buffer": "^5.1.0"
             }
@@ -47422,8 +18502,7 @@
         "react-audio-waveform": {
             "version": "0.0.5",
             "resolved": "https://registry.npmjs.org/react-audio-waveform/-/react-audio-waveform-0.0.5.tgz",
-            "integrity": "sha512-4dJwhl+LQRuywzmmjuhWT5GueT3Ai2ZhB+loVxg0sRdhplyDp96xAu10/V/+J25Cl7YqNtl2DWSxvSoI/i6l6w==",
-            "requires": {}
+            "integrity": "sha512-4dJwhl+LQRuywzmmjuhWT5GueT3Ai2ZhB+loVxg0sRdhplyDp96xAu10/V/+J25Cl7YqNtl2DWSxvSoI/i6l6w=="
         },
         "react-autosuggest": {
             "version": "9.4.3",
@@ -47448,7 +18527,7 @@
         "react-base16-styling": {
             "version": "0.5.3",
             "resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.5.3.tgz",
-            "integrity": "sha1-OFjyTpxN2MvT9wLz901YHKKRcmk=",
+            "integrity": "sha512-EPuchwVvYPSFFIjGpH0k6wM0HQsmJ0vCk7BSl5ryxMVFIWW4hX4Kksu4PNtxfgOxDebTLkJQ8iC7zwAql0eusg==",
             "requires": {
                 "base16": "^1.0.0",
                 "lodash.curry": "^4.0.1",
@@ -47517,7 +18596,7 @@
         "react-dock": {
             "version": "0.2.4",
             "resolved": "https://registry.npmjs.org/react-dock/-/react-dock-0.2.4.tgz",
-            "integrity": "sha1-5yfcdVCztzEWY13LnA4E0Lev4Xw=",
+            "integrity": "sha512-ywUJPC/TIM9PO700skka0fH4aqbrH8RojUXejZFvjtqlc5KZ+xjHqFdo4A3j+dp+0NLFZ3Nai4xzcf3FUJ9BsQ==",
             "requires": {
                 "lodash.debounce": "^3.1.1",
                 "prop-types": "^15.5.8"
@@ -47597,8 +18676,7 @@
         "react-icons": {
             "version": "4.4.0",
             "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.4.0.tgz",
-            "integrity": "sha512-fSbvHeVYo/B5/L4VhB7sBA1i2tS8MkT0Hb9t2H1AVPkwGfVHLJCqyr2Py9dKMxsyM63Eng1GkdZfbWj+Fmv8Rg==",
-            "requires": {}
+            "integrity": "sha512-fSbvHeVYo/B5/L4VhB7sBA1i2tS8MkT0Hb9t2H1AVPkwGfVHLJCqyr2Py9dKMxsyM63Eng1GkdZfbWj+Fmv8Rg=="
         },
         "react-input-autosize": {
             "version": "3.0.0",
@@ -47678,8 +18756,7 @@
         "react-loading": {
             "version": "2.0.3",
             "resolved": "https://registry.npmjs.org/react-loading/-/react-loading-2.0.3.tgz",
-            "integrity": "sha512-Vdqy79zq+bpeWJqC+xjltUjuGApyoItPgL0vgVfcJHhqwU7bAMKzysfGW/ADu6i0z0JiOCRJjo+IkFNkRNbA3A==",
-            "requires": {}
+            "integrity": "sha512-Vdqy79zq+bpeWJqC+xjltUjuGApyoItPgL0vgVfcJHhqwU7bAMKzysfGW/ADu6i0z0JiOCRJjo+IkFNkRNbA3A=="
         },
         "react-markdown": {
             "version": "8.0.3",
@@ -47729,8 +18806,7 @@
         "react-onclickoutside": {
             "version": "6.12.2",
             "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.12.2.tgz",
-            "integrity": "sha512-NMXGa223OnsrGVp5dJHkuKxQ4czdLmXSp5jSV9OqiCky9LOpPATn3vLldc+q5fK3gKbEHvr7J1u0yhBh/xYkpA==",
-            "requires": {}
+            "integrity": "sha512-NMXGa223OnsrGVp5dJHkuKxQ4czdLmXSp5jSV9OqiCky9LOpPATn3vLldc+q5fK3gKbEHvr7J1u0yhBh/xYkpA=="
         },
         "react-popper": {
             "version": "1.3.11",
@@ -47794,8 +18870,7 @@
         "react-refresh-typescript": {
             "version": "2.0.7",
             "resolved": "https://registry.npmjs.org/react-refresh-typescript/-/react-refresh-typescript-2.0.7.tgz",
-            "integrity": "sha512-KbuW57FauO11e6a9gU836sCm3M3z0b2+J2qPhUudg0QplOfz0eAF3gMeshcUC/ChfNLJCK1SZxvYmUtRxiZE5A==",
-            "requires": {}
+            "integrity": "sha512-KbuW57FauO11e6a9gU836sCm3M3z0b2+J2qPhUudg0QplOfz0eAF3gMeshcUC/ChfNLJCK1SZxvYmUtRxiZE5A=="
         },
         "react-resizable": {
             "version": "1.11.1",
@@ -47809,8 +18884,7 @@
         "react-resizable-rotatable-draggable": {
             "version": "0.2.0",
             "resolved": "https://registry.npmjs.org/react-resizable-rotatable-draggable/-/react-resizable-rotatable-draggable-0.2.0.tgz",
-            "integrity": "sha512-F8TPx3z7/AcmRViySbYV3LpUWXFpHlGAmKmNcYMgPlS+h1eYFazRG3xYS8Z6e48hWY1EcCny/YNrwRNUrap8CQ==",
-            "requires": {}
+            "integrity": "sha512-F8TPx3z7/AcmRViySbYV3LpUWXFpHlGAmKmNcYMgPlS+h1eYFazRG3xYS8Z6e48hWY1EcCny/YNrwRNUrap8CQ=="
         },
         "react-reveal": {
             "version": "1.2.2",
@@ -47895,7 +18969,7 @@
         "react-themeable": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/react-themeable/-/react-themeable-1.1.0.tgz",
-            "integrity": "sha1-fURm3ZsrX6dQWHJ4JenxUro3mg4=",
+            "integrity": "sha512-kl5tQ8K+r9IdQXZd8WLa+xxYN04lLnJXRVhHfdgwsUJr/SlKJxIejoc9z9obEkx1mdqbTw1ry43fxEUwyD9u7w==",
             "requires": {
                 "object-assign": "^3.0.0"
             },
@@ -47903,7 +18977,7 @@
                 "object-assign": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
-                    "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I="
+                    "integrity": "sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ=="
                 }
             }
         },
@@ -47958,7 +19032,7 @@
         "read-pkg": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
-            "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+            "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==",
             "requires": {
                 "load-json-file": "^1.0.0",
                 "normalize-package-data": "^2.3.2",
@@ -47968,7 +19042,7 @@
                 "path-type": {
                     "version": "1.1.0",
                     "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
-                    "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+                    "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==",
                     "requires": {
                         "graceful-fs": "^4.1.2",
                         "pify": "^2.0.0",
@@ -47980,7 +19054,7 @@
         "read-pkg-up": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
-            "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+            "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==",
             "requires": {
                 "find-up": "^1.0.0",
                 "read-pkg": "^1.0.0"
@@ -47989,7 +19063,7 @@
                 "find-up": {
                     "version": "1.1.2",
                     "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
-                    "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+                    "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==",
                     "requires": {
                         "path-exists": "^2.0.0",
                         "pinkie-promise": "^2.0.0"
@@ -47998,7 +19072,7 @@
                 "path-exists": {
                     "version": "2.1.0",
                     "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
-                    "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+                    "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==",
                     "requires": {
                         "pinkie-promise": "^2.0.0"
                     }
@@ -48044,12 +19118,12 @@
         "readline": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz",
-            "integrity": "sha1-xYDXfvLPyHUrEySYBg3JeTp6wBw="
+            "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg=="
         },
         "rechoir": {
             "version": "0.6.2",
             "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
-            "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
+            "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
             "requires": {
                 "resolve": "^1.1.6"
             }
@@ -48075,7 +19149,7 @@
         "redent": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
-            "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+            "integrity": "sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g==",
             "requires": {
                 "indent-string": "^2.1.0",
                 "strip-indent": "^1.0.1"
@@ -48084,7 +19158,7 @@
         "reduce-flatten": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz",
-            "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc="
+            "integrity": "sha512-j5WfFJfc9CoXv/WbwVLHq74i/hdTUpy+iNC534LxczMRP67vJeK3V9JOdnL0N1cIRbn9mYhE2yVjvvKXDxvNXQ=="
         },
         "redux": {
             "version": "4.2.0",
@@ -48141,7 +19215,7 @@
         "registry-url": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz",
-            "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=",
+            "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==",
             "requires": {
                 "rc": "^1.0.1"
             }
@@ -48159,7 +19233,7 @@
         "relateurl": {
             "version": "0.2.7",
             "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
-            "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk="
+            "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog=="
         },
         "remark-gfm": {
             "version": "3.0.1",
@@ -48196,7 +19270,7 @@
         "remove-trailing-separator": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
-            "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
+            "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw=="
         },
         "renderkid": {
             "version": "3.0.0",
@@ -48282,12 +19356,12 @@
         "repeat-string": {
             "version": "1.6.1",
             "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
-            "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
+            "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w=="
         },
         "repeating": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
-            "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+            "integrity": "sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==",
             "requires": {
                 "is-finite": "^1.0.0"
             }
@@ -48383,22 +19457,6 @@
                 }
             }
         },
-        "require_optional": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
-            "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
-            "requires": {
-                "resolve-from": "^2.0.0",
-                "semver": "^5.1.0"
-            },
-            "dependencies": {
-                "resolve-from": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
-                    "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c="
-                }
-            }
-        },
         "require-at": {
             "version": "1.0.6",
             "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz",
@@ -48407,7 +19465,7 @@
         "require-directory": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
-            "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
+            "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
         },
         "require-from-string": {
             "version": "2.0.2",
@@ -48422,12 +19480,28 @@
         "require-package-name": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz",
-            "integrity": "sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk="
+            "integrity": "sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q=="
+        },
+        "require_optional": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
+            "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
+            "requires": {
+                "resolve-from": "^2.0.0",
+                "semver": "^5.1.0"
+            },
+            "dependencies": {
+                "resolve-from": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
+                    "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ=="
+                }
+            }
         },
         "requires-port": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
-            "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+            "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
             "dev": true
         },
         "resize-observer-polyfill": {
@@ -48473,7 +19547,7 @@
         "resolve-url": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
-            "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
+            "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg=="
         },
         "responselike": {
             "version": "2.0.0",
@@ -48508,7 +19582,7 @@
         "retry": {
             "version": "0.12.0",
             "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
-            "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
+            "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
             "dev": true
         },
         "reveal.js": {
@@ -48519,7 +19593,7 @@
         "right-align": {
             "version": "0.1.3",
             "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
-            "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
+            "integrity": "sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==",
             "requires": {
                 "align-text": "^0.1.1"
             }
@@ -48554,7 +19628,7 @@
         "run-queue": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
-            "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
+            "integrity": "sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==",
             "dev": true,
             "requires": {
                 "aproba": "^1.1.1"
@@ -48601,7 +19675,7 @@
         "safe-regex": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
-            "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+            "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==",
             "requires": {
                 "ret": "~0.1.10"
             }
@@ -48689,13 +19763,13 @@
         "scss-loader": {
             "version": "0.0.1",
             "resolved": "https://registry.npmjs.org/scss-loader/-/scss-loader-0.0.1.tgz",
-            "integrity": "sha1-6uAXueDzjBKlMtslwiC5Avs05nE=",
+            "integrity": "sha512-SbT/smRJjkvvdHSEdAYAplosVkrtaSwwgUlnQCOuDS5sOKNjrS/eYCMvKeV6+YxK5cCOCsOJZd3vltrXatFp+g==",
             "dev": true
         },
         "scss-tokenizer": {
             "version": "0.2.3",
             "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
-            "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
+            "integrity": "sha512-dYE8LhncfBUar6POCxMTm0Ln+erjeczqEvCJib5/7XNkdw1FkUGgwMPY360FY0FgPWQxHWCx29Jl3oejyGLM9Q==",
             "requires": {
                 "js-base64": "^2.1.8",
                 "source-map": "^0.4.2"
@@ -48704,7 +19778,7 @@
                 "source-map": {
                     "version": "0.4.4",
                     "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
-                    "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+                    "integrity": "sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A==",
                     "requires": {
                         "amdefine": ">=0.0.4"
                     }
@@ -48719,17 +19793,17 @@
         "section-iterator": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/section-iterator/-/section-iterator-2.0.0.tgz",
-            "integrity": "sha1-v0RNev7rlK1Dw5rS+yYVFifMuio="
+            "integrity": "sha512-xvTNwcbeDayXotnV32zLb3duQsP+4XosHpb/F+tu6VzEZFmIjzPdNk6/O+QOOx5XTh08KL2ufdXeCO33p380pQ=="
         },
         "select": {
             "version": "1.1.2",
             "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
-            "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
+            "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
         },
         "select-hose": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
-            "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
+            "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==",
             "dev": true
         },
         "selfsigned": {
@@ -48749,12 +19823,12 @@
         "semver-compare": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
-            "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w="
+            "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow=="
         },
         "semver-diff": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz",
-            "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=",
+            "integrity": "sha512-gL8F8L4ORwsS0+iQ34yCYv///jsOq0ZL7WP55d1HnJ32o7tyFYEFQZQA22mrLIacZdU6xecaBBZ+uEiffGNyXw==",
             "requires": {
                 "semver": "^5.0.3"
             }
@@ -48805,6 +19879,7 @@
             "version": "6.0.0",
             "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
             "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+            "dev": true,
             "requires": {
                 "randombytes": "^2.1.0"
             }
@@ -48817,7 +19892,7 @@
         "serve-index": {
             "version": "1.9.1",
             "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
-            "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
+            "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==",
             "dev": true,
             "requires": {
                 "accepts": "~1.3.4",
@@ -48847,7 +19922,7 @@
                 "http-errors": {
                     "version": "1.6.3",
                     "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
-                    "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+                    "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
                     "dev": true,
                     "requires": {
                         "depd": "~1.1.2",
@@ -48859,13 +19934,13 @@
                 "inherits": {
                     "version": "2.0.3",
                     "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
-                    "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+                    "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
                     "dev": true
                 },
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
                     "dev": true
                 },
                 "setprototypeof": {
@@ -48896,7 +19971,7 @@
         "set-blocking": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
-            "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+            "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
         },
         "set-value": {
             "version": "2.0.1",
@@ -48912,7 +19987,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -48922,7 +19997,7 @@
         "setimmediate": {
             "version": "1.0.5",
             "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
-            "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
+            "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
         },
         "setprototypeof": {
             "version": "1.2.0",
@@ -49084,7 +20159,7 @@
         "shebang-command": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
-            "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+            "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
             "requires": {
                 "shebang-regex": "^1.0.0"
             }
@@ -49092,7 +20167,7 @@
         "shebang-regex": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
-            "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
+            "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="
         },
         "shelljs": {
             "version": "0.8.5",
@@ -49127,7 +20202,7 @@
         "simple-assign": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/simple-assign/-/simple-assign-0.1.0.tgz",
-            "integrity": "sha1-F/0wZqXz13OPUDIbsPFMooHMS6o="
+            "integrity": "sha512-otdSSQzuVsmDoe5MnSm4ZgHd5sl0ak6A1CTjW1R/DUHQ8xoZuU1NUzf9x6n9Dvp3nxpvW51WNMQ/7rQ9432xDg=="
         },
         "simple-concat": {
             "version": "1.0.1",
@@ -49147,7 +20222,7 @@
         "simple-swizzle": {
             "version": "0.2.2",
             "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
-            "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
+            "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
             "requires": {
                 "is-arrayish": "^0.3.1"
             },
@@ -49162,7 +20237,7 @@
         "slash": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
-            "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+            "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==",
             "dev": true
         },
         "slice-ansi": {
@@ -49179,7 +20254,7 @@
         "sliced": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
-            "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E="
+            "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA=="
         },
         "snapdragon": {
             "version": "0.8.2",
@@ -49207,7 +20282,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -49215,7 +20290,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -49223,7 +20298,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 }
             }
         },
@@ -49240,7 +20315,7 @@
                 "define-property": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-                    "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+                    "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
                     "requires": {
                         "is-descriptor": "^1.0.0"
                     }
@@ -49289,7 +20364,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -49385,7 +20460,7 @@
                 "component-emitter": {
                     "version": "1.2.1",
                     "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
-                    "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
+                    "integrity": "sha512-jPatnhd33viNplKjqXKRkGU345p263OIWzDL2wH3LGIGp5Kojo+uXizHmOADRvhGFFTnJqX3jBAKP6vvmSDKcA=="
                 },
                 "debug": {
                     "version": "4.1.1",
@@ -49398,7 +20473,7 @@
                 "isarray": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
-                    "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
+                    "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ=="
                 }
             }
         },
@@ -49468,7 +20543,7 @@
         "source-map": {
             "version": "0.5.7",
             "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-            "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+            "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="
         },
         "source-map-resolve": {
             "version": "0.5.3",
@@ -49511,7 +20586,7 @@
         "sparse-bitfield": {
             "version": "3.0.3",
             "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
-            "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
+            "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
             "optional": true,
             "requires": {
                 "memory-pager": "^1.0.2"
@@ -49614,7 +20689,7 @@
         "split-skip": {
             "version": "0.0.2",
             "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.2.tgz",
-            "integrity": "sha1-2J2Iu9L3Pka1FYqjcKVhIk6A1GE="
+            "integrity": "sha512-weHOi8BolsDnGIwhhWHbA+wKSuSpvWwjRrdj8SdbIIis2vSwOE37CQP8x3EleuzxanUr3AK8BdUy4MkiOULPZg=="
         },
         "split-string": {
             "version": "3.1.0",
@@ -49627,7 +20702,7 @@
         "sprintf-js": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
-            "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
+            "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
         },
         "sshpk": {
             "version": "1.17.0",
@@ -49679,7 +20754,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -49758,7 +20833,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
                 }
             }
         },
@@ -49773,14 +20848,6 @@
             "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
             "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY="
         },
-        "string_decoder": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-            "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-            "requires": {
-                "safe-buffer": "~5.1.0"
-            }
-        },
         "string-width": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
@@ -49831,6 +20898,14 @@
                 "es-abstract": "^1.19.5"
             }
         },
+        "string_decoder": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+            "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+            "requires": {
+                "safe-buffer": "~5.1.0"
+            }
+        },
         "stringify-parameters": {
             "version": "0.0.4",
             "resolved": "https://registry.npmjs.org/stringify-parameters/-/stringify-parameters-0.0.4.tgz",
@@ -49848,7 +20923,7 @@
                 "magicli": {
                     "version": "0.0.5",
                     "resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.5.tgz",
-                    "integrity": "sha1-zufQ+7THBRiqyxHsPrfiX/SaSSE=",
+                    "integrity": "sha512-wZbMtnl2v1b+Jp3xlqA9FU/O4I6YhGXR8xSY/eU2+gDAvut/F+W3gl4qs61iL4LELC7jqSAE6aAD5668EbmQHA==",
                     "requires": {
                         "commander": "^2.9.0",
                         "get-stdin": "^5.0.1",
@@ -49890,7 +20965,7 @@
                 "get-stdin": {
                     "version": "4.0.1",
                     "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
-                    "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="
+                    "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw=="
                 }
             }
         },
@@ -49960,8 +21035,7 @@
         "stylis-rule-sheet": {
             "version": "0.0.10",
             "resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz",
-            "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==",
-            "requires": {}
+            "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw=="
         },
         "supercluster": {
             "version": "7.1.5",
@@ -50146,6 +21220,7 @@
             "version": "5.3.3",
             "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz",
             "integrity": "sha512-Fx60G5HNYknNTNQnzQ1VePRuu89ZVYWfjRAeT5rITuCY/1b08s49e5kSQwHDirKZWuoKOBRFS98EUUoZ9kLEwQ==",
+            "dev": true,
             "requires": {
                 "@jridgewell/trace-mapping": "^0.3.7",
                 "jest-worker": "^27.4.5",
@@ -50158,6 +21233,7 @@
                     "version": "3.1.1",
                     "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
                     "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
+                    "dev": true,
                     "requires": {
                         "@types/json-schema": "^7.0.8",
                         "ajv": "^6.12.5",
@@ -50262,7 +21338,7 @@
         "to-array": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
-            "integrity": "sha512-LhVdShQD/4Mk4zXNroIQZJC+Ap3zgLcDuwEdcmLv9CCO73NWockQDwyUnW/m8VX/EElfL6FcYx7EeutN4HJA6A=="
+            "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA="
         },
         "to-fast-properties": {
             "version": "2.0.0",
@@ -50285,7 +21361,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -50333,7 +21409,7 @@
                 "nopt": {
                     "version": "1.0.10",
                     "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
-                    "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
+                    "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
                     "requires": {
                         "abbrev": "1"
                     }
@@ -50811,7 +21887,8 @@
         "typescript": {
             "version": "4.7.4",
             "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
-            "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ=="
+            "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
+            "dev": true
         },
         "typescript-collections": {
             "version": "1.3.3",
@@ -50850,7 +21927,7 @@
                 "jsonfile": {
                     "version": "4.0.0",
                     "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
-                    "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+                    "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
                     "requires": {
                         "graceful-fs": "^4.1.6"
                     }
@@ -50880,12 +21957,12 @@
                 "camelcase": {
                     "version": "1.2.1",
                     "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
-                    "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
+                    "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g=="
                 },
                 "cliui": {
                     "version": "2.1.0",
                     "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
-                    "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+                    "integrity": "sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==",
                     "requires": {
                         "center-align": "^0.1.1",
                         "right-align": "^0.1.1",
@@ -50966,7 +22043,7 @@
                 "pako": {
                     "version": "0.2.9",
                     "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
-                    "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU="
+                    "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA=="
                 }
             }
         },
@@ -51111,7 +22188,7 @@
                 "has-value": {
                     "version": "0.3.1",
                     "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
-                    "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+                    "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==",
                     "requires": {
                         "get-value": "^2.0.3",
                         "has-values": "^0.1.4",
@@ -51121,7 +22198,7 @@
                         "isobject": {
                             "version": "2.1.0",
                             "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
-                            "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+                            "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==",
                             "requires": {
                                 "isarray": "1.0.0"
                             }
@@ -51131,7 +22208,7 @@
                 "has-values": {
                     "version": "0.1.4",
                     "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
-                    "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E="
+                    "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ=="
                 }
             }
         },
@@ -51146,8 +22223,7 @@
                 "create-react-context": {
                     "version": "0.1.6",
                     "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.1.6.tgz",
-                    "integrity": "sha512-eCnYYEUEc5i32LHwpE/W7NlddOB9oHwsPaWtWzYtflNkkwa3IfindIcoXdVWs12zCbwaMCavKNu84EXogVIWHw==",
-                    "requires": {}
+                    "integrity": "sha512-eCnYYEUEc5i32LHwpE/W7NlddOB9oHwsPaWtWzYtflNkkwa3IfindIcoXdVWs12zCbwaMCavKNu84EXogVIWHw=="
                 }
             }
         },
@@ -51204,7 +22280,7 @@
                 "punycode": {
                     "version": "1.3.2",
                     "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
-                    "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
+                    "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==",
                     "dev": true
                 }
             }
@@ -51265,8 +22341,7 @@
         "use-memo-one": {
             "version": "1.1.2",
             "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz",
-            "integrity": "sha512-u2qFKtxLsia/r8qG0ZKkbytbztzRb317XCkT7yP8wxL0tZ/CzK2G+WWie5vWvpyeP7+YoPIwbJoIHJ4Ba4k0oQ==",
-            "requires": {}
+            "integrity": "sha512-u2qFKtxLsia/r8qG0ZKkbytbztzRb317XCkT7yP8wxL0tZ/CzK2G+WWie5vWvpyeP7+YoPIwbJoIHJ4Ba4k0oQ=="
         },
         "util": {
             "version": "0.12.4",
@@ -51513,6 +22588,7 @@
             "version": "2.4.0",
             "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
             "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
+            "dev": true,
             "requires": {
                 "glob-to-regexp": "^0.4.1",
                 "graceful-fs": "^4.1.2"
@@ -51554,6 +22630,7 @@
             "version": "5.73.0",
             "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz",
             "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==",
+            "dev": true,
             "requires": {
                 "@types/eslint-scope": "^3.7.3",
                 "@types/estree": "^0.0.51",
@@ -51585,6 +22662,7 @@
                     "version": "3.1.1",
                     "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
                     "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
+                    "dev": true,
                     "requires": {
                         "@types/json-schema": "^7.0.8",
                         "ajv": "^6.12.5",
@@ -51761,7 +22839,7 @@
                 "ansi-regex": {
                     "version": "2.1.1",
                     "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+                    "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
                     "dev": true
                 },
                 "debug": {
@@ -51786,7 +22864,7 @@
                 "memory-fs": {
                     "version": "0.4.1",
                     "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
-                    "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+                    "integrity": "sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ==",
                     "dev": true,
                     "requires": {
                         "errno": "^0.1.3",
@@ -51832,7 +22910,7 @@
                 "resolve-cwd": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
-                    "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+                    "integrity": "sha512-ccu8zQTrzVr954472aUVPLEcB3YpKSYR3cg/3lo1okzobPBM+1INXBbBZlDbnI/hbEocnf8j0QVo43hQKrbchg==",
                     "dev": true,
                     "requires": {
                         "resolve-from": "^3.0.0"
@@ -51841,7 +22919,7 @@
                 "resolve-from": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
-                    "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+                    "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==",
                     "dev": true
                 },
                 "semver": {
@@ -51961,7 +23039,8 @@
         "webpack-sources": {
             "version": "3.2.3",
             "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
-            "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w=="
+            "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
+            "dev": true
         },
         "webrtc-adapter": {
             "version": "7.7.1",
@@ -52230,8 +23309,7 @@
         "ws": {
             "version": "7.5.8",
             "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.8.tgz",
-            "integrity": "sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==",
-            "requires": {}
+            "integrity": "sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw=="
         },
         "xdg-basedir": {
             "version": "3.0.0",
@@ -52255,7 +23333,7 @@
                 "lodash": {
                     "version": "3.10.1",
                     "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
-                    "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
+                    "integrity": "sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ=="
                 }
             }
         },
@@ -52382,7 +23460,7 @@
         "yeast": {
             "version": "0.1.2",
             "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
-            "integrity": "sha512-8HFIh676uyGYP6wP13R/j6OJ/1HwJ46snpvzE7aHAN3Ryqh2yX6Xox2B4CUmTwwOIzlG3Bs7ocsP5dZH/R1Qbg=="
+            "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk="
         },
         "yn": {
             "version": "3.1.1",
@@ -52403,8 +23481,7 @@
         "zustand": {
             "version": "3.7.2",
             "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz",
-            "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==",
-            "requires": {}
+            "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA=="
         },
         "zwitch": {
             "version": "2.0.2",
diff --git a/package.json b/package.json
index 6c770a4ca..24d4afc2b 100644
--- a/package.json
+++ b/package.json
@@ -127,6 +127,8 @@
         "webpack-hot-middleware": "^2.25.1"
     },
     "dependencies": {
+        "@emotion/react": "^11.10.8",
+        "@emotion/styled": "^11.10.8",
         "@ffmpeg/core": "0.10.0",
         "@ffmpeg/ffmpeg": "0.10.0",
         "@fortawesome/fontawesome-svg-core": "^1.3.0",
@@ -138,6 +140,8 @@
         "@hig/theme-context": "^2.1.3",
         "@hig/theme-data": "^2.23.1",
         "@material-ui/core": "^4.12.3",
+        "@mui/icons-material": "^5.11.16",
+        "@mui/material": "^5.12.2",
         "@octokit/core": "^4.0.4",
         "@react-google-maps/api": "^2.7.0",
         "@react-three/fiber": "^6.2.3",
@@ -155,6 +159,7 @@
         "@types/three": "^0.126.2",
         "@types/web": "0.0.53",
         "@webscopeio/react-textarea-autocomplete": "^4.9.1",
+        "D": "^1.0.0",
         "adm-zip": "^0.4.16",
         "archiver": "^3.1.1",
         "array-batcher": "^1.2.3",
@@ -181,7 +186,6 @@
         "cookie-parser": "^1.4.6",
         "cookie-session": "^2.0.0",
         "cors": "^2.8.5",
-        "D": "^1.0.0",
         "depcheck": "^0.9.2",
         "equation-editor-react": "github:bobzel/equation-editor-react#useLocally",
         "exif": "^0.6.0",
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 35a7ee346..5b9d8f415 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -4,8 +4,6 @@ import React = require('react');
 import { ViewBoxAnnotatableComponent } from '../DocComponent';
 import { observer } from 'mobx-react';
 import "./PhysicsSimulationBox.scss";
-import Weight from "./PhysicsSimulationWeight";
-import Wall  from "./PhysicsSimulationWall"
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { CheckBox } from "../search/CheckBox";
 import PauseIcon from "@mui/icons-material/Pause";
@@ -33,9 +31,8 @@ import {
   Stack,
 } from "@mui/material";
 import Typography from "@mui/material/Typography";
-import React, { useEffect, useState } from "react";
 import "./App.scss";
-import { InputField } from "./InputField";
+import { InputField } from "./PhysicsSimulationInputField";
 import questions from "./PhysicsSimulationQuestions.json";
 import tutorials from "./PhysicsSimulationTutorial.json";
 import { IWallProps, Wall } from "./Wall";
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
new file mode 100644
index 000000000..91b0ad84c
--- /dev/null
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
@@ -0,0 +1,184 @@
+import { useState, useEffect } from "react";
+import { TextField, InputAdornment } from "@mui/material";
+
+import TaskAltIcon from "@mui/icons-material/TaskAlt";
+import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
+export interface IInputProps {
+  label?: JSX.Element;
+  lowerBound: number;
+  changeValue: (val: number) => any;
+  step: number;
+  unit: string;
+  upperBound: number;
+  value: number | string | Array<number | string>;
+  correctValue?: number;
+  showIcon?: boolean;
+  effect?: (val: number) => any;
+  radianEquivalent?: boolean;
+  small?: boolean;
+  mode?: string;
+  update?: boolean;
+  labelWidth?: string;
+}
+
+export const InputField = (props: IInputProps) => {
+  const {
+    changeValue,
+    correctValue,
+    effect,
+    label,
+    lowerBound,
+    mode,
+    radianEquivalent,
+    showIcon,
+    small,
+    step,
+    unit,
+    upperBound,
+    value,
+    update,
+    labelWidth,
+  } = props;
+  let epsilon: number = 0.01;
+
+  let width = small ? "6em" : "7em";
+  let margin = small ? "0px" : "10px";
+
+  const [tempValue, setTempValue] = useState<any>(
+    mode != "Freeform" && !showIcon ? 0 : value
+  );
+
+  const [tempRadianValue, setTempRadianValue] = useState(
+    mode != "Freeform" && !showIcon ? 0 : (Number(value) * Math.PI) / 180
+  );
+
+  useEffect(() => {
+    if (mode == "Freeform") {
+      if (Math.abs(tempValue - Number(value)) > 1) {
+        setTempValue(Number(value));
+      }
+    }
+  }, [value]);
+
+  const externalUpdate = () => {
+    changeValue(Number(value));
+    setTempValue(Number(value));
+    setTempRadianValue((Number(value) * Math.PI) / 180);
+  };
+
+  useEffect(() => {
+    externalUpdate();
+  }, [update]);
+
+  const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
+    let value = event.target.value == "" ? 0 : Number(event.target.value);
+    if (value > upperBound) {
+      value = upperBound;
+    } else if (value < lowerBound) {
+      value = lowerBound;
+    }
+    changeValue(value);
+    setTempValue(event.target.value == "" ? event.target.value : value);
+    setTempRadianValue((value * Math.PI) / 180);
+    if (effect) {
+      effect(value);
+    }
+  };
+
+  const onChangeRadianValue = (event: React.ChangeEvent<HTMLInputElement>) => {
+    let value = event.target.value === "" ? 0 : Number(event.target.value);
+    if (value > 2 * Math.PI) {
+      value = 2 * Math.PI;
+    } else if (value < 0) {
+      value = 0;
+    }
+    changeValue((value * 180) / Math.PI);
+    setTempValue((value * 180) / Math.PI);
+    setTempRadianValue(value);
+    if (effect) {
+      effect((value * 180) / Math.PI);
+    }
+  };
+
+  return (
+    <div
+      style={{
+        display: "flex",
+        lineHeight: "1.5",
+        textAlign: "right",
+        alignItems: "center",
+      }}
+    >
+      {label && (
+        <div
+          style={{
+            marginTop: "0.3em",
+            marginBottom: "-0.5em",
+            width: labelWidth ?? "2em",
+          }}
+        >
+          {label}
+        </div>
+      )}
+      <TextField
+        type="number"
+        variant="standard"
+        value={tempValue}
+        onChange={onChange}
+        sx={{
+          height: "1em",
+          width: { width },
+          marginLeft: { margin },
+          zIndex: "modal",
+        }}
+        inputProps={{
+          step: step,
+          min: lowerBound,
+          max: upperBound,
+          type: "number",
+        }}
+        InputProps={{
+          startAdornment: (
+            <InputAdornment position="start">
+              {Math.abs(Number(value) - (correctValue ?? 0)) < epsilon &&
+                showIcon && <TaskAltIcon color={"success"} />}
+              {Math.abs(Number(value) - (correctValue ?? 0)) >= epsilon &&
+                showIcon && <ErrorOutlineIcon color={"error"} />}
+            </InputAdornment>
+          ),
+          endAdornment: <InputAdornment position="end">{unit}</InputAdornment>,
+        }}
+      />
+      {radianEquivalent && (
+        <div
+          style={{ marginTop: "0.3em", marginBottom: "-0.5em", width: "1em" }}
+        >
+          <p>≈</p>
+        </div>
+      )}
+      {radianEquivalent && (
+        <TextField
+          type="number"
+          variant="standard"
+          value={tempRadianValue}
+          onChange={onChangeRadianValue}
+          sx={{
+            height: "1em",
+            width: { width },
+            marginLeft: { margin },
+            zIndex: "modal",
+          }}
+          inputProps={{
+            step: Math.PI / 8,
+            min: 0,
+            max: 2 * Math.PI,
+            type: "number",
+          }}
+          InputProps={{
+            endAdornment: <InputAdornment position="end">rad</InputAdornment>,
+          }}
+        />
+      )}
+    </div>
+  );
+};
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index c24438e19..3feec1ecb 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -1,8 +1,7 @@
 import { Doc } from '../../../../fields/Doc';
 import React = require('react');
-import { useEffect, useState } from "react";
 import { IWallProps } from "./PhysicsSimulationWall";
-import "./Weight.scss";
+import "./PhysicsSimulationWeight.scss";
 
 export interface IForce {
   description: string;
-- 
cgit v1.2.3-70-g09d2


From a2a72e177ef74bd2e81890e002635e67978ecfb3 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 1 May 2023 18:08:11 -0400
Subject: start refactor input

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 15 ++--
 .../PhysicsBox/PhysicsSimulationInputField.tsx     | 80 +++++++++++-----------
 .../nodes/PhysicsBox/PhysicsSimulationWall.tsx     |  2 +-
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   |  2 +-
 4 files changed, 49 insertions(+), 50 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 5b9d8f415..1e817a22d 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -1,11 +1,11 @@
 import "./PhysicsSimulationBox.scss";
-import { FieldView, FieldViewProps } from './FieldView';
+import { FieldView, FieldViewProps } from './../FieldView';
 import React = require('react');
-import { ViewBoxAnnotatableComponent } from '../DocComponent';
+import { ViewBoxAnnotatableComponent } from '../../DocComponent';
 import { observer } from 'mobx-react';
 import "./PhysicsSimulationBox.scss";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { CheckBox } from "../search/CheckBox";
+import { CheckBox } from "../../search/CheckBox";
 import PauseIcon from "@mui/icons-material/Pause";
 import PlayArrowIcon from "@mui/icons-material/PlayArrow";
 import ReplayIcon from "@mui/icons-material/Replay";
@@ -31,12 +31,12 @@ import {
   Stack,
 } from "@mui/material";
 import Typography from "@mui/material/Typography";
-import "./App.scss";
+import "./PhysicsSimulationBox.scss";
 import { InputField } from "./PhysicsSimulationInputField";
 import questions from "./PhysicsSimulationQuestions.json";
 import tutorials from "./PhysicsSimulationTutorial.json";
-import { IWallProps, Wall } from "./Wall";
-import { IForce, Weight } from "./Weight";
+import { IWallProps, Wall } from "./PhysicsSimulationWall";
+import { IForce, Weight } from "./PhysicsSimulationWeight";
 interface VectorTemplate {
   top: number;
   left: number;
@@ -2471,4 +2471,5 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       </p>
     </div>
   </div>
-  }
\ No newline at end of file
+  }
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
index 91b0ad84c..aa2d1c2cc 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
@@ -1,12 +1,13 @@
-import { useState, useEffect } from "react";
 import { TextField, InputAdornment } from "@mui/material";
-
+import { Doc } from '../../../../fields/Doc';
+import React = require('react');
 import TaskAltIcon from "@mui/icons-material/TaskAlt";
 import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
 export interface IInputProps {
   label?: JSX.Element;
   lowerBound: number;
-  changeValue: (val: number) => any;
+  dataDoc: doc;
+  prop: string;
   step: number;
   unit: string;
   upperBound: number;
@@ -21,36 +22,34 @@ export interface IInputProps {
   labelWidth?: string;
 }
 
-export const InputField = (props: IInputProps) => {
-  const {
-    changeValue,
-    correctValue,
-    effect,
-    label,
-    lowerBound,
-    mode,
-    radianEquivalent,
-    showIcon,
-    small,
-    step,
-    unit,
-    upperBound,
-    value,
-    update,
-    labelWidth,
-  } = props;
-  let epsilon: number = 0.01;
+interface IState {
+  tempValue: number,
+  tempRadianValue: number,
+}
 
-  let width = small ? "6em" : "7em";
-  let margin = small ? "0px" : "10px";
+export default class InputField extends React.Component<IInputProps, , IState> {
+  constructor(props: any) {
+    super(props)
+    this.state = {
+      tempValue: this.props.mode != "Freeform" && !this.props.showIcon ? 0 : this.props.value,
+      tempRadianValue: this.props.mode != "Freeform" && !this.props.showIcon ? 0 : (Number(this.props.value) * Math.PI) / 180
+    }
+  }
+
+  epsilon: number = 0;
+  width: string = "6em";
+  margin: string = "6em";
+  componentDidMount() {
+    this.epsilon = 0.01;
+    this.width = this.props.small ? "6em" : "7em";
+    this.margin = this.props.small ? "0px" : "10px";
+  }
+
+
+  componentDidUpdate(prevProps: Readonly<IInputProps>, prevState: Readonly<IState>, snapshot?: any): void {
+  }
 
-  const [tempValue, setTempValue] = useState<any>(
-    mode != "Freeform" && !showIcon ? 0 : value
-  );
 
-  const [tempRadianValue, setTempRadianValue] = useState(
-    mode != "Freeform" && !showIcon ? 0 : (Number(value) * Math.PI) / 180
-  );
 
   useEffect(() => {
     if (mode == "Freeform") {
@@ -60,24 +59,23 @@ export const InputField = (props: IInputProps) => {
     }
   }, [value]);
 
-  const externalUpdate = () => {
-    changeValue(Number(value));
+  externalUpdate = () => {
     setTempValue(Number(value));
     setTempRadianValue((Number(value) * Math.PI) / 180);
   };
 
   useEffect(() => {
-    externalUpdate();
+    this.externalUpdate();
   }, [update]);
 
-  const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
+  onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
     let value = event.target.value == "" ? 0 : Number(event.target.value);
-    if (value > upperBound) {
-      value = upperBound;
-    } else if (value < lowerBound) {
-      value = lowerBound;
+    if (value > this.props.upperBound) {
+      value = this.props.upperBound;
+    } else if (value < this.props.lowerBound) {
+      value = this.props.lowerBound;
     }
-    changeValue(value);
+    this.props.dataDoc[this.props.prop] = value
     setTempValue(event.target.value == "" ? event.target.value : value);
     setTempRadianValue((value * Math.PI) / 180);
     if (effect) {
@@ -85,14 +83,14 @@ export const InputField = (props: IInputProps) => {
     }
   };
 
-  const onChangeRadianValue = (event: React.ChangeEvent<HTMLInputElement>) => {
+  onChangeRadianValue = (event: React.ChangeEvent<HTMLInputElement>) => {
     let value = event.target.value === "" ? 0 : Number(event.target.value);
     if (value > 2 * Math.PI) {
       value = 2 * Math.PI;
     } else if (value < 0) {
       value = 0;
     }
-    changeValue((value * 180) / Math.PI);
+    this.props.dataDoc[this.props.prop] = (value * 180) / Math.PI
     setTempValue((value * 180) / Math.PI);
     setTempRadianValue(value);
     if (effect) {
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWall.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWall.tsx
index 9283e8d46..6e60ad85c 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWall.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWall.tsx
@@ -11,7 +11,7 @@ export interface IWallProps {
   angleInDegrees: number;
 }
 
-export default class App extends React.Component<IWallProps> {
+export default class Wall extends React.Component<IWallProps> {
 
   constructor(props: any) {
     super(props)
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 3feec1ecb..deecb03de 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -1,7 +1,7 @@
 import { Doc } from '../../../../fields/Doc';
 import React = require('react');
 import { IWallProps } from "./PhysicsSimulationWall";
-import "./PhysicsSimulationWeight.scss";
+import "./PhysicsSimulationBox.scss";
 
 export interface IForce {
   description: string;
-- 
cgit v1.2.3-70-g09d2


From e680ef59016b5574d765327cabaf5b5acd961adb Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 1 May 2023 18:32:02 -0400
Subject: debugging

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 96 +++++++++++-----------
 .../PhysicsBox/PhysicsSimulationInputField.tsx     |  1 -
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   |  1 +
 3 files changed, 50 insertions(+), 48 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 1e817a22d..b7bc81f38 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -35,8 +35,10 @@ import "./PhysicsSimulationBox.scss";
 import { InputField } from "./PhysicsSimulationInputField";
 import questions from "./PhysicsSimulationQuestions.json";
 import tutorials from "./PhysicsSimulationTutorial.json";
-import { IWallProps, Wall } from "./PhysicsSimulationWall";
-import { IForce, Weight } from "./PhysicsSimulationWeight";
+import Wall from "./PhysicsSimulationWall";
+import IWall from "./PhysicsSimulationWall";
+import Weight from "./PhysicsSimulationWeight";
+import IForce from "./PhysicsSimulationWeight";
 interface VectorTemplate {
   top: number;
   left: number;
@@ -99,9 +101,9 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.wallPositions.push({ length: 80, xPos: 69.5, yPos: 0, angleInDegrees: 90 });
 
     // Used throughout sims
-    this.xMax = this.layoutDoc._width*0.08;
-    this.yMax = this.layoutDoc._height*0.08;
-    this.radius = 0.1*this.layoutDoc._height;
+    this.xMax = this.layoutDoc._width*0.08 ?? 500;
+    this.yMax = this.layoutDoc._height*0.08 ?? 500;
+    this.radius = 0.1*this.layoutDoc._height ?? 50;
     this.dataDoc.reviewCoefficient = this.dataDoc.reviewCoefficient ?? 0;
     this.dataDoc.questionVariables = this.dataDoc.questionVariables ?? [];
     this.dataDoc.accelerationXDisplay = this.dataDoc.accelerationXDisplay ?? 0;
@@ -280,7 +282,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       this.dataDoc.showAcceleration = (false);
       if (this.dataDoc.simulationType != "Circular Motion") {
         this.dataDoc.velocityXDisplay = (0);
-        setVelocityYDisplay = (0);
+        this.dataDoc.velocityYDisplay = (0);
         this.dataDoc.showVelocity = (false);
       } else {
         this.dataDoc.velocityXDisplay = (20);
@@ -334,7 +336,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
         this.dataDoc.selectedTutorial = (tutorials.circular);
         this.dataDoc.startForces = (this.getForceFromJSON(tutorials.circular.steps[0].forces));
         this.dataDoc.showForceMagnitudes = (tutorials.circular.steps[0].showMagnitude);
-      } else if (simulationType == "Pulley") {
+      } else if (this.dataDoc.simulationType == "Pulley") {
         this.dataDoc.showForces = (true);
         this.setupPulley();
         this.dataDoc.selectedTutorial = (tutorials.pulley);
@@ -352,9 +354,9 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   }
 
   componentDidUpdate() {
-    this.xMax = this.layoutDoc._width*0.08;
-    this.yMax = this.layoutDoc._height*0.08;
-    this.radius = 0.1*this.layoutDoc._height;
+    this.xMax = this.layoutDoc._width*0.08 ?? 500;
+    this.yMax = this.layoutDoc._height*0.08 ?? 500;
+    this.radius = 0.1*this.layoutDoc._height ?? 50;
   }
 
   // Helper function to go between display and real values
@@ -368,12 +370,12 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   // Update forces when coefficient of static friction changes in freeform mode
   updateForcesWithFriction = (
     coefficient: number,
-    width: number = this.wedgeWidth,
-    height: number = this.wedgeHeight
+    width: number = this.dataDoc.wedgeWidth,
+    height: number = this.dataDoc.wedgeHeight
   ) => {
     const normalForce: IForce = {
       description: "Normal Force",
-      magnitude: Math.abs(this.gravity) * Math.cos(Math.atan(height / width)) * this.mass,
+      magnitude: Math.abs(this.dataDoc.gravity) * Math.cos(Math.atan(height / width)) * this.dataDoc.mass,
       directionInDegrees:
         180 - 90 - (Math.atan(height / width) * 180) / Math.PI,
       component: false,
@@ -382,14 +384,14 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       description: "Static Friction Force",
       magnitude:
         coefficient *
-        Math.abs(this.gravity) *
+        Math.abs(this.dataDoc.gravity) *
         Math.cos(Math.atan(height / width)) *
-        this.mass,
+        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(this.gravity) * this.mass;
+    let yForce = -Math.abs(this.dataDoc.gravity) * this.dataDoc.mass;
     yForce +=
       normalForce.magnitude *
       Math.sin((normalForce.directionInDegrees * Math.PI) / 180);
@@ -400,19 +402,19 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       frictionForce.magnitude =
         (-normalForce.magnitude *
           Math.sin((normalForce.directionInDegrees * Math.PI) / 180) +
-          Math.abs(this.gravity) * this.mass) /
+          Math.abs(this.dataDoc.gravity) * this.dataDoc.mass) /
         Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
     }
     const frictionForceComponent: IForce = {
       description: "Static Friction Force",
       magnitude:
-        coefficient * Math.abs(this.gravity) * Math.cos(Math.atan(height / width)),
+        coefficient * Math.abs(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(this.gravity) * Math.cos(Math.atan(height / width)),
+      magnitude: Math.abs(this.dataDoc.gravity) * Math.cos(Math.atan(height / width)),
       directionInDegrees:
         180 - 90 - (Math.atan(height / width) * 180) / Math.PI,
       component: true,
@@ -420,8 +422,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     const gravityParallel: IForce = {
       description: "Gravity Parallel Component",
       magnitude:
-      this.mass *
-        Math.abs(this.gravity) *
+      this.dataDoc.mass *
+        Math.abs(this.dataDoc.gravity) *
         Math.sin(Math.PI / 2 - Math.atan(height / width)),
       directionInDegrees:
         180 - 90 - (Math.atan(height / width) * 180) / Math.PI + 180,
@@ -430,15 +432,15 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     const gravityPerpendicular: IForce = {
       description: "Gravity Perpendicular Component",
       magnitude:
-      this.mass *
-        Math.abs(this.gravity) *
+      this.dataDoc.mass *
+        Math.abs(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: this.mass * Math.abs(this.gravity),
+      magnitude: this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
       directionInDegrees: 270,
       component: false,
     };
@@ -767,7 +769,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       if (this.dataDoc.questionNumber == questions.inclinePlane.length - 1) {
         this.dataDoc.questionNumber = (0);
       } else {
-        this.dataDoc.questionNumber =(questionNumber + 1);
+        this.dataDoc.questionNumber =(this.dataDoc.questionNumber + 1);
       }
       question = questions.inclinePlane[this.dataDoc.questionNumber];
 
@@ -1104,7 +1106,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     let yPos = this.yMin + 200;
     this.dataDoc.startPosY = (yPos);
     this.dataDoc.startPosX = (xPos);
-    this.dataDoc.positionYDisplay = (getDisplayYPos(yPos));
+    this.dataDoc.positionYDisplay = (this.getDisplayYPos(yPos));
     this.dataDoc.positionXDisplay = (xPos);
     let tensionMag = (this.dataDoc.mass * Math.abs(this.dataDoc.gravity)) / (2 * Math.sin(Math.PI / 4));
     const tensionForce1: IForce = {
@@ -1135,9 +1137,9 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.showComponentForces = (false);
     this.dataDoc.startPosY = ((this.yMax + this.yMin) / 2);
     this.dataDoc.startPosX = ((this.xMin + this.xMax) / 2 - 105);
-    this.dataDoc.positionYDisplay = (getDisplayYPos((this.yMax + this.yMin) / 2));
+    this.dataDoc.positionYDisplay = (this.getDisplayYPos((this.yMax + this.yMin) / 2));
     this.dataDoc.positionXDisplay = ((this.xMin + this.xMax) / 2 - 105);
-    let a = (-1 * ((mass - mass2) * Math.abs(gravity))) / (mass + mass2);
+    let a = (-1 * ((this.dataDoc.mass - this.dataDoc.mass2) * Math.abs(this.dataDoc.gravity))) / (this.dataDoc.mass + this.dataDoc.mass2);
     const gravityForce1: IForce = {
       description: "Gravity",
       magnitude: this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
@@ -1165,10 +1167,10 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     };
     this.dataDoc.updatedForces = ([gravityForce1, tensionForce1]);
     this.dataDoc.startForces = ([gravityForce1, tensionForce1]);
-    this.dataDoc.startPosY2 = ((yMax + yMin) / 2);
-    this.dataDoc.startPosX2 = ((xMin + xMax) / 2 + 5);
-    this.dataDoc.positionYDisplay2 = (getDisplayYPos((yMax + yMin) / 2));
-    this.dataDoc.positionXDisplay2 = ((xMin + xMax) / 2 + 5);
+    this.dataDoc.startPosY2 = ((this.props.yMax + this.props.yMin) / 2);
+    this.dataDoc.startPosX2 = ((this.props.xMin + this.props.xMax) / 2 + 5);
+    this.dataDoc.positionYDisplay2 = (this.getDisplayYPos((this.props.yMax + this.props.yMin) / 2));
+    this.dataDoc.positionXDisplay2 = ((this.props.xMin + this.props.xMax) / 2 + 5);
     this.dataDoc.updatedForces2 = ([gravityForce2, tensionForce2]);
     this.dataDoc.startForces2 = ([gravityForce2, tensionForce2]);
     this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
@@ -1229,7 +1231,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   }
 
   render () { 
-    <div className="physicsSimApp">
+    return <div className="physicsSimApp">
     <div className="mechanicsSimulationContainer">
       <div
         className="mechanicsSimulationContentContainer"
@@ -1533,16 +1535,16 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     this.dataDoc.selectedTutorial.steps[step].showMagnitude
                   );
                 }}
-                disabled={stepNumber == 0}
+                disabled={this.dataDoc.stepNumber == 0}
               >
                 <ArrowLeftIcon />
               </IconButton>
               <div>
                 <h3>
                   Step {this.dataDoc.stepNumber + 1}:{" "}
-                  {this.dataDoc.selectedTutorial.steps[stepNumber].description}
+                  {this.dataDoc.selectedTutorial.steps[this.dataDoc.stepNumber].description}
                 </h3>
-                <p>{this.dataDoc.selectedTutorial.steps[stepNumber].content}</p>
+                <p>{this.dataDoc.selectedTutorial.steps[this.dataDoc.stepNumber].content}</p>
               </div>
               <IconButton
                 onClick={() => {
@@ -1849,7 +1851,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   step={1}
                   unit={"N/m"}
                   upperBound={500}
-                  value={springConstant}
+                  value={this.dataDoc.springConstant}
                   effect={(val: number) => {
                     this.dataDoc.simulationReset(!this.dataDoc.simulationReset);
                   }}
@@ -1986,9 +1988,9 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   value={this.dataDoc.pendulumAngle}
                   effect={(value) => {
                     this.dataDoc.startPendulumAngle = (value);
-                    if (simulationType == "Pendulum") {
+                    if (this.dataDoc.simulationType == "Pendulum") {
                       const mag =
-                        mass *
+                      this.dataDoc.mass *
                         Math.abs(this.dataDoc.gravity) *
                         Math.cos((value * Math.PI) / 180);
 
@@ -2027,8 +2029,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                         length * Math.cos(((90 - value) * Math.PI) / 180);
                       const y =
                         length * Math.sin(((90 - value) * Math.PI) / 180);
-                      const xPos = this.xMax / 2 - x - radius;
-                      const yPos = y - radius - 5;
+                      const xPos = this.xMax / 2 - x - this.dataDoc.radius;
+                      const yPos = y - this.dataDoc.radius - 5;
                       this.dataDoc.startPosX = (xPos);
                       this.dataDoc.startPosY= (yPos);
 
@@ -2057,7 +2059,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                       ]);
                       this.dataDoc.adjustPendulumAngle = ({
                         angle: value,
-                        length: pendulumLength,
+                        length: this.dataDoc.pendulumLength,
                       });
                       this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
                     }
@@ -2075,7 +2077,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   upperBound={400}
                   value={Math.round(this.dataDoc.pendulumLength)}
                   effect={(value) => {
-                    if (simulationType == "Pendulum") {
+                    if (this.dataDoc.simulationType == "Pendulum") {
                       this.dataDoc.adjustPendulumAngle = ({
                         angle: this.dataDoc.pendulumAngle,
                         length: value,
@@ -2413,7 +2415,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     <div
       style={{
         position: "fixed",
-        top: this.layoutDoc._height - 120 + 20 + "px",
+        top: this.layoutDoc._height ?? 500 - 120 + 20 + "px",
         left: this.xMin + 90 - 80 + "px",
         zIndex: -10000,
       }}
@@ -2454,16 +2456,16 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       <p
         style={{
           position: "fixed",
-          top: this.layoutDoc._height - 120 + 40 + "px",
+          top: this.layoutDoc._height?? 500 - 120 + 40 + "px",
           left: this.xMin + 90 - 80 + "px",
         }}
       >
-        {simulationType == "Circular Motion" ? "Z" : "Y"}
+        {this.dataDoc.simulationType == "Circular Motion" ? "Z" : "Y"}
       </p>
       <p
         style={{
           position: "fixed",
-          top: this.layoutDoc._height - 120 + 80 + "px",
+          top: this.layoutDoc._height ?? 500- 120 + 80 + "px",
           left: this.xMin + 90 - 40 + "px",
         }}
       >
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
index 645c1995e..75bc28919 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
@@ -45,7 +45,6 @@ export default class InputField extends React.Component<IInputProps, , IState> {
     this.margin = this.props.small ? "0px" : "10px";
   }
 
-
   componentDidUpdate(prevProps: Readonly<IInputProps>, prevState: Readonly<IState>, snapshot?: any): void {
     if (prevProps.value != this.props.value) {
       if (this.props.mode == "Freeform") {
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index deecb03de..89bdae0a0 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -891,6 +891,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
 
   // Render weight, spring, rod(s), vectors
   render () { 
+    return
     <div style={{ zIndex: -1000 }}>
       <div
         className="weightContainer"
-- 
cgit v1.2.3-70-g09d2


From c4239e9bb5fb6389e3ceac281af8c8c683019a0c Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 1 May 2023 19:53:29 -0400
Subject: debugging

---
 .../views/nodes/PhysicsBox/PhysicsSimulationBox.tsx  | 20 ++++++++++----------
 .../nodes/PhysicsBox/PhysicsSimulationInputField.tsx |  2 +-
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx     |  4 ++--
 3 files changed, 13 insertions(+), 13 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index b7bc81f38..671466261 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -32,7 +32,7 @@ import {
 } from "@mui/material";
 import Typography from "@mui/material/Typography";
 import "./PhysicsSimulationBox.scss";
-import { InputField } from "./PhysicsSimulationInputField";
+import InputField from "./PhysicsSimulationInputField";
 import questions from "./PhysicsSimulationQuestions.json";
 import tutorials from "./PhysicsSimulationTutorial.json";
 import Wall from "./PhysicsSimulationWall";
@@ -86,13 +86,13 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   }
 
   // Constants
-  const xMin = 0;
-  const yMin = 0;
-  const xMax = 100;
-  const yMax = 100;
-  const color = `rgba(0,0,0,0.5)`;
-  const radius = 50;
-  const wallPositions: IWallProps[] = [];
+  xMin = 0;
+  yMin = 0;
+  xMax = 100;
+  yMax = 100;
+  color = `rgba(0,0,0,0.5)`;
+  radius = 50;
+  wallPositions: IWallProps[] = [];
 
   componentDidMount() {
     this.wallPositions.push({ length: 70, xPos: 0, yPos: 0, angleInDegrees: 0 });
@@ -1254,7 +1254,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               style={{
                 position: "fixed",
                 top: 1 + "em",
-                left: xMin + 12 + "px",
+                left: this.xMin + 12 + "px",
               }}
             >
               <div className="dropdownMenu">
@@ -1427,7 +1427,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
           </Stack>
           <div className="dropdownMenu">
             <select
-              value={mode}
+              value={this.dataDoc.mode}
               onChange={(event) => {
                 this.dataDoc.mode = (event.target.value);
 
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
index f3491fbd6..1125e6020 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
@@ -29,7 +29,7 @@ interface IState {
   margin: string;
 }
 
-export default class InputField extends React.Component<IInputProps, , IState> {
+export default class InputField extends React.Component<IInputProps, IState> {
   constructor(props: any) {
     super(props)
     this.state = {
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 06db9b4ce..8b7d4ed30 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -891,7 +891,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
 
   // Render weight, spring, rod(s), vectors
   render () { 
-    return
+    return (
     <div style={{ zIndex: -1000 }}>
       <div
         className="weightContainer"
@@ -1628,5 +1628,5 @@ export default class Weight extends React.Component<IWeightProps, IState> {
           );
         })}
     </div>
-  }
+  )}
 };
-- 
cgit v1.2.3-70-g09d2


From c93e1dc281c831ab08cf0ce29420df845323b0be Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 1 May 2023 20:05:49 -0400
Subject: debugging

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 86 +++++++++++++++-------
 .../PhysicsBox/PhysicsSimulationInputField.tsx     | 11 ++-
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   |  2 +-
 3 files changed, 68 insertions(+), 31 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 671466261..56c61c4f1 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -38,7 +38,13 @@ import tutorials from "./PhysicsSimulationTutorial.json";
 import Wall from "./PhysicsSimulationWall";
 import IWall from "./PhysicsSimulationWall";
 import Weight from "./PhysicsSimulationWeight";
-import IForce from "./PhysicsSimulationWeight";
+
+interface IForce {
+  description: string;
+  magnitude: number;
+  directionInDegrees: number;
+  component: boolean;
+}
 interface VectorTemplate {
   top: number;
   left: number;
@@ -833,7 +839,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             <InputField
               label={<p>Gravity magnitude</p>}
               lowerBound={0}
-              changeValue={this.dataDoc.reviewGravityMagnitude}
+              dataDoc={this.dataDoc}
+              prop={'reviewGravityMagnitude'}
               step={0.1}
               unit={"N"}
               upperBound={50}
@@ -851,7 +858,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             <InputField
               label={<p>Gravity angle</p>}
               lowerBound={0}
-              changeValue={this.dataDoc.reviewGravityAngle}
+              dataDoc={this.dataDoc}
+              prop={'reviewGravityAngle'}
               step={1}
               unit={"°"}
               upperBound={360}
@@ -870,7 +878,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             <InputField
               label={<p>Normal force magnitude</p>}
               lowerBound={0}
-              changeValue={this.dataDoc.reviewNormalMagnitude}
+              dataDoc={this.dataDoc}
+              prop={'reviewNormalMagnitude'}
               step={0.1}
               unit={"N"}
               upperBound={50}
@@ -888,7 +897,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             <InputField
               label={<p>Normal force angle</p>}
               lowerBound={0}
-              changeValue={this.dataDoc.reviewNormalAngle}
+              dataDoc={this.dataDoc}
+              prop={'reviewNormalAngle'}
               step={1}
               unit={"°"}
               upperBound={360}
@@ -907,7 +917,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             <InputField
               label={<p>Static friction magnitude</p>}
               lowerBound={0}
-              changeValue={this.dataDoc.reviewStaticMagnitude}
+              dataDoc={this.dataDoc}
+              prop={'reviewStaticMagnitude'}
               step={0.1}
               unit={"N"}
               upperBound={50}
@@ -925,7 +936,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             <InputField
               label={<p>Static friction angle</p>}
               lowerBound={0}
-              changeValue={this.dataDoc.reviewStaticAngle}
+              dataDoc={this.dataDoc}
+              prop={'reviewStaticAngle'}
               step={1}
               unit={"°"}
               upperBound={360}
@@ -948,7 +960,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 </Box>
               }
               lowerBound={0}
-              changeValue={this.dataDoc.coefficientOfStaticFriction}
+              dataDoc={this.dataDoc}
+              prop={'coefficientOfStaticFriction'}
               step={0.1}
               unit={""}
               upperBound={1}
@@ -966,7 +979,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             <InputField
               label={<Box>&theta;</Box>}
               lowerBound={0}
-              changeValue={this.dataDoc.qedgeAngle}
+              dataDoc={this.dataDoc}
+              prop={'wedgeAngle'}
               step={1}
               unit={"°"}
               upperBound={49}
@@ -1756,7 +1770,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 <InputField
                   label={<Box>Speed</Box>}
                   lowerBound={1}
-                  changeValue={this.dataDoc.simulationSpeed} //TODO - deal with input field change value now that datadoc is being used!
+                  dataDoc={this.dataDoc}
+                  prop={'simulationSpeed'}
                   step={1}
                   unit={"x"}
                   upperBound={10}
@@ -1767,7 +1782,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   <InputField
                     label={<Box>Gravity</Box>}
                     lowerBound={-30}
-                    changeValue={this.dataDoc.gravity}
+                    dataDoc={this.dataDoc}
+                    prop={'gravity'}
                     step={0.01}
                     unit={"m/s2"}
                     upperBound={0}
@@ -1782,7 +1798,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   <InputField
                     label={<Box>Mass</Box>}
                     lowerBound={1}
-                    changeValue={this.dataDoc.mass}
+                    dataDoc={this.dataDoc}
+                    prop={'mass'}
                     step={0.1}
                     unit={"kg"}
                     upperBound={5}
@@ -1797,7 +1814,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   <InputField
                     label={<Box>Red mass</Box>}
                     lowerBound={1}
-                    changeValue={this.dataDoc.mass}
+                    dataDoc={this.dataDoc}
+                    prop={'mass'}
                     step={0.1}
                     unit={"kg"}
                     upperBound={5}
@@ -1812,7 +1830,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   <InputField
                     label={<Box>Blue mass</Box>}
                     lowerBound={1}
-                    changeValue={this.dataDoc.mass2}
+                    dataDoc={this.dataDoc}
+                    prop={'mass2'}
                     step={0.1}
                     unit={"kg"}
                     upperBound={5}
@@ -1827,7 +1846,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   <InputField
                     label={<Box>Rod length</Box>}
                     lowerBound={100}
-                    changeValue={this.dataDoc.circularMotionRadius}
+                    dataDoc={this.dataDoc}
+                    prop={'circularMotionRadius'}
                     step={5}
                     unit={"kg"}
                     upperBound={250}
@@ -1847,7 +1867,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     <Typography color="inherit">Spring stiffness</Typography>
                   }
                   lowerBound={0.1}
-                  changeValue={this.dataDoc.springConstant}
+                  dataDoc={this.dataDoc}
+                  prop={'springConstant'}
                   step={1}
                   unit={"N/m"}
                   upperBound={500}
@@ -1862,7 +1883,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 <InputField
                   label={<Typography color="inherit">Rest length</Typography>}
                   lowerBound={10}
-                  changeValue={this.dataDoc.springRestLength}
+                  dataDoc={this.dataDoc}
+                  prop={'springRestLength'}
                   step={100}
                   unit={""}
                   upperBound={500}
@@ -1881,7 +1903,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     </Typography>
                   }
                   lowerBound={-(this.dataDoc.springRestLength - 10)}
-                  changeValue={(val: number) => {}}
+                  dataDoc={this.dataDoc}
+                  prop={""}
                   step={10}
                   unit={""}
                   upperBound={this.dataDoc.springRestLength}
@@ -1902,7 +1925,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 <InputField
                   label={<Box>&theta;</Box>}
                   lowerBound={0}
-                  changeValue={this.dataDoc.wedgeAngle}
+                  dataDoc={this.dataDoc}
+                  prop={'wedgeAngle'}
                   step={1}
                   unit={"°"}
                   upperBound={49}
@@ -1922,7 +1946,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     </Box>
                   }
                   lowerBound={0}
-                  changeValue={this.dataDoc.coefficientOfStaticFriction}
+                  dataDoc={this.dataDoc}
+                  prop={'coefficientOfStaticFriction'}
                   step={0.1}
                   unit={""}
                   upperBound={1}
@@ -1944,7 +1969,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     </Box>
                   }
                   lowerBound={0}
-                  changeValue={this.dataDoc.coefficientOfKineticFriction}
+                  dataDoc={this.dataDoc}
+                  prop={'coefficientOfKineticFriction'}
                   step={0.1}
                   unit={""}
                   upperBound={Number(this.dataDoc.coefficientOfStaticFriction)}
@@ -1981,7 +2007,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 <InputField
                   label={<Box>Angle</Box>}
                   lowerBound={0}
-                  changeValue={this.dataDoc.pendulumAngle}
+                  dataDoc={this.dataDoc}
+                  prop={'pendulumAngle'}
                   step={1}
                   unit={"°"}
                   upperBound={59}
@@ -2071,7 +2098,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 <InputField
                   label={<Box>Rod length</Box>}
                   lowerBound={0}
-                  changeValue={this.dataDoc.pendulumLength}
+                  dataDoc={this.dataDoc}
+                  prop={'pendulumLength'}
                   step={1}
                   unit={"m"}
                   upperBound={400}
@@ -2134,7 +2162,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                       >
                         <InputField
                           lowerBound={0}
-                          changeValue={this.dataDoc.positionXDisplay}
+                          dataDoc={this.dataDoc}
+                          prop={'positionXDisplay'}
                           step={1}
                           unit={"m"}
                           upperBound={this.xMax - 110}
@@ -2171,7 +2200,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                       >
                         <InputField
                           lowerBound={0}
-                          changeValue={this.dataDoc.positionYDisplay}
+                          dataDoc={this.dataDoc}
+                          prop={'positionYDisplay'}
                           step={1}
                           unit={"m"}
                           upperBound={this.yMax - 110}
@@ -2216,7 +2246,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                       >
                         <InputField
                           lowerBound={-50}
-                          changeValue={this.dataDoc.velocityXDisplay}
+                          dataDoc={this.dataDoc}
+                          prop={'velocityXDisplay'}
                           step={1}
                           unit={"m/s"}
                           upperBound={50}
@@ -2243,7 +2274,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     >
                       <InputField
                         lowerBound={-50}
-                        changeValue={this.dataDoc.velocityYDisplay}
+                        dataDoc={this.dataDoc}
+                        prop={'velocityYDisplay'}
                         step={1}
                         unit={"m/s"}
                         upperBound={50}
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
index 1125e6020..cd55453ea 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
@@ -23,7 +23,7 @@ export interface IInputProps {
 }
 
 interface IState {
-  tempValue: number,
+  tempValue: string | number | (string|number)[],
   tempRadianValue: number,
   width: string;
   margin: string;
@@ -71,7 +71,9 @@ export default class InputField extends React.Component<IInputProps, IState> {
     } else if (value < this.props.lowerBound) {
       value = this.props.lowerBound;
     }
-    this.props.dataDoc[this.props.prop] = value
+    if (this.props.prop != "") {
+      this.props.dataDoc[this.props.prop] = value
+    }
     this.setState({tempValue: event.target.value == "" ? event.target.value : value})
     this.setState({tempRadianValue: (value * Math.PI) / 180})
     if (this.props.effect) {
@@ -85,8 +87,9 @@ export default class InputField extends React.Component<IInputProps, IState> {
       value = 2 * Math.PI;
     } else if (value < 0) {
       value = 0;
+    }if (this.props.prop != "") {
+      this.props.dataDoc[this.props.prop] = (value * 180) / Math.PI
     }
-    this.props.dataDoc[this.props.prop] = (value * 180) / Math.PI
     this.setState({tempValue: (value * 180) / Math.PI})
     this.setState({tempRadianValue: value})
     if (this.props.effect) {
@@ -95,6 +98,7 @@ export default class InputField extends React.Component<IInputProps, IState> {
   };
 
   render () { 
+    return (
     <div
       style={{
         display: "flex",
@@ -174,5 +178,6 @@ export default class InputField extends React.Component<IInputProps, IState> {
         />
       )}
     </div>
+    )
   }
 };
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 8b7d4ed30..ed219652a 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -3,7 +3,7 @@ import React = require('react');
 import { IWallProps } from "./PhysicsSimulationWall";
 import "./PhysicsSimulationBox.scss";
 
-export interface IForce {
+interface IForce {
   description: string;
   magnitude: number;
   directionInDegrees: number;
-- 
cgit v1.2.3-70-g09d2


From da534b9792907492e2287fbe4b4f932fde994fa0 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 1 May 2023 20:37:14 -0400
Subject: debugging

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 888 +++++++++++----------
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   |  19 +-
 2 files changed, 456 insertions(+), 451 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 56c61c4f1..21cef297a 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -33,12 +33,18 @@ import {
 import Typography from "@mui/material/Typography";
 import "./PhysicsSimulationBox.scss";
 import InputField from "./PhysicsSimulationInputField";
-import questions from "./PhysicsSimulationQuestions.json";
-import tutorials from "./PhysicsSimulationTutorial.json";
+// import questions from "./PhysicsSimulationQuestions.json";
+// import tutorials from "./PhysicsSimulationTutorial.json";
 import Wall from "./PhysicsSimulationWall";
 import IWall from "./PhysicsSimulationWall";
 import Weight from "./PhysicsSimulationWeight";
 
+interface IWallProps {
+  length: number;
+  xPos: number;
+  yPos: number;
+  angleInDegrees: number;
+}
 interface IForce {
   description: string;
   magnitude: number;
@@ -143,10 +149,10 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.velocityYDisplay = this.dataDoc.velocityYDisplay ?? 0;
 
     // Used for review mode
-    this.dataDoc.answerInputFields = this.dataDoc.answerInputFields ?? <div></div>;
-    this.dataDoc.currentForceSketch = this.dataDoc.currentForceSketch ?? null;
-    this.dataDoc.deleteMode = this.dataDoc.deleteMode ?? false;
-    this.dataDoc.forceSketches = this.dataDoc.forceSketches ?? [];
+    // this.dataDoc.answerInputFields = this.dataDoc.answerInputFields ?? <div></div>;
+    // this.dataDoc.currentForceSketch = this.dataDoc.currentForceSketch ?? null;
+    // this.dataDoc.deleteMode = this.dataDoc.deleteMode ?? false;
+    // this.dataDoc.forceSketches = this.dataDoc.forceSketches ?? [];
     this.dataDoc.hintDialogueOpen = this.dataDoc.hintDialogueOpen ?? false;
     this.dataDoc.noMovement = this.dataDoc.noMovement ?? false;
     this.dataDoc.questionNumber = this.dataDoc.questionNumber ?? 0;
@@ -159,11 +165,11 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.reviewStaticAngle = this.dataDoc.reviewStaticAngle ?? 0;
     this.dataDoc.reviewStaticMagnitude = this.dataDoc.reviewStaticMagnitude ?? 0;
     this.dataDoc.selectedSolutions = this.dataDoc.selectedSolutions ?? [];
-    this.dataDoc.selectedQuestion = this.dataDoc.selectedQuestion ?? questions.inclinePlane[0];
-    this.dataDoc.sketching = this.dataDoc.sketching ?? false;
+    // 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 tutorial mode
+    // this.dataDoc.selectedTutorial = this.dataDoc.selectedTutorial ?? tutorials.inclinePlane;
 
     // Used for uniform circular motion
     this.dataDoc.circularMotionRadius = this.dataDoc.circularMotionRadius ?? 150;
@@ -260,7 +266,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       this.dataDoc.showAcceleration = (false);
       this.dataDoc.showVelocity = (false);
       this.dataDoc.showForces= (true);
-      this.generateNewQuestion();
+      // this.generateNewQuestion();
       if (this.dataDoc.simulationType == "One Weight") {
         // TODO - one weight review problems
       } else if (this.dataDoc.simulationType == "Spring") {
@@ -286,75 +292,75 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       this.dataDoc.showComponentForces = (false);
       this.dataDoc.stepNumber = (0);
       this.dataDoc.showAcceleration = (false);
-      if (this.dataDoc.simulationType != "Circular Motion") {
-        this.dataDoc.velocityXDisplay = (0);
-        this.dataDoc.velocityYDisplay = (0);
-        this.dataDoc.showVelocity = (false);
-      } else {
-        this.dataDoc.velocityXDisplay = (20);
-        this.dataDoc.velocityYDisplay = (0);
-        this.dataDoc.showVelocity = (true);
-      }
+      // if (this.dataDoc.simulationType != "Circular Motion") {
+      //   this.dataDoc.velocityXDisplay = (0);
+      //   this.dataDoc.velocityYDisplay = (0);
+      //   this.dataDoc.showVelocity = (false);
+      // } else {
+      //   this.dataDoc.velocityXDisplay = (20);
+      //   this.dataDoc.velocityYDisplay = (0);
+      //   this.dataDoc.showVelocity = (true);
+      // }
 
-      if (this.dataDoc.simulationType == "One Weight") {
-        this.dataDoc.showForces = (true);
-        this.dataDoc.startPosY = (this.yMax - 100);
-        this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
-        this.dataDoc.selectedTutorial = (tutorials.freeWeight);
-        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.freeWeight.steps[0].forces));
-        this.dataDoc.showForceMagnitudes = (tutorials.freeWeight.steps[0].showMagnitude);
-      } else if (this.dataDoc.simulationType == "Spring") {
-        this.dataDoc.showForces = (true);
-        this.setupSpring();
-        this.dataDoc.startPosY = (this.yMin + 200 + 19.62);
-        this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
-        this.dataDoc.selectedTutorial = (tutorials.spring);
-        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.spring.steps[0].forces));
-        this.dataDoc.showForceMagnitudes = (tutorials.spring.steps[0].showMagnitude);
-      } else if (this.dataDoc.simulationType == "Pendulum") {
-        this.dataDoc.showForces = (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 - this.radius;
-        const yPos = y - this.radius - 5;
-        this.dataDoc.startPosX = (xPos);
-        this.dataDoc.startPosY = (yPos);
-        this.dataDoc.selectedTutorial = (tutorials.pendulum);
-        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.pendulum.steps[0].forces));
-        this.dataDoc.showForceMagnitudes = (tutorials.pendulum.steps[0].showMagnitude);
-        this.dataDoc.pendulumAngle = (30);
-        this.dataDoc.pendulumLength = (300);
-        this.dataDoc.adjustPendulumAngle = ({ angle: 30, length: 300 });
-      } else if (this.dataDoc.simulationType == "Inclined Plane") {
-        this.dataDoc.showForces = (true);
-        this.dataDoc.wedgeAngle = (26);
-        this.changeWedgeBasedOnNewAngle(26);
-        this.dataDoc.selectedTutorial = (tutorials.inclinePlane);
-        this.dataDoc.startForces = (
-          this.getForceFromJSON(tutorials.inclinePlane.steps[0].forces)
-        );
-        this.dataDoc.showForceMagnitudes = (tutorials.inclinePlane.steps[0].showMagnitude);
-      } else if (this.dataDoc.simulationType == "Circular Motion") {
-        this.dataDoc.showForces = (true);
-        this.setupCircular(40);
-        this.dataDoc.selectedTutorial = (tutorials.circular);
-        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.circular.steps[0].forces));
-        this.dataDoc.showForceMagnitudes = (tutorials.circular.steps[0].showMagnitude);
-      } else if (this.dataDoc.simulationType == "Pulley") {
-        this.dataDoc.showForces = (true);
-        this.setupPulley();
-        this.dataDoc.selectedTutorial = (tutorials.pulley);
-        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.pulley.steps[0].forces));
-        this.dataDoc.showForceMagnitudes = (tutorials.pulley.steps[0].showMagnitude);
-      } else if (this.dataDoc.simulationType == "Suspension") {
-        this.dataDoc.showForces = (true);
-        this.setupSuspension();
-        this.dataDoc.selectedTutorial = (tutorials.suspension);
-        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.suspension.steps[0].forces));
-        this.dataDoc.showForceMagnitudes = (tutorials.suspension.steps[0].showMagnitude);
-      }
+      // if (this.dataDoc.simulationType == "One Weight") {
+      //   this.dataDoc.showForces = (true);
+      //   this.dataDoc.startPosY = (this.yMax - 100);
+      //   this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
+      //   this.dataDoc.selectedTutorial = (tutorials.freeWeight);
+      //   this.dataDoc.startForces = (this.getForceFromJSON(tutorials.freeWeight.steps[0].forces));
+      //   this.dataDoc.showForceMagnitudes = (tutorials.freeWeight.steps[0].showMagnitude);
+      // } else if (this.dataDoc.simulationType == "Spring") {
+      //   this.dataDoc.showForces = (true);
+      //   this.setupSpring();
+      //   this.dataDoc.startPosY = (this.yMin + 200 + 19.62);
+      //   this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
+      //   this.dataDoc.selectedTutorial = (tutorials.spring);
+      //   this.dataDoc.startForces = (this.getForceFromJSON(tutorials.spring.steps[0].forces));
+      //   this.dataDoc.showForceMagnitudes = (tutorials.spring.steps[0].showMagnitude);
+      // } else if (this.dataDoc.simulationType == "Pendulum") {
+      //   this.dataDoc.showForces = (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 - this.radius;
+      //   const yPos = y - this.radius - 5;
+      //   this.dataDoc.startPosX = (xPos);
+      //   this.dataDoc.startPosY = (yPos);
+      //   this.dataDoc.selectedTutorial = (tutorials.pendulum);
+      //   this.dataDoc.startForces = (this.getForceFromJSON(tutorials.pendulum.steps[0].forces));
+      //   this.dataDoc.showForceMagnitudes = (tutorials.pendulum.steps[0].showMagnitude);
+      //   this.dataDoc.pendulumAngle = (30);
+      //   this.dataDoc.pendulumLength = (300);
+      //   this.dataDoc.adjustPendulumAngle = ({ angle: 30, length: 300 });
+      // } else if (this.dataDoc.simulationType == "Inclined Plane") {
+      //   this.dataDoc.showForces = (true);
+      //   this.dataDoc.wedgeAngle = (26);
+      //   this.changeWedgeBasedOnNewAngle(26);
+      //   this.dataDoc.selectedTutorial = (tutorials.inclinePlane);
+      //   this.dataDoc.startForces = (
+      //     this.getForceFromJSON(tutorials.inclinePlane.steps[0].forces)
+      //   );
+      //   this.dataDoc.showForceMagnitudes = (tutorials.inclinePlane.steps[0].showMagnitude);
+      // } else if (this.dataDoc.simulationType == "Circular Motion") {
+      //   this.dataDoc.showForces = (true);
+      //   this.setupCircular(40);
+      //   this.dataDoc.selectedTutorial = (tutorials.circular);
+      //   this.dataDoc.startForces = (this.getForceFromJSON(tutorials.circular.steps[0].forces));
+      //   this.dataDoc.showForceMagnitudes = (tutorials.circular.steps[0].showMagnitude);
+      // } else if (this.dataDoc.simulationType == "Pulley") {
+      //   this.dataDoc.showForces = (true);
+      //   this.setupPulley();
+      //   this.dataDoc.selectedTutorial = (tutorials.pulley);
+      //   this.dataDoc.startForces = (this.getForceFromJSON(tutorials.pulley.steps[0].forces));
+      //   this.dataDoc.showForceMagnitudes = (tutorials.pulley.steps[0].showMagnitude);
+      // } else if (this.dataDoc.simulationType == "Suspension") {
+      //   this.dataDoc.showForces = (true);
+      //   this.setupSuspension();
+      //   this.dataDoc.selectedTutorial = (tutorials.suspension);
+      //   this.dataDoc.startForces = (this.getForceFromJSON(tutorials.suspension.steps[0].forces));
+      //   this.dataDoc.showForceMagnitudes = (tutorials.suspension.steps[0].showMagnitude);
+      // }
       this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
     }
   }
@@ -524,45 +530,45 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     }
   };
 
-  // In review mode, update forces when coefficient of static friction changed
-  updateReviewForcesBasedOnCoefficient = (coefficient: number) => {
-    let theta: number = Number(this.dataDoc.wedgeAngle);
-    let index =
-      this.dataDoc.selectedQuestion.variablesForQuestionSetup.indexOf("theta - max 45");
-    if (index >= 0) {
-      theta = this.dataDoc.questionVariables[index];
-    }
-    if (isNaN(theta)) {
-      return;
-    }
-    this.dataDoc.reviewGravityMagnitude = (Math.abs(this.dataDoc.gravity));
-    this.dataDoc.reviewGravityAngle = (270);
-    this.dataDoc.reviewNormalMagnitude = (
-      Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180)
-    );
-    this.dataDoc.reviewNormalAngle = (90 - theta);
-    let yForce = -Math.abs(this.dataDoc.gravity);
-    yForce +=
-      Math.abs(this.dataDoc.gravity) *
-      Math.cos((theta * Math.PI) / 180) *
-      Math.sin(((90 - theta) * Math.PI) / 180);
-    yForce +=
-      coefficient *
-      Math.abs(this.dataDoc.gravity) *
-      Math.cos((theta * Math.PI) / 180) *
-      Math.sin(((180 - theta) * Math.PI) / 180);
-    let friction =
-      coefficient * Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180);
-    if (yForce > 0) {
-      friction =
-        (-(Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180)) *
-          Math.sin(((90 - theta) * Math.PI) / 180) +
-          Math.abs(this.dataDoc.gravity)) /
-        Math.sin(((180 - theta) * Math.PI) / 180);
-    }
-    this.dataDoc.reviewStaticMagnitude = (friction);
-    this.dataDoc.reviewStaticAngle = (180 - theta);
-  };
+  // // In review mode, update forces when coefficient of static friction changed
+  // updateReviewForcesBasedOnCoefficient = (coefficient: number) => {
+  //   let theta: number = Number(this.dataDoc.wedgeAngle);
+  //   let index =
+  //     this.dataDoc.selectedQuestion.variablesForQuestionSetup.indexOf("theta - max 45");
+  //   if (index >= 0) {
+  //     theta = this.dataDoc.questionVariables[index];
+  //   }
+  //   if (isNaN(theta)) {
+  //     return;
+  //   }
+  //   this.dataDoc.reviewGravityMagnitude = (Math.abs(this.dataDoc.gravity));
+  //   this.dataDoc.reviewGravityAngle = (270);
+  //   this.dataDoc.reviewNormalMagnitude = (
+  //     Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180)
+  //   );
+  //   this.dataDoc.reviewNormalAngle = (90 - theta);
+  //   let yForce = -Math.abs(this.dataDoc.gravity);
+  //   yForce +=
+  //     Math.abs(this.dataDoc.gravity) *
+  //     Math.cos((theta * Math.PI) / 180) *
+  //     Math.sin(((90 - theta) * Math.PI) / 180);
+  //   yForce +=
+  //     coefficient *
+  //     Math.abs(this.dataDoc.gravity) *
+  //     Math.cos((theta * Math.PI) / 180) *
+  //     Math.sin(((180 - theta) * Math.PI) / 180);
+  //   let friction =
+  //     coefficient * Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180);
+  //   if (yForce > 0) {
+  //     friction =
+  //       (-(Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180)) *
+  //         Math.sin(((90 - theta) * Math.PI) / 180) +
+  //         Math.abs(this.dataDoc.gravity)) /
+  //       Math.sin(((180 - theta) * Math.PI) / 180);
+  //   }
+  //   this.dataDoc.reviewStaticMagnitude = (friction);
+  //   this.dataDoc.reviewStaticAngle = (180 - theta);
+  // };
 
   // In review mode, update forces when wedge angle changed
   updateReviewForcesBasedOnAngle = (angle: number) => {
@@ -672,84 +678,84 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     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(this.dataDoc.reviewGravityMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon
-          ) {
-            error = true;
-          }
-        } else if (this.dataDoc.selectedQuestion.answerParts[i] == "angle of gravity") {
-          if (Math.abs(this.dataDoc.reviewGravityAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
-            error = true;
-          }
-        } else if (this.dataDoc.selectedQuestion.answerParts[i] == "normal force") {
-          if (
-            Math.abs(this.dataDoc.reviewNormalMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon
-          ) {
-            error = true;
-          }
-        } else if (this.dataDoc.selectedQuestion.answerParts[i] == "angle of normal force") {
-          if (Math.abs(this.dataDoc.reviewNormalAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
-            error = true;
-          }
-        } else if (
-          this.dataDoc.selectedQuestion.answerParts[i] == "force of static friction"
-        ) {
-          if (
-            Math.abs(this.dataDoc.reviewStaticMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon
-          ) {
-            error = true;
-          }
-        } else if (
-          this.dataDoc.selectedQuestion.answerParts[i] == "angle of static friction"
-        ) {
-          if (Math.abs(this.dataDoc.reviewStaticAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
-            error = true;
-          }
-        } else if (
-          this.dataDoc.selectedQuestion.answerParts[i] == "coefficient of static friction"
-        ) {
-          if (
-            Math.abs(
-              Number(this.dataDoc.coefficientOfStaticFriction) - this.dataDoc.selectedSolutions[i]
-            ) > epsilon
-          ) {
-            error = true;
-          }
-        } else if (this.dataDoc.selectedQuestion.answerParts[i] == "wedge angle") {
-          if (Math.abs(Number(this.dataDoc.wedgeAngle) - this.dataDoc.selectedSolutions[i]) > epsilon) {
-            error = true;
-          }
-        }
-      }
-    }
-    if (showAlert) {
-      if (!error) {
-        this.dataDoc.simulationPaused = (false);
-        setTimeout(() => {
-          this.dataDoc.simulationPaused = (true);
-        }, 3000);
-      } else {
-        this.dataDoc.simulationPaused = (false);
-        setTimeout(() => {
-          this.dataDoc.simulationPaused = (true);
-        }, 3000);
-      }
-    }
-    if (this.dataDoc.selectedQuestion.goal == "noMovement") {
-      if (!error) {
-        this.dataDoc.noMovement = (true);
-      } else {
-        this.dataDoc.roMovement = (false);
-      }
-    }
-  };
+  // // 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(this.dataDoc.reviewGravityMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon
+  //         ) {
+  //           error = true;
+  //         }
+  //       } else if (this.dataDoc.selectedQuestion.answerParts[i] == "angle of gravity") {
+  //         if (Math.abs(this.dataDoc.reviewGravityAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
+  //           error = true;
+  //         }
+  //       } else if (this.dataDoc.selectedQuestion.answerParts[i] == "normal force") {
+  //         if (
+  //           Math.abs(this.dataDoc.reviewNormalMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon
+  //         ) {
+  //           error = true;
+  //         }
+  //       } else if (this.dataDoc.selectedQuestion.answerParts[i] == "angle of normal force") {
+  //         if (Math.abs(this.dataDoc.reviewNormalAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
+  //           error = true;
+  //         }
+  //       } else if (
+  //         this.dataDoc.selectedQuestion.answerParts[i] == "force of static friction"
+  //       ) {
+  //         if (
+  //           Math.abs(this.dataDoc.reviewStaticMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon
+  //         ) {
+  //           error = true;
+  //         }
+  //       } else if (
+  //         this.dataDoc.selectedQuestion.answerParts[i] == "angle of static friction"
+  //       ) {
+  //         if (Math.abs(this.dataDoc.reviewStaticAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
+  //           error = true;
+  //         }
+  //       } else if (
+  //         this.dataDoc.selectedQuestion.answerParts[i] == "coefficient of static friction"
+  //       ) {
+  //         if (
+  //           Math.abs(
+  //             Number(this.dataDoc.coefficientOfStaticFriction) - this.dataDoc.selectedSolutions[i]
+  //           ) > epsilon
+  //         ) {
+  //           error = true;
+  //         }
+  //       } else if (this.dataDoc.selectedQuestion.answerParts[i] == "wedge angle") {
+  //         if (Math.abs(Number(this.dataDoc.wedgeAngle) - this.dataDoc.selectedSolutions[i]) > epsilon) {
+  //           error = true;
+  //         }
+  //       }
+  //     }
+  //   }
+  //   if (showAlert) {
+  //     if (!error) {
+  //       this.dataDoc.simulationPaused = (false);
+  //       setTimeout(() => {
+  //         this.dataDoc.simulationPaused = (true);
+  //       }, 3000);
+  //     } else {
+  //       this.dataDoc.simulationPaused = (false);
+  //       setTimeout(() => {
+  //         this.dataDoc.simulationPaused = (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 = () => {
@@ -764,248 +770,248 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.answerInputFields = (<div></div>);
   };
 
-  // In review mode, reset problem variables and generate a new question
-  generateNewQuestion = () => {
-    this.resetReviewValuesToDefault();
+  // // In review mode, reset problem variables and generate a new question
+  // generateNewQuestion = () => {
+  //   this.resetReviewValuesToDefault();
 
-    const vars: number[] = [];
-    let question: QuestionTemplate = questions.inclinePlane[0];
+  //   const vars: number[] = [];
+  //   let question: QuestionTemplate = questions.inclinePlane[0];
 
-    if (this.dataDoc.simulationType == "Inclined Plane") {
-      if (this.dataDoc.questionNumber == questions.inclinePlane.length - 1) {
-        this.dataDoc.questionNumber = (0);
-      } else {
-        this.dataDoc.questionNumber =(this.dataDoc.questionNumber + 1);
-      }
-      question = questions.inclinePlane[this.dataDoc.questionNumber];
+  //   if (this.dataDoc.simulationType == "Inclined Plane") {
+  //     if (this.dataDoc.questionNumber == questions.inclinePlane.length - 1) {
+  //       this.dataDoc.questionNumber = (0);
+  //     } else {
+  //       this.dataDoc.questionNumber =(this.dataDoc.questionNumber + 1);
+  //     }
+  //     question = questions.inclinePlane[this.dataDoc.questionNumber];
 
-      let coefficient = 0;
-      let wedgeAngle = 0;
+  //     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.reviewCoefficient = 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 = vars;
-    this.dataDoc.selectedQuestion = (question);
-    this.dataDoc.questionPartOne = (q);
-    this.dataDoc.questionPartTwo = (question.question);
-    const answers = this.getAnswersToQuestion(question, vars);
-    this.generateInputFieldsForQuestion(false, question, answers);
-    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
-  };
+  //     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.reviewCoefficient = 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 = vars;
+  //   this.dataDoc.selectedQuestion = (question);
+  //   this.dataDoc.questionPartOne = (q);
+  //   this.dataDoc.questionPartTwo = (question.question);
+  //   const answers = this.getAnswersToQuestion(question, vars);
+  //   this.generateInputFieldsForQuestion(false, question, answers);
+  //   this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+  // };
 
-  // Generate answerInputFields for new review question
-  generateInputFieldsForQuestion = (
-    showIcon: boolean = false,
-    question: QuestionTemplate = this.dataDoc.selectedQuestion,
-    answers: number[] = this.dataDoc.selectedSolutions
-  ) => {
-    let answerInput = [];
-    const d = new Date();
-    for (let i = 0; i < question.answerParts.length; i++) {
-      if (question.answerParts[i] == "force of gravity") {
-        this.dataDoc.reviewGravityMagnitude = (0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={<p>Gravity magnitude</p>}
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'reviewGravityMagnitude'}
-              step={0.1}
-              unit={"N"}
-              upperBound={50}
-              value={this.dataDoc.reviewGravityMagnitude}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-              labelWidth={"7em"}
-            />
-          </div>
-        );
-      } else if (question.answerParts[i] == "angle of gravity") {
-        this.dataDoc.reviewGravityAngle = (0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={<p>Gravity angle</p>}
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'reviewGravityAngle'}
-              step={1}
-              unit={"°"}
-              upperBound={360}
-              value={this.dataDoc.reviewGravityAngle}
-              radianEquivalent={true}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-              labelWidth={"7em"}
-            />
-          </div>
-        );
-      } else if (question.answerParts[i] == "normal force") {
-        this.dataDoc.reviewNormalMagnitude = (0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={<p>Normal force magnitude</p>}
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'reviewNormalMagnitude'}
-              step={0.1}
-              unit={"N"}
-              upperBound={50}
-              value={this.dataDoc.reviewNormalMagnitude}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-              labelWidth={"7em"}
-            />
-          </div>
-        );
-      } else if (question.answerParts[i] == "angle of normal force") {
-        this.dataDoc.reviewNormalAngle = (0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={<p>Normal force angle</p>}
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'reviewNormalAngle'}
-              step={1}
-              unit={"°"}
-              upperBound={360}
-              value={this.dataDoc.reviewNormalAngle}
-              radianEquivalent={true}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-              labelWidth={"7em"}
-            />
-          </div>
-        );
-      } else if (question.answerParts[i] == "force of static friction") {
-        this.dataDoc.reviewStaticMagnitude = (0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={<p>Static friction magnitude</p>}
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'reviewStaticMagnitude'}
-              step={0.1}
-              unit={"N"}
-              upperBound={50}
-              value={this.dataDoc.reviewStaticMagnitude}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-              labelWidth={"7em"}
-            />
-          </div>
-        );
-      } else if (question.answerParts[i] == "angle of static friction") {
-        this.dataDoc.reviewStaticAngle = (0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={<p>Static friction angle</p>}
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'reviewStaticAngle'}
-              step={1}
-              unit={"°"}
-              upperBound={360}
-              value={this.dataDoc.reviewStaticAngle}
-              radianEquivalent={true}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-              labelWidth={"7em"}
-            />
-          </div>
-        );
-      } else if (question.answerParts[i] == "coefficient of static friction") {
-        this.updateReviewForcesBasedOnCoefficient(0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={
-                <Box>
-                  &mu;<sub>s</sub>
-                </Box>
-              }
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'coefficientOfStaticFriction'}
-              step={0.1}
-              unit={""}
-              upperBound={1}
-              value={this.dataDoc.coefficientOfStaticFriction}
-              effect={this.updateReviewForcesBasedOnCoefficient}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-            />
-          </div>
-        );
-      } else if (question.answerParts[i] == "wedge angle") {
-        this.updateReviewForcesBasedOnAngle(0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={<Box>&theta;</Box>}
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'wedgeAngle'}
-              step={1}
-              unit={"°"}
-              upperBound={49}
-              value={this.dataDoc.wedgeAngle}
-              effect={(val: number) => {
-                this.changeWedgeBasedOnNewAngle(val);
-                this.updateReviewForcesBasedOnAngle(val);
-              }}
-              radianEquivalent={true}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-            />
-          </div>
-        );
-      }
-    }
+  // // Generate answerInputFields for new review question
+  // generateInputFieldsForQuestion = (
+  //   showIcon: boolean = false,
+  //   question: QuestionTemplate = this.dataDoc.selectedQuestion,
+  //   answers: number[] = this.dataDoc.selectedSolutions
+  // ) => {
+  //   let answerInput = [];
+  //   const d = new Date();
+  //   for (let i = 0; i < question.answerParts.length; i++) {
+  //     if (question.answerParts[i] == "force of gravity") {
+  //       this.dataDoc.reviewGravityMagnitude = (0);
+  //       answerInput.push(
+  //         <div key={i + d.getTime()}>
+  //           <InputField
+  //             label={<p>Gravity magnitude</p>}
+  //             lowerBound={0}
+  //             dataDoc={this.dataDoc}
+  //             prop={'reviewGravityMagnitude'}
+  //             step={0.1}
+  //             unit={"N"}
+  //             upperBound={50}
+  //             value={this.dataDoc.reviewGravityMagnitude}
+  //             showIcon={showIcon}
+  //             correctValue={answers[i]}
+  //             labelWidth={"7em"}
+  //           />
+  //         </div>
+  //       );
+  //     } else if (question.answerParts[i] == "angle of gravity") {
+  //       this.dataDoc.reviewGravityAngle = (0);
+  //       answerInput.push(
+  //         <div key={i + d.getTime()}>
+  //           <InputField
+  //             label={<p>Gravity angle</p>}
+  //             lowerBound={0}
+  //             dataDoc={this.dataDoc}
+  //             prop={'reviewGravityAngle'}
+  //             step={1}
+  //             unit={"°"}
+  //             upperBound={360}
+  //             value={this.dataDoc.reviewGravityAngle}
+  //             radianEquivalent={true}
+  //             showIcon={showIcon}
+  //             correctValue={answers[i]}
+  //             labelWidth={"7em"}
+  //           />
+  //         </div>
+  //       );
+  //     } else if (question.answerParts[i] == "normal force") {
+  //       this.dataDoc.reviewNormalMagnitude = (0);
+  //       answerInput.push(
+  //         <div key={i + d.getTime()}>
+  //           <InputField
+  //             label={<p>Normal force magnitude</p>}
+  //             lowerBound={0}
+  //             dataDoc={this.dataDoc}
+  //             prop={'reviewNormalMagnitude'}
+  //             step={0.1}
+  //             unit={"N"}
+  //             upperBound={50}
+  //             value={this.dataDoc.reviewNormalMagnitude}
+  //             showIcon={showIcon}
+  //             correctValue={answers[i]}
+  //             labelWidth={"7em"}
+  //           />
+  //         </div>
+  //       );
+  //     } else if (question.answerParts[i] == "angle of normal force") {
+  //       this.dataDoc.reviewNormalAngle = (0);
+  //       answerInput.push(
+  //         <div key={i + d.getTime()}>
+  //           <InputField
+  //             label={<p>Normal force angle</p>}
+  //             lowerBound={0}
+  //             dataDoc={this.dataDoc}
+  //             prop={'reviewNormalAngle'}
+  //             step={1}
+  //             unit={"°"}
+  //             upperBound={360}
+  //             value={this.dataDoc.reviewNormalAngle}
+  //             radianEquivalent={true}
+  //             showIcon={showIcon}
+  //             correctValue={answers[i]}
+  //             labelWidth={"7em"}
+  //           />
+  //         </div>
+  //       );
+  //     } else if (question.answerParts[i] == "force of static friction") {
+  //       this.dataDoc.reviewStaticMagnitude = (0);
+  //       answerInput.push(
+  //         <div key={i + d.getTime()}>
+  //           <InputField
+  //             label={<p>Static friction magnitude</p>}
+  //             lowerBound={0}
+  //             dataDoc={this.dataDoc}
+  //             prop={'reviewStaticMagnitude'}
+  //             step={0.1}
+  //             unit={"N"}
+  //             upperBound={50}
+  //             value={this.dataDoc.reviewStaticMagnitude}
+  //             showIcon={showIcon}
+  //             correctValue={answers[i]}
+  //             labelWidth={"7em"}
+  //           />
+  //         </div>
+  //       );
+  //     } else if (question.answerParts[i] == "angle of static friction") {
+  //       this.dataDoc.reviewStaticAngle = (0);
+  //       answerInput.push(
+  //         <div key={i + d.getTime()}>
+  //           <InputField
+  //             label={<p>Static friction angle</p>}
+  //             lowerBound={0}
+  //             dataDoc={this.dataDoc}
+  //             prop={'reviewStaticAngle'}
+  //             step={1}
+  //             unit={"°"}
+  //             upperBound={360}
+  //             value={this.dataDoc.reviewStaticAngle}
+  //             radianEquivalent={true}
+  //             showIcon={showIcon}
+  //             correctValue={answers[i]}
+  //             labelWidth={"7em"}
+  //           />
+  //         </div>
+  //       );
+  //     } else if (question.answerParts[i] == "coefficient of static friction") {
+  //       this.updateReviewForcesBasedOnCoefficient(0);
+  //       answerInput.push(
+  //         <div key={i + d.getTime()}>
+  //           <InputField
+  //             label={
+  //               <Box>
+  //                 &mu;<sub>s</sub>
+  //               </Box>
+  //             }
+  //             lowerBound={0}
+  //             dataDoc={this.dataDoc}
+  //             prop={'coefficientOfStaticFriction'}
+  //             step={0.1}
+  //             unit={""}
+  //             upperBound={1}
+  //             value={this.dataDoc.coefficientOfStaticFriction}
+  //             effect={this.updateReviewForcesBasedOnCoefficient}
+  //             showIcon={showIcon}
+  //             correctValue={answers[i]}
+  //           />
+  //         </div>
+  //       );
+  //     } else if (question.answerParts[i] == "wedge angle") {
+  //       this.updateReviewForcesBasedOnAngle(0);
+  //       answerInput.push(
+  //         <div key={i + d.getTime()}>
+  //           <InputField
+  //             label={<Box>&theta;</Box>}
+  //             lowerBound={0}
+  //             dataDoc={this.dataDoc}
+  //             prop={'wedgeAngle'}
+  //             step={1}
+  //             unit={"°"}
+  //             upperBound={49}
+  //             value={this.dataDoc.wedgeAngle}
+  //             effect={(val: number) => {
+  //               this.changeWedgeBasedOnNewAngle(val);
+  //               this.updateReviewForcesBasedOnAngle(val);
+  //             }}
+  //             radianEquivalent={true}
+  //             showIcon={showIcon}
+  //             correctValue={answers[i]}
+  //           />
+  //         </div>
+  //       );
+  //     }
+  //   }
 
-    this.dataDoc.answerInputFields = (
-      <div
-        style={{ display: "flex", flexDirection: "column", alignItems: "left" }}
-      >
-        {answerInput}
-      </div>
-    );
-  };
+  //   this.dataDoc.answerInputFields = (
+  //     <div
+  //       style={{ display: "flex", flexDirection: "column", alignItems: "left" }}
+  //     >
+  //       {answerInput}
+  //     </div>
+  //   );
+  // };
   
   // Default setup for uniform circular motion simulation
   setupCircular = (value: number) => {
@@ -1393,7 +1399,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
           </div>
           <div>
             {(this.dataDoc.simulationType == "One Weight" ||
-              this.dataDoc.simulationType == "Inclined Plane") &&
+              this.dataDoc.simulationType == "Inclined Plane") && this.wallPositions &&
               this.wallPositions.map((element, index) => {
                 return (
                   <Wall
@@ -1455,7 +1461,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             </select>
           </div>
         </div>
-        {this.dataDoc.mode == "Review" && this.dataDoc.simulationType != "Inclined Plane" && (
+        {/* {this.dataDoc.mode == "Review" && this.dataDoc.simulationType != "Inclined Plane" && (
           <div className="wordProblemBox">
             <p>{this.dataDoc.simulationType} review problems in progress!</p>
           </div>
@@ -1484,7 +1490,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             >
               <DialogTitle>Hints</DialogTitle>
               <DialogContent>
-                {this.dataDoc.selectedQuestion.hints.map((hint, index) => {
+                {this.dataDoc.selectedQuestion.hints && (this.dataDoc.selectedQuestion.hints.map((hint, index) => {
                   return (
                     <div key={index}>
                       <DialogContentText>
@@ -1499,7 +1505,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                       </DialogContentText>
                     </div>
                   );
-                })}
+                }))}
               </DialogContent>
               <DialogActions>
                 <Button
@@ -1519,8 +1525,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               <div className="answer">{this.dataDoc.answerInputFields}</div>
             </div>
           </div>
-        )}
-        {this.dataDoc.mode == "Tutorial" && (
+        )} */}
+        {/* {this.dataDoc.mode == "Tutorial" && (
           <div className="wordProblemBox">
             <div className="question">
               <h2>Problem</h2>
@@ -1664,8 +1670,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               )}
             </div>
           </div>
-        )}
-        {this.dataDoc.mode == "Review" && this.dataDoc.simulationType == "Inclined Plane" && (
+        )} */}
+        {/* {this.dataDoc.mode == "Review" && this.dataDoc.simulationType == "Inclined Plane" && (
           <div
             style={{
               display: "flex",
@@ -1703,7 +1709,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               </Button>
             </div>
           </div>
-        )}
+        )} */}
         {this.dataDoc.mode == "Freeform" && (
           <div className="vars">
             <FormControl component="fieldset">
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index ed219652a..3b2c2e270 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -65,13 +65,12 @@ interface IState {
   kineticFriction: boolean,
   maxPosYConservation: number,
   timer: number,
-  update: boolean,
-  updatedStartPosX: number,
-  updatedStartPosY: number,
+  updatedStartPosX: any,
+  updatedStartPosY: any,
   walls: IWallProps[],
-  xPosition: number,
+  xPosition: any,
   xVelocity: number,
-  yPosition: number,
+  yPosition: any,
   yVelocity: number,
   xAccel: number,
   yAccel: number,
@@ -584,7 +583,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     if (this.state.xVelocity != 0) {
       this.state.walls.forEach((wall) => {
         if (wall.angleInDegrees == 90) {
-          const wallX = (wall.xPos / 100) * this.props.layoutDoc._width ?? 500;
+          const wallX = (wall.xPos / 100) * this.props.layoutDoc._width;
           if (wall.xPos < 0.35) {
             if (minX <= wallX) {
               this.setState({xPosition: wallX+0.01});
@@ -620,7 +619,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     if (this.state.yVelocity > 0) {
       this.state.walls.forEach((wall) => {
         if (wall.angleInDegrees == 0 && wall.yPos > 0.4) {
-          const groundY = (wall.yPos / 100) * this.props.layoutDoc._height ?? 500;
+          const groundY = (wall.yPos / 100) * this.props.layoutDoc._height;
           if (maxY > groundY) {
             this.setState({yPosition: groundY- 2 * this.props.radius-0.01});
             if (this.props.elasticCollisions) {
@@ -666,7 +665,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     if (this.state.yVelocity < 0) {
       this.state.walls.forEach((wall) => {
         if (wall.angleInDegrees == 0 && wall.yPos < 0.4) {
-          const groundY = (wall.yPos / 100) * this.props.layoutDoc._height ?? 500;
+          const groundY = (wall.yPos / 100) * this.props.layoutDoc._height;
           if (minY < groundY) {
             this.setState({yPosition: groundY + 0.01});
             if (this.props.elasticCollisions) {
@@ -1281,7 +1280,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
               position: "absolute",
               zIndex: 500,
               left: Math.round(this.props.xMax * 0.5 - 200 + this.props.wedgeWidth - 80) + "px",
-              top: Math.round(this.props.layoutDoc._height * 0.8 - 40) + "px",
+              top: Math.round(this.yMax - 40) + "px",
             }}
           >
             {Math.round(
@@ -1518,7 +1517,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
           );
         })}
       {!this.state.dragging &&
-        this.props.showForces &&
+        this.props.showForces && this.props.updatedForces &&
         this.props.updatedForces.map((force, index) => {
           if (force.magnitude < this.epsilon) {
             return;
-- 
cgit v1.2.3-70-g09d2


From cb55cf455ef4b4e2acc0e1e54cb1be99c131b967 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 1 May 2023 20:47:33 -0400
Subject: something appears

---
 src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx    |  4 ++--
 src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx | 10 +++++-----
 2 files changed, 7 insertions(+), 7 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 21cef297a..91627687a 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -1298,7 +1298,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             </div>
           </div>
           <div className="mechanicsSimulationElements">
-            <Weight
+            {/* <Weight
               dataDoc={this.dataDoc}
               layoutDoc={this.layoutDoc}
               adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
@@ -1345,7 +1345,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               xMin={this.xMin}
               yMax={this.yMax}
               yMin={this.yMin}
-            />
+            /> */}
             {this.dataDoc.simulationType == "Pulley" && (
               <Weight
                 dataDoc={this.dataDoc}
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 3b2c2e270..c25cb9985 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -109,12 +109,12 @@ export default class Weight extends React.Component<IWeightProps, IState> {
   }
 
   // Constants
-  const draggable =
+  draggable =
     this.props.dataDoc['simulationType'] != "Inclined Plane" &&
     this.props.dataDoc['simulationType'] != "Pendulum" &&
     this.props.dataDoc['mode'] == "Freeform";
-  const epsilon = 0.0001;
-  const labelBackgroundColor = `rgba(255,255,255,0.5)`;
+  epsilon = 0.0001;
+  labelBackgroundColor = `rgba(255,255,255,0.5)`;
 
   // Variables
   weightStyle = {
@@ -1516,7 +1516,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             </div>
           );
         })}
-      {!this.state.dragging &&
+      {/* {!this.state.dragging &&
         this.props.showForces && this.props.updatedForces &&
         this.props.updatedForces.map((force, index) => {
           if (force.magnitude < this.epsilon) {
@@ -1625,7 +1625,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
               </div>
             </div>
           );
-        })}
+        })} */}
     </div>
   )}
 };
-- 
cgit v1.2.3-70-g09d2


From d2e56061dd9cb7913ede040e7d16aa451e39adc0 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Mon, 1 May 2023 21:02:27 -0400
Subject: something appears

---
 src/client/documents/Documents.ts                  |   4 +-
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      |   4 +-
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   | 164 ++++++++++-----------
 3 files changed, 86 insertions(+), 86 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 31c8a7890..0f3d5867e 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -661,7 +661,7 @@ export namespace Docs {
                  DocumentType.SIMULATION, 
                  { 
                      layout: { view: PhysicsSimulationBox, dataField: defaultDataKey }, 
-                     options: { _height: 150 } 
+                     options: { _height: 500 } 
                  }
             ]
         ]);
@@ -669,7 +669,7 @@ export namespace Docs {
         const suffix = 'Proto';
 
         /**
-         * This function loads or initializes the prototype for each docment type.
+         * This function loads or initializes the prototype for each document type.
          *
          * This is an asynchronous function because it has to attempt
          * to fetch the prototype documents from the server.
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 91627687a..21cef297a 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -1298,7 +1298,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             </div>
           </div>
           <div className="mechanicsSimulationElements">
-            {/* <Weight
+            <Weight
               dataDoc={this.dataDoc}
               layoutDoc={this.layoutDoc}
               adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
@@ -1345,7 +1345,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               xMin={this.xMin}
               yMax={this.yMax}
               yMin={this.yMin}
-            /> */}
+            />
             {this.dataDoc.simulationType == "Pulley" && (
               <Weight
                 dataDoc={this.dataDoc}
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index c25cb9985..192ff1d04 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -194,39 +194,39 @@ export default class Weight extends React.Component<IWeightProps, IState> {
       this.props.dataDoc['pendulumLength'] = this.props.adjustPendulumAngle.length
     }
 
-    // When display values updated by user, update real values
-    if (prevProps.updateDisplay != this.props.updateDisplay) {
-      if (this.props.updateDisplay.xDisplay != this.state.xPosition) {
-        let x = this.props.updateDisplay.xDisplay;
-        x = Math.max(0, x);
-        x = Math.min(x, this.props.xMax - 2 * this.props.radius);
-        this.setState({updatedStartPosX: x})
-        this.setState({xPosition: x})
-        this.props.dataDoc['positionXDisplay'] = x
-      }
+    // // When display values updated by user, update real values
+    // if (prevProps.updateDisplay != this.props.updateDisplay) {
+    //   if (this.props.updateDisplay.xDisplay != this.state.xPosition) {
+    //     let x = this.props.updateDisplay.xDisplay;
+    //     x = Math.max(0, x);
+    //     x = Math.min(x, this.props.xMax - 2 * this.props.radius);
+    //     this.setState({updatedStartPosX: x})
+    //     this.setState({xPosition: x})
+    //     this.props.dataDoc['positionXDisplay'] = x
+    //   }
   
-      if (this.props.updateDisplay.yDisplay != this.getDisplayYPos(this.state.yPosition)) {
-        let y = this.props.updateDisplay.yDisplay;
-        y = Math.max(0, y);
-        y = Math.min(y, this.props.yMax - 2 * this.props.radius);
-        let coordinatePosition = this.getYPosFromDisplay(y);
-        this.setState({updatedStartPosY: coordinatePosition})
-        this.setState({yPosition: coordinatePosition})
-        this.props.dataDoc['positionYDisplay'] = y
-      }
+    //   if (this.props.updateDisplay.yDisplay != this.getDisplayYPos(this.state.yPosition)) {
+    //     let y = this.props.updateDisplay.yDisplay;
+    //     y = Math.max(0, y);
+    //     y = Math.min(y, this.props.yMax - 2 * this.props.radius);
+    //     let coordinatePosition = this.getYPosFromDisplay(y);
+    //     this.setState({updatedStartPosY: coordinatePosition})
+    //     this.setState({yPosition: coordinatePosition})
+    //     this.props.dataDoc['positionYDisplay'] = y
+    //   }
   
-      if (this.props.displayXVelocity != this.state.xVelocity) {
-        let x = this.props.displayXVelocity;
-        this.setState({xVelocity: x})
-        this.props.dataDoc['velocityXDisplay'] = x
-      }
+    //   if (this.props.displayXVelocity != this.state.xVelocity) {
+    //     let x = this.props.displayXVelocity;
+    //     this.setState({xVelocity: x})
+    //     this.props.dataDoc['velocityXDisplay'] = x
+    //   }
   
-      if (this.props.displayYVelocity != -this.state.yVelocity) {
-        let y = this.props.displayYVelocity;
-        this.setState({yVelocity: -y})
-        this.props.dataDoc['velocityYDisplay'] = y
-      }
-    }
+    //   if (this.props.displayYVelocity != -this.state.yVelocity) {
+    //     let y = this.props.displayYVelocity;
+    //     this.setState({yVelocity: -y})
+    //     this.props.dataDoc['velocityYDisplay'] = y
+    //   }
+    // }
     
     // Prevent bug when switching between sims
     if (prevProps.startForces != this.props.startForces) {
@@ -235,43 +235,43 @@ export default class Weight extends React.Component<IWeightProps, IState> {
       this.setDisplayValues();
     }
 
-    // Make sure weight doesn't go above max height
-    if (prevState.updatedStartPosY != this.state.updatedStartPosY || prevProps.startVelY != this.props.startVelY) {
-      if (this.props.dataDoc['simulationType'] == "One Weight") {
-        let maxYPos = this.state.updatedStartPosY;
-        if (this.props.startVelY != 0) {
-          maxYPos -= (this.props.startVelY * this.props.startVelY) / (2 * Math.abs(this.props.gravity));
-        }
-        if (maxYPos < 0) {
-          maxYPos = 0;
-        }
-        this.setState({maxPosYConservation: maxYPos})
-      }
-    }
+    // // Make sure weight doesn't go above max height
+    // if (prevState.updatedStartPosY != this.state.updatedStartPosY || prevProps.startVelY != this.props.startVelY) {
+    //   if (this.props.dataDoc['simulationType'] == "One Weight") {
+    //     let maxYPos = this.state.updatedStartPosY;
+    //     if (this.props.startVelY != 0) {
+    //       maxYPos -= (this.props.startVelY * this.props.startVelY) / (2 * Math.abs(this.props.gravity));
+    //     }
+    //     if (maxYPos < 0) {
+    //       maxYPos = 0;
+    //     }
+    //     this.setState({maxPosYConservation: maxYPos})
+    //   }
+    // }
 
-    // Check for collisions and update
-    if (prevState.timer != this.state.timer) {
-      if (!this.props.paused && !this.props.noMovement) {
-        let collisions = false;
-        if (
-          this.props.dataDoc['simulationType'] == "One Weight" ||
-          this.props.dataDoc['simulationType'] == "Inclined Plane"
-        ) {
-          const collisionsWithGround = this.checkForCollisionsWithGround();
-          const collisionsWithWalls = this.checkForCollisionsWithWall();
-          collisions = collisionsWithGround || collisionsWithWalls;
-        }
-        if (this.props.dataDoc['simulationType'] == "Pulley") {
-          if (this.state.yPosition <= this.props.yMin + 100 || this.state.yPosition >= this.props.yMax - 100) {
-            collisions = true;
-          }
-        }
-        if (!collisions) {
-          this.update();
-        }
-        this.setDisplayValues();
-      }
-    }
+    // // Check for collisions and update
+    // if (prevState.timer != this.state.timer) {
+    //   if (!this.props.paused && !this.props.noMovement) {
+    //     let collisions = false;
+    //     if (
+    //       this.props.dataDoc['simulationType'] == "One Weight" ||
+    //       this.props.dataDoc['simulationType'] == "Inclined Plane"
+    //     ) {
+    //       const collisionsWithGround = this.checkForCollisionsWithGround();
+    //       const collisionsWithWalls = this.checkForCollisionsWithWall();
+    //       collisions = collisionsWithGround || collisionsWithWalls;
+    //     }
+    //     if (this.props.dataDoc['simulationType'] == "Pulley") {
+    //       if (this.state.yPosition <= this.props.yMin + 100 || this.state.yPosition >= this.props.yMax - 100) {
+    //         collisions = true;
+    //       }
+    //     }
+    //     if (!collisions) {
+    //       this.update();
+    //     }
+    //     this.setDisplayValues();
+    //   }
+    // }
 
     // Reset everything on reset button click
     if (prevProps.reset != this.props.reset) {
@@ -406,24 +406,24 @@ export default class Weight extends React.Component<IWeightProps, IState> {
       this.setState({walls: w})
     }
 
-    // Update x position when start pos x changes
-    if (prevProps.startPosX != this.props.startPosX) {
-      if (this.props.paused) {
-        this.setState({xPosition: this.props.startPosX})
-        this.setState({updatedStartPosX: this.props.startPosX})
-        this.props.dataDoc['positionXDisplay'] = this.props.startPosX
-      }
-    }
+    // // Update x position when start pos x changes
+    // if (prevProps.startPosX != this.props.startPosX) {
+    //   if (this.props.paused) {
+    //     this.setState({xPosition: this.props.startPosX})
+    //     this.setState({updatedStartPosX: this.props.startPosX})
+    //     this.props.dataDoc['positionXDisplay'] = this.props.startPosX
+    //   }
+    // }
 
 
-    // Update y position when start pos y changes
-    if (prevProps.startPosY != this.props.startPosY) {
-       if (this.props.paused) {
-        this.setState({yPosition: this.props.startPosY})
-        this.setState({updatedStartPosY: this.props.startPosY})
-        this.props.dataDoc['positionYDisplay'] = this.props.startPosY
-      }
-    }
+    // // Update y position when start pos y changes
+    // if (prevProps.startPosY != this.props.startPosY) {
+    //    if (this.props.paused) {
+    //     this.setState({yPosition: this.props.startPosY})
+    //     this.setState({updatedStartPosY: this.props.startPosY})
+    //     this.props.dataDoc['positionYDisplay'] = this.props.startPosY
+    //   }
+    // }
 
     // Update wedge coordinates
     if (prevProps.wedgeWidth != this.props.wedgeWidth || prevProps.wedgeHeight != this.props.wedgeHeight) {
-- 
cgit v1.2.3-70-g09d2


From f363260bd8857834176fb5bba215fe5218ec8d87 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Tue, 2 May 2023 15:27:42 -0400
Subject: debugging

---
 src/client/documents/Documents.ts                  |  2 +-
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 26 ++++++++++++++--------
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   |  3 ---
 3 files changed, 18 insertions(+), 13 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 0f3d5867e..13d0f41a9 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -661,7 +661,7 @@ export namespace Docs {
                  DocumentType.SIMULATION, 
                  { 
                      layout: { view: PhysicsSimulationBox, dataField: defaultDataKey }, 
-                     options: { _height: 500 } 
+                     options: { _height: 100 } 
                  }
             ]
         ]);
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 21cef297a..691f1145c 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -113,9 +113,11 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.wallPositions.push({ length: 80, xPos: 69.5, yPos: 0, angleInDegrees: 90 });
 
     // Used throughout sims
-    this.xMax = this.layoutDoc._width*0.08 ?? 500;
-    this.yMax = this.layoutDoc._height*0.08 ?? 500;
-    this.radius = 0.1*this.layoutDoc._height ?? 50;
+    this.layoutDoc._width = 1000;
+    this.layoutDoc._height = 1000;
+    this.xMax = this.layoutDoc._width*0.8 ?? 800;
+    this.yMax = this.layoutDoc._height*0.8 ?? 800;
+    this.radius = 50;
     this.dataDoc.reviewCoefficient = this.dataDoc.reviewCoefficient ?? 0;
     this.dataDoc.questionVariables = this.dataDoc.questionVariables ?? [];
     this.dataDoc.accelerationXDisplay = this.dataDoc.accelerationXDisplay ?? 0;
@@ -363,12 +365,18 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       // }
       this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
     }
+
+
+    console.log("width: ", this.xMax)
+    console.log("height: ", this.yMax)
   }
 
   componentDidUpdate() {
-    this.xMax = this.layoutDoc._width*0.08 ?? 500;
-    this.yMax = this.layoutDoc._height*0.08 ?? 500;
-    this.radius = 0.1*this.layoutDoc._height ?? 50;
+    this.xMax = this.layoutDoc._width*0.8 ?? 800;
+    this.yMax = this.layoutDoc._height*0.8 ?? 800;
+    this.radius = 0.05*this.layoutDoc._height ?? 50;
+    console.log("width: ", this.xMax)
+    console.log("height: ", this.yMax)
   }
 
   // Helper function to go between display and real values
@@ -2453,7 +2461,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     <div
       style={{
         position: "fixed",
-        top: this.layoutDoc._height ?? 500 - 120 + 20 + "px",
+        top: this.yMax - 120 + 20 + "px",
         left: this.xMin + 90 - 80 + "px",
         zIndex: -10000,
       }}
@@ -2494,7 +2502,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       <p
         style={{
           position: "fixed",
-          top: this.layoutDoc._height?? 500 - 120 + 40 + "px",
+          top: this.yMax - 120 + 40 + "px",
           left: this.xMin + 90 - 80 + "px",
         }}
       >
@@ -2503,7 +2511,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       <p
         style={{
           position: "fixed",
-          top: this.layoutDoc._height ?? 500- 120 + 80 + "px",
+          top: this.yMax - 120 + 80 + "px",
           left: this.xMin + 90 - 40 + "px",
         }}
       >
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 013b1bb5b..ab7ae8450 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -895,7 +895,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         className="weightContainer"
         onPointerDown={(e) => {
           if (this.draggable) {
-            e.preventDefault();
             this.props.dataDoc['paused'] = true;
             this.setState({dragging: true});
             this.setState({clickPositionX: e.clientX});
@@ -903,7 +902,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
           } 
         }}
         onPointerMove={(e) => {
-          e.preventDefault();
           if (this.state.dragging) {
             let newY = this.state.yPosition + e.clientY - this.state.clickPositionY;
             if (newY > this.props.yMax - 2 * this.props.radius - 10) {
@@ -946,7 +944,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         }}
         onPointerUp={(e) => {
           if (this.state.dragging) {
-            e.preventDefault();
             if (
               this.props.dataDoc['simulationType'] != "Pendulum" &&
               this.props.dataDoc['simulationType'] != "Suspension"
-- 
cgit v1.2.3-70-g09d2


From aed2cab6e4898d41a991a7f01a908275465da6ff Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Tue, 2 May 2023 16:22:26 -0400
Subject: debug

---
 src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 691f1145c..143ff9896 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -115,8 +115,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     // Used throughout sims
     this.layoutDoc._width = 1000;
     this.layoutDoc._height = 1000;
-    this.xMax = this.layoutDoc._width*0.8 ?? 800;
-    this.yMax = this.layoutDoc._height*0.8 ?? 800;
+    this.xMax = this.layoutDoc._width*0.7 ?? 700;
+    this.yMax = this.layoutDoc._height*0.7 ?? 700;
     this.radius = 50;
     this.dataDoc.reviewCoefficient = this.dataDoc.reviewCoefficient ?? 0;
     this.dataDoc.questionVariables = this.dataDoc.questionVariables ?? [];
@@ -372,8 +372,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   }
 
   componentDidUpdate() {
-    this.xMax = this.layoutDoc._width*0.8 ?? 800;
-    this.yMax = this.layoutDoc._height*0.8 ?? 800;
+    this.xMax = this.layoutDoc._width*0.7 ?? 700;
+    this.yMax = this.layoutDoc._height*0.7 ?? 700;
     this.radius = 0.05*this.layoutDoc._height ?? 50;
     console.log("width: ", this.xMax)
     console.log("height: ", this.yMax)
-- 
cgit v1.2.3-70-g09d2


From 6b7c2b5e3069710bd91406475dc480fe514c50c8 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Tue, 2 May 2023 17:39:24 -0400
Subject: debugging

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 39 +++++++++++-----------
 .../nodes/PhysicsBox/PhysicsSimulationWall.tsx     |  4 +--
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   | 22 ++++++------
 3 files changed, 32 insertions(+), 33 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 143ff9896..5335fc1ec 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -141,8 +141,10 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.simulationSpeed = this.dataDoc.simulationSpeed ?? 2;
     this.dataDoc.simulationType = this.dataDoc.simulationType ?? "Inclined Plane";
     this.dataDoc.startForces = this.dataDoc.startForces ?? [];
-    this.dataDoc.startPosX = this.dataDoc.startPosX ?? 0;
-    this.dataDoc.startPosY = this.dataDoc.startPosY ?? 0;
+    this.dataDoc.startPosX = this.dataDoc.startPosX ?? Math.round((this.xMax * 0.5 - 200) * 10) / 10;
+    this.dataDoc.startPosY = this.dataDoc.startPosY ?? this.getDisplayYPos(
+      (400 - this.radius) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26)
+    );
     this.dataDoc.startVelX = this.dataDoc.startVelX ?? 0;
     this.dataDoc.startVelY = this.dataDoc.startVelY ?? 0;
     this.dataDoc.stepNumber = this.dataDoc.stepNumber ?? 0;
@@ -209,6 +211,16 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.mass2 = this.dataDoc.mass2 ?? 1;
 
     // Setup simulation
+    this.setupSimulation()
+  }
+
+  componentDidUpdate() {
+    this.xMax = this.layoutDoc._width*0.7 ?? 700;
+    this.yMax = this.layoutDoc._height*0.7 ?? 700;
+    this.radius = 0.05*this.layoutDoc._height ?? 50;
+  }
+
+  setupSimulation = () => {
     if (this.dataDoc.simulationType != "Circular Motion") {
       this.dataDoc.startVelX = 0;
       this.dataDoc.setStartVelY = 0;
@@ -365,18 +377,6 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       // }
       this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
     }
-
-
-    console.log("width: ", this.xMax)
-    console.log("height: ", this.yMax)
-  }
-
-  componentDidUpdate() {
-    this.xMax = this.layoutDoc._width*0.7 ?? 700;
-    this.yMax = this.layoutDoc._height*0.7 ?? 700;
-    this.radius = 0.05*this.layoutDoc._height ?? 50;
-    console.log("width: ", this.xMax)
-    console.log("height: ", this.yMax)
   }
 
   // Helper function to go between display and real values
@@ -1270,9 +1270,9 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               <div
                 style={{
                   position: "fixed",
-                  left: "10vw",
-                  top: "95vh",
-                  width: "50vw",
+                  left: 0.10*this.layoutDoc._width + "px",
+                  top: 0.95*this.layoutDoc._height + "px",
+                  width: 0.50*this.layoutDoc._width + "px",
                 }}
               >
                 <LinearProgress />
@@ -1290,7 +1290,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   value={this.dataDoc.simulationType}
                   onChange={(event) => {
                     this.dataDoc.simulationType = (event.target.value);
-                    // TODO change simulation type based on mode/type
+                    this.setupSimulation()
                   }}
                   style={{ height: "2em", width: "100%", fontSize: "16px" }}
                 >
@@ -1458,8 +1458,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               value={this.dataDoc.mode}
               onChange={(event) => {
                 this.dataDoc.mode = (event.target.value);
-
-                // TODO setup simulation based on type and mode
+                this.setupSimulation()
               }}
               style={{ height: "2em", width: "100%", fontSize: "16px" }}
             >
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWall.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWall.tsx
index 6e60ad85c..83dff660a 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWall.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWall.tsx
@@ -18,8 +18,8 @@ export default class Wall extends React.Component<IWallProps> {
   }
 
   wallStyle = {
-    width: this.props.angleInDegrees == 0 ? this.props.length + "%" : "3%",
-    height: this.props.angleInDegrees == 0 ? "3%" : this.props.length + "%",
+    width: this.props.angleInDegrees == 0 ? this.props.length + "%" : "1%",
+    height: this.props.angleInDegrees == 0 ? "1%" : this.props.length + "%",
     position: "absolute" as "absolute",
     left: this.props.xPos + "%",
     top: this.props.yPos + "%",
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index ab7ae8450..a5bd5a04e 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -235,7 +235,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
       this.setDisplayValues();
     }
 
-    // Make sure weight doesn't go above max height
+    // Make sure weight doesn't go above max height 
     if (prevState.updatedStartPosY != this.state.updatedStartPosY || prevProps.startVelY != this.props.startVelY) {
       if (this.props.dataDoc['simulationType'] == "One Weight") {
         let maxYPos = this.state.updatedStartPosY;
@@ -401,7 +401,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         w.push({ length: 70, xPos: 0, yPos: 0, angleInDegrees: 0 });
         w.push({ length: 70, xPos: 0, yPos: 80, angleInDegrees: 0 });
         w.push({ length: 80, xPos: 0, yPos: 0, angleInDegrees: 90 });
-        w.push({ length: 80, xPos: 69.5, yPos: 0, angleInDegrees: 90 });
+        w.push({ length: 85, xPos: 69.5, yPos: 0, angleInDegrees: 90 });
       }
       this.setState({walls: w})
     }
@@ -415,14 +415,14 @@ export default class Weight extends React.Component<IWeightProps, IState> {
       }
     }
 
-    // Update y position when start pos y changes
-    if (prevProps.startPosY != this.props.startPosY) {
-       if (this.props.paused) {
-        // this.setState({yPosition: this.props.startPosY})
-        // this.setState({updatedStartPosY: this.props.startPosY})
-        this.props.dataDoc['positionYDisplay'] = this.props.startPosY
-      }
-    }
+    // Update y position when start pos y changes TODO debug
+    // if (prevProps.startPosY != this.props.startPosY) {
+    //    if (this.props.paused) {
+    //     this.setState({yPosition: this.props.startPosY})
+    //     this.setState({updatedStartPosY: this.props.startPosY})
+    //     this.props.dataDoc['positionYDisplay'] = this.getDisplayYPos(this.props.startPosY)
+    //   }
+    // }
 
     // Update wedge coordinates
     if (prevProps.wedgeWidth != this.props.wedgeWidth || prevProps.wedgeHeight != this.props.wedgeHeight) {
@@ -1276,7 +1276,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
               position: "absolute",
               zIndex: 500,
               left: Math.round(this.props.xMax * 0.5 - 200 + this.props.wedgeWidth - 80) + "px",
-              top: Math.round(this.yMax - 40) + "px",
+              top: Math.round(this.props.yMax - 40) + "px",
             }}
           >
             {Math.round(
-- 
cgit v1.2.3-70-g09d2


From 617d008889a6b9640bc9cf8a87d24a5ed24cb660 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Tue, 2 May 2023 20:39:02 -0400
Subject: debug

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.scss     |   4 +
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 102 ++++++++++-----------
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   |  58 ++++--------
 3 files changed, 70 insertions(+), 94 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
index 0f05010b4..2e16417f5 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
@@ -69,4 +69,8 @@ button {
 
 .mechanicsSimulationSettingsMenuRowDescription {
   width: 50%;
+}
+
+.dropdownMenu {
+  z-index: 50;
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 5335fc1ec..3cb34d5b9 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -33,10 +33,9 @@ import {
 import Typography from "@mui/material/Typography";
 import "./PhysicsSimulationBox.scss";
 import InputField from "./PhysicsSimulationInputField";
-// import questions from "./PhysicsSimulationQuestions.json";
-// import tutorials from "./PhysicsSimulationTutorial.json";
+import questions from "./PhysicsSimulationQuestions.json";
+import tutorials from "./PhysicsSimulationTutorial.json";
 import Wall from "./PhysicsSimulationWall";
-import IWall from "./PhysicsSimulationWall";
 import Weight from "./PhysicsSimulationWeight";
 
 interface IWallProps {
@@ -211,7 +210,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.mass2 = this.dataDoc.mass2 ?? 1;
 
     // Setup simulation
-    this.setupSimulation()
+    this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
   }
 
   componentDidUpdate() {
@@ -220,16 +219,17 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.radius = 0.05*this.layoutDoc._height ?? 50;
   }
 
-  setupSimulation = () => {
-    if (this.dataDoc.simulationType != "Circular Motion") {
+  setupSimulation = (simulationType: string, mode: string) => {
+    this.dataDoc.simulationPaused = true;
+    if (simulationType != "Circular Motion") {
       this.dataDoc.startVelX = 0;
       this.dataDoc.setStartVelY = 0;
       this.dataDoc.velocityXDisplay = (0);
       this.dataDoc.velocityYDisplay = (0);
     }
-    if (this.dataDoc.mode == "Freeform") {
+    if (mode == "Freeform") {
       this.dataDoc.showForceMagnitudes = (true);
-      if (this.dataDoc.simulationType == "One Weight") {
+      if (simulationType == "One Weight") {
         this.dataDoc.showComponentForces = false;
         this.dataDoc.startPosY = (this.yMin + this.radius);
         this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
@@ -252,7 +252,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
           },
         ]);
         this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
-      } else if (this.dataDoc.simulationType == "Inclined Plane") {
+      } else if (simulationType == "Inclined Plane") {
         this.changeWedgeBasedOnNewAngle(26);
         this.dataDoc.startForces = ([
           {
@@ -263,46 +263,46 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
           },
         ]);
         this.updateForcesWithFriction(Number(this.dataDoc.coefficientOfStaticFriction));
-      } else if (this.dataDoc.simulationType == "Pendulum") {
+      } else if (simulationType == "Pendulum") {
         this.setupPendulum();
-      } else if (this.dataDoc.simulationType == "Spring") {
+      } else if (simulationType == "Spring") {
         this.setupSpring();
-      } else if (this.dataDoc.simulationType == "Circular Motion") {
+      } else if (simulationType == "Circular Motion") {
         this.setupCircular(0);
-      } else if (this.dataDoc.simulationType == "Pulley") {
+      } else if (simulationType == "Pulley") {
         this.setupPulley();
-      } else if (this.dataDoc.simulationType == "Suspension") {
+      } else if (simulationType == "Suspension") {
         this.setupSuspension();
       }
-    } else if (this.dataDoc.mode == "Review") {
+    } else if (mode == "Review") {
       this.dataDoc.showComponentForces = (false);
       this.dataDoc.showForceMagnitudes = (true);
       this.dataDoc.showAcceleration = (false);
       this.dataDoc.showVelocity = (false);
       this.dataDoc.showForces= (true);
       // this.generateNewQuestion();
-      if (this.dataDoc.simulationType == "One Weight") {
+      if (simulationType == "One Weight") {
         // TODO - one weight review problems
-      } else if (this.dataDoc.simulationType == "Spring") {
+      } else if (simulationType == "Spring") {
         this.setupSpring();
         // TODO - spring review problems
-      } else if (this.dataDoc.simulationType == "Inclined Plane") {
+      } else if (simulationType == "Inclined Plane") {
         this.dataDoc.updatedForces = ([]);
         this.dataDoc.startForces = ([]);
-      } else if (this.dataDoc.simulationType == "Pendulum") {
+      } else if (simulationType == "Pendulum") {
         this.setupPendulum();
         // TODO - pendulum review problems
-      } else if (this.dataDoc.simulationType == "Circular Motion") {
+      } else if (simulationType == "Circular Motion") {
         this.setupCircular(0);
         // TODO - circular motion review problems
-      } else if (this.dataDoc.simulationType == "Pulley") {
+      } else if (simulationType == "Pulley") {
         this.setupPulley();
         // TODO - pulley tutorial review problems
-      } else if (this.dataDoc.simulationType == "Suspension") {
+      } else if (simulationType == "Suspension") {
         this.setupSuspension();
         // TODO - suspension tutorial review problems
       }
-    } else if (this.dataDoc.mode == "Tutorial") {
+    } else if (mode == "Tutorial") {
       this.dataDoc.showComponentForces = (false);
       this.dataDoc.stepNumber = (0);
       this.dataDoc.showAcceleration = (false);
@@ -1195,10 +1195,10 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     };
     this.dataDoc.updatedForces = ([gravityForce1, tensionForce1]);
     this.dataDoc.startForces = ([gravityForce1, tensionForce1]);
-    this.dataDoc.startPosY2 = ((this.props.yMax + this.props.yMin) / 2);
-    this.dataDoc.startPosX2 = ((this.props.xMin + this.props.xMax) / 2 + 5);
-    this.dataDoc.positionYDisplay2 = (this.getDisplayYPos((this.props.yMax + this.props.yMin) / 2));
-    this.dataDoc.positionXDisplay2 = ((this.props.xMin + this.props.xMax) / 2 + 5);
+    this.dataDoc.startPosY2 = ((this.yMax + this.yMin) / 2);
+    this.dataDoc.startPosX2 = ((this.xMin + this.xMax) / 2 + 5);
+    this.dataDoc.positionYDisplay2 = (this.getDisplayYPos((this.yMax + this.yMin) / 2));
+    this.dataDoc.positionXDisplay2 = ((this.xMin + this.xMax) / 2 + 5);
     this.dataDoc.updatedForces2 = ([gravityForce2, tensionForce2]);
     this.dataDoc.startForces2 = ([gravityForce2, tensionForce2]);
     this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
@@ -1278,32 +1278,6 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 <LinearProgress />
               </div>
             )}
-            <div
-              style={{
-                position: "fixed",
-                top: 1 + "em",
-                left: this.xMin + 12 + "px",
-              }}
-            >
-              <div className="dropdownMenu">
-                <select
-                  value={this.dataDoc.simulationType}
-                  onChange={(event) => {
-                    this.dataDoc.simulationType = (event.target.value);
-                    this.setupSimulation()
-                  }}
-                  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>
           </div>
           <div className="mechanicsSimulationElements">
             <Weight
@@ -1341,7 +1315,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               springRestLength={this.dataDoc.springRestLength}
               startForces={this.dataDoc.startForces}
               startPosX={this.dataDoc.startPosX}
-              startPosY={this.dataDoc.startPosY}
+              startPosY={this.dataDoc.startPosY ?? 0}
               startVelX={this.dataDoc.startVelX}
               startVelY={this.dataDoc.startVelY}
               timestepSize={0.05}
@@ -1453,12 +1427,30 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               </IconButton>
             )}
           </Stack>
+          <div className="dropdownMenu">
+                <select
+                  value={this.dataDoc.simulationType}
+                  onChange={(event) => {
+                    this.dataDoc.simulationType = (event.target.value);
+                    this.setupSimulation(event.target.value, 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={this.dataDoc.mode}
               onChange={(event) => {
                 this.dataDoc.mode = (event.target.value);
-                this.setupSimulation()
+                this.setupSimulation(this.dataDoc.simulationType, event.target.value)
               }}
               style={{ height: "2em", width: "100%", fontSize: "16px" }}
             >
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 368f35f3c..f78f14704 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -179,7 +179,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
   componentDidUpdate(prevProps: Readonly<IWeightProps>, prevState: Readonly<IState>, snapshot?: any): void {
     // Change pendulum angle from input field
     if (prevProps.adjustPendulumAngle != this.props.adjustPendulumAngle) {
-      console.log('pendulum angle')
       let length = this.props.adjustPendulumAngle.length;
       const x =
         length * Math.cos(((90 - this.props.adjustPendulumAngle.angle) * Math.PI) / 180);
@@ -197,7 +196,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
 
     // When display values updated by user, update real values
     if (prevProps.updateDisplay != this.props.updateDisplay) {
-      console.log('update display')
       if (this.props.updateDisplay.xDisplay != this.state.xPosition) {
         let x = this.props.updateDisplay.xDisplay;
         x = Math.max(0, x);
@@ -232,26 +230,25 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     
     // Prevent bug when switching between sims
     if (prevProps.startForces != this.props.startForces) {
-      console.log('switch sims')
       this.setState({xVelocity: this.props.startVelX})
       this.setState({yVelocity: this.props.startVelY})
       this.setDisplayValues();
     }
 
-    // Make sure weight doesn't go above max height 
-    if (prevState.updatedStartPosY != this.state.updatedStartPosY || prevProps.startVelY != this.props.startVelY) {
-      console.log('max height check')
-      if (this.props.dataDoc['simulationType'] == "One Weight") {
-        let maxYPos = this.state.updatedStartPosY;
-        if (this.props.startVelY != 0) {
-          maxYPos -= (this.props.startVelY * this.props.startVelY) / (2 * Math.abs(this.props.gravity));
-        }
-        if (maxYPos < 0) {
-          maxYPos = 0;
-        }
-        this.setState({maxPosYConservation: maxYPos})
-      }
-    }
+    // // Make sure weight doesn't go above max height 
+    // if (prevState.updatedStartPosY != this.state.updatedStartPosY || prevProps.startVelY != this.props.startVelY) {
+    //   console.log('max height check')
+    //   if (this.props.dataDoc['simulationType'] == "One Weight") {
+    //     let maxYPos = this.state.updatedStartPosY;
+    //     if (this.props.startVelY != 0) {
+    //       maxYPos -= (this.props.startVelY * this.props.startVelY) / (2 * Math.abs(this.props.gravity));
+    //     }
+    //     if (maxYPos < 0) {
+    //       maxYPos = 0;
+    //     }
+    //     this.setState({maxPosYConservation: maxYPos})
+    //   }
+    // }
 
     // Check for collisions and update
     if (prevState.timer != this.state.timer) {
@@ -416,8 +413,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
 
     // Update x position when start pos x changes
     if (prevProps.startPosX != this.props.startPosX) {
-      console.log('xpos')
-      if (this.props.paused) {
+      if (this.props.paused && !isNaN(this.props.startPosX)) {
         this.setState({xPosition: this.props.startPosX})
         this.setState({updatedStartPosX: this.props.startPosX})
         this.setXPosDisplay(this.props.startPosX)
@@ -426,11 +422,10 @@ export default class Weight extends React.Component<IWeightProps, IState> {
 
     // Update y position when start pos y changes TODO debug
     if (prevProps.startPosY != this.props.startPosY) {
-      console.log('ypos')
-       if (this.props.paused) {
-        // this.setState({yPosition: this.props.startPosY})
-        this.setState({updatedStartPosY: this.props.startPosY})
-        this.setYPosDisplay(this.props.startPosY)
+       if (this.props.paused && !isNaN(this.props.startPosY)) {
+        this.setState({yPosition: this.props.startPosY})
+        this.setState({updatedStartPosY: this.props.startPosY ?? 0})
+        this.setYPosDisplay(this.props.startPosY ?? 0)
       }
     }
 
@@ -1110,7 +1105,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             position: "absolute",
             left: 0,
             top: 0,
-            zIndex: -2,
           }}
         >
           <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
@@ -1133,7 +1127,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             position: "absolute",
             left: 0,
             top: 0,
-            zIndex: -2,
           }}
         >
           <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
@@ -1149,7 +1142,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
           <p
             style={{
               position: "absolute",
-              zIndex: 10,
               left: (this.props.xMax + this.props.xMin) / 2 - this.props.radius - this.props.yMin - 200 + 80 + "px",
               top: 10 + "px",
               backgroundColor: this.labelBackgroundColor,
@@ -1178,7 +1170,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             position: "absolute",
             left: 0,
             top: 0,
-            zIndex: -2,
           }}
         >
           <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
@@ -1195,7 +1186,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
           <p
             style={{
               position: "absolute",
-              zIndex: 10,
               left: (this.props.xMax + this.props.xMin) / 2 + this.props.yMin + 200 + this.props.radius - 80 + "px",
               top: 10 + "px",
               backgroundColor: this.labelBackgroundColor,
@@ -1226,7 +1216,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             position: "absolute",
             left: 0,
             top: 0,
-            zIndex: -2,
           }}
         >
           <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
@@ -1249,7 +1238,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             position: "absolute",
             left: 0,
             top: 0,
-            zIndex: -2,
           }}
         >
           <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
@@ -1278,7 +1266,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
               <p
                 style={{
                   position: "absolute",
-                  zIndex: -1,
                   left: this.props.xMax / 2 + "px",
                   top: 30 + "px",
                   backgroundColor: this.labelBackgroundColor,
@@ -1320,7 +1307,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             style={{
               pointerEvents: "none",
               position: "absolute",
-              zIndex: -1,
               left: 0,
               top: 0,
             }}
@@ -1355,7 +1341,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 position: "absolute",
                 left: this.state.xPosition + this.props.radius + this.state.xAccel * 3 + 25 + "px",
                 top: this.state.yPosition + this.props.radius + this.state.yAccel * 3 + 70 + "px",
-                zIndex: -1,
                 lineHeight: 0.5,
               }}
             >
@@ -1376,7 +1361,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             style={{
               pointerEvents: "none",
               position: "absolute",
-              zIndex: -1,
               left: 0,
               top: 0,
             }}
@@ -1411,7 +1395,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 position: "absolute",
                 left: this.state.xPosition + this.props.radius + this.state.xVelocity * 3 + 25 + "px",
                 top: this.state.yPosition +  this.props.radius + this.state.yVelocity * 3 + "px",
-                zIndex: -1,
                 lineHeight: 0.5,
               }}
             >
@@ -1473,7 +1456,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 style={{
                   pointerEvents: "none",
                   position: "absolute",
-                  zIndex: -1,
                   left: this.props.xMin,
                   top: this.props.yMin,
                 }}
@@ -1526,7 +1508,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                   position: "absolute",
                   left: labelLeft + "px",
                   top: labelTop + "px",
-                  // zIndex: -1,
                   lineHeight: 0.5,
                   backgroundColor: this.labelBackgroundColor,
                 }}
@@ -1584,7 +1565,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 style={{
                   pointerEvents: "none",
                   position: "absolute",
-                  zIndex: -1,
                   left: this.props.xMin,
                   top: this.props.yMin,
                 }}
-- 
cgit v1.2.3-70-g09d2


From 051d0b8feb3c6901788137f6c72a4bba34be2507 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Tue, 2 May 2023 20:47:11 -0400
Subject: debugging

---
 src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 3cb34d5b9..5b2a30bfc 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -381,10 +381,10 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
 
   // Helper function to go between display and real values
   getDisplayYPos = (yPos: number) => {
-    return this.yMax - this.dataDoc.yPos - 2 * this.radius + 5;
+    return this.yMax - yPos - 2 * this.radius + 5;
   };
   getYPosFromDisplay = (yDisplay: number) => {
-    return this.yMax - this.dataDoc.yDisplay - 2 * this.radius + 5;
+    return this.yMax - yDisplay - 2 * this.radius + 5;
   };
 
   // Update forces when coefficient of static friction changes in freeform mode
@@ -1350,7 +1350,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 paused={this.dataDoc.simulationPaused}
                 pendulumAngle={this.dataDoc.pendulumAngle}
                 pendulumLength={this.dataDoc.pendulumLength}
-                radius={this.dataDoc.radius}
+                radius={this.radius}
                 reset={this.dataDoc.simulationReset}
                 simulationSpeed={this.dataDoc.simulationSpeed}
                 startPendulumAngle={this.dataDoc.startPendulumAngle}
-- 
cgit v1.2.3-70-g09d2


From 30068f771a1a6e69c43097948439855dea896e83 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Tue, 2 May 2023 20:53:47 -0400
Subject: mostly works

---
 src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx    | 2 +-
 src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 5b2a30bfc..9a16c5c73 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -107,7 +107,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
 
   componentDidMount() {
     this.wallPositions.push({ length: 70, xPos: 0, yPos: 0, angleInDegrees: 0 });
-    this.wallPositions.push({ length: 70, xPos: 0, yPos: 80, angleInDegrees: 0 });
+    this.wallPositions.push({ length: 70, xPos: 0, yPos: 70, angleInDegrees: 0 });
     this.wallPositions.push({ length: 80, xPos: 0, yPos: 0, angleInDegrees: 90 });
     this.wallPositions.push({ length: 80, xPos: 69.5, yPos: 0, angleInDegrees: 90 });
 
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index f78f14704..c0bcd783a 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -404,9 +404,9 @@ export default class Weight extends React.Component<IWeightProps, IState> {
       let w: IWallProps[] = [];
       if (this.props.dataDoc['simulationType'] == "One Weight" || this.props.dataDoc['simulationType'] == "Inclined Plane") {
         w.push({ length: 70, xPos: 0, yPos: 0, angleInDegrees: 0 });
-        w.push({ length: 70, xPos: 0, yPos: 80, angleInDegrees: 0 });
-        w.push({ length: 80, xPos: 0, yPos: 0, angleInDegrees: 90 });
-        w.push({ length: 85, xPos: 69.5, yPos: 0, angleInDegrees: 90 });
+        w.push({ length: 70, xPos: 0, yPos: 70, angleInDegrees: 0 });
+        w.push({ length: 70, xPos: 0, yPos: 0, angleInDegrees: 90 });
+        w.push({ length: 70, xPos: 69.5, yPos: 0, angleInDegrees: 90 });
       }
       this.setState({walls: w})
     }
-- 
cgit v1.2.3-70-g09d2


From 018077581b70483ac2f3453ba813b5f4adb61fd5 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Wed, 3 May 2023 13:06:09 -0400
Subject: debugging

---
 .../views/nodes/PhysicsBox/PhysicsSimulationBox.tsx       | 15 ++++++++++-----
 .../views/nodes/PhysicsBox/PhysicsSimulationWall.tsx      |  4 ++--
 .../views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx    | 15 +++++++++------
 3 files changed, 21 insertions(+), 13 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 9a16c5c73..315e64e79 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -106,11 +106,6 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   wallPositions: IWallProps[] = [];
 
   componentDidMount() {
-    this.wallPositions.push({ length: 70, xPos: 0, yPos: 0, angleInDegrees: 0 });
-    this.wallPositions.push({ length: 70, xPos: 0, yPos: 70, angleInDegrees: 0 });
-    this.wallPositions.push({ length: 80, xPos: 0, yPos: 0, angleInDegrees: 90 });
-    this.wallPositions.push({ length: 80, xPos: 69.5, yPos: 0, angleInDegrees: 90 });
-
     // Used throughout sims
     this.layoutDoc._width = 1000;
     this.layoutDoc._height = 1000;
@@ -211,6 +206,14 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
 
     // Setup simulation
     this.setupSimulation(this.dataDoc.simulationType, 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() {
@@ -1283,6 +1286,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             <Weight
               dataDoc={this.dataDoc}
               layoutDoc={this.layoutDoc}
+              wallPositions={this.wallPositions}
               adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
               gravity={this.dataDoc.gravity}
               circularMotionRadius={this.dataDoc.circularMotionRadius}
@@ -1332,6 +1336,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               <Weight
                 dataDoc={this.dataDoc}
                 layoutDoc={this.layoutDoc}
+                wallPositions={this.wallPositions}
                 adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
                 circularMotionRadius={this.dataDoc.circularMotionRadius}
                 gravity={this.dataDoc.gravity}
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWall.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWall.tsx
index 83dff660a..8cc1d0fbf 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWall.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWall.tsx
@@ -18,8 +18,8 @@ export default class Wall extends React.Component<IWallProps> {
   }
 
   wallStyle = {
-    width: this.props.angleInDegrees == 0 ? this.props.length + "%" : "1%",
-    height: this.props.angleInDegrees == 0 ? "1%" : this.props.length + "%",
+    width: this.props.angleInDegrees == 0 ? this.props.length + "%" : "5px",
+    height: this.props.angleInDegrees == 0 ? "5px" : this.props.length + "%",
     position: "absolute" as "absolute",
     left: this.props.xPos + "%",
     top: this.props.yPos + "%",
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index c0bcd783a..597256d44 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -3,6 +3,12 @@ import React = require('react');
 import { IWallProps } from "./PhysicsSimulationWall";
 import "./PhysicsSimulationBox.scss";
 
+interface IWallProps {
+  length: number;
+  xPos: number;
+  yPos: number;
+  angleInDegrees: number;
+}
 interface IForce {
   description: string;
   magnitude: number;
@@ -48,6 +54,7 @@ export interface IWeightProps {
   timestepSize: number;
   updateDisplay: { xDisplay: number; yDisplay: number };
   updatedForces: IForce[];
+  wallPositions: IWallProps[];
   wedgeHeight: number;
   wedgeWidth: number;
   xMax: number;
@@ -403,10 +410,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
       console.log('walls')
       let w: IWallProps[] = [];
       if (this.props.dataDoc['simulationType'] == "One Weight" || this.props.dataDoc['simulationType'] == "Inclined Plane") {
-        w.push({ length: 70, xPos: 0, yPos: 0, angleInDegrees: 0 });
-        w.push({ length: 70, xPos: 0, yPos: 70, angleInDegrees: 0 });
-        w.push({ length: 70, xPos: 0, yPos: 0, angleInDegrees: 90 });
-        w.push({ length: 70, xPos: 69.5, yPos: 0, angleInDegrees: 90 });
+        w = this.props.wallPositions
       }
       this.setState({walls: w})
     }
@@ -431,17 +435,16 @@ export default class Weight extends React.Component<IWeightProps, IState> {
 
     // Update wedge coordinates
     if (prevProps.wedgeWidth != this.props.wedgeWidth || prevProps.wedgeHeight != this.props.wedgeHeight) {
-      console.log('wedge')
       const left = this.props.xMax * 0.5 - 200;
       const coordinatePair1 = Math.round(left) + "," + this.props.yMax + " ";
       const coordinatePair2 = Math.round(left + this.props.wedgeWidth) + "," + this.props.yMax + " ";
       const coordinatePair3 = Math.round(left) + "," + (this.props.yMax - this.props.wedgeHeight);
       const coord = coordinatePair1 + coordinatePair2 + coordinatePair3;
+      console.log('coord ', coord)
       this.setState({coordinates: coord})
     } 
 
     if (this.state.xPosition != prevState.xPosition || this.state.yPosition != prevState.yPosition) {
-      console.log('style')
       this.weightStyle = {
         alignItems: "center",
         backgroundColor: this.props.color,
-- 
cgit v1.2.3-70-g09d2


From 2e3df73d84228b04b8d1f284b5e18f7e48fad759 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Wed, 3 May 2023 16:04:02 -0400
Subject: debugging json import

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 22 +++++++++++-----------
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   | 10 +++-------
 tsconfig.json                                      |  3 ++-
 3 files changed, 16 insertions(+), 19 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 315e64e79..056f79368 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -33,8 +33,8 @@ import {
 import Typography from "@mui/material/Typography";
 import "./PhysicsSimulationBox.scss";
 import InputField from "./PhysicsSimulationInputField";
-import questions from "./PhysicsSimulationQuestions.json";
-import tutorials from "./PhysicsSimulationTutorial.json";
+import * as questions from "./PhysicsSimulationQuestions.json";
+import * as tutorials from "./PhysicsSimulationTutorial.json";
 import Wall from "./PhysicsSimulationWall";
 import Weight from "./PhysicsSimulationWeight";
 
@@ -108,9 +108,9 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   componentDidMount() {
     // Used throughout sims
     this.layoutDoc._width = 1000;
-    this.layoutDoc._height = 1000;
-    this.xMax = this.layoutDoc._width*0.7 ?? 700;
-    this.yMax = this.layoutDoc._height*0.7 ?? 700;
+    this.layoutDoc._height = 800;
+    this.xMax = this.layoutDoc._width*0.7;
+    this.yMax = this.layoutDoc._height*0.9;
     this.radius = 50;
     this.dataDoc.reviewCoefficient = this.dataDoc.reviewCoefficient ?? 0;
     this.dataDoc.questionVariables = this.dataDoc.questionVariables ?? [];
@@ -147,7 +147,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.velocityYDisplay = this.dataDoc.velocityYDisplay ?? 0;
 
     // Used for review mode
-    // this.dataDoc.answerInputFields = this.dataDoc.answerInputFields ?? <div></div>;
+    this.dataDoc.answerInputFields = this.dataDoc.answerInputFields ?? <div></div>;
     // this.dataDoc.currentForceSketch = this.dataDoc.currentForceSketch ?? null;
     // this.dataDoc.deleteMode = this.dataDoc.deleteMode ?? false;
     // this.dataDoc.forceSketches = this.dataDoc.forceSketches ?? [];
@@ -163,11 +163,11 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.reviewStaticAngle = this.dataDoc.reviewStaticAngle ?? 0;
     this.dataDoc.reviewStaticMagnitude = this.dataDoc.reviewStaticMagnitude ?? 0;
     this.dataDoc.selectedSolutions = this.dataDoc.selectedSolutions ?? [];
-    // this.dataDoc.selectedQuestion = this.dataDoc.selectedQuestion ?? questions.inclinePlane[0];
+    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 tutorial mode
+    this.dataDoc.selectedTutorial = this.dataDoc.selectedTutorial ?? tutorials.inclinePlane;
 
     // Used for uniform circular motion
     this.dataDoc.circularMotionRadius = this.dataDoc.circularMotionRadius ?? 150;
@@ -217,8 +217,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   }
 
   componentDidUpdate() {
-    this.xMax = this.layoutDoc._width*0.7 ?? 700;
-    this.yMax = this.layoutDoc._height*0.7 ?? 700;
+    this.xMax = this.layoutDoc._width*0.7;
+    this.yMax = this.layoutDoc._height*0.9;
     this.radius = 0.05*this.layoutDoc._height ?? 50;
   }
 
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 597256d44..8369a994a 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -244,7 +244,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
 
     // // Make sure weight doesn't go above max height 
     // if (prevState.updatedStartPosY != this.state.updatedStartPosY || prevProps.startVelY != this.props.startVelY) {
-    //   console.log('max height check')
     //   if (this.props.dataDoc['simulationType'] == "One Weight") {
     //     let maxYPos = this.state.updatedStartPosY;
     //     if (this.props.startVelY != 0) {
@@ -258,9 +257,9 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     // }
 
     // Check for collisions and update
+    if (!this.props.paused) {
     if (prevState.timer != this.state.timer) {
-      console.log('update')
-      if (!this.props.paused && !this.props.noMovement) {
+      if (!this.props.noMovement) {
         let collisions = false;
         if (
           this.props.dataDoc['simulationType'] == "One Weight" ||
@@ -281,16 +280,15 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         this.setDisplayValues();
       }
     }
+    }
 
     // Reset everything on reset button click
     if (prevProps.reset != this.props.reset) {
-      console.log('reset')
       this.resetEverything();
     }
     
     // Convert from static to kinetic friction if/when weight slips on inclined plane
     if (prevState.xVelocity != this.state.xVelocity) {
-      console.log('friction')
       if (
         this.props.dataDoc['simulationType'] == "Inclined Plane" &&
         Math.abs(this.state.xVelocity) > 0.1 &&
@@ -407,7 +405,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
 
     // Add/remove walls when simulation type changes
     if (prevProps.simulationType != this.props.simulationType) {
-      console.log('walls')
       let w: IWallProps[] = [];
       if (this.props.dataDoc['simulationType'] == "One Weight" || this.props.dataDoc['simulationType'] == "Inclined Plane") {
         w = this.props.wallPositions
@@ -440,7 +437,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
       const coordinatePair2 = Math.round(left + this.props.wedgeWidth) + "," + this.props.yMax + " ";
       const coordinatePair3 = Math.round(left) + "," + (this.props.yMax - this.props.wedgeHeight);
       const coord = coordinatePair1 + coordinatePair2 + coordinatePair3;
-      console.log('coord ', coord)
       this.setState({coordinates: coord})
     } 
 
diff --git a/tsconfig.json b/tsconfig.json
index 993ab13b9..06901fe31 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -22,7 +22,8 @@
         "types": [
             "youtube",
             "node"
-        ]
+        ],
+        "resolveJsonModule": true
     },
     // "exclude": [
     //   "node_modules",
-- 
cgit v1.2.3-70-g09d2


From d7b4700e0a00349c2961f04f5b9d1b882cca6746 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Wed, 3 May 2023 17:33:25 -0400
Subject: debug questions and tutorials

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 866 ++++++++++-----------
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   |  65 +-
 2 files changed, 465 insertions(+), 466 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 056f79368..9caf41445 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -109,9 +109,9 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     // Used throughout sims
     this.layoutDoc._width = 1000;
     this.layoutDoc._height = 800;
-    this.xMax = this.layoutDoc._width*0.7;
+    this.xMax = this.layoutDoc._width*0.6;
     this.yMax = this.layoutDoc._height*0.9;
-    this.radius = 50;
+    this.radius = 100;
     this.dataDoc.reviewCoefficient = this.dataDoc.reviewCoefficient ?? 0;
     this.dataDoc.questionVariables = this.dataDoc.questionVariables ?? [];
     this.dataDoc.accelerationXDisplay = this.dataDoc.accelerationXDisplay ?? 0;
@@ -217,9 +217,9 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   }
 
   componentDidUpdate() {
-    this.xMax = this.layoutDoc._width*0.7;
+    this.xMax = this.layoutDoc._width*0.6;
     this.yMax = this.layoutDoc._height*0.9;
-    this.radius = 0.05*this.layoutDoc._height ?? 50;
+    this.radius = 0.1*this.layoutDoc._height ?? 100;
   }
 
   setupSimulation = (simulationType: string, mode: string) => {
@@ -309,75 +309,75 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       this.dataDoc.showComponentForces = (false);
       this.dataDoc.stepNumber = (0);
       this.dataDoc.showAcceleration = (false);
-      // if (this.dataDoc.simulationType != "Circular Motion") {
-      //   this.dataDoc.velocityXDisplay = (0);
-      //   this.dataDoc.velocityYDisplay = (0);
-      //   this.dataDoc.showVelocity = (false);
-      // } else {
-      //   this.dataDoc.velocityXDisplay = (20);
-      //   this.dataDoc.velocityYDisplay = (0);
-      //   this.dataDoc.showVelocity = (true);
-      // }
+      if (this.dataDoc.simulationType != "Circular Motion") {
+        this.dataDoc.velocityXDisplay = (0);
+        this.dataDoc.velocityYDisplay = (0);
+        this.dataDoc.showVelocity = (false);
+      } else {
+        this.dataDoc.velocityXDisplay = (20);
+        this.dataDoc.velocityYDisplay = (0);
+        this.dataDoc.showVelocity = (true);
+      }
 
-      // if (this.dataDoc.simulationType == "One Weight") {
-      //   this.dataDoc.showForces = (true);
-      //   this.dataDoc.startPosY = (this.yMax - 100);
-      //   this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
-      //   this.dataDoc.selectedTutorial = (tutorials.freeWeight);
-      //   this.dataDoc.startForces = (this.getForceFromJSON(tutorials.freeWeight.steps[0].forces));
-      //   this.dataDoc.showForceMagnitudes = (tutorials.freeWeight.steps[0].showMagnitude);
-      // } else if (this.dataDoc.simulationType == "Spring") {
-      //   this.dataDoc.showForces = (true);
-      //   this.setupSpring();
-      //   this.dataDoc.startPosY = (this.yMin + 200 + 19.62);
-      //   this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
-      //   this.dataDoc.selectedTutorial = (tutorials.spring);
-      //   this.dataDoc.startForces = (this.getForceFromJSON(tutorials.spring.steps[0].forces));
-      //   this.dataDoc.showForceMagnitudes = (tutorials.spring.steps[0].showMagnitude);
-      // } else if (this.dataDoc.simulationType == "Pendulum") {
-      //   this.dataDoc.showForces = (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 - this.radius;
-      //   const yPos = y - this.radius - 5;
-      //   this.dataDoc.startPosX = (xPos);
-      //   this.dataDoc.startPosY = (yPos);
-      //   this.dataDoc.selectedTutorial = (tutorials.pendulum);
-      //   this.dataDoc.startForces = (this.getForceFromJSON(tutorials.pendulum.steps[0].forces));
-      //   this.dataDoc.showForceMagnitudes = (tutorials.pendulum.steps[0].showMagnitude);
-      //   this.dataDoc.pendulumAngle = (30);
-      //   this.dataDoc.pendulumLength = (300);
-      //   this.dataDoc.adjustPendulumAngle = ({ angle: 30, length: 300 });
-      // } else if (this.dataDoc.simulationType == "Inclined Plane") {
-      //   this.dataDoc.showForces = (true);
-      //   this.dataDoc.wedgeAngle = (26);
-      //   this.changeWedgeBasedOnNewAngle(26);
-      //   this.dataDoc.selectedTutorial = (tutorials.inclinePlane);
-      //   this.dataDoc.startForces = (
-      //     this.getForceFromJSON(tutorials.inclinePlane.steps[0].forces)
-      //   );
-      //   this.dataDoc.showForceMagnitudes = (tutorials.inclinePlane.steps[0].showMagnitude);
-      // } else if (this.dataDoc.simulationType == "Circular Motion") {
-      //   this.dataDoc.showForces = (true);
-      //   this.setupCircular(40);
-      //   this.dataDoc.selectedTutorial = (tutorials.circular);
-      //   this.dataDoc.startForces = (this.getForceFromJSON(tutorials.circular.steps[0].forces));
-      //   this.dataDoc.showForceMagnitudes = (tutorials.circular.steps[0].showMagnitude);
-      // } else if (this.dataDoc.simulationType == "Pulley") {
-      //   this.dataDoc.showForces = (true);
-      //   this.setupPulley();
-      //   this.dataDoc.selectedTutorial = (tutorials.pulley);
-      //   this.dataDoc.startForces = (this.getForceFromJSON(tutorials.pulley.steps[0].forces));
-      //   this.dataDoc.showForceMagnitudes = (tutorials.pulley.steps[0].showMagnitude);
-      // } else if (this.dataDoc.simulationType == "Suspension") {
-      //   this.dataDoc.showForces = (true);
-      //   this.setupSuspension();
-      //   this.dataDoc.selectedTutorial = (tutorials.suspension);
-      //   this.dataDoc.startForces = (this.getForceFromJSON(tutorials.suspension.steps[0].forces));
-      //   this.dataDoc.showForceMagnitudes = (tutorials.suspension.steps[0].showMagnitude);
-      // }
+      if (this.dataDoc.simulationType == "One Weight") {
+        this.dataDoc.showForces = (true);
+        this.dataDoc.startPosY = (this.yMax - 100);
+        this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
+        this.dataDoc.selectedTutorial = (tutorials.freeWeight);
+        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.freeWeight.steps[0].forces));
+        this.dataDoc.showForceMagnitudes = (tutorials.freeWeight.steps[0].showMagnitude);
+      } else if (this.dataDoc.simulationType == "Spring") {
+        this.dataDoc.showForces = (true);
+        this.setupSpring();
+        this.dataDoc.startPosY = (this.yMin + 200 + 19.62);
+        this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
+        this.dataDoc.selectedTutorial = (tutorials.spring);
+        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.spring.steps[0].forces));
+        this.dataDoc.showForceMagnitudes = (tutorials.spring.steps[0].showMagnitude);
+      } else if (this.dataDoc.simulationType == "Pendulum") {
+        this.dataDoc.showForces = (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 - this.radius;
+        const yPos = y - this.radius - 5;
+        this.dataDoc.startPosX = (xPos);
+        this.dataDoc.startPosY = (yPos);
+        this.dataDoc.selectedTutorial = (tutorials.pendulum);
+        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.pendulum.steps[0].forces));
+        this.dataDoc.showForceMagnitudes = (tutorials.pendulum.steps[0].showMagnitude);
+        this.dataDoc.pendulumAngle = (30);
+        this.dataDoc.pendulumLength = (300);
+        this.dataDoc.adjustPendulumAngle = ({ angle: 30, length: 300 });
+      } else if (this.dataDoc.simulationType == "Inclined Plane") {
+        this.dataDoc.showForces = (true);
+        this.dataDoc.wedgeAngle = (26);
+        this.changeWedgeBasedOnNewAngle(26);
+        this.dataDoc.selectedTutorial = (tutorials.inclinePlane);
+        this.dataDoc.startForces = (
+          this.getForceFromJSON(tutorials.inclinePlane.steps[0].forces)
+        );
+        this.dataDoc.showForceMagnitudes = (tutorials.inclinePlane.steps[0].showMagnitude);
+      } else if (this.dataDoc.simulationType == "Circular Motion") {
+        this.dataDoc.showForces = (true);
+        this.setupCircular(40);
+        this.dataDoc.selectedTutorial = (tutorials.circular);
+        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.circular.steps[0].forces));
+        this.dataDoc.showForceMagnitudes = (tutorials.circular.steps[0].showMagnitude);
+      } else if (this.dataDoc.simulationType == "Pulley") {
+        this.dataDoc.showForces = (true);
+        this.setupPulley();
+        this.dataDoc.selectedTutorial = (tutorials.pulley);
+        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.pulley.steps[0].forces));
+        this.dataDoc.showForceMagnitudes = (tutorials.pulley.steps[0].showMagnitude);
+      } else if (this.dataDoc.simulationType == "Suspension") {
+        this.dataDoc.showForces = (true);
+        this.setupSuspension();
+        this.dataDoc.selectedTutorial = (tutorials.suspension);
+        this.dataDoc.startForces = (this.getForceFromJSON(tutorials.suspension.steps[0].forces));
+        this.dataDoc.showForceMagnitudes = (tutorials.suspension.steps[0].showMagnitude);
+      }
       this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
     }
   }
@@ -541,45 +541,45 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     }
   };
 
-  // // In review mode, update forces when coefficient of static friction changed
-  // updateReviewForcesBasedOnCoefficient = (coefficient: number) => {
-  //   let theta: number = Number(this.dataDoc.wedgeAngle);
-  //   let index =
-  //     this.dataDoc.selectedQuestion.variablesForQuestionSetup.indexOf("theta - max 45");
-  //   if (index >= 0) {
-  //     theta = this.dataDoc.questionVariables[index];
-  //   }
-  //   if (isNaN(theta)) {
-  //     return;
-  //   }
-  //   this.dataDoc.reviewGravityMagnitude = (Math.abs(this.dataDoc.gravity));
-  //   this.dataDoc.reviewGravityAngle = (270);
-  //   this.dataDoc.reviewNormalMagnitude = (
-  //     Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180)
-  //   );
-  //   this.dataDoc.reviewNormalAngle = (90 - theta);
-  //   let yForce = -Math.abs(this.dataDoc.gravity);
-  //   yForce +=
-  //     Math.abs(this.dataDoc.gravity) *
-  //     Math.cos((theta * Math.PI) / 180) *
-  //     Math.sin(((90 - theta) * Math.PI) / 180);
-  //   yForce +=
-  //     coefficient *
-  //     Math.abs(this.dataDoc.gravity) *
-  //     Math.cos((theta * Math.PI) / 180) *
-  //     Math.sin(((180 - theta) * Math.PI) / 180);
-  //   let friction =
-  //     coefficient * Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180);
-  //   if (yForce > 0) {
-  //     friction =
-  //       (-(Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180)) *
-  //         Math.sin(((90 - theta) * Math.PI) / 180) +
-  //         Math.abs(this.dataDoc.gravity)) /
-  //       Math.sin(((180 - theta) * Math.PI) / 180);
-  //   }
-  //   this.dataDoc.reviewStaticMagnitude = (friction);
-  //   this.dataDoc.reviewStaticAngle = (180 - theta);
-  // };
+  // In review mode, update forces when coefficient of static friction changed
+  updateReviewForcesBasedOnCoefficient = (coefficient: number) => {
+    let theta: number = Number(this.dataDoc.wedgeAngle);
+    let index =
+      this.dataDoc.selectedQuestion.variablesForQuestionSetup.indexOf("theta - max 45");
+    if (index >= 0) {
+      theta = this.dataDoc.questionVariables[index];
+    }
+    if (isNaN(theta)) {
+      return;
+    }
+    this.dataDoc.reviewGravityMagnitude = (Math.abs(this.dataDoc.gravity));
+    this.dataDoc.reviewGravityAngle = (270);
+    this.dataDoc.reviewNormalMagnitude = (
+      Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180)
+    );
+    this.dataDoc.reviewNormalAngle = (90 - theta);
+    let yForce = -Math.abs(this.dataDoc.gravity);
+    yForce +=
+      Math.abs(this.dataDoc.gravity) *
+      Math.cos((theta * Math.PI) / 180) *
+      Math.sin(((90 - theta) * Math.PI) / 180);
+    yForce +=
+      coefficient *
+      Math.abs(this.dataDoc.gravity) *
+      Math.cos((theta * Math.PI) / 180) *
+      Math.sin(((180 - theta) * Math.PI) / 180);
+    let friction =
+      coefficient * Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180);
+    if (yForce > 0) {
+      friction =
+        (-(Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180)) *
+          Math.sin(((90 - theta) * Math.PI) / 180) +
+          Math.abs(this.dataDoc.gravity)) /
+        Math.sin(((180 - theta) * Math.PI) / 180);
+    }
+    this.dataDoc.reviewStaticMagnitude = (friction);
+    this.dataDoc.reviewStaticAngle = (180 - theta);
+  };
 
   // In review mode, update forces when wedge angle changed
   updateReviewForcesBasedOnAngle = (angle: number) => {
@@ -689,84 +689,84 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     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(this.dataDoc.reviewGravityMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon
-  //         ) {
-  //           error = true;
-  //         }
-  //       } else if (this.dataDoc.selectedQuestion.answerParts[i] == "angle of gravity") {
-  //         if (Math.abs(this.dataDoc.reviewGravityAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
-  //           error = true;
-  //         }
-  //       } else if (this.dataDoc.selectedQuestion.answerParts[i] == "normal force") {
-  //         if (
-  //           Math.abs(this.dataDoc.reviewNormalMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon
-  //         ) {
-  //           error = true;
-  //         }
-  //       } else if (this.dataDoc.selectedQuestion.answerParts[i] == "angle of normal force") {
-  //         if (Math.abs(this.dataDoc.reviewNormalAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
-  //           error = true;
-  //         }
-  //       } else if (
-  //         this.dataDoc.selectedQuestion.answerParts[i] == "force of static friction"
-  //       ) {
-  //         if (
-  //           Math.abs(this.dataDoc.reviewStaticMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon
-  //         ) {
-  //           error = true;
-  //         }
-  //       } else if (
-  //         this.dataDoc.selectedQuestion.answerParts[i] == "angle of static friction"
-  //       ) {
-  //         if (Math.abs(this.dataDoc.reviewStaticAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
-  //           error = true;
-  //         }
-  //       } else if (
-  //         this.dataDoc.selectedQuestion.answerParts[i] == "coefficient of static friction"
-  //       ) {
-  //         if (
-  //           Math.abs(
-  //             Number(this.dataDoc.coefficientOfStaticFriction) - this.dataDoc.selectedSolutions[i]
-  //           ) > epsilon
-  //         ) {
-  //           error = true;
-  //         }
-  //       } else if (this.dataDoc.selectedQuestion.answerParts[i] == "wedge angle") {
-  //         if (Math.abs(Number(this.dataDoc.wedgeAngle) - this.dataDoc.selectedSolutions[i]) > epsilon) {
-  //           error = true;
-  //         }
-  //       }
-  //     }
-  //   }
-  //   if (showAlert) {
-  //     if (!error) {
-  //       this.dataDoc.simulationPaused = (false);
-  //       setTimeout(() => {
-  //         this.dataDoc.simulationPaused = (true);
-  //       }, 3000);
-  //     } else {
-  //       this.dataDoc.simulationPaused = (false);
-  //       setTimeout(() => {
-  //         this.dataDoc.simulationPaused = (true);
-  //       }, 3000);
-  //     }
-  //   }
-  //   if (this.dataDoc.selectedQuestion.goal == "noMovement") {
-  //     if (!error) {
-  //       this.dataDoc.noMovement = (true);
-  //     } else {
-  //       this.dataDoc.roMovement = (false);
-  //     }
-  //   }
-  // };
+  // 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(this.dataDoc.reviewGravityMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon
+          ) {
+            error = true;
+          }
+        } else if (this.dataDoc.selectedQuestion.answerParts[i] == "angle of gravity") {
+          if (Math.abs(this.dataDoc.reviewGravityAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
+            error = true;
+          }
+        } else if (this.dataDoc.selectedQuestion.answerParts[i] == "normal force") {
+          if (
+            Math.abs(this.dataDoc.reviewNormalMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon
+          ) {
+            error = true;
+          }
+        } else if (this.dataDoc.selectedQuestion.answerParts[i] == "angle of normal force") {
+          if (Math.abs(this.dataDoc.reviewNormalAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
+            error = true;
+          }
+        } else if (
+          this.dataDoc.selectedQuestion.answerParts[i] == "force of static friction"
+        ) {
+          if (
+            Math.abs(this.dataDoc.reviewStaticMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon
+          ) {
+            error = true;
+          }
+        } else if (
+          this.dataDoc.selectedQuestion.answerParts[i] == "angle of static friction"
+        ) {
+          if (Math.abs(this.dataDoc.reviewStaticAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
+            error = true;
+          }
+        } else if (
+          this.dataDoc.selectedQuestion.answerParts[i] == "coefficient of static friction"
+        ) {
+          if (
+            Math.abs(
+              Number(this.dataDoc.coefficientOfStaticFriction) - this.dataDoc.selectedSolutions[i]
+            ) > epsilon
+          ) {
+            error = true;
+          }
+        } else if (this.dataDoc.selectedQuestion.answerParts[i] == "wedge angle") {
+          if (Math.abs(Number(this.dataDoc.wedgeAngle) - this.dataDoc.selectedSolutions[i]) > epsilon) {
+            error = true;
+          }
+        }
+      }
+    }
+    if (showAlert) {
+      if (!error) {
+        this.dataDoc.simulationPaused = (false);
+        setTimeout(() => {
+          this.dataDoc.simulationPaused = (true);
+        }, 3000);
+      } else {
+        this.dataDoc.simulationPaused = (false);
+        setTimeout(() => {
+          this.dataDoc.simulationPaused = (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 = () => {
@@ -781,248 +781,248 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.answerInputFields = (<div></div>);
   };
 
-  // // In review mode, reset problem variables and generate a new question
-  // generateNewQuestion = () => {
-  //   this.resetReviewValuesToDefault();
+  // In review mode, reset problem variables and generate a new question
+  generateNewQuestion = () => {
+    this.resetReviewValuesToDefault();
 
-  //   const vars: number[] = [];
-  //   let question: QuestionTemplate = questions.inclinePlane[0];
+    const vars: number[] = [];
+    let question: QuestionTemplate = questions.inclinePlane[0];
 
-  //   if (this.dataDoc.simulationType == "Inclined Plane") {
-  //     if (this.dataDoc.questionNumber == questions.inclinePlane.length - 1) {
-  //       this.dataDoc.questionNumber = (0);
-  //     } else {
-  //       this.dataDoc.questionNumber =(this.dataDoc.questionNumber + 1);
-  //     }
-  //     question = questions.inclinePlane[this.dataDoc.questionNumber];
+    if (this.dataDoc.simulationType == "Inclined Plane") {
+      if (this.dataDoc.questionNumber == questions.inclinePlane.length - 1) {
+        this.dataDoc.questionNumber = (0);
+      } else {
+        this.dataDoc.questionNumber =(this.dataDoc.questionNumber + 1);
+      }
+      question = questions.inclinePlane[this.dataDoc.questionNumber];
 
-  //     let coefficient = 0;
-  //     let wedgeAngle = 0;
+      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.reviewCoefficient = 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 = vars;
-  //   this.dataDoc.selectedQuestion = (question);
-  //   this.dataDoc.questionPartOne = (q);
-  //   this.dataDoc.questionPartTwo = (question.question);
-  //   const answers = this.getAnswersToQuestion(question, vars);
-  //   this.generateInputFieldsForQuestion(false, question, answers);
-  //   this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
-  // };
+      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.reviewCoefficient = 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 = vars;
+    this.dataDoc.selectedQuestion = (question);
+    this.dataDoc.questionPartOne = (q);
+    this.dataDoc.questionPartTwo = (question.question);
+    const answers = this.getAnswersToQuestion(question, vars);
+    this.generateInputFieldsForQuestion(false, question, answers);
+    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+  };
 
-  // // Generate answerInputFields for new review question
-  // generateInputFieldsForQuestion = (
-  //   showIcon: boolean = false,
-  //   question: QuestionTemplate = this.dataDoc.selectedQuestion,
-  //   answers: number[] = this.dataDoc.selectedSolutions
-  // ) => {
-  //   let answerInput = [];
-  //   const d = new Date();
-  //   for (let i = 0; i < question.answerParts.length; i++) {
-  //     if (question.answerParts[i] == "force of gravity") {
-  //       this.dataDoc.reviewGravityMagnitude = (0);
-  //       answerInput.push(
-  //         <div key={i + d.getTime()}>
-  //           <InputField
-  //             label={<p>Gravity magnitude</p>}
-  //             lowerBound={0}
-  //             dataDoc={this.dataDoc}
-  //             prop={'reviewGravityMagnitude'}
-  //             step={0.1}
-  //             unit={"N"}
-  //             upperBound={50}
-  //             value={this.dataDoc.reviewGravityMagnitude}
-  //             showIcon={showIcon}
-  //             correctValue={answers[i]}
-  //             labelWidth={"7em"}
-  //           />
-  //         </div>
-  //       );
-  //     } else if (question.answerParts[i] == "angle of gravity") {
-  //       this.dataDoc.reviewGravityAngle = (0);
-  //       answerInput.push(
-  //         <div key={i + d.getTime()}>
-  //           <InputField
-  //             label={<p>Gravity angle</p>}
-  //             lowerBound={0}
-  //             dataDoc={this.dataDoc}
-  //             prop={'reviewGravityAngle'}
-  //             step={1}
-  //             unit={"°"}
-  //             upperBound={360}
-  //             value={this.dataDoc.reviewGravityAngle}
-  //             radianEquivalent={true}
-  //             showIcon={showIcon}
-  //             correctValue={answers[i]}
-  //             labelWidth={"7em"}
-  //           />
-  //         </div>
-  //       );
-  //     } else if (question.answerParts[i] == "normal force") {
-  //       this.dataDoc.reviewNormalMagnitude = (0);
-  //       answerInput.push(
-  //         <div key={i + d.getTime()}>
-  //           <InputField
-  //             label={<p>Normal force magnitude</p>}
-  //             lowerBound={0}
-  //             dataDoc={this.dataDoc}
-  //             prop={'reviewNormalMagnitude'}
-  //             step={0.1}
-  //             unit={"N"}
-  //             upperBound={50}
-  //             value={this.dataDoc.reviewNormalMagnitude}
-  //             showIcon={showIcon}
-  //             correctValue={answers[i]}
-  //             labelWidth={"7em"}
-  //           />
-  //         </div>
-  //       );
-  //     } else if (question.answerParts[i] == "angle of normal force") {
-  //       this.dataDoc.reviewNormalAngle = (0);
-  //       answerInput.push(
-  //         <div key={i + d.getTime()}>
-  //           <InputField
-  //             label={<p>Normal force angle</p>}
-  //             lowerBound={0}
-  //             dataDoc={this.dataDoc}
-  //             prop={'reviewNormalAngle'}
-  //             step={1}
-  //             unit={"°"}
-  //             upperBound={360}
-  //             value={this.dataDoc.reviewNormalAngle}
-  //             radianEquivalent={true}
-  //             showIcon={showIcon}
-  //             correctValue={answers[i]}
-  //             labelWidth={"7em"}
-  //           />
-  //         </div>
-  //       );
-  //     } else if (question.answerParts[i] == "force of static friction") {
-  //       this.dataDoc.reviewStaticMagnitude = (0);
-  //       answerInput.push(
-  //         <div key={i + d.getTime()}>
-  //           <InputField
-  //             label={<p>Static friction magnitude</p>}
-  //             lowerBound={0}
-  //             dataDoc={this.dataDoc}
-  //             prop={'reviewStaticMagnitude'}
-  //             step={0.1}
-  //             unit={"N"}
-  //             upperBound={50}
-  //             value={this.dataDoc.reviewStaticMagnitude}
-  //             showIcon={showIcon}
-  //             correctValue={answers[i]}
-  //             labelWidth={"7em"}
-  //           />
-  //         </div>
-  //       );
-  //     } else if (question.answerParts[i] == "angle of static friction") {
-  //       this.dataDoc.reviewStaticAngle = (0);
-  //       answerInput.push(
-  //         <div key={i + d.getTime()}>
-  //           <InputField
-  //             label={<p>Static friction angle</p>}
-  //             lowerBound={0}
-  //             dataDoc={this.dataDoc}
-  //             prop={'reviewStaticAngle'}
-  //             step={1}
-  //             unit={"°"}
-  //             upperBound={360}
-  //             value={this.dataDoc.reviewStaticAngle}
-  //             radianEquivalent={true}
-  //             showIcon={showIcon}
-  //             correctValue={answers[i]}
-  //             labelWidth={"7em"}
-  //           />
-  //         </div>
-  //       );
-  //     } else if (question.answerParts[i] == "coefficient of static friction") {
-  //       this.updateReviewForcesBasedOnCoefficient(0);
-  //       answerInput.push(
-  //         <div key={i + d.getTime()}>
-  //           <InputField
-  //             label={
-  //               <Box>
-  //                 &mu;<sub>s</sub>
-  //               </Box>
-  //             }
-  //             lowerBound={0}
-  //             dataDoc={this.dataDoc}
-  //             prop={'coefficientOfStaticFriction'}
-  //             step={0.1}
-  //             unit={""}
-  //             upperBound={1}
-  //             value={this.dataDoc.coefficientOfStaticFriction}
-  //             effect={this.updateReviewForcesBasedOnCoefficient}
-  //             showIcon={showIcon}
-  //             correctValue={answers[i]}
-  //           />
-  //         </div>
-  //       );
-  //     } else if (question.answerParts[i] == "wedge angle") {
-  //       this.updateReviewForcesBasedOnAngle(0);
-  //       answerInput.push(
-  //         <div key={i + d.getTime()}>
-  //           <InputField
-  //             label={<Box>&theta;</Box>}
-  //             lowerBound={0}
-  //             dataDoc={this.dataDoc}
-  //             prop={'wedgeAngle'}
-  //             step={1}
-  //             unit={"°"}
-  //             upperBound={49}
-  //             value={this.dataDoc.wedgeAngle}
-  //             effect={(val: number) => {
-  //               this.changeWedgeBasedOnNewAngle(val);
-  //               this.updateReviewForcesBasedOnAngle(val);
-  //             }}
-  //             radianEquivalent={true}
-  //             showIcon={showIcon}
-  //             correctValue={answers[i]}
-  //           />
-  //         </div>
-  //       );
-  //     }
-  //   }
+  // Generate answerInputFields for new review question
+  generateInputFieldsForQuestion = (
+    showIcon: boolean = false,
+    question: QuestionTemplate = this.dataDoc.selectedQuestion,
+    answers: number[] = this.dataDoc.selectedSolutions
+  ) => {
+    let answerInput = [];
+    const d = new Date();
+    for (let i = 0; i < question.answerParts.length; i++) {
+      if (question.answerParts[i] == "force of gravity") {
+        this.dataDoc.reviewGravityMagnitude = (0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={<p>Gravity magnitude</p>}
+              lowerBound={0}
+              dataDoc={this.dataDoc}
+              prop={'reviewGravityMagnitude'}
+              step={0.1}
+              unit={"N"}
+              upperBound={50}
+              value={this.dataDoc.reviewGravityMagnitude}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+              labelWidth={"7em"}
+            />
+          </div>
+        );
+      } else if (question.answerParts[i] == "angle of gravity") {
+        this.dataDoc.reviewGravityAngle = (0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={<p>Gravity angle</p>}
+              lowerBound={0}
+              dataDoc={this.dataDoc}
+              prop={'reviewGravityAngle'}
+              step={1}
+              unit={"°"}
+              upperBound={360}
+              value={this.dataDoc.reviewGravityAngle}
+              radianEquivalent={true}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+              labelWidth={"7em"}
+            />
+          </div>
+        );
+      } else if (question.answerParts[i] == "normal force") {
+        this.dataDoc.reviewNormalMagnitude = (0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={<p>Normal force magnitude</p>}
+              lowerBound={0}
+              dataDoc={this.dataDoc}
+              prop={'reviewNormalMagnitude'}
+              step={0.1}
+              unit={"N"}
+              upperBound={50}
+              value={this.dataDoc.reviewNormalMagnitude}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+              labelWidth={"7em"}
+            />
+          </div>
+        );
+      } else if (question.answerParts[i] == "angle of normal force") {
+        this.dataDoc.reviewNormalAngle = (0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={<p>Normal force angle</p>}
+              lowerBound={0}
+              dataDoc={this.dataDoc}
+              prop={'reviewNormalAngle'}
+              step={1}
+              unit={"°"}
+              upperBound={360}
+              value={this.dataDoc.reviewNormalAngle}
+              radianEquivalent={true}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+              labelWidth={"7em"}
+            />
+          </div>
+        );
+      } else if (question.answerParts[i] == "force of static friction") {
+        this.dataDoc.reviewStaticMagnitude = (0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={<p>Static friction magnitude</p>}
+              lowerBound={0}
+              dataDoc={this.dataDoc}
+              prop={'reviewStaticMagnitude'}
+              step={0.1}
+              unit={"N"}
+              upperBound={50}
+              value={this.dataDoc.reviewStaticMagnitude}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+              labelWidth={"7em"}
+            />
+          </div>
+        );
+      } else if (question.answerParts[i] == "angle of static friction") {
+        this.dataDoc.reviewStaticAngle = (0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={<p>Static friction angle</p>}
+              lowerBound={0}
+              dataDoc={this.dataDoc}
+              prop={'reviewStaticAngle'}
+              step={1}
+              unit={"°"}
+              upperBound={360}
+              value={this.dataDoc.reviewStaticAngle}
+              radianEquivalent={true}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+              labelWidth={"7em"}
+            />
+          </div>
+        );
+      } else if (question.answerParts[i] == "coefficient of static friction") {
+        this.updateReviewForcesBasedOnCoefficient(0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={
+                <Box>
+                  &mu;<sub>s</sub>
+                </Box>
+              }
+              lowerBound={0}
+              dataDoc={this.dataDoc}
+              prop={'coefficientOfStaticFriction'}
+              step={0.1}
+              unit={""}
+              upperBound={1}
+              value={this.dataDoc.coefficientOfStaticFriction}
+              effect={this.updateReviewForcesBasedOnCoefficient}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+            />
+          </div>
+        );
+      } else if (question.answerParts[i] == "wedge angle") {
+        this.updateReviewForcesBasedOnAngle(0);
+        answerInput.push(
+          <div key={i + d.getTime()}>
+            <InputField
+              label={<Box>&theta;</Box>}
+              lowerBound={0}
+              dataDoc={this.dataDoc}
+              prop={'wedgeAngle'}
+              step={1}
+              unit={"°"}
+              upperBound={49}
+              value={this.dataDoc.wedgeAngle}
+              effect={(val: number) => {
+                this.changeWedgeBasedOnNewAngle(val);
+                this.updateReviewForcesBasedOnAngle(val);
+              }}
+              radianEquivalent={true}
+              showIcon={showIcon}
+              correctValue={answers[i]}
+            />
+          </div>
+        );
+      }
+    }
 
-  //   this.dataDoc.answerInputFields = (
-  //     <div
-  //       style={{ display: "flex", flexDirection: "column", alignItems: "left" }}
-  //     >
-  //       {answerInput}
-  //     </div>
-  //   );
-  // };
+    this.dataDoc.answerInputFields = (
+      <div
+        style={{ display: "flex", flexDirection: "column", alignItems: "left" }}
+      >
+        {answerInput}
+      </div>
+    );
+  };
   
   // Default setup for uniform circular motion simulation
   setupCircular = (value: number) => {
@@ -1465,7 +1465,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
             </select>
           </div>
         </div>
-        {/* {this.dataDoc.mode == "Review" && this.dataDoc.simulationType != "Inclined Plane" && (
+        {this.dataDoc.mode == "Review" && this.dataDoc.simulationType != "Inclined Plane" && (
           <div className="wordProblemBox">
             <p>{this.dataDoc.simulationType} review problems in progress!</p>
           </div>
@@ -1479,8 +1479,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 }}
                 sx={{
                   position: "fixed",
-                  left: xMax - 50 + "px",
-                  top: yMin + 14 + "px",
+                  left: this.xMax - 50 + "px",
+                  top: this.yMin + 14 + "px",
                 }}
               >
                 <QuestionMarkIcon />
@@ -1529,8 +1529,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               <div className="answer">{this.dataDoc.answerInputFields}</div>
             </div>
           </div>
-        )} */}
-        {/* {this.dataDoc.mode == "Tutorial" && (
+        )}
+        {this.dataDoc.mode == "Tutorial" && (
           <div className="wordProblemBox">
             <div className="question">
               <h2>Problem</h2>
@@ -1674,8 +1674,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               )}
             </div>
           </div>
-        )} */}
-        {/* {this.dataDoc.mode == "Review" && this.dataDoc.simulationType == "Inclined Plane" && (
+        )}
+        {this.dataDoc.mode == "Review" && this.dataDoc.simulationType == "Inclined Plane" && (
           <div
             style={{
               display: "flex",
@@ -1713,7 +1713,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               </Button>
             </div>
           </div>
-        )} */}
+        )}
         {this.dataDoc.mode == "Freeform" && (
           <div className="vars">
             <FormControl component="fieldset">
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 8369a994a..b973d30c8 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -1,6 +1,5 @@
 import { Doc } from '../../../../fields/Doc';
 import React = require('react');
-import { IWallProps } from "./PhysicsSimulationWall";
 import "./PhysicsSimulationBox.scss";
 
 interface IWallProps {
@@ -242,45 +241,45 @@ export default class Weight extends React.Component<IWeightProps, IState> {
       this.setDisplayValues();
     }
 
-    // // Make sure weight doesn't go above max height 
-    // if (prevState.updatedStartPosY != this.state.updatedStartPosY || prevProps.startVelY != this.props.startVelY) {
-    //   if (this.props.dataDoc['simulationType'] == "One Weight") {
-    //     let maxYPos = this.state.updatedStartPosY;
-    //     if (this.props.startVelY != 0) {
-    //       maxYPos -= (this.props.startVelY * this.props.startVelY) / (2 * Math.abs(this.props.gravity));
-    //     }
-    //     if (maxYPos < 0) {
-    //       maxYPos = 0;
-    //     }
-    //     this.setState({maxPosYConservation: maxYPos})
-    //   }
-    // }
+    // Make sure weight doesn't go above max height 
+    if ((prevState.updatedStartPosY != this.state.updatedStartPosY || prevProps.startVelY != this.props.startVelY) && !isNaN(this.state.updatedStartPosY) && !isNaN(this.props.startVelY)){
+      if (this.props.dataDoc['simulationType'] == "One Weight") {
+        let maxYPos = this.state.updatedStartPosY;
+        if (this.props.startVelY != 0) {
+          maxYPos -= (this.props.startVelY * this.props.startVelY) / (2 * Math.abs(this.props.gravity));
+        }
+        if (maxYPos < 0) {
+          maxYPos = 0;
+        }
+        this.setState({maxPosYConservation: maxYPos})
+      }
+    }
 
     // Check for collisions and update
     if (!this.props.paused) {
-    if (prevState.timer != this.state.timer) {
-      if (!this.props.noMovement) {
-        let collisions = false;
-        if (
-          this.props.dataDoc['simulationType'] == "One Weight" ||
-          this.props.dataDoc['simulationType'] == "Inclined Plane"
-        ) {
-          const collisionsWithGround = this.checkForCollisionsWithGround();
-          const collisionsWithWalls = this.checkForCollisionsWithWall();
-          collisions = collisionsWithGround || collisionsWithWalls;
-        }
-        if (this.props.dataDoc['simulationType'] == "Pulley") {
-          if (this.state.yPosition <= this.props.yMin + 100 || this.state.yPosition >= this.props.yMax - 100) {
-            collisions = true;
+      if (prevState.timer != this.state.timer) {
+        if (!this.props.noMovement) {
+          let collisions = false;
+          if (
+            this.props.dataDoc['simulationType'] == "One Weight" ||
+            this.props.dataDoc['simulationType'] == "Inclined Plane"
+          ) {
+            const collisionsWithGround = this.checkForCollisionsWithGround();
+            const collisionsWithWalls = this.checkForCollisionsWithWall();
+            collisions = collisionsWithGround || collisionsWithWalls;
           }
+          if (this.props.dataDoc['simulationType'] == "Pulley") {
+            if (this.state.yPosition <= this.props.yMin + 100 || this.state.yPosition >= this.props.yMax - 100) {
+              collisions = true;
+            }
+          }
+          if (!collisions) {
+            this.update();
+          }
+          this.setDisplayValues();
         }
-        if (!collisions) {
-          this.update();
-        }
-        this.setDisplayValues();
       }
     }
-    }
 
     // Reset everything on reset button click
     if (prevProps.reset != this.props.reset) {
-- 
cgit v1.2.3-70-g09d2


From 743cf203720ccfa89a48095ef26858a3ee2b4622 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Wed, 3 May 2023 17:41:50 -0400
Subject: styling

---
 src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss | 2 +-
 src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx  | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
index 2e16417f5..7193e3157 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
@@ -11,7 +11,7 @@
 
  .mechanicsSimulationEquationContainer {
    position: fixed;
-   left: 70%;
+   left: 60%;
    padding: 1em;
 
    .mechanicsSimulationControls {
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 9caf41445..b24591a0d 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -111,7 +111,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.layoutDoc._height = 800;
     this.xMax = this.layoutDoc._width*0.6;
     this.yMax = this.layoutDoc._height*0.9;
-    this.radius = 100;
+    this.radius = 75;
     this.dataDoc.reviewCoefficient = this.dataDoc.reviewCoefficient ?? 0;
     this.dataDoc.questionVariables = this.dataDoc.questionVariables ?? [];
     this.dataDoc.accelerationXDisplay = this.dataDoc.accelerationXDisplay ?? 0;
@@ -219,7 +219,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   componentDidUpdate() {
     this.xMax = this.layoutDoc._width*0.6;
     this.yMax = this.layoutDoc._height*0.9;
-    this.radius = 0.1*this.layoutDoc._height ?? 100;
+    this.radius = 0.9*this.layoutDoc._height ?? 75;
   }
 
   setupSimulation = (simulationType: string, mode: string) => {
-- 
cgit v1.2.3-70-g09d2


From b904681b9b417220e5e350f935b70a98f15ba41c Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Thu, 4 May 2023 00:13:05 -0400
Subject: debug issue with projectile forces

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 43 ++++++++++++----------
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   | 15 +++++---
 2 files changed, 32 insertions(+), 26 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index b24591a0d..7efb8b73a 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -111,7 +111,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.layoutDoc._height = 800;
     this.xMax = this.layoutDoc._width*0.6;
     this.yMax = this.layoutDoc._height*0.9;
-    this.radius = 75;
+    this.radius = 60;
     this.dataDoc.reviewCoefficient = this.dataDoc.reviewCoefficient ?? 0;
     this.dataDoc.questionVariables = this.dataDoc.questionVariables ?? [];
     this.dataDoc.accelerationXDisplay = this.dataDoc.accelerationXDisplay ?? 0;
@@ -217,9 +217,12 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   }
 
   componentDidUpdate() {
-    this.xMax = this.layoutDoc._width*0.6;
-    this.yMax = this.layoutDoc._height*0.9;
-    this.radius = 0.9*this.layoutDoc._height ?? 75;
+    if (this.xMax != this.layoutDoc._width*0.6 || this.yMax != this.layoutDoc._height*0.9) {
+      this.xMax = this.layoutDoc._width*0.6;
+      this.yMax = this.layoutDoc._height*0.9;
+      this.radius = 0.08*this.layoutDoc._height ?? 60;
+      this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+    }
   }
 
   setupSimulation = (simulationType: string, mode: string) => {
@@ -237,7 +240,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
         this.dataDoc.startPosY = (this.yMin + this.radius);
         this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
         this.dataDoc.positionYDisplay = (this.getDisplayYPos(this.yMin + this.radius));
-        this.dataDoc.positionXDisplay((this.xMax + this.xMin) / 2 - this.radius);
+        this.dataDoc.positionXDisplay = ((this.xMax + this.xMin) / 2 - this.radius);
         this.dataDoc.updatedForces = ([
           {
             description: "Gravity",
@@ -1001,7 +1004,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               step={1}
               unit={"°"}
               upperBound={49}
-              value={this.dataDoc.wedgeAngle}
+              value={this.dataDoc.wedgeAngle ?? 26}
               effect={(val: number) => {
                 this.changeWedgeBasedOnNewAngle(val);
                 this.updateReviewForcesBasedOnAngle(val);
@@ -1785,7 +1788,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   step={1}
                   unit={"x"}
                   upperBound={10}
-                  value={this.dataDoc.simulationSpeed}
+                  value={this.dataDoc.simulationSpeed ?? 2}
                   labelWidth={"5em"}
                 />
                 {this.dataDoc.simulationPaused && this.dataDoc.simulationType != "Circular Motion" && (
@@ -1797,7 +1800,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     step={0.01}
                     unit={"m/s2"}
                     upperBound={0}
-                    value={this.dataDoc.gravity}
+                    value={this.dataDoc.gravity ?? -9.81}
                     effect={(val: number) => {
                       this.dataDoc.resetAll = (!this.dataDoc.resetAll);
                     }}
@@ -1813,7 +1816,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     step={0.1}
                     unit={"kg"}
                     upperBound={5}
-                    value={this.dataDoc.mass}
+                    value={this.dataDoc.mass ?? 1}
                     effect={(val: number) => {
                       this.dataDoc.resetAll = (!this.dataDoc.resetAll);
                     }}
@@ -1829,7 +1832,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     step={0.1}
                     unit={"kg"}
                     upperBound={5}
-                    value={this.dataDoc.mass}
+                    value={this.dataDoc.mass ?? 1}
                     effect={(val: number) => {
                       this.dataDoc.resetAll = (!this.dataDoc.resetAll);
                     }}
@@ -1845,7 +1848,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     step={0.1}
                     unit={"kg"}
                     upperBound={5}
-                    value={this.dataDoc.mass2}
+                    value={this.dataDoc.mass2 ?? 1}
                     effect={(val: number) => {
                       this.dataDoc.resetAll = (!this.dataDoc.resetAll);
                     }}
@@ -1859,9 +1862,9 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     dataDoc={this.dataDoc}
                     prop={'circularMotionRadius'}
                     step={5}
-                    unit={"kg"}
+                    unit={"m"}
                     upperBound={250}
-                    value={this.dataDoc.circularMotionRadius}
+                    value={this.dataDoc.circularMotionRadius ?? 100}
                     effect={(val: number) => {
                       this.dataDoc.resetAll = (!this.dataDoc.resetAll);
                     }}
@@ -1882,7 +1885,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   step={1}
                   unit={"N/m"}
                   upperBound={500}
-                  value={this.dataDoc.springConstant}
+                  value={this.dataDoc.springConstant ?? 0.5}
                   effect={(val: number) => {
                     this.dataDoc.simulationReset(!this.dataDoc.simulationReset);
                   }}
@@ -1898,7 +1901,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   step={100}
                   unit={""}
                   upperBound={500}
-                  value={this.dataDoc.springRestLength}
+                  value={this.dataDoc.springRestLength ?? 200}
                   effect={(val: number) => {
                     this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
                   }}
@@ -1918,7 +1921,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   step={10}
                   unit={""}
                   upperBound={this.dataDoc.springRestLength}
-                  value={this.dataDoc.springStartLength - this.dataDoc.springRestLength}
+                  value={this.dataDoc.springStartLength - this.dataDoc.springRestLength ?? 0}
                   effect={(val: number) => {
                     this.dataDoc.startPosY = (this.dataDoc.springRestLength + val);
                     this.dataDoc.springStartLength = (this.dataDoc.springRestLength + val);
@@ -1940,7 +1943,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   step={1}
                   unit={"°"}
                   upperBound={49}
-                  value={this.dataDoc.wedgeAngle}
+                  value={this.dataDoc.wedgeAngle ?? 26}
                   effect={(val: number) => {
                     this.changeWedgeBasedOnNewAngle(val);
                     this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
@@ -1961,7 +1964,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   step={0.1}
                   unit={""}
                   upperBound={1}
-                  value={this.dataDoc.coefficientOfStaticFriction}
+                  value={this.dataDoc.coefficientOfStaticFriction ?? 0}
                   effect={(val: number) => {
                     this.updateForcesWithFriction(val);
                     if (val < Number(this.dataDoc.coefficientOfKineticFriction)) {
@@ -1984,7 +1987,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   step={0.1}
                   unit={""}
                   upperBound={Number(this.dataDoc.coefficientOfStaticFriction)}
-                  value={this.dataDoc.coefficientOfKineticFriction}
+                  value={this.dataDoc.coefficientOfKineticFriction ?? 0}
                   effect={(val: number) => {
                     this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
                   }}
@@ -2022,7 +2025,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                   step={1}
                   unit={"°"}
                   upperBound={59}
-                  value={this.dataDoc.pendulumAngle}
+                  value={this.dataDoc.pendulumAngle ?? 30}
                   effect={(value) => {
                     this.dataDoc.startPendulumAngle = (value);
                     if (this.dataDoc.simulationType == "Pendulum") {
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index b973d30c8..7407d6fa6 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -919,6 +919,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         className="weightContainer"
         onPointerDown={(e) => {
           if (this.draggable) {
+            console.log('dragging = true')
             this.props.dataDoc['paused'] = true;
             this.setState({dragging: true});
             this.setState({clickPositionX: e.clientX});
@@ -927,6 +928,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         }}
         onPointerMove={(e) => {
           if (this.state.dragging) {
+            console.log('dragging')
             let newY = this.state.yPosition + e.clientY - this.state.clickPositionY;
             if (newY > this.props.yMax - 2 * this.props.radius - 10) {
               newY = this.props.yMax - 2 * this.props.radius - 10;
@@ -968,6 +970,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         }}
         onPointerUp={(e) => {
           if (this.state.dragging) {
+            console.log('dragging = false')
             if (
               this.props.dataDoc['simulationType'] != "Pendulum" &&
               this.props.dataDoc['simulationType'] != "Suspension"
@@ -1339,7 +1342,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 position: "absolute",
                 left: this.state.xPosition + this.props.radius + this.state.xAccel * 3 + 25 + "px",
                 top: this.state.yPosition + this.props.radius + this.state.yAccel * 3 + 70 + "px",
-                lineHeight: 0.5,
+                lineHeight: 1,
               }}
             >
               <p>
@@ -1393,7 +1396,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 position: "absolute",
                 left: this.state.xPosition + this.props.radius + this.state.xVelocity * 3 + 25 + "px",
                 top: this.state.yPosition +  this.props.radius + this.state.yVelocity * 3 + "px",
-                lineHeight: 0.5,
+                lineHeight: 1,
               }}
             >
               <p>
@@ -1506,7 +1509,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                   position: "absolute",
                   left: labelLeft + "px",
                   top: labelTop + "px",
-                  lineHeight: 0.5,
+                  lineHeight: 1,
                   backgroundColor: this.labelBackgroundColor,
                 }}
               >
@@ -1519,7 +1522,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             </div>
           );
         })}
-      {/* {!this.state.dragging &&
+      {!this.state.dragging &&
         this.props.showForces && this.props.updatedForces &&
         this.props.updatedForces.map((force, index) => {
           if (force.magnitude < this.epsilon) {
@@ -1615,7 +1618,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                   position: "absolute",
                   left: labelLeft + "px",
                   top: labelTop + "px",
-                  lineHeight: 0.5,
+                  lineHeight: 1,
                   backgroundColor: this.labelBackgroundColor,
                 }}
               >
@@ -1627,7 +1630,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
               </div>
             </div>
           );
-        })} */}
+        })}
     </div>
   )}
 };
-- 
cgit v1.2.3-70-g09d2


From 6c1143b27293f22ef4c21ac53c6bdbda381ee09d Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Thu, 4 May 2023 10:39:00 -0400
Subject: debugging change size

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 95 +++++++---------------
 .../PhysicsBox/PhysicsSimulationInputField.tsx     |  4 +-
 2 files changed, 33 insertions(+), 66 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 7efb8b73a..53e1cd15f 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -111,7 +111,6 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.layoutDoc._height = 800;
     this.xMax = this.layoutDoc._width*0.6;
     this.yMax = this.layoutDoc._height*0.9;
-    this.radius = 60;
     this.dataDoc.reviewCoefficient = this.dataDoc.reviewCoefficient ?? 0;
     this.dataDoc.questionVariables = this.dataDoc.questionVariables ?? [];
     this.dataDoc.accelerationXDisplay = this.dataDoc.accelerationXDisplay ?? 0;
@@ -137,7 +136,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.startForces = this.dataDoc.startForces ?? [];
     this.dataDoc.startPosX = this.dataDoc.startPosX ?? Math.round((this.xMax * 0.5 - 200) * 10) / 10;
     this.dataDoc.startPosY = this.dataDoc.startPosY ?? this.getDisplayYPos(
-      (400 - this.radius) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26)
+      (400 - (0.08*this.layoutDoc._height)) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26)
     );
     this.dataDoc.startVelX = this.dataDoc.startVelX ?? 0;
     this.dataDoc.startVelY = this.dataDoc.startVelY ?? 0;
@@ -187,8 +186,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.coefficientOfKineticFriction = this.dataDoc.coefficientOfKineticFriction ?? 0;
     this.dataDoc.coefficientOfStaticFriction = this.dataDoc.coefficientOfStaticFriction ?? 0;
     this.dataDoc.wedgeAngle = this.dataDoc.wedgeAngle ?? 26;
-    this.dataDoc.wedgeHeight = this.dataDoc.wedgeHeight ?? Math.tan((26 * Math.PI) / 180) * 400;
-    this.dataDoc.wedgeWidth = this.dataDoc.wedgeWidth ?? 400;
+    this.dataDoc.wedgeHeight = this.dataDoc.wedgeHeight ?? Math.tan((26 * Math.PI) / 180) * this.xMax*0.5;
+    this.dataDoc.wedgeWidth = this.dataDoc.wedgeWidth ?? this.xMax*0.5;
 
     // Used for pulley simulation
     this.dataDoc.positionXDisplay2 = this.dataDoc.positionXDisplay2 ?? 0;
@@ -220,9 +219,10 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     if (this.xMax != this.layoutDoc._width*0.6 || this.yMax != this.layoutDoc._height*0.9) {
       this.xMax = this.layoutDoc._width*0.6;
       this.yMax = this.layoutDoc._height*0.9;
-      this.radius = 0.08*this.layoutDoc._height ?? 60;
-      this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+      this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
+      console.log('reset sim')
     }
+    console.log('update')
   }
 
   setupSimulation = (simulationType: string, mode: string) => {
@@ -237,10 +237,10 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       this.dataDoc.showForceMagnitudes = (true);
       if (simulationType == "One Weight") {
         this.dataDoc.showComponentForces = false;
-        this.dataDoc.startPosY = (this.yMin + this.radius);
-        this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
-        this.dataDoc.positionYDisplay = (this.getDisplayYPos(this.yMin + this.radius));
-        this.dataDoc.positionXDisplay = ((this.xMax + this.xMin) / 2 - this.radius);
+        this.dataDoc.startPosY = (this.yMin + (0.08*this.layoutDoc._height));
+        this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - (0.08*this.layoutDoc._height));
+        this.dataDoc.positionYDisplay = (this.getDisplayYPos(this.yMin + (0.08*this.layoutDoc._height)));
+        this.dataDoc.positionXDisplay = ((this.xMax + this.xMin) / 2 - (0.08*this.layoutDoc._height));
         this.dataDoc.updatedForces = ([
           {
             description: "Gravity",
@@ -325,7 +325,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       if (this.dataDoc.simulationType == "One Weight") {
         this.dataDoc.showForces = (true);
         this.dataDoc.startPosY = (this.yMax - 100);
-        this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
+        this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - (0.08*this.layoutDoc._height));
         this.dataDoc.selectedTutorial = (tutorials.freeWeight);
         this.dataDoc.startForces = (this.getForceFromJSON(tutorials.freeWeight.steps[0].forces));
         this.dataDoc.showForceMagnitudes = (tutorials.freeWeight.steps[0].showMagnitude);
@@ -333,7 +333,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
         this.dataDoc.showForces = (true);
         this.setupSpring();
         this.dataDoc.startPosY = (this.yMin + 200 + 19.62);
-        this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - this.radius);
+        this.dataDoc.startPosX = ((this.xMax + this.xMin) / 2 - (0.08*this.layoutDoc._height));
         this.dataDoc.selectedTutorial = (tutorials.spring);
         this.dataDoc.startForces = (this.getForceFromJSON(tutorials.spring.steps[0].forces));
         this.dataDoc.showForceMagnitudes = (tutorials.spring.steps[0].showMagnitude);
@@ -343,8 +343,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
         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 - this.radius;
-        const yPos = y - this.radius - 5;
+        const xPos = this.xMax / 2 - x - (0.08*this.layoutDoc._height);
+        const yPos = y - (0.08*this.layoutDoc._height) - 5;
         this.dataDoc.startPosX = (xPos);
         this.dataDoc.startPosY = (yPos);
         this.dataDoc.selectedTutorial = (tutorials.pendulum);
@@ -387,10 +387,10 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
 
   // Helper function to go between display and real values
   getDisplayYPos = (yPos: number) => {
-    return this.yMax - yPos - 2 * this.radius + 5;
+    return this.yMax - yPos - 2 * (0.08*this.layoutDoc._height) + 5;
   };
   getYPosFromDisplay = (yDisplay: number) => {
-    return this.yMax - yDisplay - 2 * this.radius + 5;
+    return this.yMax - yDisplay - 2 * (0.08*this.layoutDoc._height) + 5;
   };
 
   // Update forces when coefficient of static friction changes in freeform mode
@@ -492,49 +492,14 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
 
   // Change wedge height and width and weight position to match new wedge angle
   changeWedgeBasedOnNewAngle = (angle: number) => {
-    let width = 0;
-    let height = 0;
-    if (angle < 50) {
-      width = 400;
-      height = Math.tan((angle * Math.PI) / 180) * 400;
-      this.dataDoc.wedgeWidth = width;
-      this.dataDoc.wedgeHeight = height;
-    } else if (angle < 70) {
-      width = 200;
-      height = Math.tan((angle * Math.PI) / 180) * 200;
-      this.dataDoc.wedgeWidth = width;
-      this.dataDoc.wedgeHeight = height;
-    } else {
-      width = 100;
-      height = Math.tan((angle * Math.PI) / 180) * 100;
-      this.dataDoc.wedgeWidth = width;
-      this.dataDoc.wedgeHeight = height;
-    }
+    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 = (width - this.radius) * Math.tan((angle * Math.PI) / 180);
-    if (angle < 40) {
-      yPos += Math.sqrt(angle);
-    } else if (angle < 58) {
-      yPos += angle / 2;
-    } else if (angle < 68) {
-      yPos += angle;
-    } else if (angle < 70) {
-      yPos += angle * 1.3;
-    } else if (angle < 75) {
-      yPos += angle * 1.5;
-    } else if (angle < 78) {
-      yPos += angle * 2;
-    } else if (angle < 79) {
-      yPos += angle * 2.25;
-    } else if (angle < 80) {
-      yPos += angle * 2.6;
-    } else {
-      yPos += angle * 3;
-    }
-
+    let yPos = this.yMax - (0.08*this.layoutDoc._height) - Math.tan((angle * Math.PI) / 180) * this.xMax*0.5;
+    
     this.dataDoc.startPosX = Math.round((this.xMax * 0.5 - 200) * 10) / 10;
-    this.dataDoc.startPosY = this.getDisplayYPos(yPos);
+    this.dataDoc.startPosY = yPos;
     if (this.dataDoc.mode == "Freeform") {
       this.updateForcesWithFriction(
         Number(this.dataDoc.coefficientOfStaticFriction),
@@ -1032,8 +997,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.showComponentForces = (false);
     this.dataDoc.startVelY = (0);
     this.dataDoc.startVelX = (value);
-    let xPos = (this.xMax + this.xMin) / 2 - this.radius;
-    let yPos = (this.yMax + this.yMin) / 2 + this.dataDoc.circularMotionRadius - this.radius;
+    let xPos = (this.xMax + this.xMin) / 2 - (0.08*this.layoutDoc._height);
+    let yPos = (this.yMax + this.yMin) / 2 + this.dataDoc.circularMotionRadius - (0.08*this.layoutDoc._height);
     this.dataDoc.startPosY = (yPos);
     this.dataDoc.startPosX = (xPos);
     const tensionForce: IForce = {
@@ -1053,8 +1018,8 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     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 - this.radius;
-    const yPos = y - this.radius - 5;
+    const xPos = this.xMax / 2 - x - (0.08*this.layoutDoc._height);
+    const yPos = y - (0.08*this.layoutDoc._height) - 5;
     this.dataDoc.startPosX = (xPos);
     this.dataDoc.startPosY = (yPos);
     const mag = this.dataDoc.mass * Math.abs(this.dataDoc.gravity) * Math.sin((60 * Math.PI) / 180);
@@ -1126,7 +1091,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     };
     this.dataDoc.updatedForces = ([gravityForce]);
     this.dataDoc.startForces = ([gravityForce]);
-    this.dataDoc.startPosX = (this.xMax / 2 - this.radius);
+    this.dataDoc.startPosX = (this.xMax / 2 - (0.08*this.layoutDoc._height));
     this.dataDoc.startPosY = (200);
     this.dataDoc.springConstant = (0.5);
     this.dataDoc.springRestLength = (200);
@@ -1136,7 +1101,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
 
   // Default setup for suspension simulation
   setupSuspension = () => {
-    let xPos = (this.xMax + this.xMin) / 2 - this.radius;
+    let xPos = (this.xMax + this.xMin) / 2 - (0.08*this.layoutDoc._height);
     let yPos = this.yMin + 200;
     this.dataDoc.startPosY = (yPos);
     this.dataDoc.startPosX = (xPos);
@@ -1199,6 +1164,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       directionInDegrees: 90,
       component: false,
     };
+
     this.dataDoc.updatedForces = ([gravityForce1, tensionForce1]);
     this.dataDoc.startForces = ([gravityForce1, tensionForce1]);
     this.dataDoc.startPosY2 = ((this.yMax + this.yMin) / 2);
@@ -1207,6 +1173,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.positionXDisplay2 = ((this.xMin + this.xMax) / 2 + 5);
     this.dataDoc.updatedForces2 = ([gravityForce2, tensionForce2]);
     this.dataDoc.startForces2 = ([gravityForce2, tensionForce2]);
+    
     this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
   };
 
@@ -1308,7 +1275,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
               paused={this.dataDoc.simulationPaused}
               pendulumAngle={this.dataDoc.pendulumAngle}
               pendulumLength={this.dataDoc.pendulumLength}
-              radius={this.radius}
+              radius={(0.08*this.layoutDoc._height)}
               reset={this.dataDoc.simulationReset}
               simulationSpeed={this.dataDoc.simulationSpeed}
               startPendulumAngle={this.dataDoc.startPendulumAngle}
@@ -1358,7 +1325,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 paused={this.dataDoc.simulationPaused}
                 pendulumAngle={this.dataDoc.pendulumAngle}
                 pendulumLength={this.dataDoc.pendulumLength}
-                radius={this.radius}
+                radius={(0.08*this.layoutDoc._height)}
                 reset={this.dataDoc.simulationReset}
                 simulationSpeed={this.dataDoc.simulationSpeed}
                 startPendulumAngle={this.dataDoc.startPendulumAngle}
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
index 85c20760e..3386bfd1c 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
@@ -44,10 +44,10 @@ export default class InputField extends React.Component<IInputProps, IState> {
   epsilon: number = 0.01;
 
   componentDidUpdate(prevProps: Readonly<IInputProps>, prevState: Readonly<IState>, snapshot?: any): void {
-    if (prevProps.value != this.props.value) {
+    if (prevProps.value != this.props.value && !isNaN(this.props.value)) {
       if (this.props.mode == "Freeform") {
         if (Math.abs(this.state.tempValue - Number(this.props.value)) > 1) {
-          console.log('update temp value')
+          console.log('update temp value', Number(this.props.value))
           this.setState({tempValue: Number(this.props.value)})
         }
       }
-- 
cgit v1.2.3-70-g09d2


From 346fab5afab9c7c994c2e4dbed6b18d3895ec966 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Thu, 4 May 2023 10:44:54 -0400
Subject: debugging change size

---
 src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 53e1cd15f..c7bf155cb 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -496,15 +496,15 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     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._height) - Math.tan((angle * Math.PI) / 180) * this.xMax*0.5;
+    let yPos = this.yMax - (0.08*this.layoutDoc._height*1.2) - Math.tan((angle * Math.PI) / 180) * this.xMax*0.5;
     
-    this.dataDoc.startPosX = Math.round((this.xMax * 0.5 - 200) * 10) / 10;
+    this.dataDoc.startPosX = this.xMax*0.25;
     this.dataDoc.startPosY = yPos;
     if (this.dataDoc.mode == "Freeform") {
       this.updateForcesWithFriction(
         Number(this.dataDoc.coefficientOfStaticFriction),
-        width,
-        height
+        this.xMax*0.5,
+        Math.tan((angle * Math.PI) / 180) * this.xMax*0.5
       );
     }
   };
-- 
cgit v1.2.3-70-g09d2


From d980b13b7e161b68af0eb0f47cdac63e891f86b5 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Thu, 4 May 2023 11:30:17 -0400
Subject: adjust incline plane position

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index c7bf155cb..cf873da1d 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -217,12 +217,12 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
 
   componentDidUpdate() {
     if (this.xMax != this.layoutDoc._width*0.6 || this.yMax != this.layoutDoc._height*0.9) {
+      this.layoutDoc._width = Math.max(this.layoutDoc._width, 800)
+      this.layoutDoc._height = Math.max(this.layoutDoc._height, 600)
       this.xMax = this.layoutDoc._width*0.6;
       this.yMax = this.layoutDoc._height*0.9;
       this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
-      console.log('reset sim')
     }
-    console.log('update')
   }
 
   setupSimulation = (simulationType: string, mode: string) => {
@@ -496,9 +496,23 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     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._height*1.2) - Math.tan((angle * Math.PI) / 180) * this.xMax*0.5;
+    let yPos = this.yMax - (0.08*this.layoutDoc._height*2) - Math.tan((angle * Math.PI) / 180) * this.xMax*0.5;
+
+    // adjust y position
+    if (angle >= 5 && angle < 10) {
+      yPos += 0.08*this.layoutDoc._height*0.2
+    } else if (angle >= 10 && angle < 15) {
+      yPos += 0.08*this.layoutDoc._height*0.23
+    } else if (angle >= 15 && angle < 20) {
+      yPos += 0.08*this.layoutDoc._height*0.26
+    } else if (angle >= 20 && angle < 25) {
+      yPos += 0.08*this.layoutDoc._height*0.28
+    } else if (angle >=25 && angle < 40) {
+      yPos += 0.08*this.layoutDoc._height*0.3
+    } 
+    
     
-    this.dataDoc.startPosX = this.xMax*0.25;
+    this.dataDoc.startPosX = this.xMax*0.25-(0.08*this.layoutDoc._height);
     this.dataDoc.startPosY = yPos;
     if (this.dataDoc.mode == "Freeform") {
       this.updateForcesWithFriction(
-- 
cgit v1.2.3-70-g09d2


From 550d2d4b02bbaa19d6ca1b7f4d6146f4ed171bab Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Thu, 4 May 2023 11:36:18 -0400
Subject: pulley debugging

---
 src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx    | 10 +++++-----
 src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx |  6 +++---
 2 files changed, 8 insertions(+), 8 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index cf873da1d..db187d1b8 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -512,7 +512,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     } 
     
     
-    this.dataDoc.startPosX = this.xMax*0.25-(0.08*this.layoutDoc._height);
+    this.dataDoc.startPosX = this.xMax*0.25;
     this.dataDoc.startPosY = yPos;
     if (this.dataDoc.mode == "Freeform") {
       this.updateForcesWithFriction(
@@ -1149,9 +1149,9 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   setupPulley = () => {
     this.dataDoc.showComponentForces = (false);
     this.dataDoc.startPosY = ((this.yMax + this.yMin) / 2);
-    this.dataDoc.startPosX = ((this.xMin + this.xMax) / 2 - 105);
+    this.dataDoc.startPosX = ((this.xMin + this.xMax) / 2 - 2*(0.08*this.layoutDoc._height)-5);
     this.dataDoc.positionYDisplay = (this.getDisplayYPos((this.yMax + this.yMin) / 2));
-    this.dataDoc.positionXDisplay = ((this.xMin + this.xMax) / 2 - 105);
+    this.dataDoc.positionXDisplay = ((this.xMin + this.xMax) / 2 - 2*(0.08*this.layoutDoc._height)-5);
     let a = (-1 * ((this.dataDoc.mass - this.dataDoc.mass2) * Math.abs(this.dataDoc.gravity))) / (this.dataDoc.mass + this.dataDoc.mass2);
     const gravityForce1: IForce = {
       description: "Gravity",
@@ -1182,9 +1182,9 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.updatedForces = ([gravityForce1, tensionForce1]);
     this.dataDoc.startForces = ([gravityForce1, tensionForce1]);
     this.dataDoc.startPosY2 = ((this.yMax + this.yMin) / 2);
-    this.dataDoc.startPosX2 = ((this.xMin + this.xMax) / 2 + 5);
+    this.dataDoc.startPosX2 = ((this.xMin + this.xMax) / 2 + 5 + (0.08*this.layoutDoc._height));
     this.dataDoc.positionYDisplay2 = (this.getDisplayYPos((this.yMax + this.yMin) / 2));
-    this.dataDoc.positionXDisplay2 = ((this.xMin + this.xMax) / 2 + 5);
+    this.dataDoc.positionXDisplay2 = ((this.xMin + this.xMax) / 2 + 5 + (0.08*this.layoutDoc._height));
     this.dataDoc.updatedForces2 = ([gravityForce2, tensionForce2]);
     this.dataDoc.startForces2 = ([gravityForce2, tensionForce2]);
     
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 27f57070e..4e7d0e7e6 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -132,9 +132,9 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     display: "flex",
     height: 2 * this.props.radius + "px",
     justifyContent: "center",
-    left: this.props.dataDoc['startPosX'] + "px",
+    left: this.props.startPosX + "px",
     position: "absolute" as "absolute",
-    top: this.props.dataDoc['startPosY'] + "px",
+    top: this.props.startPosY + "px",
     touchAction: "none",
     width: 2 * this.props.radius + "px",
     zIndex: 5,
@@ -436,7 +436,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
 
     // Update wedge coordinates
     if (prevProps.wedgeWidth != this.props.wedgeWidth || prevProps.wedgeHeight != this.props.wedgeHeight) {
-      const left = this.props.xMax * 0.5 - 200;
+      const left = this.props.xMax * 0.25;
       const coordinatePair1 = Math.round(left) + "," + this.props.yMax + " ";
       const coordinatePair2 = Math.round(left + this.props.wedgeWidth) + "," + this.props.yMax + " ";
       const coordinatePair3 = Math.round(left) + "," + (this.props.yMax - this.props.wedgeHeight);
-- 
cgit v1.2.3-70-g09d2


From fbc3750dcfb124411965420bed6e04e36be18d09 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Thu, 4 May 2023 11:47:33 -0400
Subject: debug incline plane and pulley positioning

---
 .../views/nodes/PhysicsBox/PhysicsSimulationBox.tsx  | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index db187d1b8..58ea745ef 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -500,15 +500,23 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
 
     // adjust y position
     if (angle >= 5 && angle < 10) {
-      yPos += 0.08*this.layoutDoc._height*0.2
+      yPos += 0.08*this.layoutDoc._height*0.1
     } else if (angle >= 10 && angle < 15) {
       yPos += 0.08*this.layoutDoc._height*0.23
     } else if (angle >= 15 && angle < 20) {
       yPos += 0.08*this.layoutDoc._height*0.26
     } else if (angle >= 20 && angle < 25) {
-      yPos += 0.08*this.layoutDoc._height*0.28
-    } else if (angle >=25 && angle < 40) {
-      yPos += 0.08*this.layoutDoc._height*0.3
+      yPos += 0.08*this.layoutDoc._height*0.32
+    } else if (angle >= 25 && angle < 30) {
+      yPos += 0.08*this.layoutDoc._height*0.34
+    } else if (angle >= 30 && angle < 35) {
+      yPos += 0.08*this.layoutDoc._height*0.37
+    } else if (angle >= 35 && angle < 40) {
+      yPos += 0.08*this.layoutDoc._height*0.42
+    } else if (angle >= 40 && angle < 45) {
+      yPos += 0.08*this.layoutDoc._height*0.44
+    } else if (angle >= 45) {
+      yPos += 0.08*this.layoutDoc._height*0.46
     } 
     
     
@@ -1182,9 +1190,9 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.updatedForces = ([gravityForce1, tensionForce1]);
     this.dataDoc.startForces = ([gravityForce1, tensionForce1]);
     this.dataDoc.startPosY2 = ((this.yMax + this.yMin) / 2);
-    this.dataDoc.startPosX2 = ((this.xMin + this.xMax) / 2 + 5 + (0.08*this.layoutDoc._height));
+    this.dataDoc.startPosX2 = ((this.xMin + this.xMax) / 2 + 5 );
     this.dataDoc.positionYDisplay2 = (this.getDisplayYPos((this.yMax + this.yMin) / 2));
-    this.dataDoc.positionXDisplay2 = ((this.xMin + this.xMax) / 2 + 5 + (0.08*this.layoutDoc._height));
+    this.dataDoc.positionXDisplay2 = ((this.xMin + this.xMax) / 2 + 5);
     this.dataDoc.updatedForces2 = ([gravityForce2, tensionForce2]);
     this.dataDoc.startForces2 = ([gravityForce2, tensionForce2]);
     
-- 
cgit v1.2.3-70-g09d2


From bfc445334a5aeee27256ea59cb9f958ef844397d Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Thu, 4 May 2023 21:02:38 -0400
Subject: debug pulley

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 23 ++++-----
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   | 59 ++++++++++++++--------
 2 files changed, 50 insertions(+), 32 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 58ea745ef..695b0733d 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -123,7 +123,6 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.mode = this.dataDoc.mode ?? "Freeform";
     this.dataDoc.positionXDisplay = this.dataDoc.positionXDisplay ?? 0;
     this.dataDoc.positionYDisplay = this.dataDoc.positionYDisplay ?? 0;
-    this.dataDoc.resetAll = this.dataDoc.resetAll ?? true;
     this.dataDoc.showAcceleration = this.dataDoc.showAcceleration ?? false;
     this.dataDoc.showComponentForces = this.dataDoc.showComponentForces ?? false;
     this.dataDoc.showForces = this.dataDoc.showForces ?? true;
@@ -506,17 +505,17 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     } else if (angle >= 15 && angle < 20) {
       yPos += 0.08*this.layoutDoc._height*0.26
     } else if (angle >= 20 && angle < 25) {
-      yPos += 0.08*this.layoutDoc._height*0.32
+      yPos += 0.08*this.layoutDoc._height*0.33
     } else if (angle >= 25 && angle < 30) {
-      yPos += 0.08*this.layoutDoc._height*0.34
+      yPos += 0.08*this.layoutDoc._height*0.35
     } else if (angle >= 30 && angle < 35) {
-      yPos += 0.08*this.layoutDoc._height*0.37
+      yPos += 0.08*this.layoutDoc._height*0.40
     } else if (angle >= 35 && angle < 40) {
-      yPos += 0.08*this.layoutDoc._height*0.42
+      yPos += 0.08*this.layoutDoc._height*0.45
     } else if (angle >= 40 && angle < 45) {
-      yPos += 0.08*this.layoutDoc._height*0.44
+      yPos += 0.08*this.layoutDoc._height*0.47
     } else if (angle >= 45) {
-      yPos += 0.08*this.layoutDoc._height*0.46
+      yPos += 0.08*this.layoutDoc._height*0.52
     } 
     
     
@@ -1791,7 +1790,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     upperBound={0}
                     value={this.dataDoc.gravity ?? -9.81}
                     effect={(val: number) => {
-                      this.dataDoc.resetAll = (!this.dataDoc.resetAll);
+                      this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
                     }}
                     labelWidth={"5em"}
                   />
@@ -1807,7 +1806,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     upperBound={5}
                     value={this.dataDoc.mass ?? 1}
                     effect={(val: number) => {
-                      this.dataDoc.resetAll = (!this.dataDoc.resetAll);
+                      this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
                     }}
                     labelWidth={"5em"}
                   />
@@ -1823,7 +1822,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     upperBound={5}
                     value={this.dataDoc.mass ?? 1}
                     effect={(val: number) => {
-                      this.dataDoc.resetAll = (!this.dataDoc.resetAll);
+                      this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
                     }}
                     labelWidth={"5em"}
                   />
@@ -1839,7 +1838,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     upperBound={5}
                     value={this.dataDoc.mass2 ?? 1}
                     effect={(val: number) => {
-                      this.dataDoc.resetAll = (!this.dataDoc.resetAll);
+                      this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
                     }}
                     labelWidth={"5em"}
                   />
@@ -1855,7 +1854,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     upperBound={250}
                     value={this.dataDoc.circularMotionRadius ?? 100}
                     effect={(val: number) => {
-                      this.dataDoc.resetAll = (!this.dataDoc.resetAll);
+                      this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
                     }}
                     labelWidth={"5em"}
                   />
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 4e7d0e7e6..3ab78e339 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -151,16 +151,29 @@ export default class Weight extends React.Component<IWeightProps, IState> {
   // Set display values based on real values
   setYPosDisplay = (yPos: number) => {
     const displayPos = this.getDisplayYPos(yPos);
-    this.props.dataDoc['positionYDisplay'] = Math.round(displayPos * 100) / 100
+    if (this.props.color == 'red') {
+      this.props.dataDoc['positionYDisplay'] = Math.round(displayPos * 100) / 100
+    } else {
+      this.props.dataDoc['positionYDisplay2'] = Math.round(displayPos * 100) / 100
+    }
   };
   setXPosDisplay = (xPos: number) => {
-    this.props.dataDoc['positionXDisplay'] = Math.round(xPos * 100) / 100;
+    if (this.props.color == 'red') {
+      this.props.dataDoc['positionXDisplay'] = Math.round(xPos * 100) / 100;
+    } else {
+      this.props.dataDoc['positionXDisplay2'] = Math.round(xPos * 100) / 100;}
   };
   setYVelDisplay = (yVel: number) => {
-    this.props.dataDoc['velocityYDisplay'] = (-1 * Math.round(yVel * 100)) / 100;
+    if (this.props.color == 'red') {
+      this.props.dataDoc['velocityYDisplay'] = (-1 * Math.round(yVel * 100)) / 100;
+    } else {
+      this.props.dataDoc['velocityYDisplay2'] = (-1 * Math.round(yVel * 100)) / 100;}
   };
   setXVelDisplay = (xVel: number) => {
-    this.props.dataDoc['velocityXDisplay'] = Math.round(xVel * 100) / 100;
+    if (this.props.color == 'red') {
+      this.props.dataDoc['velocityXDisplay'] = Math.round(xVel * 100) / 100;
+    } else {
+      this.props.dataDoc['velocityXDisplay2'] = Math.round(xVel * 100) / 100;}
   };
 
   // Update display values when simulation updates
@@ -213,7 +226,11 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         x = Math.min(x, this.props.xMax - 2 * this.props.radius);
         this.setState({updatedStartPosX: x})
         this.setState({xPosition: x})
+        if (this.props.color == 'red') {
         this.props.dataDoc['positionXDisplay'] = x
+        } else {
+          this.props.dataDoc['positionXDisplay2'] = x
+        }
       }
   
       if (this.props.updateDisplay.yDisplay != this.getDisplayYPos(this.state.yPosition)) {
@@ -223,19 +240,31 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         let coordinatePosition = this.getYPosFromDisplay(y);
         this.setState({updatedStartPosY: coordinatePosition})
         this.setState({yPosition: coordinatePosition})
+        if (this.props.color == 'red') {
         this.props.dataDoc['positionYDisplay'] = y
+        } else {
+          this.props.dataDoc['positionYDisplay2'] = y
+        }
       }
   
       if (this.props.displayXVelocity != this.state.xVelocity) {
         let x = this.props.displayXVelocity;
         this.setState({xVelocity: x})
-        this.props.dataDoc['velocityXDisplay'] = x
+        if (this.props.color == 'red') {
+          this.props.dataDoc['velocityXDisplay'] = x
+        } else {
+          this.props.dataDoc['velocityXDisplay2'] = x
+        }
       }
   
       if (this.props.displayYVelocity != -this.state.yVelocity) {
         let y = this.props.displayYVelocity;
         this.setState({yVelocity: -y})
-        this.props.dataDoc['velocityYDisplay'] = y
+        if (this.props.color == 'red') {
+          this.props.dataDoc['velocityYDisplay'] = y
+        } else {
+          this.props.dataDoc['velocityYDisplay2'] = y
+        }
       }
     }
     
@@ -474,18 +503,20 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     this.props.dataDoc['pendulumAngle'] = this.props.dataDoc['startPendulumAngle']
     this.props.dataDoc['updatedForces'] = (this.props.dataDoc['startForces'])
     this.props.dataDoc['updatedForces2'] = (this.props.dataDoc['startForces2'])
-    this.props.dataDoc['accelerationXDisplay'] = 0
-    this.props.dataDoc['accelerationYDisplay'] = 0
     if (this.props.color == 'red') {
       this.props.dataDoc['positionXDisplay'] = this.state.updatedStartPosX
       this.props.dataDoc['positionYDisplay'] = this.state.updatedStartPosY
       this.props.dataDoc['velocityXDisplay'] = this.props.startVelX ?? 0
       this.props.dataDoc['velocityYDisplay'] = this.props.startVelY ?? 0
+      this.props.dataDoc['accelerationXDisplay'] = 0
+      this.props.dataDoc['accelerationYDisplay'] = 0
     } else {
       this.props.dataDoc['positionXDisplay2'] = this.state.updatedStartPosX
       this.props.dataDoc['positionYDisplay2'] = this.state.updatedStartPosY
       this.props.dataDoc['velocityXDisplay2'] = this.props.startVelX ?? 0
       this.props.dataDoc['velocityYDisplay2'] = this.props.startVelY ?? 0
+      this.props.dataDoc['accelerationXDisplay2'] = 0
+      this.props.dataDoc['accelerationYDisplay2'] = 0
     }
     this.setState({angleLabel: Math.round(this.props.dataDoc['pendulumAngle'] ?? 0 * 100) / 100})
   };
@@ -1174,18 +1205,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             ) / 100}
             °
           </p>
-        </div>
-      )}
-      {this.props.dataDoc['simulationType'] == "Suspension" && (
-        <div
-          className="rod"
-          style={{
-            pointerEvents: "none",
-            position: "absolute",
-            left: 0,
-            top: 0,
-          }}
-        >
           <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
             <line
               x1={this.state.xPosition + this.props.radius}
-- 
cgit v1.2.3-70-g09d2


From 697c2bd76fc6c6c7cfe78b4a5d4d84f23b884d8c Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Sat, 6 May 2023 15:23:50 -0400
Subject: refactor answer inputs

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 332 +++++++++------------
 .../PhysicsBox/PhysicsSimulationInputField.tsx     |   1 -
 2 files changed, 139 insertions(+), 194 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 695b0733d..340004cef 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -145,10 +145,10 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.velocityYDisplay = this.dataDoc.velocityYDisplay ?? 0;
 
     // Used for review mode
-    this.dataDoc.answerInputFields = this.dataDoc.answerInputFields ?? <div></div>;
     // this.dataDoc.currentForceSketch = this.dataDoc.currentForceSketch ?? null;
     // this.dataDoc.deleteMode = this.dataDoc.deleteMode ?? false;
     // this.dataDoc.forceSketches = this.dataDoc.forceSketches ?? [];
+    this.dataDoc.answers = [];
     this.dataDoc.hintDialogueOpen = this.dataDoc.hintDialogueOpen ?? false;
     this.dataDoc.noMovement = this.dataDoc.noMovement ?? false;
     this.dataDoc.questionNumber = this.dataDoc.questionNumber ?? 0;
@@ -285,7 +285,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
       this.dataDoc.showAcceleration = (false);
       this.dataDoc.showVelocity = (false);
       this.dataDoc.showForces= (true);
-      // this.generateNewQuestion();
+      this.generateNewQuestion();
       if (simulationType == "One Weight") {
         // TODO - one weight review problems
       } else if (simulationType == "Spring") {
@@ -767,7 +767,6 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.reviewStaticAngle = (0);
     this.dataDoc.coefficientOfKineticFriction = (0);
     this.dataDoc.simulationPaused = (true);
-    this.dataDoc.answerInputFields = (<div></div>);
   };
 
   // In review mode, reset problem variables and generate a new question
@@ -824,195 +823,10 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.selectedQuestion = (question);
     this.dataDoc.questionPartOne = (q);
     this.dataDoc.questionPartTwo = (question.question);
-    const answers = this.getAnswersToQuestion(question, vars);
-    this.generateInputFieldsForQuestion(false, question, answers);
-    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+    this.dataDoc.answers = this.getAnswersToQuestion(question, vars);
+    //this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
   };
 
-  // Generate answerInputFields for new review question
-  generateInputFieldsForQuestion = (
-    showIcon: boolean = false,
-    question: QuestionTemplate = this.dataDoc.selectedQuestion,
-    answers: number[] = this.dataDoc.selectedSolutions
-  ) => {
-    let answerInput = [];
-    const d = new Date();
-    for (let i = 0; i < question.answerParts.length; i++) {
-      if (question.answerParts[i] == "force of gravity") {
-        this.dataDoc.reviewGravityMagnitude = (0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={<p>Gravity magnitude</p>}
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'reviewGravityMagnitude'}
-              step={0.1}
-              unit={"N"}
-              upperBound={50}
-              value={this.dataDoc.reviewGravityMagnitude}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-              labelWidth={"7em"}
-            />
-          </div>
-        );
-      } else if (question.answerParts[i] == "angle of gravity") {
-        this.dataDoc.reviewGravityAngle = (0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={<p>Gravity angle</p>}
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'reviewGravityAngle'}
-              step={1}
-              unit={"°"}
-              upperBound={360}
-              value={this.dataDoc.reviewGravityAngle}
-              radianEquivalent={true}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-              labelWidth={"7em"}
-            />
-          </div>
-        );
-      } else if (question.answerParts[i] == "normal force") {
-        this.dataDoc.reviewNormalMagnitude = (0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={<p>Normal force magnitude</p>}
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'reviewNormalMagnitude'}
-              step={0.1}
-              unit={"N"}
-              upperBound={50}
-              value={this.dataDoc.reviewNormalMagnitude}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-              labelWidth={"7em"}
-            />
-          </div>
-        );
-      } else if (question.answerParts[i] == "angle of normal force") {
-        this.dataDoc.reviewNormalAngle = (0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={<p>Normal force angle</p>}
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'reviewNormalAngle'}
-              step={1}
-              unit={"°"}
-              upperBound={360}
-              value={this.dataDoc.reviewNormalAngle}
-              radianEquivalent={true}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-              labelWidth={"7em"}
-            />
-          </div>
-        );
-      } else if (question.answerParts[i] == "force of static friction") {
-        this.dataDoc.reviewStaticMagnitude = (0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={<p>Static friction magnitude</p>}
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'reviewStaticMagnitude'}
-              step={0.1}
-              unit={"N"}
-              upperBound={50}
-              value={this.dataDoc.reviewStaticMagnitude}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-              labelWidth={"7em"}
-            />
-          </div>
-        );
-      } else if (question.answerParts[i] == "angle of static friction") {
-        this.dataDoc.reviewStaticAngle = (0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={<p>Static friction angle</p>}
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'reviewStaticAngle'}
-              step={1}
-              unit={"°"}
-              upperBound={360}
-              value={this.dataDoc.reviewStaticAngle}
-              radianEquivalent={true}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-              labelWidth={"7em"}
-            />
-          </div>
-        );
-      } else if (question.answerParts[i] == "coefficient of static friction") {
-        this.updateReviewForcesBasedOnCoefficient(0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={
-                <Box>
-                  &mu;<sub>s</sub>
-                </Box>
-              }
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'coefficientOfStaticFriction'}
-              step={0.1}
-              unit={""}
-              upperBound={1}
-              value={this.dataDoc.coefficientOfStaticFriction}
-              effect={this.updateReviewForcesBasedOnCoefficient}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-            />
-          </div>
-        );
-      } else if (question.answerParts[i] == "wedge angle") {
-        this.updateReviewForcesBasedOnAngle(0);
-        answerInput.push(
-          <div key={i + d.getTime()}>
-            <InputField
-              label={<Box>&theta;</Box>}
-              lowerBound={0}
-              dataDoc={this.dataDoc}
-              prop={'wedgeAngle'}
-              step={1}
-              unit={"°"}
-              upperBound={49}
-              value={this.dataDoc.wedgeAngle ?? 26}
-              effect={(val: number) => {
-                this.changeWedgeBasedOnNewAngle(val);
-                this.updateReviewForcesBasedOnAngle(val);
-              }}
-              radianEquivalent={true}
-              showIcon={showIcon}
-              correctValue={answers[i]}
-            />
-          </div>
-        );
-      }
-    }
-
-    this.dataDoc.answerInputFields = (
-      <div
-        style={{ display: "flex", flexDirection: "column", alignItems: "left" }}
-      >
-        {answerInput}
-      </div>
-    );
-  };
-  
   // Default setup for uniform circular motion simulation
   setupCircular = (value: number) => {
     this.dataDoc.showComponentForces = (false);
@@ -1459,6 +1273,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
         {this.dataDoc.mode == "Review" && this.dataDoc.simulationType != "Inclined Plane" && (
           <div className="wordProblemBox">
             <p>{this.dataDoc.simulationType} review problems in progress!</p>
+            <hr/>
           </div>
         )}
         {this.dataDoc.mode == "Review" && this.dataDoc.simulationType == "Inclined Plane" && (
@@ -1517,9 +1332,140 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 <p>{this.dataDoc.questionPartOne}</p>
                 <p>{this.dataDoc.questionPartTwo}</p>
               </div>
-              <div className="answer">{this.dataDoc.answerInputFields}</div>
-            </div>
-          </div>
+              <div className="answers">
+                {this.dataDoc.selectedQuestion.answerParts.includes("force of gravity") &&
+                  (<InputField
+                    label={<p>Gravity magnitude</p>}
+                    lowerBound={0}
+                    dataDoc={this.dataDoc}
+                    prop={'reviewGravityMagnitude'}
+                    step={0.1}
+                    unit={"N"}
+                    upperBound={50}
+                    value={this.dataDoc.reviewGravityMagnitude}
+                    showIcon={false}
+                    correctValue={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={'reviewGravityAngle'}
+                    step={1}
+                    unit={"°"}
+                    upperBound={360}
+                    value={this.dataDoc.reviewGravityAngle}
+                    radianEquivalent={true}
+                    showIcon={false}
+                    correctValue={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={'reviewNormalMagnitude'}
+                    step={0.1}
+                    unit={"N"}
+                    upperBound={50}
+                    value={this.dataDoc.reviewNormalMagnitude}
+                    showIcon={false}
+                    correctValue={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={'reviewNormalAngle'}
+                    step={1}
+                    unit={"°"}
+                    upperBound={360}
+                    value={this.dataDoc.reviewNormalAngle}
+                    radianEquivalent={true}
+                    showIcon={false}
+                    correctValue={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={'reviewStaticMagnitude'}
+                  step={0.1}
+                  unit={"N"}
+                  upperBound={50}
+                  value={this.dataDoc.reviewStaticMagnitude}
+                  showIcon={false}
+                  correctValue={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={'reviewStaticAngle'}
+                    step={1}
+                    unit={"°"}
+                    upperBound={360}
+                    value={this.dataDoc.reviewStaticAngle}
+                    radianEquivalent={true}
+                    showIcon={false}
+                    correctValue={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={this.dataDoc.coefficientOfStaticFriction}
+                    effect={this.updateReviewForcesBasedOnCoefficient}
+                    showIcon={false}
+                    correctValue={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={this.dataDoc.wedgeAngle ?? 26}
+                    effect={(val: number) => {
+                      this.changeWedgeBasedOnNewAngle(val);
+                      this.updateReviewForcesBasedOnAngle(val);
+                    }}
+                    radianEquivalent={true}
+                    showIcon={false}
+                    correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf("wedge angle")]}
+                  />
+                )}
+              </div>
+           </div>
         )}
         {this.dataDoc.mode == "Tutorial" && (
           <div className="wordProblemBox">
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
index 353b386a6..5e5a60edd 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationInputField.tsx
@@ -50,7 +50,6 @@ export default class InputField extends React.Component<IInputProps, IState> {
     if (prevProps.value != this.props.value && !isNaN(this.props.value)) {
       if (this.props.mode == "Freeform") {
         if (Math.abs(this.state.tempValue - Number(this.props.value)) > 1) {
-          console.log('update temp value', Number(this.props.value))
           this.setState({tempValue: Number(this.props.value)})
         }
       }
-- 
cgit v1.2.3-70-g09d2


From c48c72536a22a144bf383dc13d287e4a8233878a Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Sat, 6 May 2023 15:39:38 -0400
Subject: review questions appear

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 2493 ++++++++++----------
 1 file changed, 1250 insertions(+), 1243 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 340004cef..7bb5d0e98 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -120,7 +120,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     this.dataDoc.elasticCollisions = this.dataDoc.elasticCollisions ?? false;
     this.dataDoc.gravity = this.dataDoc.gravity ?? -9.81;
     this.dataDoc.mass = this.dataDoc.mass ?? 1;
-    this.dataDoc.mode = this.dataDoc.mode ?? "Freeform";
+    this.dataDoc.mode = "Freeform";
     this.dataDoc.positionXDisplay = this.dataDoc.positionXDisplay ?? 0;
     this.dataDoc.positionYDisplay = this.dataDoc.positionYDisplay ?? 0;
     this.dataDoc.showAcceleration = this.dataDoc.showAcceleration ?? false;
@@ -149,18 +149,19 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
     // this.dataDoc.deleteMode = this.dataDoc.deleteMode ?? false;
     // this.dataDoc.forceSketches = this.dataDoc.forceSketches ?? [];
     this.dataDoc.answers = [];
-    this.dataDoc.hintDialogueOpen = this.dataDoc.hintDialogueOpen ?? false;
-    this.dataDoc.noMovement = this.dataDoc.noMovement ?? false;
-    this.dataDoc.questionNumber = this.dataDoc.questionNumber ?? 0;
-    this.dataDoc.questionPartOne = this.dataDoc.questionPartOne ?? "";
-    this.dataDoc.questionPartTwo = this.dataDoc.questionPartTwo ?? "";
-    this.dataDoc.reviewGravityAngle = this.dataDoc.reviewGravityAngle ?? 0;
-    this.dataDoc.reviewGravityMagnitude = this.dataDoc.reviewGravityMagnitude ?? 0;
-    this.dataDoc.reviewNormalAngle = this.dataDoc.reviewNormalAngle ?? 0;
-    this.dataDoc.reviewNormalMagnitude = this.dataDoc.reviewNormalMagnitude ?? 0;
-    this.dataDoc.reviewStaticAngle = this.dataDoc.reviewStaticAngle ?? 0;
-    this.dataDoc.reviewStaticMagnitude = this.dataDoc.reviewStaticMagnitude ?? 0;
-    this.dataDoc.selectedSolutions = this.dataDoc.selectedSolutions ?? [];
+    this.dataDoc.showIcon = false;
+    this.dataDoc.hintDialogueOpen = false;
+    this.dataDoc.noMovement = false;
+    this.dataDoc.questionNumber = 0;
+    this.dataDoc.questionPartOne = "";
+    this.dataDoc.questionPartTwo = "";
+    this.dataDoc.reviewGravityAngle = 0;
+    this.dataDoc.reviewGravityMagnitude = 0;
+    this.dataDoc.reviewNormalAngle = 0;
+    this.dataDoc.reviewNormalMagnitude = 0;
+    this.dataDoc.reviewStaticAngle = 0;
+    this.dataDoc.reviewStaticMagnitude = 0;
+    this.dataDoc.selectedSolutions = [];
     this.dataDoc.selectedQuestion = this.dataDoc.selectedQuestion ?? questions.inclinePlane[0];
     // this.dataDoc.sketching = this.dataDoc.sketching ?? false;
 
@@ -1067,94 +1068,45 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
   }
 
   render () { 
-    return <div className="physicsSimApp">
-    <div className="mechanicsSimulationContainer">
-      <div
-        className="mechanicsSimulationContentContainer"
-      >
-        <div className="mechanicsSimulationButtonsAndElements">
-          <div className="mechanicsSimulationButtons">
-            {!this.dataDoc.simulationPaused && (
-              <div
-                style={{
-                  position: "fixed",
-                  left: 0.10*this.layoutDoc._width + "px",
-                  top: 0.95*this.layoutDoc._height + "px",
-                  width: 0.50*this.layoutDoc._width + "px",
-                }}
-              >
-                <LinearProgress />
-              </div>
-            )}
-          </div>
-          <div className="mechanicsSimulationElements">
-            <Weight
-              dataDoc={this.dataDoc}
-              layoutDoc={this.layoutDoc}
-              wallPositions={this.wallPositions}
-              adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
-              gravity={this.dataDoc.gravity}
-              circularMotionRadius={this.dataDoc.circularMotionRadius}
-              componentForces={this.dataDoc.componentForces}
-              showComponentForces={this.dataDoc.showComponentForces}
-              color={"red"}
-              coefficientOfKineticFriction={Number(
-                this.dataDoc.coefficientOfKineticFriction
+    return (
+    <div className="physicsSimApp">
+      <div className="mechanicsSimulationContainer">
+        <div
+          className="mechanicsSimulationContentContainer"
+        >
+          <div className="mechanicsSimulationButtonsAndElements">
+            <div className="mechanicsSimulationButtons">
+              {!this.dataDoc.simulationPaused && (
+                <div
+                  style={{
+                    position: "fixed",
+                    left: 0.10*this.layoutDoc._width + "px",
+                    top: 0.95*this.layoutDoc._height + "px",
+                    width: 0.50*this.layoutDoc._width + "px",
+                  }}
+                >
+                  <LinearProgress />
+                </div>
               )}
-              displayXVelocity={this.dataDoc.velocityXDisplay}
-              displayYVelocity={this.dataDoc.velocityYDisplay}
-              elasticCollisions={this.dataDoc.elasticCollisions}
-              mass={this.dataDoc.mass}
-              mode={this.dataDoc.mode}
-              noMovement={this.dataDoc.noMovement}
-              paused={this.dataDoc.simulationPaused}
-              pendulumAngle={this.dataDoc.pendulumAngle}
-              pendulumLength={this.dataDoc.pendulumLength}
-              radius={(0.08*this.layoutDoc._height)}
-              reset={this.dataDoc.simulationReset}
-              simulationSpeed={this.dataDoc.simulationSpeed}
-              startPendulumAngle={this.dataDoc.startPendulumAngle}
-              showAcceleration={this.dataDoc.showAcceleration}
-              showForceMagnitudes={this.dataDoc.showForceMagnitudes}
-              showForces={this.dataDoc.showForces}
-              showVelocity={this.dataDoc.showVelocity}
-              simulationType={this.dataDoc.simulationType}
-              springConstant={this.dataDoc.springConstant}
-              springStartLength={this.dataDoc.springStartLength}
-              springRestLength={this.dataDoc.springRestLength}
-              startForces={this.dataDoc.startForces}
-              startPosX={this.dataDoc.startPosX}
-              startPosY={this.dataDoc.startPosY ?? 0}
-              startVelX={this.dataDoc.startVelX}
-              startVelY={this.dataDoc.startVelY}
-              timestepSize={0.05}
-              updateDisplay={this.dataDoc.displayChange}
-              updatedForces={this.dataDoc.updatedForces}
-              wedgeHeight={this.dataDoc.wedgeHeight}
-              wedgeWidth={this.dataDoc.wedgeWidth}
-              xMax={this.xMax}
-              xMin={this.xMin}
-              yMax={this.yMax}
-              yMin={this.yMin}
-            />
-            {this.dataDoc.simulationType == "Pulley" && (
+            </div>
+            <div className="mechanicsSimulationElements">
               <Weight
                 dataDoc={this.dataDoc}
                 layoutDoc={this.layoutDoc}
                 wallPositions={this.wallPositions}
                 adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
-                circularMotionRadius={this.dataDoc.circularMotionRadius}
                 gravity={this.dataDoc.gravity}
+                circularMotionRadius={this.dataDoc.circularMotionRadius}
                 componentForces={this.dataDoc.componentForces}
                 showComponentForces={this.dataDoc.showComponentForces}
-                color={"blue"}
+                color={"red"}
                 coefficientOfKineticFriction={Number(
                   this.dataDoc.coefficientOfKineticFriction
                 )}
-                displayXVelocity={this.dataDoc.velocityXDisplay2}
-                displayYVelocity={this.dataDoc.velocityYDisplay2}
+                displayXVelocity={this.dataDoc.velocityXDisplay}
+                displayYVelocity={this.dataDoc.velocityYDisplay}
                 elasticCollisions={this.dataDoc.elasticCollisions}
-                mass={this.dataDoc.mass2}
+                mass={this.dataDoc.mass}
                 mode={this.dataDoc.mode}
                 noMovement={this.dataDoc.noMovement}
                 paused={this.dataDoc.simulationPaused}
@@ -1172,14 +1124,14 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 springConstant={this.dataDoc.springConstant}
                 springStartLength={this.dataDoc.springStartLength}
                 springRestLength={this.dataDoc.springRestLength}
-                startForces={this.dataDoc.startForces2}
-                startPosX={this.dataDoc.startPosX2}
-                startPosY={this.dataDoc.startPosY2}
+                startForces={this.dataDoc.startForces}
+                startPosX={this.dataDoc.startPosX}
+                startPosY={this.dataDoc.startPosY ?? 0}
                 startVelX={this.dataDoc.startVelX}
                 startVelY={this.dataDoc.startVelY}
                 timestepSize={0.05}
-                updateDisplay={this.dataDoc.displayChange2}
-                updatedForces={this.dataDoc.updatedForces2}
+                updateDisplay={this.dataDoc.displayChange}
+                updatedForces={this.dataDoc.updatedForces}
                 wedgeHeight={this.dataDoc.wedgeHeight}
                 wedgeWidth={this.dataDoc.wedgeWidth}
                 xMax={this.xMax}
@@ -1187,246 +1139,759 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                 yMax={this.yMax}
                 yMin={this.yMin}
               />
-            )}
-          </div>
-          <div>
-            {(this.dataDoc.simulationType == "One Weight" ||
-              this.dataDoc.simulationType == "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}
-                  />
-                );
-              })}
+              {this.dataDoc.simulationType == "Pulley" && (
+                <Weight
+                  dataDoc={this.dataDoc}
+                  layoutDoc={this.layoutDoc}
+                  wallPositions={this.wallPositions}
+                  adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
+                  circularMotionRadius={this.dataDoc.circularMotionRadius}
+                  gravity={this.dataDoc.gravity}
+                  componentForces={this.dataDoc.componentForces}
+                  showComponentForces={this.dataDoc.showComponentForces}
+                  color={"blue"}
+                  coefficientOfKineticFriction={Number(
+                    this.dataDoc.coefficientOfKineticFriction
+                  )}
+                  displayXVelocity={this.dataDoc.velocityXDisplay2}
+                  displayYVelocity={this.dataDoc.velocityYDisplay2}
+                  elasticCollisions={this.dataDoc.elasticCollisions}
+                  mass={this.dataDoc.mass2}
+                  mode={this.dataDoc.mode}
+                  noMovement={this.dataDoc.noMovement}
+                  paused={this.dataDoc.simulationPaused}
+                  pendulumAngle={this.dataDoc.pendulumAngle}
+                  pendulumLength={this.dataDoc.pendulumLength}
+                  radius={(0.08*this.layoutDoc._height)}
+                  reset={this.dataDoc.simulationReset}
+                  simulationSpeed={this.dataDoc.simulationSpeed}
+                  startPendulumAngle={this.dataDoc.startPendulumAngle}
+                  showAcceleration={this.dataDoc.showAcceleration}
+                  showForceMagnitudes={this.dataDoc.showForceMagnitudes}
+                  showForces={this.dataDoc.showForces}
+                  showVelocity={this.dataDoc.showVelocity}
+                  simulationType={this.dataDoc.simulationType}
+                  springConstant={this.dataDoc.springConstant}
+                  springStartLength={this.dataDoc.springStartLength}
+                  springRestLength={this.dataDoc.springRestLength}
+                  startForces={this.dataDoc.startForces2}
+                  startPosX={this.dataDoc.startPosX2}
+                  startPosY={this.dataDoc.startPosY2}
+                  startVelX={this.dataDoc.startVelX}
+                  startVelY={this.dataDoc.startVelY}
+                  timestepSize={0.05}
+                  updateDisplay={this.dataDoc.displayChange2}
+                  updatedForces={this.dataDoc.updatedForces2}
+                  wedgeHeight={this.dataDoc.wedgeHeight}
+                  wedgeWidth={this.dataDoc.wedgeWidth}
+                  xMax={this.xMax}
+                  xMin={this.xMin}
+                  yMax={this.yMax}
+                  yMin={this.yMin}
+                />
+              )}
+            </div>
+            <div>
+              {(this.dataDoc.simulationType == "One Weight" ||
+                this.dataDoc.simulationType == "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>
-      <div className="mechanicsSimulationEquationContainer">
-        <div className="mechanicsSimulationControls">
-          <Stack direction="row" spacing={1}>
-            {this.dataDoc.simulationPaused && this.dataDoc.mode != "Tutorial" && (
-              <IconButton
-                onClick={() => {
-                  this.dataDoc.simulationPaused = (false);
+        <div className="mechanicsSimulationEquationContainer">
+          <div className="mechanicsSimulationControls">
+            <Stack direction="row" spacing={1}>
+              {this.dataDoc.simulationPaused && this.dataDoc.mode != "Tutorial" && (
+                <IconButton
+                  onClick={() => {
+                    this.dataDoc.simulationPaused = (false);
+                  }}
+                >
+                  <PlayArrowIcon />
+                </IconButton>
+              )}
+              {!this.dataDoc.simulationPaused && this.dataDoc.mode != "Tutorial" && (
+                <IconButton
+                  onClick={() => {
+                    this.dataDoc.simulationPaused = (true);
+                  }}
+                >
+                  <PauseIcon />
+                </IconButton>
+              )}
+              {this.dataDoc.simulationPaused && this.dataDoc.mode != "Tutorial" && (
+                <IconButton
+                  onClick={() => {
+                    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+                  }}
+                >
+                  <ReplayIcon />
+                </IconButton>
+              )}
+            </Stack>
+            <div className="dropdownMenu">
+                  <select
+                    value={this.dataDoc.simulationType}
+                    onChange={(event) => {
+                      this.dataDoc.simulationType = (event.target.value);
+                      this.setupSimulation(event.target.value, 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={this.dataDoc.mode}
+                onChange={(event) => {
+                  this.dataDoc.mode = (event.target.value);
+                  this.setupSimulation(this.dataDoc.simulationType, event.target.value)
                 }}
+                style={{ height: "2em", width: "100%", fontSize: "16px" }}
               >
-                <PlayArrowIcon />
-              </IconButton>
-            )}
-            {!this.dataDoc.simulationPaused && this.dataDoc.mode != "Tutorial" && (
-              <IconButton
-                onClick={() => {
-                  this.dataDoc.simulationPaused = (true);
-                }}
+                <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.simulationType != "Inclined Plane" && (
+            <div className="wordProblemBox">
+              <p>{this.dataDoc.simulationType} review problems in progress!</p>
+              <hr/>
+            </div>
+          )}
+          {this.dataDoc.mode == "Review" && this.dataDoc.simulationType == "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={this.dataDoc.hintDialogueOpen}
+                onClose={() => this.dataDoc.hintDialogueOpen = (false)}
               >
-                <PauseIcon />
-              </IconButton>
-            )}
-            {this.dataDoc.simulationPaused && this.dataDoc.mode != "Tutorial" && (
-              <IconButton
-                onClick={() => {
-                  this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+                <DialogTitle>Hints</DialogTitle>
+                <DialogContent>
+                  {this.dataDoc.selectedQuestion.hints && (this.dataDoc.selectedQuestion.hints.map((hint, index) => {
+                    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>{this.dataDoc.questionPartOne}</p>
+                  <p>{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={'reviewGravityMagnitude'}
+                      step={0.1}
+                      unit={"N"}
+                      upperBound={50}
+                      value={this.dataDoc.reviewGravityMagnitude}
+                      showIcon={this.dataDoc.showIcon}
+                      correctValue={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={'reviewGravityAngle'}
+                      step={1}
+                      unit={"°"}
+                      upperBound={360}
+                      value={this.dataDoc.reviewGravityAngle}
+                      radianEquivalent={true}
+                      showIcon={this.dataDoc.showIcon}
+                      correctValue={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={'reviewNormalMagnitude'}
+                      step={0.1}
+                      unit={"N"}
+                      upperBound={50}
+                      value={this.dataDoc.reviewNormalMagnitude}
+                      showIcon={this.dataDoc.showIcon}
+                      correctValue={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={'reviewNormalAngle'}
+                      step={1}
+                      unit={"°"}
+                      upperBound={360}
+                      value={this.dataDoc.reviewNormalAngle}
+                      radianEquivalent={true}
+                      showIcon={this.dataDoc.showIcon}
+                      correctValue={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={'reviewStaticMagnitude'}
+                    step={0.1}
+                    unit={"N"}
+                    upperBound={50}
+                    value={this.dataDoc.reviewStaticMagnitude}
+                    showIcon={this.dataDoc.showIcon}
+                    correctValue={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={'reviewStaticAngle'}
+                      step={1}
+                      unit={"°"}
+                      upperBound={360}
+                      value={this.dataDoc.reviewStaticAngle}
+                      radianEquivalent={true}
+                      showIcon={this.dataDoc.showIcon}
+                      correctValue={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={this.dataDoc.coefficientOfStaticFriction}
+                      effect={this.updateReviewForcesBasedOnCoefficient}
+                      showIcon={this.dataDoc.showIcon}
+                      correctValue={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={this.dataDoc.wedgeAngle ?? 26}
+                      effect={(val: number) => {
+                        this.changeWedgeBasedOnNewAngle(val);
+                        this.updateReviewForcesBasedOnAngle(val);
+                      }}
+                      radianEquivalent={true}
+                      showIcon={this.dataDoc.showIcon}
+                      correctValue={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%",
                 }}
               >
-                <ReplayIcon />
-              </IconButton>
-            )}
-          </Stack>
-          <div className="dropdownMenu">
-                <select
-                  value={this.dataDoc.simulationType}
-                  onChange={(event) => {
-                    this.dataDoc.simulationType = (event.target.value);
-                    this.setupSimulation(event.target.value, this.dataDoc.mode)
+                <IconButton
+                  onClick={() => {
+                    let step = 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.startForces = (
+                      this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces)
+                    );
+                    this.dataDoc.updatedForces = (
+                      this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces)
+                    );
+                    this.dataDoc.showForceMagnitudes = (
+                      this.dataDoc.selectedTutorial.steps[step].showMagnitude
+                    );
+                  }}
+                  disabled={this.dataDoc.stepNumber == 0}
+                >
+                  <ArrowLeftIcon />
+                </IconButton>
+                <div>
+                  <h3>
+                    Step {this.dataDoc.stepNumber + 1}:{" "}
+                    {this.dataDoc.selectedTutorial.steps[this.dataDoc.stepNumber].description}
+                  </h3>
+                  <p>{this.dataDoc.selectedTutorial.steps[this.dataDoc.stepNumber].content}</p>
+                </div>
+                <IconButton
+                  onClick={() => {
+                    let step = 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.startForces = (
+                      this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces)
+                    );
+                    this.dataDoc.updatedForces = (
+                      this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces)
+                    );
+                    this.dataDoc.showForceMagnitudes = (
+                      this.dataDoc.selectedTutorial.steps[step].showMagnitude
+                    );
                   }}
-                  style={{ height: "2em", width: "100%", fontSize: "16px" }}
+                  disabled={this.dataDoc.stepNumber == this.dataDoc.selectedTutorial.steps.length - 1}
                 >
-                  <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>
+                  <ArrowRightIcon />
+                </IconButton>
+              </div>
+              <div>
+                {(this.dataDoc.simulationType == "One Weight" ||
+                  this.dataDoc.simulationType == "Inclined Plane" ||
+                  this.dataDoc.simulationType == "Pendulum") && <p>Resources</p>}
+                {this.dataDoc.simulationType == "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.simulationType == "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.simulationType == "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 className="dropdownMenu">
-            <select
-              value={this.dataDoc.mode}
-              onChange={(event) => {
-                this.dataDoc.mode = (event.target.value);
-                this.setupSimulation(this.dataDoc.simulationType, event.target.value)
+            </div>
+          )}
+          {this.dataDoc.mode == "Review" && this.dataDoc.simulationType == "Inclined Plane" && (
+            <div
+              style={{
+                display: "flex",
+                justifyContent: "space-between",
+                marginTop: "10px",
               }}
-              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.simulationType != "Inclined Plane" && (
-          <div className="wordProblemBox">
-            <p>{this.dataDoc.simulationType} review problems in progress!</p>
-            <hr/>
-          </div>
-        )}
-        {this.dataDoc.mode == "Review" && this.dataDoc.simulationType == "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",
+              <p
+                style={{
+                  color: "blue",
+                  textDecoration: "underline",
+                  cursor: "pointer",
                 }}
+                onClick={() => this.dataDoc.mode = ("Tutorial")}
               >
-                <QuestionMarkIcon />
-              </IconButton>
-            )}
-            <Dialog
-              maxWidth={"sm"}
-              fullWidth={true}
-              open={this.dataDoc.hintDialogueOpen}
-              onClose={() => this.dataDoc.hintDialogueOpen = (false)}
-            >
-              <DialogTitle>Hints</DialogTitle>
-              <DialogContent>
-                {this.dataDoc.selectedQuestion.hints && (this.dataDoc.selectedQuestion.hints.map((hint, index) => {
-                  return (
-                    <div key={index}>
-                      <DialogContentText>
-                        <details>
-                          <summary>
-                            <b>
-                              Hint {index + 1}: {hint.description}
-                            </b>
-                          </summary>
-                          {hint.content}
-                        </details>
-                      </DialogContentText>
-                    </div>
-                  );
-                }))}
-              </DialogContent>
-              <DialogActions>
+                {" "}
+                Go to walkthrough{" "}
+              </p>
+              <div style={{ display: "flex", flexDirection: "column" }}>
                 <Button
                   onClick={() => {
-                    this.dataDoc.hintDialogueOpen = (false);
+                    this.dataDoc.simulationReset= (!this.dataDoc.simulationReset);
+                    this.checkAnswers();
+                    this.dataDoc.showIcon = true;
                   }}
+                  variant="outlined"
                 >
-                  Close
+                  <p>Submit</p>
+                </Button>
+                <Button
+                  onClick={() => {
+                    this.generateNewQuestion();
+                    this.dataDoc.showIcon = false;
+                  }}
+                  variant="outlined"
+                >
+                  <p>New question</p>
                 </Button>
-              </DialogActions>
-            </Dialog>
-            <div className="wordProblemBox">
-              <div className="question">
-                <p>{this.dataDoc.questionPartOne}</p>
-                <p>{this.dataDoc.questionPartTwo}</p>
               </div>
-              <div className="answers">
-                {this.dataDoc.selectedQuestion.answerParts.includes("force of gravity") &&
-                  (<InputField
-                    label={<p>Gravity magnitude</p>}
-                    lowerBound={0}
+            </div>
+          )}
+          {this.dataDoc.mode == "Freeform" && (
+            <div className="vars">
+              <FormControl component="fieldset">
+                <FormGroup>
+                  {this.dataDoc.simulationType == "One Weight" && (
+                    <FormControlLabel
+                      control={
+                        <Checkbox
+                          checked={this.dataDoc.elasticCollisions}
+                          onChange={() =>
+                            this.dataDoc.elasticCollisions= (!this.dataDoc.elasticCollisions)
+                          }
+                        />
+                      }
+                      label="Make collisions elastic"
+                      labelPlacement="start"
+                    />
+                  )}
+                  <FormControlLabel
+                    control={
+                      <Checkbox
+                        checked={this.dataDoc.showForces}
+                        onChange={() => this.dataDoc.showForces = (!this.dataDoc.showForces)}
+                      />
+                    }
+                    label="Show force vectors"
+                    labelPlacement="start"
+                  />
+                  {(this.dataDoc.simulationType == "Inclined Plane" ||
+                    this.dataDoc.simulationType == "Pendulum") && (
+                    <FormControlLabel
+                      control={
+                        <Checkbox
+                          checked={this.dataDoc.showForces}
+                          onChange={() =>
+                            this.dataDoc.showComponentForces = (!this.dataDoc.showComponentForces)
+                          }
+                        />
+                      }
+                      label="Show component force vectors"
+                      labelPlacement="start"
+                    />
+                  )}
+                  <FormControlLabel
+                    control={
+                      <Checkbox
+                        checked={this.dataDoc.showAcceleration}
+                        onChange={() => this.dataDoc.showAcceleration = (!this.dataDoc.showAcceleration)}
+                      />
+                    }
+                    label="Show acceleration vector"
+                    labelPlacement="start"
+                  />
+                  <FormControlLabel
+                    control={
+                      <Checkbox
+                        checked={this.dataDoc.showVelocity}
+                        onChange={() => this.dataDoc.showVelocity = (!this.dataDoc.showVelocity)}
+                      />
+                    }
+                    label="Show velocity vector"
+                    labelPlacement="start"
+                  />
+                  <InputField
+                    label={<Box>Speed</Box>}
+                    lowerBound={1}
                     dataDoc={this.dataDoc}
-                    prop={'reviewGravityMagnitude'}
-                    step={0.1}
-                    unit={"N"}
-                    upperBound={50}
-                    value={this.dataDoc.reviewGravityMagnitude}
-                    showIcon={false}
-                    correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf("force of gravity")]}
-                    labelWidth={"7em"}
-                  />)
-                }
-                {this.dataDoc.selectedQuestion.answerParts.includes("angle of gravity") && (
+                    prop={'simulationSpeed'}
+                    step={1}
+                    unit={"x"}
+                    upperBound={10}
+                    value={this.dataDoc.simulationSpeed ?? 2}
+                    labelWidth={"5em"}
+                  />
+                  {this.dataDoc.simulationPaused && this.dataDoc.simulationType != "Circular Motion" && (
+                    <InputField
+                      label={<Box>Gravity</Box>}
+                      lowerBound={-30}
+                      dataDoc={this.dataDoc}
+                      prop={'gravity'}
+                      step={0.01}
+                      unit={"m/s2"}
+                      upperBound={0}
+                      value={this.dataDoc.gravity ?? -9.81}
+                      effect={(val: number) => {
+                        this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
+                      }}
+                      labelWidth={"5em"}
+                    />
+                  )}
+                  {this.dataDoc.simulationPaused && this.dataDoc.simulationType != "Pulley" && (
+                    <InputField
+                      label={<Box>Mass</Box>}
+                      lowerBound={1}
+                      dataDoc={this.dataDoc}
+                      prop={'mass'}
+                      step={0.1}
+                      unit={"kg"}
+                      upperBound={5}
+                      value={this.dataDoc.mass ?? 1}
+                      effect={(val: number) => {
+                        this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
+                      }}
+                      labelWidth={"5em"}
+                    />
+                  )}
+                  {this.dataDoc.simulationPaused && this.dataDoc.simulationType == "Pulley" && (
+                    <InputField
+                      label={<Box>Red mass</Box>}
+                      lowerBound={1}
+                      dataDoc={this.dataDoc}
+                      prop={'mass'}
+                      step={0.1}
+                      unit={"kg"}
+                      upperBound={5}
+                      value={this.dataDoc.mass ?? 1}
+                      effect={(val: number) => {
+                        this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
+                      }}
+                      labelWidth={"5em"}
+                    />
+                  )}
+                  {this.dataDoc.simulationPaused && this.dataDoc.simulationType == "Pulley" && (
+                    <InputField
+                      label={<Box>Blue mass</Box>}
+                      lowerBound={1}
+                      dataDoc={this.dataDoc}
+                      prop={'mass2'}
+                      step={0.1}
+                      unit={"kg"}
+                      upperBound={5}
+                      value={this.dataDoc.mass2 ?? 1}
+                      effect={(val: number) => {
+                        this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
+                      }}
+                      labelWidth={"5em"}
+                    />
+                  )}
+                  {this.dataDoc.simulationPaused && this.dataDoc.simulationType == "Circular Motion" && (
+                    <InputField
+                      label={<Box>Rod length</Box>}
+                      lowerBound={100}
+                      dataDoc={this.dataDoc}
+                      prop={'circularMotionRadius'}
+                      step={5}
+                      unit={"m"}
+                      upperBound={250}
+                      value={this.dataDoc.circularMotionRadius ?? 100}
+                      effect={(val: number) => {
+                        this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
+                      }}
+                      labelWidth={"5em"}
+                    />
+                  )}
+                </FormGroup>
+              </FormControl>
+              {this.dataDoc.simulationType == "Spring" && this.dataDoc.simulationPaused && (
+                <div>
                   <InputField
-                    label={<p>Gravity angle</p>}
-                    lowerBound={0}
+                    label={
+                      <Typography color="inherit">Spring stiffness</Typography>
+                    }
+                    lowerBound={0.1}
                     dataDoc={this.dataDoc}
-                    prop={'reviewGravityAngle'}
+                    prop={'springConstant'}
                     step={1}
-                    unit={"°"}
-                    upperBound={360}
-                    value={this.dataDoc.reviewGravityAngle}
-                    radianEquivalent={true}
-                    showIcon={false}
-                    correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf("angle of gravity")]}
+                    unit={"N/m"}
+                    upperBound={500}
+                    value={this.dataDoc.springConstant ?? 0.5}
+                    effect={(val: number) => {
+                      this.dataDoc.simulationReset(!this.dataDoc.simulationReset);
+                    }}
+                    radianEquivalent={false}
+                    mode={"Freeform"}
                     labelWidth={"7em"}
                   />
-                )}
-                {this.dataDoc.selectedQuestion.answerParts.includes("normal force") && (
                   <InputField
-                    label={<p>Normal force magnitude</p>}
-                    lowerBound={0}
+                    label={<Typography color="inherit">Rest length</Typography>}
+                    lowerBound={10}
                     dataDoc={this.dataDoc}
-                    prop={'reviewNormalMagnitude'}
-                    step={0.1}
-                    unit={"N"}
-                    upperBound={50}
-                    value={this.dataDoc.reviewNormalMagnitude}
-                    showIcon={false}
-                    correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf("normal force")]}
+                    prop={'springRestLength'}
+                    step={100}
+                    unit={""}
+                    upperBound={500}
+                    value={this.dataDoc.springRestLength ?? 200}
+                    effect={(val: number) => {
+                      this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+                    }}
+                    radianEquivalent={false}
+                    mode={"Freeform"}
                     labelWidth={"7em"}
                   />
-                )}
-                {this.dataDoc.selectedQuestion.answerParts.includes("angle of normal force") && (
                   <InputField
-                    label={<p>Normal force angle</p>}
-                    lowerBound={0}
+                    label={
+                      <Typography color="inherit">
+                        Starting displacement
+                      </Typography>
+                    }
+                    lowerBound={-(this.dataDoc.springRestLength - 10)}
                     dataDoc={this.dataDoc}
-                    prop={'reviewNormalAngle'}
-                    step={1}
-                    unit={"°"}
-                    upperBound={360}
-                    value={this.dataDoc.reviewNormalAngle}
-                    radianEquivalent={true}
-                    showIcon={false}
-                    correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf("angle of normal force")]}
+                    prop={""}
+                    step={10}
+                    unit={""}
+                    upperBound={this.dataDoc.springRestLength}
+                    value={this.dataDoc.springStartLength - this.dataDoc.springRestLength ?? 0}
+                    effect={(val: number) => {
+                      this.dataDoc.startPosY = (this.dataDoc.springRestLength + val);
+                      this.dataDoc.springStartLength = (this.dataDoc.springRestLength + val);
+                      this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+                    }}
+                    radianEquivalent={false}
+                    mode={"Freeform"}
                     labelWidth={"7em"}
                   />
-                )}
-                {this.dataDoc.selectedQuestion.answerParts.includes("force of static friction") && (
-                <InputField
-                  label={<p>Static friction magnitude</p>}
-                  lowerBound={0}
-                  dataDoc={this.dataDoc}
-                  prop={'reviewStaticMagnitude'}
-                  step={0.1}
-                  unit={"N"}
-                  upperBound={50}
-                  value={this.dataDoc.reviewStaticMagnitude}
-                  showIcon={false}
-                  correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf("force of static friction")]}
-                  labelWidth={"7em"}
-                />
-                )}
-                {this.dataDoc.selectedQuestion.answerParts.includes("angle of static friction") && (
+                </div>
+              )}
+              {this.dataDoc.simulationType == "Inclined Plane" && this.dataDoc.simulationPaused && (
+                <div>
                   <InputField
-                    label={<p>Static friction angle</p>}
+                    label={<Box>&theta;</Box>}
                     lowerBound={0}
                     dataDoc={this.dataDoc}
-                    prop={'reviewStaticAngle'}
+                    prop={'wedgeAngle'}
                     step={1}
                     unit={"°"}
-                    upperBound={360}
-                    value={this.dataDoc.reviewStaticAngle}
+                    upperBound={49}
+                    value={this.dataDoc.wedgeAngle ?? 26}
+                    effect={(val: number) => {
+                      this.changeWedgeBasedOnNewAngle(val);
+                      this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+                    }}
                     radianEquivalent={true}
-                    showIcon={false}
-                    correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf("angle of static friction")]}
-                    labelWidth={"7em"}
+                    mode={"Freeform"}
+                    labelWidth={"2em"}
                   />
-                )}
-                {this.dataDoc.selectedQuestion.answerParts.includes("coefficient of static friction") && (
                   <InputField
                     label={
                       <Box>
@@ -1439,753 +1904,322 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     step={0.1}
                     unit={""}
                     upperBound={1}
-                    value={this.dataDoc.coefficientOfStaticFriction}
-                    effect={this.updateReviewForcesBasedOnCoefficient}
-                    showIcon={false}
-                    correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf("coefficient of static friction")]}
+                    value={this.dataDoc.coefficientOfStaticFriction ?? 0}
+                    effect={(val: number) => {
+                      this.updateForcesWithFriction(val);
+                      if (val < Number(this.dataDoc.coefficientOfKineticFriction)) {
+                        this.dataDoc.soefficientOfKineticFriction = (val);
+                      }
+                      this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+                    }}
+                    mode={"Freeform"}
+                    labelWidth={"2em"}
                   />
-                )}
-                {this.dataDoc.selectedQuestion.answerParts.includes("wedge angle") && (
                   <InputField
-                    label={<Box>&theta;</Box>}
+                    label={
+                      <Box>
+                        &mu;<sub>k</sub>
+                      </Box>
+                    }
                     lowerBound={0}
                     dataDoc={this.dataDoc}
-                    prop={'wedgeAngle'}
+                    prop={'coefficientOfKineticFriction'}
+                    step={0.1}
+                    unit={""}
+                    upperBound={Number(this.dataDoc.coefficientOfStaticFriction)}
+                    value={this.dataDoc.coefficientOfKineticFriction ?? 0}
+                    effect={(val: number) => {
+                      this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+                    }}
+                    mode={"Freeform"}
+                    labelWidth={"2em"}
+                  />
+                </div>
+              )}
+              {this.dataDoc.simulationType == "Inclined Plane" && !this.dataDoc.simulationPaused && (
+                <Typography>
+                  &theta;: {Math.round(Number(this.dataDoc.wedgeAngle) * 100) / 100}° ≈{" "}
+                  {Math.round(((Number(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.simulationType == "Pendulum" && !this.dataDoc.simulationPaused && (
+                <Typography>
+                  &theta;: {Math.round(this.dataDoc.pendulumAngle * 100) / 100}° ≈{" "}
+                  {Math.round(((this.dataDoc.pendulumAngle * Math.PI) / 180) * 100) / 100}{" "}
+                  rad
+                </Typography>
+              )}
+              {this.dataDoc.simulationType == "Pendulum" && this.dataDoc.simulationPaused && (
+                <div>
+                  <InputField
+                    label={<Box>Angle</Box>}
+                    lowerBound={0}
+                    dataDoc={this.dataDoc}
+                    prop={'pendulumAngle'}
                     step={1}
                     unit={"°"}
-                    upperBound={49}
-                    value={this.dataDoc.wedgeAngle ?? 26}
-                    effect={(val: number) => {
-                      this.changeWedgeBasedOnNewAngle(val);
-                      this.updateReviewForcesBasedOnAngle(val);
+                    upperBound={59}
+                    value={this.dataDoc.pendulumAngle ?? 30}
+                    effect={(value) => {
+                      this.dataDoc.startPendulumAngle = (value);
+                      if (this.dataDoc.simulationType == "Pendulum") {
+                        const mag =
+                        this.dataDoc.mass *
+                          Math.abs(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(this.dataDoc.gravity) *
+                            Math.cos((value * Math.PI) / 180),
+                          directionInDegrees: 270 - value,
+                          component: true,
+                        };
+                        const gravityPerpendicular: IForce = {
+                          description: "Gravity Perpendicular Component",
+                          magnitude:
+                            Math.abs(this.dataDoc.gravity) *
+                            Math.sin((value * Math.PI) / 180),
+                          directionInDegrees: -value,
+                          component: true,
+                        };
+
+                        const length = this.dataDoc.pendulumLength;
+                        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 - this.dataDoc.radius;
+                        const yPos = y - this.dataDoc.radius - 5;
+                        this.dataDoc.startPosX = (xPos);
+                        this.dataDoc.startPosY= (yPos);
+
+                        this.dataDoc.startForces = ([
+                          {
+                            description: "Gravity",
+                            magnitude: Math.abs(this.dataDoc.gravity) * this.dataDoc.mass,
+                            directionInDegrees: 270,
+                            component: false,
+                          },
+                          forceOfTension,
+                        ]);
+                        this.dataDoc.updatedForces = ([
+                          {
+                            description: "Gravity",
+                            magnitude: Math.abs(this.dataDoc.gravity) * this.dataDoc.mass,
+                            directionInDegrees: 270,
+                            component: false,
+                          },
+                          forceOfTension,
+                        ]);
+                        this.dataDoc.componentForces = ([
+                          tensionComponent,
+                          gravityParallel,
+                          gravityPerpendicular,
+                        ]);
+                        this.dataDoc.adjustPendulumAngle = ({
+                          angle: value,
+                          length: this.dataDoc.pendulumLength,
+                        });
+                        this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+                      }
                     }}
                     radianEquivalent={true}
-                    showIcon={false}
-                    correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf("wedge angle")]}
+                    mode={"Freeform"}
+                    labelWidth={"5em"}
                   />
-                )}
-              </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 = 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.startForces = (
-                    this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces)
-                  );
-                  this.dataDoc.updatedForces = (
-                    this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces)
-                  );
-                  this.dataDoc.showForceMagnitudes = (
-                    this.dataDoc.selectedTutorial.steps[step].showMagnitude
-                  );
-                }}
-                disabled={this.dataDoc.stepNumber == 0}
-              >
-                <ArrowLeftIcon />
-              </IconButton>
-              <div>
-                <h3>
-                  Step {this.dataDoc.stepNumber + 1}:{" "}
-                  {this.dataDoc.selectedTutorial.steps[this.dataDoc.stepNumber].description}
-                </h3>
-                <p>{this.dataDoc.selectedTutorial.steps[this.dataDoc.stepNumber].content}</p>
-              </div>
-              <IconButton
-                onClick={() => {
-                  let step = 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.startForces = (
-                    this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces)
-                  );
-                  this.dataDoc.updatedForces = (
-                    this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces)
-                  );
-                  this.dataDoc.showForceMagnitudes = (
-                    this.dataDoc.selectedTutorial.steps[step].showMagnitude
-                  );
-                }}
-                disabled={this.dataDoc.stepNumber == this.dataDoc.selectedTutorial.steps.length - 1}
-              >
-                <ArrowRightIcon />
-              </IconButton>
-            </div>
-            <div>
-              {(this.dataDoc.simulationType == "One Weight" ||
-                this.dataDoc.simulationType == "Inclined Plane" ||
-                this.dataDoc.simulationType == "Pendulum") && <p>Resources</p>}
-              {this.dataDoc.simulationType == "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.simulationType == "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.simulationType == "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.simulationType == "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.simulationReset= (!this.dataDoc.simulationReset);
-                  this.checkAnswers();
-                  this.generateInputFieldsForQuestion(true);
-                }}
-                variant="outlined"
-              >
-                <p>Submit</p>
-              </Button>
-              <Button
-                onClick={() => this.generateNewQuestion()}
-                variant="outlined"
-              >
-                <p>New question</p>
-              </Button>
-            </div>
-          </div>
-        )}
-        {this.dataDoc.mode == "Freeform" && (
-          <div className="vars">
-            <FormControl component="fieldset">
-              <FormGroup>
-                {this.dataDoc.simulationType == "One Weight" && (
-                  <FormControlLabel
-                    control={
-                      <Checkbox
-                        checked={this.dataDoc.elasticCollisions}
-                        onChange={() =>
-                          this.dataDoc.elasticCollisions= (!this.dataDoc.elasticCollisions)
-                        }
-                      />
-                    }
-                    label="Make collisions elastic"
-                    labelPlacement="start"
-                  />
-                )}
-                <FormControlLabel
-                  control={
-                    <Checkbox
-                      checked={this.dataDoc.showForces}
-                      onChange={() => this.dataDoc.showForces = (!this.dataDoc.showForces)}
-                    />
-                  }
-                  label="Show force vectors"
-                  labelPlacement="start"
-                />
-                {(this.dataDoc.simulationType == "Inclined Plane" ||
-                  this.dataDoc.simulationType == "Pendulum") && (
-                  <FormControlLabel
-                    control={
-                      <Checkbox
-                        checked={this.dataDoc.showForces}
-                        onChange={() =>
-                          this.dataDoc.showComponentForces = (!this.dataDoc.showComponentForces)
-                        }
-                      />
-                    }
-                    label="Show component force vectors"
-                    labelPlacement="start"
-                  />
-                )}
-                <FormControlLabel
-                  control={
-                    <Checkbox
-                      checked={this.dataDoc.showAcceleration}
-                      onChange={() => this.dataDoc.showAcceleration = (!this.dataDoc.showAcceleration)}
-                    />
-                  }
-                  label="Show acceleration vector"
-                  labelPlacement="start"
-                />
-                <FormControlLabel
-                  control={
-                    <Checkbox
-                      checked={this.dataDoc.showVelocity}
-                      onChange={() => this.dataDoc.showVelocity = (!this.dataDoc.showVelocity)}
-                    />
-                  }
-                  label="Show velocity vector"
-                  labelPlacement="start"
-                />
-                <InputField
-                  label={<Box>Speed</Box>}
-                  lowerBound={1}
-                  dataDoc={this.dataDoc}
-                  prop={'simulationSpeed'}
-                  step={1}
-                  unit={"x"}
-                  upperBound={10}
-                  value={this.dataDoc.simulationSpeed ?? 2}
-                  labelWidth={"5em"}
-                />
-                {this.dataDoc.simulationPaused && this.dataDoc.simulationType != "Circular Motion" && (
-                  <InputField
-                    label={<Box>Gravity</Box>}
-                    lowerBound={-30}
-                    dataDoc={this.dataDoc}
-                    prop={'gravity'}
-                    step={0.01}
-                    unit={"m/s2"}
-                    upperBound={0}
-                    value={this.dataDoc.gravity ?? -9.81}
-                    effect={(val: number) => {
-                      this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
-                    }}
-                    labelWidth={"5em"}
-                  />
-                )}
-                {this.dataDoc.simulationPaused && this.dataDoc.simulationType != "Pulley" && (
-                  <InputField
-                    label={<Box>Mass</Box>}
-                    lowerBound={1}
-                    dataDoc={this.dataDoc}
-                    prop={'mass'}
-                    step={0.1}
-                    unit={"kg"}
-                    upperBound={5}
-                    value={this.dataDoc.mass ?? 1}
-                    effect={(val: number) => {
-                      this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
-                    }}
-                    labelWidth={"5em"}
-                  />
-                )}
-                {this.dataDoc.simulationPaused && this.dataDoc.simulationType == "Pulley" && (
-                  <InputField
-                    label={<Box>Red mass</Box>}
-                    lowerBound={1}
-                    dataDoc={this.dataDoc}
-                    prop={'mass'}
-                    step={0.1}
-                    unit={"kg"}
-                    upperBound={5}
-                    value={this.dataDoc.mass ?? 1}
-                    effect={(val: number) => {
-                      this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
-                    }}
-                    labelWidth={"5em"}
-                  />
-                )}
-                {this.dataDoc.simulationPaused && this.dataDoc.simulationType == "Pulley" && (
-                  <InputField
-                    label={<Box>Blue mass</Box>}
-                    lowerBound={1}
-                    dataDoc={this.dataDoc}
-                    prop={'mass2'}
-                    step={0.1}
-                    unit={"kg"}
-                    upperBound={5}
-                    value={this.dataDoc.mass2 ?? 1}
-                    effect={(val: number) => {
-                      this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
-                    }}
-                    labelWidth={"5em"}
-                  />
-                )}
-                {this.dataDoc.simulationPaused && this.dataDoc.simulationType == "Circular Motion" && (
                   <InputField
                     label={<Box>Rod length</Box>}
-                    lowerBound={100}
+                    lowerBound={0}
                     dataDoc={this.dataDoc}
-                    prop={'circularMotionRadius'}
-                    step={5}
+                    prop={'pendulumLength'}
+                    step={1}
                     unit={"m"}
-                    upperBound={250}
-                    value={this.dataDoc.circularMotionRadius ?? 100}
-                    effect={(val: number) => {
-                      this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode)
+                    upperBound={400}
+                    value={Math.round(this.dataDoc.pendulumLength)}
+                    effect={(value) => {
+                      if (this.dataDoc.simulationType == "Pendulum") {
+                        this.dataDoc.adjustPendulumAngle = ({
+                          angle: this.dataDoc.pendulumAngle,
+                          length: value,
+                        });
+                        this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+                      }
                     }}
+                    radianEquivalent={false}
+                    mode={"Freeform"}
                     labelWidth={"5em"}
                   />
-                )}
-              </FormGroup>
-            </FormControl>
-            {this.dataDoc.simulationType == "Spring" && this.dataDoc.simulationPaused && (
-              <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={this.dataDoc.springConstant ?? 0.5}
-                  effect={(val: number) => {
-                    this.dataDoc.simulationReset(!this.dataDoc.simulationReset);
-                  }}
-                  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={this.dataDoc.springRestLength ?? 200}
-                  effect={(val: number) => {
-                    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
-                  }}
-                  radianEquivalent={false}
-                  mode={"Freeform"}
-                  labelWidth={"7em"}
-                />
-                <InputField
-                  label={
-                    <Typography color="inherit">
-                      Starting displacement
-                    </Typography>
-                  }
-                  lowerBound={-(this.dataDoc.springRestLength - 10)}
-                  dataDoc={this.dataDoc}
-                  prop={""}
-                  step={10}
-                  unit={""}
-                  upperBound={this.dataDoc.springRestLength}
-                  value={this.dataDoc.springStartLength - this.dataDoc.springRestLength ?? 0}
-                  effect={(val: number) => {
-                    this.dataDoc.startPosY = (this.dataDoc.springRestLength + val);
-                    this.dataDoc.springStartLength = (this.dataDoc.springRestLength + val);
-                    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
-                  }}
-                  radianEquivalent={false}
-                  mode={"Freeform"}
-                  labelWidth={"7em"}
-                />
-              </div>
-            )}
-            {this.dataDoc.simulationType == "Inclined Plane" && this.dataDoc.simulationPaused && (
-              <div>
-                <InputField
-                  label={<Box>&theta;</Box>}
-                  lowerBound={0}
-                  dataDoc={this.dataDoc}
-                  prop={'wedgeAngle'}
-                  step={1}
-                  unit={"°"}
-                  upperBound={49}
-                  value={this.dataDoc.wedgeAngle ?? 26}
-                  effect={(val: number) => {
-                    this.changeWedgeBasedOnNewAngle(val);
-                    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
-                  }}
-                  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={this.dataDoc.coefficientOfStaticFriction ?? 0}
-                  effect={(val: number) => {
-                    this.updateForcesWithFriction(val);
-                    if (val < Number(this.dataDoc.coefficientOfKineticFriction)) {
-                      this.dataDoc.soefficientOfKineticFriction = (val);
-                    }
-                    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
-                  }}
-                  mode={"Freeform"}
-                  labelWidth={"2em"}
-                />
-                <InputField
-                  label={
-                    <Box>
-                      &mu;<sub>k</sub>
-                    </Box>
-                  }
-                  lowerBound={0}
-                  dataDoc={this.dataDoc}
-                  prop={'coefficientOfKineticFriction'}
-                  step={0.1}
-                  unit={""}
-                  upperBound={Number(this.dataDoc.coefficientOfStaticFriction)}
-                  value={this.dataDoc.coefficientOfKineticFriction ?? 0}
-                  effect={(val: number) => {
-                    this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
-                  }}
-                  mode={"Freeform"}
-                  labelWidth={"2em"}
-                />
-              </div>
-            )}
-            {this.dataDoc.simulationType == "Inclined Plane" && !this.dataDoc.simulationPaused && (
-              <Typography>
-                &theta;: {Math.round(Number(this.dataDoc.wedgeAngle) * 100) / 100}° ≈{" "}
-                {Math.round(((Number(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.simulationType == "Pendulum" && !this.dataDoc.simulationPaused && (
-              <Typography>
-                &theta;: {Math.round(this.dataDoc.pendulumAngle * 100) / 100}° ≈{" "}
-                {Math.round(((this.dataDoc.pendulumAngle * Math.PI) / 180) * 100) / 100}{" "}
-                rad
-              </Typography>
-            )}
-            {this.dataDoc.simulationType == "Pendulum" && this.dataDoc.simulationPaused && (
-              <div>
-                <InputField
-                  label={<Box>Angle</Box>}
-                  lowerBound={0}
-                  dataDoc={this.dataDoc}
-                  prop={'pendulumAngle'}
-                  step={1}
-                  unit={"°"}
-                  upperBound={59}
-                  value={this.dataDoc.pendulumAngle ?? 30}
-                  effect={(value) => {
-                    this.dataDoc.startPendulumAngle = (value);
-                    if (this.dataDoc.simulationType == "Pendulum") {
-                      const mag =
-                      this.dataDoc.mass *
-                        Math.abs(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(this.dataDoc.gravity) *
-                          Math.cos((value * Math.PI) / 180),
-                        directionInDegrees: 270 - value,
-                        component: true,
-                      };
-                      const gravityPerpendicular: IForce = {
-                        description: "Gravity Perpendicular Component",
-                        magnitude:
-                          Math.abs(this.dataDoc.gravity) *
-                          Math.sin((value * Math.PI) / 180),
-                        directionInDegrees: -value,
-                        component: true,
-                      };
-
-                      const length = this.dataDoc.pendulumLength;
-                      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 - this.dataDoc.radius;
-                      const yPos = y - this.dataDoc.radius - 5;
-                      this.dataDoc.startPosX = (xPos);
-                      this.dataDoc.startPosY= (yPos);
-
-                      this.dataDoc.startForces = ([
-                        {
-                          description: "Gravity",
-                          magnitude: Math.abs(this.dataDoc.gravity) * this.dataDoc.mass,
-                          directionInDegrees: 270,
-                          component: false,
-                        },
-                        forceOfTension,
-                      ]);
-                      this.dataDoc.updatedForces = ([
-                        {
-                          description: "Gravity",
-                          magnitude: Math.abs(this.dataDoc.gravity) * this.dataDoc.mass,
-                          directionInDegrees: 270,
-                          component: false,
-                        },
-                        forceOfTension,
-                      ]);
-                      this.dataDoc.componentForces = ([
-                        tensionComponent,
-                        gravityParallel,
-                        gravityPerpendicular,
-                      ]);
-                      this.dataDoc.adjustPendulumAngle = ({
-                        angle: value,
-                        length: this.dataDoc.pendulumLength,
-                      });
-                      this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
-                    }
-                  }}
-                  radianEquivalent={true}
-                  mode={"Freeform"}
-                  labelWidth={"5em"}
-                />
-                <InputField
-                  label={<Box>Rod length</Box>}
-                  lowerBound={0}
-                  dataDoc={this.dataDoc}
-                  prop={'pendulumLength'}
-                  step={1}
-                  unit={"m"}
-                  upperBound={400}
-                  value={Math.round(this.dataDoc.pendulumLength)}
-                  effect={(value) => {
-                    if (this.dataDoc.simulationType == "Pendulum") {
-                      this.dataDoc.adjustPendulumAngle = ({
-                        angle: this.dataDoc.pendulumAngle,
-                        length: value,
-                      });
-                      this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
-                    }
-                  }}
-                  radianEquivalent={false}
-                  mode={"Freeform"}
-                  labelWidth={"5em"}
-                />
-              </div>
-            )}
-          </div>
-        )}
-        <div className="mechanicsSimulationEquation">
-          {this.dataDoc.mode == "Freeform" && (
-            <table>
-              <tbody>
-                <tr>
-                  <td>{this.dataDoc.simulationType == "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.simulationPaused ||
-                    this.dataDoc.simulationType == "Inclined Plane" ||
-                    this.dataDoc.simulationType == "Suspension" ||
-                    this.dataDoc.simulationType == "Circular Motion" ||
-                    this.dataDoc.simulationType == "Pulley") && (
-                    <td style={{ cursor: "default" }}>
-                      {this.dataDoc.positionXDisplay} m
+                </div>
+              )}
+            </div>
+          )}
+          <div className="mechanicsSimulationEquation">
+            {this.dataDoc.mode == "Freeform" && (
+              <table>
+                <tbody>
+                  <tr>
+                    <td>{this.dataDoc.simulationType == "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.simulationPaused &&
-                    this.dataDoc.simulationType != "Inclined Plane" &&
-                    this.dataDoc.simulationType != "Suspension" &&
-                    this.dataDoc.simulationType != "Circular Motion" &&
-                    this.dataDoc.simulationType != "Pulley" && (
-                      <td
-                        style={{
-                          cursor: "default",
-                        }}
-                      >
-                        <InputField
-                          lowerBound={0}
-                          dataDoc={this.dataDoc}
-                          prop={'positionXDisplay'}
-                          step={1}
-                          unit={"m"}
-                          upperBound={this.xMax - 110}
-                          value={this.dataDoc.positionXDisplay}
-                          effect={(value) => {
-                            this.dataDoc.displayChange = ({
-                              xDisplay: value,
-                              yDisplay: this.dataDoc.positionYDisplay,
-                            });
+                    {(!this.dataDoc.simulationPaused ||
+                      this.dataDoc.simulationType == "Inclined Plane" ||
+                      this.dataDoc.simulationType == "Suspension" ||
+                      this.dataDoc.simulationType == "Circular Motion" ||
+                      this.dataDoc.simulationType == "Pulley") && (
+                      <td style={{ cursor: "default" }}>
+                        {this.dataDoc.positionXDisplay} m
+                      </td>
+                    )}{" "}
+                    {this.dataDoc.simulationPaused &&
+                      this.dataDoc.simulationType != "Inclined Plane" &&
+                      this.dataDoc.simulationType != "Suspension" &&
+                      this.dataDoc.simulationType != "Circular Motion" &&
+                      this.dataDoc.simulationType != "Pulley" && (
+                        <td
+                          style={{
+                            cursor: "default",
                           }}
-                          small={true}
-                          mode={"Freeform"}
-                        />
+                        >
+                          <InputField
+                            lowerBound={0}
+                            dataDoc={this.dataDoc}
+                            prop={'positionXDisplay'}
+                            step={1}
+                            unit={"m"}
+                            upperBound={this.xMax - 110}
+                            value={this.dataDoc.positionXDisplay}
+                            effect={(value) => {
+                              this.dataDoc.displayChange = ({
+                                xDisplay: value,
+                                yDisplay: this.dataDoc.positionYDisplay,
+                              });
+                            }}
+                            small={true}
+                            mode={"Freeform"}
+                          />
+                        </td>
+                      )}{" "}
+                    {(!this.dataDoc.simulationPaused ||
+                      this.dataDoc.simulationType == "Inclined Plane" ||
+                      this.dataDoc.simulationType == "Suspension" ||
+                      this.dataDoc.simulationType == "Circular Motion" ||
+                      this.dataDoc.simulationType == "Pulley") && (
+                      <td style={{ cursor: "default" }}>
+                        {this.dataDoc.positionYDisplay} m
                       </td>
                     )}{" "}
-                  {(!this.dataDoc.simulationPaused ||
-                    this.dataDoc.simulationType == "Inclined Plane" ||
-                    this.dataDoc.simulationType == "Suspension" ||
-                    this.dataDoc.simulationType == "Circular Motion" ||
-                    this.dataDoc.simulationType == "Pulley") && (
-                    <td style={{ cursor: "default" }}>
-                      {this.dataDoc.positionYDisplay} m
+                    {this.dataDoc.simulationPaused &&
+                      this.dataDoc.simulationType != "Inclined Plane" &&
+                      this.dataDoc.simulationType != "Suspension" &&
+                      this.dataDoc.simulationType != "Circular Motion" &&
+                      this.dataDoc.simulationType != "Pulley" && (
+                        <td
+                          style={{
+                            cursor: "default",
+                          }}
+                        >
+                          <InputField
+                            lowerBound={0}
+                            dataDoc={this.dataDoc}
+                            prop={'positionYDisplay'}
+                            step={1}
+                            unit={"m"}
+                            upperBound={this.yMax - 110}
+                            value={this.dataDoc.positionYDisplay}
+                            effect={(value) => {
+                              this.dataDoc.displayChange = ({
+                                xDisplay: this.dataDoc.positionXDisplay,
+                                yDisplay: value,
+                              });
+                            }}
+                            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.simulationPaused &&
-                    this.dataDoc.simulationType != "Inclined Plane" &&
-                    this.dataDoc.simulationType != "Suspension" &&
-                    this.dataDoc.simulationType != "Circular Motion" &&
-                    this.dataDoc.simulationType != "Pulley" && (
-                      <td
-                        style={{
-                          cursor: "default",
-                        }}
-                      >
-                        <InputField
-                          lowerBound={0}
-                          dataDoc={this.dataDoc}
-                          prop={'positionYDisplay'}
-                          step={1}
-                          unit={"m"}
-                          upperBound={this.yMax - 110}
-                          value={this.dataDoc.positionYDisplay}
-                          effect={(value) => {
-                            this.dataDoc.displayChange = ({
-                              xDisplay: this.dataDoc.positionXDisplay,
-                              yDisplay: value,
-                            });
+                    {(!this.dataDoc.simulationPaused ||
+                      (this.dataDoc.simulationType != "One Weight" &&
+                      this.dataDoc.simulationType != "Circular Motion")) && (
+                      <td style={{ cursor: "default" }}>
+                        {this.dataDoc.velocityXDisplay} m/s
+                      </td>
+                    )}{" "}
+                    {this.dataDoc.simulationPaused &&
+                      (this.dataDoc.simulationType == "One Weight" ||
+                      this.dataDoc.simulationType == "Circular Motion") && (
+                        <td
+                          style={{
+                            cursor: "default",
                           }}
-                          small={true}
-                          mode={"Freeform"}
-                        />
+                        >
+                          <InputField
+                            lowerBound={-50}
+                            dataDoc={this.dataDoc}
+                            prop={'velocityXDisplay'}
+                            step={1}
+                            unit={"m/s"}
+                            upperBound={50}
+                            value={this.dataDoc.velocityXDisplay}
+                            effect={(value) => {
+                              this.dataDoc.startVelX = (value);
+                              this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+                            }}
+                            small={true}
+                            mode={"Freeform"}
+                          />
+                        </td>
+                      )}{" "}
+                    {(!this.dataDoc.simulationPaused || this.dataDoc.simulationType != "One Weight") && (
+                      <td style={{ cursor: "default" }}>
+                        {this.dataDoc.velocityYDisplay} m/s
                       </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.simulationPaused ||
-                    (this.dataDoc.simulationType != "One Weight" &&
-                    this.dataDoc.simulationType != "Circular Motion")) && (
-                    <td style={{ cursor: "default" }}>
-                      {this.dataDoc.velocityXDisplay} m/s
-                    </td>
-                  )}{" "}
-                  {this.dataDoc.simulationPaused &&
-                    (this.dataDoc.simulationType == "One Weight" ||
-                    this.dataDoc.simulationType == "Circular Motion") && (
+                    {this.dataDoc.simulationPaused && this.dataDoc.simulationType == "One Weight" && (
                       <td
                         style={{
                           cursor: "default",
@@ -2194,263 +2228,236 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                         <InputField
                           lowerBound={-50}
                           dataDoc={this.dataDoc}
-                          prop={'velocityXDisplay'}
+                          prop={'velocityYDisplay'}
                           step={1}
                           unit={"m/s"}
                           upperBound={50}
-                          value={this.dataDoc.velocityXDisplay}
+                          value={this.dataDoc.velocityYDisplay}
                           effect={(value) => {
-                            this.dataDoc.startVelX = (value);
-                            this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+                            this.dataDoc.startVelY = (-value);
+                            this.dataDoc.displayChange = ({
+                              xDisplay: this.dataDoc.positionXDisplay,
+                              yDisplay: this.dataDoc.positionYDisplay,
+                            });
                           }}
                           small={true}
                           mode={"Freeform"}
                         />
                       </td>
                     )}{" "}
-                  {(!this.dataDoc.simulationPaused || this.dataDoc.simulationType != "One Weight") && (
-                    <td style={{ cursor: "default" }}>
-                      {this.dataDoc.velocityYDisplay} m/s
-                    </td>
-                  )}{" "}
-                  {this.dataDoc.simulationPaused && this.dataDoc.simulationType == "One Weight" && (
+                  </tr>
+                  <tr>
                     <td
-                      style={{
-                        cursor: "default",
-                      }}
+                      style={{ cursor: "help" }}
+                      // onClick={() => {
+                      //   window.open(
+                      //     "https://www.khanacademy.org/science/physics/two-dimensional-motion"
+                      //   );
+                      // }}
                     >
-                      <InputField
-                        lowerBound={-50}
-                        dataDoc={this.dataDoc}
-                        prop={'velocityYDisplay'}
-                        step={1}
-                        unit={"m/s"}
-                        upperBound={50}
-                        value={this.dataDoc.velocityYDisplay}
-                        effect={(value) => {
-                          this.dataDoc.startVelY = (-value);
-                          this.dataDoc.displayChange = ({
-                            xDisplay: this.dataDoc.positionXDisplay,
-                            yDisplay: this.dataDoc.positionYDisplay,
-                          });
-                        }}
-                        small={true}
-                        mode={"Freeform"}
-                      />
+                      <Box>Acceleration</Box>
+                    </td>
+                    <td style={{ cursor: "default" }}>
+                      {this.dataDoc.accelerationXDisplay} m/s<sup>2</sup>
+                    </td>
+                    <td style={{ cursor: "default" }}>
+                      {this.dataDoc.accelerationYDisplay} m/s<sup>2</sup>
+                    </td>
+                  </tr>
+                  <tr>
+                    <td>
+                      <Box>Momentum</Box>
+                    </td>
+                    <td>
+                      {Math.round(this.dataDoc.velocityXDisplay * this.dataDoc.mass * 10) / 10} kg*m/s
+                    </td>
+                    <td>
+                      {Math.round(this.dataDoc.velocityYDisplay * this.dataDoc.mass * 10) / 10} kg*m/s
+                    </td>
+                  </tr>
+                </tbody>
+              </table>
+            )}
+            {this.dataDoc.mode == "Freeform" && this.dataDoc.simulationType == "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.positionXDisplay2} m</td>
+                    <td style={{ cursor: "default" }}>{this.dataDoc.positionYDisplay2} m</td>
+                  </tr>
+                  <tr>
+                    <td>
+                      <Box>Velocity</Box>
+                    </td>
+                    <td style={{ cursor: "default" }}>
+                      {this.dataDoc.velocityXDisplay2} m/s
                     </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.accelerationXDisplay} m/s<sup>2</sup>
-                  </td>
-                  <td style={{ cursor: "default" }}>
-                    {this.dataDoc.accelerationYDisplay} m/s<sup>2</sup>
-                  </td>
-                </tr>
-                <tr>
-                  <td>
-                    <Box>Momentum</Box>
-                  </td>
-                  <td>
-                    {Math.round(this.dataDoc.velocityXDisplay * this.dataDoc.mass * 10) / 10} kg*m/s
-                  </td>
-                  <td>
-                    {Math.round(this.dataDoc.velocityYDisplay * this.dataDoc.mass * 10) / 10} kg*m/s
-                  </td>
-                </tr>
-              </tbody>
-            </table>
-          )}
-          {this.dataDoc.mode == "Freeform" && this.dataDoc.simulationType == "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.positionXDisplay2} m</td>
-                  <td style={{ cursor: "default" }}>{this.dataDoc.positionYDisplay2} m</td>
-                </tr>
-                <tr>
-                  <td>
-                    <Box>Velocity</Box>
-                  </td>
-                  <td style={{ cursor: "default" }}>
-                    {this.dataDoc.velocityXDisplay2} m/s
-                  </td>
 
-                  <td style={{ cursor: "default" }}>
-                    {this.dataDoc.velocityYDisplay2} m/s
-                  </td>
-                </tr>
-                <tr>
-                  <td>
-                    <Box>Acceleration</Box>
-                  </td>
-                  <td style={{ cursor: "default" }}>
-                    {this.dataDoc.accelerationXDisplay2} m/s<sup>2</sup>
-                  </td>
-                  <td style={{ cursor: "default" }}>
-                    {this.dataDoc.accelerationYDisplay2} m/s<sup>2</sup>
-                  </td>
-                </tr>
-                <tr>
-                  <td>
-                    <Box>Momentum</Box>
-                  </td>
-                  <td>
-                    {Math.round(this.dataDoc.velocityXDisplay2 * this.dataDoc.mass * 10) / 10} kg*m/s
-                  </td>
-                  <td>
-                    {Math.round(this.dataDoc.velocityYDisplay2 * this.dataDoc.mass * 10) / 10} kg*m/s
-                  </td>
-                </tr>
-              </tbody>
-            </table>
-          )}
-        </div>
-        {this.dataDoc.simulationType != "Pendulum" && this.dataDoc.simulationType != "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>
+                    <td style={{ cursor: "default" }}>
+                      {this.dataDoc.velocityYDisplay2} m/s
+                    </td>
+                  </tr>
+                  <tr>
+                    <td>
+                      <Box>Acceleration</Box>
+                    </td>
+                    <td style={{ cursor: "default" }}>
+                      {this.dataDoc.accelerationXDisplay2} m/s<sup>2</sup>
+                    </td>
+                    <td style={{ cursor: "default" }}>
+                      {this.dataDoc.accelerationYDisplay2} m/s<sup>2</sup>
+                    </td>
+                  </tr>
+                  <tr>
+                    <td>
+                      <Box>Momentum</Box>
+                    </td>
+                    <td>
+                      {Math.round(this.dataDoc.velocityXDisplay2 * this.dataDoc.mass * 10) / 10} kg*m/s
+                    </td>
+                    <td>
+                      {Math.round(this.dataDoc.velocityYDisplay2 * this.dataDoc.mass * 10) / 10} kg*m/s
+                    </td>
+                  </tr>
+                </tbody>
+              </table>
+            )}
           </div>
-        )}
-        {this.dataDoc.simulationType == "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>
+          {this.dataDoc.simulationType != "Pendulum" && this.dataDoc.simulationType != "Spring" && (
+            <div>
+              <p>Kinematic Equations</p>
               <ul>
                 <li>
-                  Maximum when system is at maximum displacement, 0 when
-                  system is at 0 displacement
+                  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>
-              <li>
-                Translational kinetic energy: K=<sup>1</sup>&frasl;
-                <sub>2</sub>mv<sup>2</sup>
-              </li>
+            </div>
+          )}
+          {this.dataDoc.simulationType == "Spring" && (
+            <div>
+              <p>Harmonic Motion Equations: Spring</p>
               <ul>
                 <li>
-                  Maximum when system is at maximum/minimum velocity (at 0
-                  displacement), 0 when velocity is 0 (at maximum
-                  displacement)
+                  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>
-            </ul>
-          </div>
-        )}
-        {this.dataDoc.simulationType == "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>
+          )}
+          {this.dataDoc.simulationType == "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>
-    <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
+      <div
         style={{
           position: "fixed",
-          top: this.yMax - 120 + 40 + "px",
+          top: this.yMax - 120 + 20 + "px",
           left: this.xMin + 90 - 80 + "px",
+          zIndex: -10000,
         }}
       >
-        {this.dataDoc.simulationType == "Circular Motion" ? "Z" : "Y"}
-      </p>
-      <p
-        style={{
-          position: "fixed",
-          top: this.yMax - 120 + 80 + "px",
-          left: this.xMin + 90 - 40 + "px",
-        }}
-      >
-        X
-      </p>
+        <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.simulationType == "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>
-  </div>
+    )
   }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From d8fe4e0b9924b6f7f6f79da7745642d68bef5436 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Tue, 16 May 2023 21:22:46 -0400
Subject: finish tutorial

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      |  80 +++++++++++-
 .../PhysicsBox/PhysicsSimulationTutorial.json      | 136 ++++++++++++++++++++-
 2 files changed, 207 insertions(+), 9 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 7bb5d0e98..9741ddc3e 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -2105,7 +2105,6 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     )}{" "}
                     {this.dataDoc.simulationPaused &&
                       this.dataDoc.simulationType != "Inclined Plane" &&
-                      this.dataDoc.simulationType != "Suspension" &&
                       this.dataDoc.simulationType != "Circular Motion" &&
                       this.dataDoc.simulationType != "Pulley" && (
                         <td
@@ -2114,18 +2113,54 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                           }}
                         >
                           <InputField
-                            lowerBound={0}
+                            lowerBound={this.dataDoc.simulationType == "Projectile" ? 1 : (this.xMax + this.xMin) / 4 - this.radius - 15}
                             dataDoc={this.dataDoc}
                             prop={'positionXDisplay'}
                             step={1}
                             unit={"m"}
-                            upperBound={this.xMax - 110}
+                            upperBound={this.dataDoc.simulationType == "Projectile" ? this.xMax - 110 : (3 * (this.xMax + this.xMin)) / 4 - this.radius / 2 - 15}
                             value={this.dataDoc.positionXDisplay}
                             effect={(value) => {
                               this.dataDoc.displayChange = ({
                                 xDisplay: value,
                                 yDisplay: this.dataDoc.positionYDisplay,
                               });
+                              if (this.dataDoc['simulationType'] == "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(this.dataDoc.positionYDisplay) + this.radius;
+                                let dir1T = Math.PI - Math.atan(deltaY / deltaX1);
+                                let dir2T = Math.atan(deltaY / deltaX2);
+                                let tensionMag2 =
+                                  (this.dataDoc.mass * Math.abs(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: this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
+                                  directionInDegrees: 270,
+                                  component: false,
+                                };
+                                this.dataDoc['updatedForces'] = ([tensionForce1, tensionForce2, grav]);
+                              }
                             }}
                             small={true}
                             mode={"Freeform"}
@@ -2143,7 +2178,6 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     )}{" "}
                     {this.dataDoc.simulationPaused &&
                       this.dataDoc.simulationType != "Inclined Plane" &&
-                      this.dataDoc.simulationType != "Suspension" &&
                       this.dataDoc.simulationType != "Circular Motion" &&
                       this.dataDoc.simulationType != "Pulley" && (
                         <td
@@ -2152,7 +2186,7 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                           }}
                         >
                           <InputField
-                            lowerBound={0}
+                            lowerBound={1}
                             dataDoc={this.dataDoc}
                             prop={'positionYDisplay'}
                             step={1}
@@ -2164,6 +2198,42 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                                 xDisplay: this.dataDoc.positionXDisplay,
                                 yDisplay: value,
                               });
+                              if (this.dataDoc['simulationType'] == "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 = this.dataDoc.positionXDisplay + this.radius - x1rod;
+                                let deltaX2 = x2rod - (this.dataDoc.positionXDisplay + 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 =
+                                  (this.dataDoc.mass * Math.abs(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: this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
+                                  directionInDegrees: 270,
+                                  component: false,
+                                };
+                                this.dataDoc['updatedForces'] = ([tensionForce1, tensionForce2, grav]);
+                              }
                             }}
                             small={true}
                             mode={"Freeform"}
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationTutorial.json b/src/client/views/nodes/PhysicsBox/PhysicsSimulationTutorial.json
index 16d1de96c..3015deaa4 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationTutorial.json
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationTutorial.json
@@ -403,7 +403,7 @@
           },
           {
             "description": "Tension",
-            "magnitude": 16.68,
+            "magnitude": 11.77,
             "directionInDegrees": 90,
             "component": false
           }
@@ -423,14 +423,32 @@
         ],
         "showMagnitude": true
       },
-
       {
         "description": "Tension",
-        "content": "The force of tension acts in the positive y direction: π/2 rad. We know that the acceleration in a simple pulley system is  .",
+        "content": "The force of tension acts in the positive y direction: π/2 rad. We know that the acceleration in a simple pulley system is (mass  2 - mass 1) * acceleration due to gravity / (mass 1 + mass 2) = (1.5-1) * 9.81 / (1.5+1) = 1.962 m/s^2. Because the acceleration is caused by the force of gravity and force of tension, we can solve for the force of tension acting on the weight as mass 1 * (a + acceleration due to gravity) = 1 * (1.962+9.81) = 11.77.",
         "forces": [
           {
             "description": "Tension",
-            "magnitude": 16.68,
+            "magnitude": 11.77,
+            "directionInDegrees": 90,
+            "component": false
+          }
+        ],
+        "showMagnitude": true
+      },
+      {
+        "description": "All Forces",
+        "content": "Combining all of the forces, we get the following free body diagram.",
+        "forces": [
+          {
+            "description": "Gravity",
+            "magnitude": 9.81,
+            "directionInDegrees": 270,
+            "component": false
+          },
+          {
+            "description": "Tension",
+            "magnitude": 11.77,
             "directionInDegrees": 90,
             "component": false
           }
@@ -466,6 +484,116 @@
           }
         ],
         "showMagnitude": false
+      },
+      {
+      "description": "Force X Components",
+        "content": "There are two forces with x components to consider: the tension from the left rod and the tension from the right rod. These must cancel each other out so that the net x force is 0.",
+        "forces": [
+          {
+            "description": "Left Tension X Component",
+            "magnitude": 4.907,
+            "directionInDegrees": 180,
+            "component": true
+          },
+          {
+            "description": "Right Tension X Component",
+            "magnitude": 4.907,
+            "directionInDegrees": 0,
+            "component": true
+          }
+        ],
+        "showMagnitude": false
+      }, {
+      "description": "Force Y Components",
+      "content": "There are three forces with y components to consider: the tension from the left rod, the tension from the right rod, and the force of gravity.",
+      "forces": [
+        {
+          "description": "Left Tension Y Component",
+          "magnitude": 4.907,
+          "directionInDegrees": 90,
+          "component": true
+        },
+        {
+          "description": "Right Tension Y Component",
+          "magnitude": 4.907,
+          "directionInDegrees": 90,
+          "component": true
+        },
+        {
+          "description": "Gravity Y Component",
+          "magnitude": 9.81,
+          "directionInDegrees": 270,
+          "component": true
+        }
+      ],
+      "showMagnitude": false
+      }, {
+      "description": "Force Y Components",
+        "content": "The y components of forces must cancel each other out so that the net y force is 0. Thus, gravity = left tension y component + right tension y component. Because the x components of tension are the same and the angles of each rod are the same, the y components must be the same. Thus, the y component for each force of tension must be 9.81/2.",
+        "forces": [
+          {
+            "description": "Left Tension Y Component",
+            "magnitude": 4.907,
+            "directionInDegrees": 90,
+            "component": true
+          },
+          {
+            "description": "Right Tension Y Component",
+            "magnitude": 4.907,
+            "directionInDegrees": 90,
+            "component": true
+          },
+          {
+            "description": "Gravity Y Component",
+            "magnitude": 9.81,
+            "directionInDegrees": 270,
+            "component": true
+          }
+        ],
+        "showMagnitude": true
+      }, {
+      "description": "Tension",
+        "content": "Now that we know the y component of tension for each rod is 4.907, we can solve for the full force of tension as 4.907 = T * sin(45°) -> T = 6.94.",
+        "forces": [
+          {
+            "description": "Left Tension",
+            "magnitude": 6.94,
+            "directionInDegrees": 135,
+            "component": false
+          },
+          {
+            "description": "Right Tension",
+            "magnitude": 6.94,
+            "directionInDegrees": 45,
+            "component": false
+          }
+        ],
+        "showMagnitude": true
+      },
+      {
+        "description": "All Forces",
+        "content": "Combining all of the forces, we get the following free body diagram.",
+        "forces": [
+          {
+            "description": "Gravity",
+            "magnitude": 9.81,
+            "directionInDegrees": 270,
+            "component": false
+          },
+          {
+            "description": "Left Tension",
+            "magnitude": 6.94,
+            "directionInDegrees": 135,
+            "component": false
+          },
+          {
+            "description": "Right Tension",
+            "magnitude": 6.94,
+            "directionInDegrees": 45,
+            "component": false
+          }
+        ],
+        "showMagnitude": true
       }
     ]
   }
-- 
cgit v1.2.3-70-g09d2


From 887a4f7e0fc25fde87b20a5de2e7b0aee561cc78 Mon Sep 17 00:00:00 2001
From: brynnchernosky <56202540+brynnchernosky@users.noreply.github.com>
Date: Tue, 16 May 2023 22:21:32 -0400
Subject: debugging

---
 src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx    | 2 --
 src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx | 5 +----
 2 files changed, 1 insertion(+), 6 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 9741ddc3e..aaea988a2 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -2096,7 +2096,6 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                     </td>
                     {(!this.dataDoc.simulationPaused ||
                       this.dataDoc.simulationType == "Inclined Plane" ||
-                      this.dataDoc.simulationType == "Suspension" ||
                       this.dataDoc.simulationType == "Circular Motion" ||
                       this.dataDoc.simulationType == "Pulley") && (
                       <td style={{ cursor: "default" }}>
@@ -2169,7 +2168,6 @@ export default class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<Fi
                       )}{" "}
                     {(!this.dataDoc.simulationPaused ||
                       this.dataDoc.simulationType == "Inclined Plane" ||
-                      this.dataDoc.simulationType == "Suspension" ||
                       this.dataDoc.simulationType == "Circular Motion" ||
                       this.dataDoc.simulationType == "Pulley") && (
                       <td style={{ cursor: "default" }}>
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index a571f03f7..88af37791 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -971,7 +971,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         className="weightContainer"
         onPointerDown={(e) => {
           if (this.draggable) {
-            console.log('dragging = true')
             this.props.dataDoc['paused'] = true;
             this.setState({dragging: true});
             this.setState({clickPositionX: e.clientX});
@@ -980,7 +979,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         }}
         onPointerMove={(e) => {
           if (this.state.dragging) {
-            console.log('dragging')
             let newY = this.state.yPosition + e.clientY - this.state.clickPositionY;
             if (newY > this.props.yMax - 2 * this.props.radius - 10) {
               newY = this.props.yMax - 2 * this.props.radius - 10;
@@ -1022,7 +1020,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         }}
         onPointerUp={(e) => {
           if (this.state.dragging) {
-            console.log('dragging = false')
             if (
               this.props.dataDoc['simulationType'] != "Pendulum" &&
               this.props.dataDoc['simulationType'] != "Suspension"
@@ -1214,7 +1211,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             ) / 100}
             °
           </p>
-          <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
+          <svg width={this.props.layoutDoc._width + "px"} height={this.props.layoutDoc._height + "px"}>
             <line
               x1={this.state.xPosition + this.props.radius}
               y1={this.state.yPosition + this.props.radius}
-- 
cgit v1.2.3-70-g09d2


From c43b5f144eef86bd07fbb447b7c8a7087f4d0cac Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 22 May 2023 15:32:15 -0400
Subject: start of physics cleanup

---
 src/client/documents/Documents.ts                  |    3 +-
 src/client/util/CurrentUserUtils.ts                |    2 +-
 .../nodes/PhysicsBox/PhysicsSimulationBox.scss     |  128 +-
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 1131 ++++----
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   | 2840 +++++++++-----------
 src/fields/Doc.ts                                  |    2 +-
 6 files changed, 1874 insertions(+), 2232 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 6f8582c2e..4ee3368ab 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -688,8 +688,9 @@ export namespace Docs {
             [
                 DocumentType.SIMULATION,
                 {
+                    data: '',
                     layout: { view: PhysicsSimulationBox, dataField: defaultDataKey },
-                    options: { _height: 100 },
+                    options: { _height: 100, position: '', velocity: '', acceleration: '', pendulum: '',  simulation: '', review: '', show: '', start: '' },
                 },
             ],
         ]);
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index fffb9c79b..4a702cef3 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -266,7 +266,7 @@ export class CurrentUserUtils {
             {key: "Flashcard",  creator: opts => Docs.Create.TextDocument("", opts),        opts: { _width: 200, _layout_autoHeight: true, _layout_altContentUI: true}},
             {key: "Equation",   creator: opts => Docs.Create.EquationDocument(opts),        opts: { _width: 300, _height: 35, }},
             {key: "Noteboard",  creator: opts => Docs.Create.NoteTakingDocument([], opts),  opts: { _width: 250, _height: 200, _layout_fitWidth: true}},
-            {key: "Simulation", creator: opts => Docs.Create.SimulationDocument(opts),      opts: { _width: 300, _height: 300, _freeform_backgroundGrid: true, }},
+            {key: "Simulation", creator: opts => Docs.Create.SimulationDocument(opts),      opts: { _width: 300, _height: 300, }},
             {key: "Collection", creator: opts => Docs.Create.FreeformDocument([], opts),    opts: { _width: 150, _height: 100, _layout_fitWidth: true }},
             {key: "Webpage",    creator: opts => Docs.Create.WebDocument("",opts),          opts: { _width: 400, _height: 512, _nativeWidth: 850, data_useCors: true, }},
             {key: "Comparison", creator: Docs.Create.ComparisonDocument,                    opts: { _width: 300, _height: 300 }},
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
index 7193e3157..c29e36a97 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
@@ -1,76 +1,78 @@
-* {
- box-sizing: border-box;
- font-size: 14px;
-}
+.physicsSimApp {
+    * {
+        box-sizing: border-box;
+        font-size: 14px;
+    }
 
-.mechanicsSimulationContainer {
- background-color: white;
- height: 100%;
- width: 100%;
- display: flex;
+    .mechanicsSimulationContainer {
+        background-color: white;
+        height: 100%;
+        width: 100%;
+        display: flex;
 
- .mechanicsSimulationEquationContainer {
-   position: fixed;
-   left: 60%;
-   padding: 1em;
+        .mechanicsSimulationEquationContainer {
+            position: fixed;
+            left: 60%;
+            padding: 1em;
 
-   .mechanicsSimulationControls {
-     display: flex;
-     justify-content: space-between;
-   }
- }
-}
+            .mechanicsSimulationControls {
+                display: flex;
+                justify-content: space-between;
+            }
+        }
+    }
 
-.coordinateSystem {
- z-index: -100;
-}
+    .coordinateSystem {
+        z-index: -100;
+    }
 
-th,
-td {
- border-collapse: collapse;
- padding: 1em;
-}
+    th,
+    td {
+        border-collapse: collapse;
+        padding: 1em;
+    }
 
-table {
- min-width: 300px;
-}
+    table {
+        min-width: 300px;
+    }
 
-tr:nth-child(even) {
- background-color: #d6eeee;
-}
+    tr:nth-child(even) {
+        background-color: #d6eeee;
+    }
 
-button {
- z-index: 50;
-}
+    button {
+        z-index: 50;
+    }
 
-.angleLabel {
- font-weight: bold;
- font-size: 20px;
- user-select: none;
- pointer-events: none;
-}
+    .angleLabel {
+        font-weight: bold;
+        font-size: 20px;
+        user-select: none;
+        pointer-events: none;
+    }
 
-.mechanicsSimulationSettingsMenu {
-  width: 100%;
-  height: 100%;
-  font-size: 12px;
-  background-color: rgb(224, 224, 224);
-  border-radius: 2px;
-  border-color: black;
-  border-style: solid;
-  padding: 10px;
-  position: fixed;
-  z-index: 1000;
-}
+    .mechanicsSimulationSettingsMenu {
+        width: 100%;
+        height: 100%;
+        font-size: 12px;
+        background-color: rgb(224, 224, 224);
+        border-radius: 2px;
+        border-color: black;
+        border-style: solid;
+        padding: 10px;
+        position: fixed;
+        z-index: 1000;
+    }
 
-.mechanicsSimulationSettingsMenuRow {
-  display: flex;
-}
+    .mechanicsSimulationSettingsMenuRow {
+        display: flex;
+    }
 
-.mechanicsSimulationSettingsMenuRowDescription {
-  width: 50%;
-}
+    .mechanicsSimulationSettingsMenuRowDescription {
+        width: 50%;
+    }
 
-.dropdownMenu {
-  z-index: 50;
-}
\ No newline at end of file
+    .dropdownMenu {
+        z-index: 50;
+    }
+}
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index ab93583df..db15c9a5c 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -1,29 +1,24 @@
-import './PhysicsSimulationBox.scss';
-import { FieldView, FieldViewProps } from './../FieldView';
-import React = require('react');
-import { ViewBoxAnnotatableComponent } from '../../DocComponent';
-import { observer } from 'mobx-react';
-import './PhysicsSimulationBox.scss';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { CheckBox } from '../../search/CheckBox';
+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 ReplayIcon from '@mui/icons-material/Replay';
 import QuestionMarkIcon from '@mui/icons-material/QuestionMark';
-import ArrowLeftIcon from '@mui/icons-material/ArrowLeft';
-import ArrowRightIcon from '@mui/icons-material/ArrowRight';
-import EditIcon from '@mui/icons-material/Edit';
-import EditOffIcon from '@mui/icons-material/EditOff';
-import { Box, Button, Checkbox, Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, FormControl, FormControlLabel, FormGroup, IconButton, LinearProgress, Stack } from '@mui/material';
+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 { NumCast } from '../../../../fields/Types';
-import { HeightSym, WidthSym } from '../../../../fields/Doc';
+import React = require('react');
+import { BoolCast, NumCast, StrCast } from '../../../../fields/Types';
+import { List } from '../../../../fields/List';
 
 interface IWallProps {
     length: number;
@@ -70,7 +65,7 @@ interface TutorialTemplate {
             directionInDegrees: number;
             component: boolean;
         }[];
-        showMagnitude: boolean;
+        show_Magnitude: boolean;
     }[];
 }
 
@@ -99,54 +94,36 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.layoutDoc._height = 800;
         this.xMax = this.layoutDoc._width * 0.6;
         this.yMax = this.layoutDoc._height * 0.9;
-        this.dataDoc.reviewCoefficient = this.dataDoc.reviewCoefficient ?? 0;
-        this.dataDoc.questionVariables = this.dataDoc.questionVariables ?? [];
-        this.dataDoc.accelerationXDisplay = this.dataDoc.accelerationXDisplay ?? 0;
-        this.dataDoc.accelerationYDisplay = this.dataDoc.accelerationYDisplay ?? 0;
         this.dataDoc.componentForces = this.dataDoc.componentForces ?? [];
-        this.dataDoc.displayChange = this.dataDoc.displayChange ?? { xDisplay: 0, yDisplay: 0 };
-        this.dataDoc.elasticCollisions = this.dataDoc.elasticCollisions ?? false;
-        this.dataDoc.gravity = this.dataDoc.gravity ?? -9.81;
-        this.dataDoc.mass = this.dataDoc.mass ?? 1;
+        this.dataDoc.gravity = NumCast(this.dataDoc.gravity, -9.81);
+        this.dataDoc.mass = NumCast(this.dataDoc.mass, 1);
         this.dataDoc.mode = 'Freeform';
-        this.dataDoc.positionXDisplay = this.dataDoc.positionXDisplay ?? 0;
-        this.dataDoc.positionYDisplay = this.dataDoc.positionYDisplay ?? 0;
-        this.dataDoc.showAcceleration = this.dataDoc.showAcceleration ?? false;
-        this.dataDoc.showComponentForces = this.dataDoc.showComponentForces ?? false;
-        this.dataDoc.showForces = this.dataDoc.showForces ?? true;
-        this.dataDoc.showForceMagnitudes = this.dataDoc.showForceMagnitudes ?? true;
-        this.dataDoc.showVelocity = this.dataDoc.showVelocity ?? false;
-        this.dataDoc.simulationPaused = this.dataDoc.simulationPaused ?? true;
-        this.dataDoc.simulationReset = this.dataDoc.simulationReset ?? false;
-        this.dataDoc.simulationSpeed = this.dataDoc.simulationSpeed ?? 2;
-        this.dataDoc.simulationType = this.dataDoc.simulationType ?? 'Inclined Plane';
-        this.dataDoc.startForces = this.dataDoc.startForces ?? [];
-        this.dataDoc.startPosX = this.dataDoc.startPosX ?? Math.round((this.xMax * 0.5 - 200) * 10) / 10;
-        this.dataDoc.startPosY = this.dataDoc.startPosY ?? this.getDisplayYPos((400 - 0.08 * this.layoutDoc._height) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26));
-        this.dataDoc.startVelX = this.dataDoc.startVelX ?? 0;
-        this.dataDoc.startVelY = this.dataDoc.startVelY ?? 0;
-        this.dataDoc.stepNumber = this.dataDoc.stepNumber ?? 0;
+        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 ?? [];
-        this.dataDoc.velocityXDisplay = this.dataDoc.velocityXDisplay ?? 0;
-        this.dataDoc.velocityYDisplay = this.dataDoc.velocityYDisplay ?? 0;
 
         // 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 = [];
-        this.dataDoc.showIcon = false;
+        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.reviewGravityAngle = 0;
-        this.dataDoc.reviewGravityMagnitude = 0;
-        this.dataDoc.reviewNormalAngle = 0;
-        this.dataDoc.reviewNormalMagnitude = 0;
-        this.dataDoc.reviewStaticAngle = 0;
-        this.dataDoc.reviewStaticMagnitude = 0;
+        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;
@@ -158,39 +135,25 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.circularMotionRadius = this.dataDoc.circularMotionRadius ?? 150;
 
         // Used for spring simulation
-        this.dataDoc.springConstant = this.dataDoc.springConstant ?? 0.5;
-        this.dataDoc.springRestLength = this.dataDoc.springRestLength ?? 200;
-        this.dataDoc.springStartLength = this.dataDoc.springStartLength ?? 200;
+        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.adjustPendulumAngle = this.dataDoc.adjustPendulumAngle ?? { angle: 0, length: 0 };
-        this.dataDoc.pendulumAngle = this.dataDoc.pendulumAngle ?? 0;
-        this.dataDoc.pendulumLength = this.dataDoc.pendulumLength ?? 300;
-        this.dataDoc.startPendulumAngle = this.dataDoc.startPendulumAngle ?? 0;
+        this.dataDoc.pendulum_length = NumCast(this.dataDoc.pendulum_length, 300);
 
         // Used for wedge simulation
-        this.dataDoc.coefficientOfKineticFriction = this.dataDoc.coefficientOfKineticFriction ?? 0;
-        this.dataDoc.coefficientOfStaticFriction = this.dataDoc.coefficientOfStaticFriction ?? 0;
-        this.dataDoc.wedgeAngle = this.dataDoc.wedgeAngle ?? 26;
-        this.dataDoc.wedgeHeight = this.dataDoc.wedgeHeight ?? Math.tan((26 * Math.PI) / 180) * this.xMax * 0.5;
-        this.dataDoc.wedgeWidth = this.dataDoc.wedgeWidth ?? this.xMax * 0.5;
+        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.positionXDisplay2 = this.dataDoc.positionXDisplay2 ?? 0;
-        this.dataDoc.velocityXDisplay2 = this.dataDoc.velocityXDisplay2 ?? 0;
-        this.dataDoc.accelerationXDisplay2 = this.dataDoc.accelerationXDisplay2 ?? 0;
-        this.dataDoc.positionYDisplay2 = this.dataDoc.positionYDisplay2 ?? 0;
-        this.dataDoc.velocityYDisplay2 = this.dataDoc.velocityYDisplay2 ?? 0;
-        this.dataDoc.accelerationYDisplay2 = this.dataDoc.accelerationYDisplay2 ?? 0;
-        this.dataDoc.startPosX2 = this.dataDoc.startPosX2 ?? 0;
-        this.dataDoc.startPosY2 = this.dataDoc.startPosY2 ?? 0;
-        this.dataDoc.displayChange2 = this.dataDoc.displayChange2 ?? { xDisplay: 0, yDisplay: 0 };
-        this.dataDoc.startForces2 = this.dataDoc.startForces2 ?? [];
+        this.dataDoc.start_Forces2 = this.dataDoc.start_Forces2 ?? [];
         this.dataDoc.updatedForces2 = this.dataDoc.updatedForces2 ?? [];
-        this.dataDoc.mass2 = this.dataDoc.mass2 ?? 1;
+        this.dataDoc.mass2 = NumCast(this.dataDoc.mass2, 1);
 
         // Setup simulation
-        this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode);
+        this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
 
         // Create walls
         let walls = [];
@@ -207,54 +170,54 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             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(this.dataDoc.simulationType, this.dataDoc.mode);
+            this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
         }
     }
 
     setupSimulation = (simulationType: string, mode: string) => {
-        this.dataDoc.simulationPaused = true;
+        this.dataDoc.simulation_Paused = true;
         if (simulationType != 'Circular Motion') {
-            this.dataDoc.startVelX = 0;
+            this.dataDoc.start_VelX = 0;
             this.dataDoc.setStartVelY = 0;
-            this.dataDoc.velocityXDisplay = 0;
-            this.dataDoc.velocityYDisplay = 0;
+            this.dataDoc.velocity_XDisplay = 0;
+            this.dataDoc.velocity_YDisplay = 0;
         }
         if (mode == 'Freeform') {
-            this.dataDoc.showForceMagnitudes = true;
+            this.dataDoc.show_ForceMagnitudes = true;
             if (simulationType == 'One Weight') {
-                this.dataDoc.showComponentForces = false;
-                this.dataDoc.startPosY = this.yMin + 0.08 * this.layoutDoc[HeightSym]();
-                this.dataDoc.startPosX = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
-                this.dataDoc.positionYDisplay = this.getDisplayYPos(this.yMin + 0.08 * this.layoutDoc[HeightSym]());
-                this.dataDoc.positionXDisplay = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
+                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(this.dataDoc.gravity) * this.dataDoc.mass,
+                        magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
                         directionInDegrees: 270,
                         component: false,
                     },
                 ];
-                this.dataDoc.startForces = [
+                this.dataDoc.start_Forces = [
                     {
                         description: 'Gravity',
-                        magnitude: Math.abs(this.dataDoc.gravity) * this.dataDoc.mass,
+                        magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
                         directionInDegrees: 270,
                         component: false,
                     },
                 ];
-                this.dataDoc.simulationReset = !this.dataDoc.simulationReset;
+                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
             } else if (simulationType == 'Inclined Plane') {
                 this.changeWedgeBasedOnNewAngle(26);
-                this.dataDoc.startForces = [
+                this.dataDoc.start_Forces = [
                     {
                         description: 'Gravity',
-                        magnitude: Math.abs(this.dataDoc.gravity) * this.dataDoc.mass,
+                        magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
                         directionInDegrees: 270,
                         component: false,
                     },
                 ];
-                this.updateForcesWithFriction(Number(this.dataDoc.coefficientOfStaticFriction));
+                this.updateForcesWithFriction(NumCast(this.dataDoc.coefficientOfStaticFriction));
             } else if (simulationType == 'Pendulum') {
                 this.setupPendulum();
             } else if (simulationType == 'Spring') {
@@ -267,11 +230,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.setupSuspension();
             }
         } else if (mode == 'Review') {
-            this.dataDoc.showComponentForces = false;
-            this.dataDoc.showForceMagnitudes = true;
-            this.dataDoc.showAcceleration = false;
-            this.dataDoc.showVelocity = false;
-            this.dataDoc.showForces = true;
+            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
@@ -280,7 +243,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 // TODO - spring review problems
             } else if (simulationType == 'Inclined Plane') {
                 this.dataDoc.updatedForces = [];
-                this.dataDoc.startForces = [];
+                this.dataDoc.start_Forces = [];
             } else if (simulationType == 'Pendulum') {
                 this.setupPendulum();
                 // TODO - pendulum review problems
@@ -295,77 +258,78 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 // TODO - suspension tutorial review problems
             }
         } else if (mode == 'Tutorial') {
-            this.dataDoc.showComponentForces = false;
+            this.dataDoc.show_ComponentForces = false;
             this.dataDoc.stepNumber = 0;
-            this.dataDoc.showAcceleration = false;
-            if (this.dataDoc.simulationType != 'Circular Motion') {
-                this.dataDoc.velocityXDisplay = 0;
-                this.dataDoc.velocityYDisplay = 0;
-                this.dataDoc.showVelocity = false;
+            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.velocityXDisplay = 20;
-                this.dataDoc.velocityYDisplay = 0;
-                this.dataDoc.showVelocity = true;
+                this.dataDoc.velocity_XDisplay = 20;
+                this.dataDoc.velocity_YDisplay = 0;
+                this.dataDoc.show_Velocity = true;
             }
 
-            if (this.dataDoc.simulationType == 'One Weight') {
-                this.dataDoc.showForces = true;
-                this.dataDoc.startPosY = this.yMax - 100;
-                this.dataDoc.startPosX = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
+            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.startForces = this.getForceFromJSON(tutorials.freeWeight.steps[0].forces);
-                this.dataDoc.showForceMagnitudes = tutorials.freeWeight.steps[0].showMagnitude;
-            } else if (this.dataDoc.simulationType == 'Spring') {
-                this.dataDoc.showForces = true;
+                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.startPosY = this.yMin + 200 + 19.62;
-                this.dataDoc.startPosX = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
+                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.startForces = this.getForceFromJSON(tutorials.spring.steps[0].forces);
-                this.dataDoc.showForceMagnitudes = tutorials.spring.steps[0].showMagnitude;
-            } else if (this.dataDoc.simulationType == 'Pendulum') {
-                this.dataDoc.showForces = true;
+                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.startPosX = xPos;
-                this.dataDoc.startPosY = yPos;
+                this.dataDoc.start_PosX = xPos;
+                this.dataDoc.start_PosY = yPos;
                 this.dataDoc.selectedTutorial = tutorials.pendulum;
-                this.dataDoc.startForces = this.getForceFromJSON(tutorials.pendulum.steps[0].forces);
-                this.dataDoc.showForceMagnitudes = tutorials.pendulum.steps[0].showMagnitude;
-                this.dataDoc.pendulumAngle = 30;
-                this.dataDoc.pendulumLength = 300;
-                this.dataDoc.adjustPendulumAngle = { angle: 30, length: 300 };
-            } else if (this.dataDoc.simulationType == 'Inclined Plane') {
-                this.dataDoc.showForces = true;
+                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.startForces = this.getForceFromJSON(tutorials.inclinePlane.steps[0].forces);
-                this.dataDoc.showForceMagnitudes = tutorials.inclinePlane.steps[0].showMagnitude;
-            } else if (this.dataDoc.simulationType == 'Circular Motion') {
-                this.dataDoc.showForces = true;
+                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.startForces = this.getForceFromJSON(tutorials.circular.steps[0].forces);
-                this.dataDoc.showForceMagnitudes = tutorials.circular.steps[0].showMagnitude;
-            } else if (this.dataDoc.simulationType == 'Pulley') {
-                this.dataDoc.showForces = true;
+                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.startForces = this.getForceFromJSON(tutorials.pulley.steps[0].forces);
-                this.dataDoc.showForceMagnitudes = tutorials.pulley.steps[0].showMagnitude;
-            } else if (this.dataDoc.simulationType == 'Suspension') {
-                this.dataDoc.showForces = true;
+                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.startForces = this.getForceFromJSON(tutorials.suspension.steps[0].forces);
-                this.dataDoc.showForceMagnitudes = tutorials.suspension.steps[0].showMagnitude;
+                this.dataDoc.start_Forces = this.getForceFromJSON(tutorials.suspension.steps[0].forces);
+                this.dataDoc.show_ForceMagnitudes = tutorials.suspension.steps[0].showMagnitude;
             }
-            this.dataDoc.simulationReset = !this.dataDoc.simulationReset;
+            this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
         }
     };
 
@@ -378,62 +342,63 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     };
 
     // Update forces when coefficient of static friction changes in freeform mode
-    updateForcesWithFriction = (coefficient: number, width: number = this.dataDoc.wedgeWidth, height: number = this.dataDoc.wedgeHeight) => {
+    updateForcesWithFriction = (coefficient: number, width: number = NumCast(this.dataDoc.wedgeWidth), height: number = NumCast(this.dataDoc.wedgeHeight)) => {
         const normalForce: IForce = {
             description: 'Normal Force',
-            magnitude: Math.abs(this.dataDoc.gravity) * Math.cos(Math.atan(height / width)) * this.dataDoc.mass,
+            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(this.dataDoc.gravity) * Math.cos(Math.atan(height / width)) * this.dataDoc.mass,
+            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(this.dataDoc.gravity) * this.dataDoc.mass;
+        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(this.dataDoc.gravity) * this.dataDoc.mass) / Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
+            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(this.dataDoc.gravity) * Math.cos(Math.atan(height / width)),
+            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(this.dataDoc.gravity) * Math.cos(Math.atan(height / width)),
+            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: this.dataDoc.mass * Math.abs(this.dataDoc.gravity) * Math.sin(Math.PI / 2 - Math.atan(height / width)),
+            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: this.dataDoc.mass * Math.abs(this.dataDoc.gravity) * Math.cos(Math.PI / 2 - Math.atan(height / width)),
+            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: this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
+            magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
             directionInDegrees: 270,
             component: false,
         };
         if (coefficient != 0) {
-            this.dataDoc.startForces = [gravityForce, normalForce, frictionForce];
+            this.dataDoc.start_Forces = [gravityForce, normalForce, frictionForce];
             this.dataDoc.updatedForces = [gravityForce, normalForce, frictionForce];
             this.dataDoc.componentForces = [frictionForceComponent, normalForceComponent, gravityParallel, gravityPerpendicular];
         } else {
-            this.dataDoc.startForces = [gravityForce, normalForce];
+            this.dataDoc.start_Forces = [gravityForce, normalForce];
             this.dataDoc.updatedForces = [gravityForce, normalForce];
             this.dataDoc.componentForces = [normalForceComponent, gravityParallel, gravityPerpendicular];
         }
@@ -468,65 +433,65 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.52;
         }
 
-        this.dataDoc.startPosX = this.xMax * 0.25;
-        this.dataDoc.startPosY = yPos;
+        this.dataDoc.start_PosX = this.xMax * 0.25;
+        this.dataDoc.start_PosY = yPos;
         if (this.dataDoc.mode == 'Freeform') {
-            this.updateForcesWithFriction(Number(this.dataDoc.coefficientOfStaticFriction), this.xMax * 0.5, Math.tan((angle * Math.PI) / 180) * this.xMax * 0.5);
+            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 = Number(this.dataDoc.wedgeAngle);
+        let theta: number = NumCast(this.dataDoc.wedgeAngle);
         let index = this.dataDoc.selectedQuestion.variablesForQuestionSetup.indexOf('theta - max 45');
         if (index >= 0) {
-            theta = this.dataDoc.questionVariables[index];
+            theta = NumListCast(this.dataDoc.questionVariables)[index];
         }
         if (isNaN(theta)) {
             return;
         }
-        this.dataDoc.reviewGravityMagnitude = Math.abs(this.dataDoc.gravity);
-        this.dataDoc.reviewGravityAngle = 270;
-        this.dataDoc.reviewNormalMagnitude = Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180);
-        this.dataDoc.reviewNormalAngle = 90 - theta;
-        let yForce = -Math.abs(this.dataDoc.gravity);
-        yForce += Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180) * Math.sin(((90 - theta) * Math.PI) / 180);
-        yForce += coefficient * Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180) * Math.sin(((180 - theta) * Math.PI) / 180);
-        let friction = coefficient * Math.abs(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180);
+        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(this.dataDoc.gravity) * Math.cos((theta * Math.PI) / 180)) * Math.sin(((90 - theta) * Math.PI) / 180) + Math.abs(this.dataDoc.gravity)) / Math.sin(((180 - theta) * Math.PI) / 180);
+            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.reviewStaticMagnitude = friction;
-        this.dataDoc.reviewStaticAngle = 180 - theta;
+        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.reviewGravityMagnitude = Math.abs(this.dataDoc.gravity);
-        this.dataDoc.reviewGravityAngle = 270;
-        this.dataDoc.reviewNormalMagnitude = Math.abs(this.dataDoc.gravity) * Math.cos((Number(angle) * Math.PI) / 180);
-        this.dataDoc.reviewNormalAngle = 90 - angle;
-        let yForce = -Math.abs(this.dataDoc.gravity);
-        yForce += Math.abs(this.dataDoc.gravity) * Math.cos((Number(angle) * Math.PI) / 180) * Math.sin(((90 - Number(angle)) * Math.PI) / 180);
-        yForce += this.dataDoc.reviewCoefficient * Math.abs(this.dataDoc.gravity) * Math.cos((Number(angle) * Math.PI) / 180) * Math.sin(((180 - Number(angle)) * Math.PI) / 180);
-        let friction = this.dataDoc.reviewCoefficient * Math.abs(this.dataDoc.gravity) * Math.cos((Number(angle) * Math.PI) / 180);
+        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(this.dataDoc.gravity) * Math.cos((Number(angle) * Math.PI) / 180)) * Math.sin(((90 - Number(angle)) * Math.PI) / 180) + Math.abs(this.dataDoc.gravity)) / Math.sin(((180 - Number(angle)) * Math.PI) / 180);
+            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.reviewStaticMagnitude = friction;
-        this.dataDoc.reviewStaticAngle = 180 - angle;
+        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 = Number(this.dataDoc.wedgeAngle);
+        let theta: number = NumCast(this.dataDoc.wedgeAngle);
         let index = question.variablesForQuestionSetup.indexOf('theta - max 45');
         if (index >= 0) {
             theta = questionVars[index];
         }
-        let muS: number = Number(this.dataDoc.coefficientOfStaticFriction);
+        let muS: number = NumCast(this.dataDoc.coefficientOfStaticFriction);
         index = question.variablesForQuestionSetup.indexOf('coefficient of static friction');
         if (index >= 0) {
             muS = questionVars[index];
@@ -534,25 +499,25 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
 
         for (let i = 0; i < question.answerSolutionDescriptions.length; i++) {
             const description = question.answerSolutionDescriptions[i];
-            if (!isNaN(Number(description))) {
-                solutions.push(Number(description));
+            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(this.dataDoc.gravity) * Math.cos((theta / 180) * Math.PI));
+                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(this.dataDoc.gravity) * Math.cos((theta / 180) * Math.PI);
+                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(this.dataDoc.gravity)) / Math.sin((frictionForceAngle * Math.PI) / 180);
+                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(this.dataDoc.gravity) * Math.cos((theta / 180) * Math.PI);
+                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(this.dataDoc.gravity)) / Math.sin((frictionForceAngle * Math.PI) / 180);
+                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') {
@@ -570,35 +535,35 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         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(this.dataDoc.reviewGravityMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon) {
+                    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(this.dataDoc.reviewGravityAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
+                    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(this.dataDoc.reviewNormalMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon) {
+                    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(this.dataDoc.reviewNormalAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
+                    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(this.dataDoc.reviewStaticMagnitude - this.dataDoc.selectedSolutions[i]) > epsilon) {
+                    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(this.dataDoc.reviewStaticAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
+                    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(Number(this.dataDoc.coefficientOfStaticFriction) - this.dataDoc.selectedSolutions[i]) > epsilon) {
+                    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(Number(this.dataDoc.wedgeAngle) - this.dataDoc.selectedSolutions[i]) > epsilon) {
+                    if (Math.abs(NumCast(this.dataDoc.wedgeAngle) - this.dataDoc.selectedSolutions[i]) > epsilon) {
                         error = true;
                     }
                 }
@@ -606,14 +571,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         }
         if (showAlert) {
             if (!error) {
-                this.dataDoc.simulationPaused = false;
+                this.dataDoc.simulation_Paused = false;
                 setTimeout(() => {
-                    this.dataDoc.simulationPaused = true;
+                    this.dataDoc.simulation_Paused = true;
                 }, 3000);
             } else {
-                this.dataDoc.simulationPaused = false;
+                this.dataDoc.simulation_Paused = false;
                 setTimeout(() => {
-                    this.dataDoc.simulationPaused = true;
+                    this.dataDoc.simulation_Paused = true;
                 }, 3000);
             }
         }
@@ -628,14 +593,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
 
     // Reset all review values to default
     resetReviewValuesToDefault = () => {
-        this.dataDoc.reviewGravityMagnitude = 0;
-        this.dataDoc.reviewGravityAngle = 0;
-        this.dataDoc.reviewNormalMagnitude = 0;
-        this.dataDoc.reviewNormalAngle = 0;
-        this.dataDoc.reviewStaticMagnitude = 0;
-        this.dataDoc.reviewStaticAngle = 0;
+        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.simulationPaused = true;
+        this.dataDoc.simulation_Paused = true;
     };
 
     // In review mode, reset problem variables and generate a new question
@@ -645,13 +610,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         const vars: number[] = [];
         let question: QuestionTemplate = questions.inclinePlane[0];
 
-        if (this.dataDoc.simulationType == 'Inclined Plane') {
-            if (this.dataDoc.questionNumber == questions.inclinePlane.length - 1) {
+        if (this.dataDoc.simulation_Type == 'Inclined Plane') {
+            if (this.dataDoc.questionNumber === questions.inclinePlane.length - 1) {
                 this.dataDoc.questionNumber = 0;
             } else {
-                this.dataDoc.questionNumber = this.dataDoc.questionNumber + 1;
+                this.dataDoc.questionNumber = NumCast(this.dataDoc.questionNumber) + 1;
             }
-            question = questions.inclinePlane[this.dataDoc.questionNumber];
+            question = questions.inclinePlane[NumCast(this.dataDoc.questionNumber)];
 
             let coefficient = 0;
             let wedgeAngle = 0;
@@ -670,7 +635,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             this.dataDoc.wedgeAngle = wedgeAngle;
             this.changeWedgeBasedOnNewAngle(wedgeAngle);
             this.dataDoc.coefficientOfStaticFriction = coefficient;
-            this.dataDoc.reviewCoefficient = coefficient;
+            this.dataDoc.review_Coefficient = coefficient;
         }
         let q = '';
         for (let i = 0; i < question.questionSetup.length; i++) {
@@ -682,32 +647,32 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 }
             }
         }
-        this.dataDoc.questionVariables = vars;
+        this.dataDoc.questionVariables = new List<number>(vars);
         this.dataDoc.selectedQuestion = question;
         this.dataDoc.questionPartOne = q;
         this.dataDoc.questionPartTwo = question.question;
-        this.dataDoc.answers = this.getAnswersToQuestion(question, vars);
-        //this.dataDoc.simulationReset = (!this.dataDoc.simulationReset);
+        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.showComponentForces = false;
-        this.dataDoc.startVelY = 0;
-        this.dataDoc.startVelX = value;
+        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 + this.dataDoc.circularMotionRadius - 0.08 * this.layoutDoc[HeightSym]();
-        this.dataDoc.startPosY = yPos;
-        this.dataDoc.startPosX = xPos;
+        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.startVelX ** 2 * this.dataDoc.mass) / this.dataDoc.circularMotionRadius,
+            magnitude: (this.dataDoc.start_VelX ** 2 * NumCast(this.dataDoc.mass)) / NumCast(this.dataDoc.circularMotionRadius),
             directionInDegrees: 90,
             component: false,
         };
         this.dataDoc.updatedForces = [tensionForce];
-        this.dataDoc.startForces = [tensionForce];
-        this.dataDoc.simulationReset = !this.dataDoc.simulationReset;
+        this.dataDoc.start_Forces = [tensionForce];
+        this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
     };
 
     // Default setup for pendulum simulation
@@ -718,9 +683,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         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.startPosX = xPos;
-        this.dataDoc.startPosY = yPos;
-        const mag = this.dataDoc.mass * Math.abs(this.dataDoc.gravity) * Math.sin((60 * Math.PI) / 180);
+        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,
@@ -736,13 +701,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         };
         const gravityParallel: IForce = {
             description: 'Gravity Parallel Component',
-            magnitude: this.dataDoc.mass * Math.abs(this.dataDoc.gravity) * Math.sin(((90 - angle) * Math.PI) / 180),
+            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: this.dataDoc.mass * Math.abs(this.dataDoc.gravity) * Math.cos(((90 - angle) * Math.PI) / 180),
+            magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos(((90 - angle) * Math.PI) / 180),
             directionInDegrees: -angle,
             component: true,
         };
@@ -751,55 +716,56 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.updatedForces = [
             {
                 description: 'Gravity',
-                magnitude: this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
+                magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
                 directionInDegrees: 270,
                 component: false,
             },
             forceOfTension,
         ];
-        this.dataDoc.startForces = [
+        this.dataDoc.start_Forces = [
             {
                 description: 'Gravity',
-                magnitude: this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
+                magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
                 directionInDegrees: 270,
                 component: false,
             },
             forceOfTension,
         ];
-        this.dataDoc.startPendulumAngle = 30;
-        this.dataDoc.pendulumAngle = 30;
-        this.dataDoc.pendulumLength = 300;
-        this.dataDoc.adjustPendulumAngle = { angle: 30, length: 300 };
+        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.showComponentForces = false;
+        this.dataDoc.show_ComponentForces = false;
         const gravityForce: IForce = {
             description: 'Gravity',
-            magnitude: Math.abs(this.dataDoc.gravity) * this.dataDoc.mass,
+            magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
             directionInDegrees: 270,
             component: false,
         };
         this.dataDoc.updatedForces = [gravityForce];
-        this.dataDoc.startForces = [gravityForce];
-        this.dataDoc.startPosX = this.xMax / 2 - 0.08 * this.layoutDoc[HeightSym]();
-        this.dataDoc.startPosY = 200;
+        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.simulationReset = !this.dataDoc.simulationReset;
+        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.startPosY = yPos;
-        this.dataDoc.startPosX = xPos;
-        this.dataDoc.positionYDisplay = this.getDisplayYPos(yPos);
-        this.dataDoc.positionXDisplay = xPos;
-        let tensionMag = (this.dataDoc.mass * Math.abs(this.dataDoc.gravity)) / (2 * Math.sin(Math.PI / 4));
+        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,
@@ -814,59 +780,59 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         };
         const grav: IForce = {
             description: 'Gravity',
-            magnitude: this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
+            magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
             directionInDegrees: 270,
             component: false,
         };
         this.dataDoc.updatedForces = [tensionForce1, tensionForce2, grav];
-        this.dataDoc.startForces = [tensionForce1, tensionForce2, grav];
-        this.dataDoc.simulationReset = !this.dataDoc.simulationReset;
+        this.dataDoc.start_Forces = [tensionForce1, tensionForce2, grav];
+        this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
     };
 
     // Default setup for pulley simulation
     setupPulley = () => {
-        this.dataDoc.showComponentForces = false;
-        this.dataDoc.startPosY = (this.yMax + this.yMin) / 2;
-        this.dataDoc.startPosX = (this.xMin + this.xMax) / 2 - 2 * (0.08 * this.layoutDoc[HeightSym]()) - 5;
-        this.dataDoc.positionYDisplay = this.getDisplayYPos((this.yMax + this.yMin) / 2);
-        this.dataDoc.positionXDisplay = (this.xMin + this.xMax) / 2 - 2 * (0.08 * this.layoutDoc[HeightSym]()) - 5;
-        let a = (-1 * ((this.dataDoc.mass - this.dataDoc.mass2) * Math.abs(this.dataDoc.gravity))) / (this.dataDoc.mass + this.dataDoc.mass2);
+        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: this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
+            magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
             directionInDegrees: 270,
             component: false,
         };
         const tensionForce1: IForce = {
             description: 'Tension',
-            magnitude: this.dataDoc.mass * a + this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
+            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: this.dataDoc.mass2 * Math.abs(this.dataDoc.gravity),
+            magnitude: NumCast(this.dataDoc.mass2) * Math.abs(NumCast(this.dataDoc.gravity)),
             directionInDegrees: 270,
             component: false,
         };
         const tensionForce2: IForce = {
             description: 'Tension',
-            magnitude: this.dataDoc.mass2 * a + this.dataDoc.mass2 * Math.abs(this.dataDoc.gravity),
+            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.startForces = [gravityForce1, tensionForce1];
-        this.dataDoc.startPosY2 = (this.yMax + this.yMin) / 2;
-        this.dataDoc.startPosX2 = (this.xMin + this.xMax) / 2 + 5;
-        this.dataDoc.positionYDisplay2 = this.getDisplayYPos((this.yMax + this.yMin) / 2);
-        this.dataDoc.positionXDisplay2 = (this.xMin + this.xMax) / 2 + 5;
+        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.startForces2 = [gravityForce2, tensionForce2];
+        this.dataDoc.start_Forces2 = [gravityForce2, tensionForce2];
 
-        this.dataDoc.simulationReset = !this.dataDoc.simulationReset;
+        this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
     };
 
     // Helper function used for tutorial and review mode
@@ -895,23 +861,23 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     updateReviewModeValues = () => {
         const forceOfGravityReview: IForce = {
             description: 'Gravity',
-            magnitude: this.dataDoc.reviewGravityMagnitude,
-            directionInDegrees: this.dataDoc.reviewGravityAngle,
+            magnitude: NumCast(this.dataDoc.review_GravityMagnitude),
+            directionInDegrees: NumCast(this.dataDoc.review_GravityAngle),
             component: false,
         };
         const normalForceReview: IForce = {
             description: 'Normal Force',
-            magnitude: this.dataDoc.reviewNormalMagnitude,
-            directionInDegrees: this.dataDoc.reviewNormalAngle,
+            magnitude: NumCast(this.dataDoc.review_NormalMagnitude),
+            directionInDegrees: NumCast(this.dataDoc.review_NormalAngle),
             component: false,
         };
         const staticFrictionForceReview: IForce = {
             description: 'Static Friction Force',
-            magnitude: this.dataDoc.reviewStaticMagnitude,
-            directionInDegrees: this.dataDoc.reviewStaticAngle,
+            magnitude: NumCast(this.dataDoc.review_StaticMagnitude),
+            directionInDegrees: NumCast(this.dataDoc.review_StaticAngle),
             component: false,
         };
-        this.dataDoc.startForces = [forceOfGravityReview, normalForceReview, staticFrictionForceReview];
+        this.dataDoc.start_Forces = [forceOfGravityReview, normalForceReview, staticFrictionForceReview];
         this.dataDoc.updatedForces = [forceOfGravityReview, normalForceReview, staticFrictionForceReview];
     };
 
@@ -922,7 +888,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                     <div className="mechanicsSimulationContentContainer">
                         <div className="mechanicsSimulationButtonsAndElements">
                             <div className="mechanicsSimulationButtons">
-                                {!this.dataDoc.simulationPaused && (
+                                {!this.dataDoc.simulation_Paused && (
                                     <div
                                         style={{
                                             position: 'fixed',
@@ -939,92 +905,96 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     dataDoc={this.dataDoc}
                                     layoutDoc={this.layoutDoc}
                                     wallPositions={this.wallPositions}
-                                    adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
-                                    gravity={this.dataDoc.gravity}
-                                    circularMotionRadius={this.dataDoc.circularMotionRadius}
+                                    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={this.dataDoc.showComponentForces}
+                                    showComponentForces={BoolCast(this.dataDoc.show_ComponentForces)}
                                     color={'red'}
-                                    coefficientOfKineticFriction={Number(this.dataDoc.coefficientOfKineticFriction)}
-                                    displayXVelocity={this.dataDoc.velocityXDisplay}
-                                    displayYVelocity={this.dataDoc.velocityYDisplay}
-                                    elasticCollisions={this.dataDoc.elasticCollisions}
-                                    mass={this.dataDoc.mass}
-                                    mode={this.dataDoc.mode}
-                                    noMovement={this.dataDoc.noMovement}
-                                    paused={this.dataDoc.simulationPaused}
-                                    pendulumAngle={this.dataDoc.pendulumAngle}
-                                    pendulumLength={this.dataDoc.pendulumLength}
+                                    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={this.dataDoc.simulationReset}
-                                    simulationSpeed={this.dataDoc.simulationSpeed}
-                                    startPendulumAngle={this.dataDoc.startPendulumAngle}
-                                    showAcceleration={this.dataDoc.showAcceleration}
-                                    showForceMagnitudes={this.dataDoc.showForceMagnitudes}
-                                    showForces={this.dataDoc.showForces}
-                                    showVelocity={this.dataDoc.showVelocity}
-                                    simulationType={this.dataDoc.simulationType}
-                                    springConstant={this.dataDoc.springConstant}
-                                    springStartLength={this.dataDoc.springStartLength}
-                                    springRestLength={this.dataDoc.springRestLength}
-                                    startForces={this.dataDoc.startForces}
-                                    startPosX={this.dataDoc.startPosX}
-                                    startPosY={this.dataDoc.startPosY ?? 0}
-                                    startVelX={this.dataDoc.startVelX}
-                                    startVelY={this.dataDoc.startVelY}
+                                    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}
-                                    updateDisplay={this.dataDoc.displayChange}
+                                    updateXDisplay={NumCast(this.dataDoc.display_xChange)}
+                                    updateYDisplay={NumCast(this.dataDoc.display_yChange)}
                                     updatedForces={this.dataDoc.updatedForces}
-                                    wedgeHeight={this.dataDoc.wedgeHeight}
-                                    wedgeWidth={this.dataDoc.wedgeWidth}
+                                    wedgeHeight={NumCast(this.dataDoc.wedgeHeight)}
+                                    wedgeWidth={NumCast(this.dataDoc.wedgeWidth)}
                                     xMax={this.xMax}
                                     xMin={this.xMin}
                                     yMax={this.yMax}
                                     yMin={this.yMin}
                                 />
-                                {this.dataDoc.simulationType == 'Pulley' && (
+                                {this.dataDoc.simulation_Type == 'Pulley' && (
                                     <Weight
                                         dataDoc={this.dataDoc}
                                         layoutDoc={this.layoutDoc}
                                         wallPositions={this.wallPositions}
-                                        adjustPendulumAngle={this.dataDoc.adjustPendulumAngle}
-                                        circularMotionRadius={this.dataDoc.circularMotionRadius}
-                                        gravity={this.dataDoc.gravity}
+                                        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={this.dataDoc.showComponentForces}
+                                        showComponentForces={BoolCast(this.dataDoc.show_ComponentForces)}
                                         color={'blue'}
-                                        coefficientOfKineticFriction={Number(this.dataDoc.coefficientOfKineticFriction)}
-                                        displayXVelocity={this.dataDoc.velocityXDisplay2}
-                                        displayYVelocity={this.dataDoc.velocityYDisplay2}
-                                        elasticCollisions={this.dataDoc.elasticCollisions}
-                                        mass={this.dataDoc.mass2}
-                                        mode={this.dataDoc.mode}
-                                        noMovement={this.dataDoc.noMovement}
-                                        paused={this.dataDoc.simulationPaused}
-                                        pendulumAngle={this.dataDoc.pendulumAngle}
-                                        pendulumLength={this.dataDoc.pendulumLength}
+                                        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={this.dataDoc.simulationReset}
-                                        simulationSpeed={this.dataDoc.simulationSpeed}
-                                        startPendulumAngle={this.dataDoc.startPendulumAngle}
-                                        showAcceleration={this.dataDoc.showAcceleration}
-                                        showForceMagnitudes={this.dataDoc.showForceMagnitudes}
-                                        showForces={this.dataDoc.showForces}
-                                        showVelocity={this.dataDoc.showVelocity}
-                                        simulationType={this.dataDoc.simulationType}
-                                        springConstant={this.dataDoc.springConstant}
-                                        springStartLength={this.dataDoc.springStartLength}
-                                        springRestLength={this.dataDoc.springRestLength}
-                                        startForces={this.dataDoc.startForces2}
-                                        startPosX={this.dataDoc.startPosX2}
-                                        startPosY={this.dataDoc.startPosY2}
-                                        startVelX={this.dataDoc.startVelX}
-                                        startVelY={this.dataDoc.startVelY}
+                                        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}
-                                        updateDisplay={this.dataDoc.displayChange2}
+                                        updateXDisplay={NumCast(this.dataDoc.display_xChange2)}
+                                        updateYDisplay={NumCast(this.dataDoc.display_yChange2)}
                                         updatedForces={this.dataDoc.updatedForces2}
-                                        wedgeHeight={this.dataDoc.wedgeHeight}
-                                        wedgeWidth={this.dataDoc.wedgeWidth}
+                                        wedgeHeight={NumCast(this.dataDoc.wedgeHeight)}
+                                        wedgeWidth={NumCast(this.dataDoc.wedgeWidth)}
                                         xMax={this.xMax}
                                         xMin={this.xMin}
                                         yMax={this.yMax}
@@ -1033,7 +1003,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 )}
                             </div>
                             <div>
-                                {(this.dataDoc.simulationType == 'One Weight' || this.dataDoc.simulationType == 'Inclined Plane') &&
+                                {(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} />;
@@ -1044,26 +1014,26 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                     <div className="mechanicsSimulationEquationContainer">
                         <div className="mechanicsSimulationControls">
                             <Stack direction="row" spacing={1}>
-                                {this.dataDoc.simulationPaused && this.dataDoc.mode != 'Tutorial' && (
+                                {this.dataDoc.simulation_Paused && this.dataDoc.mode != 'Tutorial' && (
                                     <IconButton
                                         onClick={() => {
-                                            this.dataDoc.simulationPaused = false;
+                                            this.dataDoc.simulation_Paused = false;
                                         }}>
                                         <PlayArrowIcon />
                                     </IconButton>
                                 )}
-                                {!this.dataDoc.simulationPaused && this.dataDoc.mode != 'Tutorial' && (
+                                {!this.dataDoc.simulation_Paused && this.dataDoc.mode != 'Tutorial' && (
                                     <IconButton
                                         onClick={() => {
-                                            this.dataDoc.simulationPaused = true;
+                                            this.dataDoc.simulation_Paused = true;
                                         }}>
                                         <PauseIcon />
                                     </IconButton>
                                 )}
-                                {this.dataDoc.simulationPaused && this.dataDoc.mode != 'Tutorial' && (
+                                {this.dataDoc.simulation_Paused && this.dataDoc.mode != 'Tutorial' && (
                                     <IconButton
                                         onClick={() => {
-                                            this.dataDoc.simulationReset = !this.dataDoc.simulationReset;
+                                            this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                         }}>
                                         <ReplayIcon />
                                     </IconButton>
@@ -1071,10 +1041,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                             </Stack>
                             <div className="dropdownMenu">
                                 <select
-                                    value={this.dataDoc.simulationType}
+                                    value={StrCast(this.dataDoc.simulation_Type)}
                                     onChange={event => {
-                                        this.dataDoc.simulationType = event.target.value;
-                                        this.setupSimulation(event.target.value, this.dataDoc.mode);
+                                        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>
@@ -1088,10 +1058,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                             </div>
                             <div className="dropdownMenu">
                                 <select
-                                    value={this.dataDoc.mode}
+                                    value={StrCast(this.dataDoc.mode)}
                                     onChange={event => {
                                         this.dataDoc.mode = event.target.value;
-                                        this.setupSimulation(this.dataDoc.simulationType, 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>
@@ -1100,13 +1070,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </select>
                             </div>
                         </div>
-                        {this.dataDoc.mode == 'Review' && this.dataDoc.simulationType != 'Inclined Plane' && (
+                        {this.dataDoc.mode == 'Review' && this.dataDoc.simulation_Type != 'Inclined Plane' && (
                             <div className="wordProblemBox">
-                                <p>{this.dataDoc.simulationType} review problems in progress!</p>
+                                <p>{this.dataDoc.simulation_Type} review problems in progress!</p>
                                 <hr />
                             </div>
                         )}
-                        {this.dataDoc.mode == 'Review' && this.dataDoc.simulationType == 'Inclined Plane' && (
+                        {this.dataDoc.mode == 'Review' && this.dataDoc.simulation_Type == 'Inclined Plane' && (
                             <div>
                                 {!this.dataDoc.hintDialogueOpen && (
                                     <IconButton
@@ -1121,26 +1091,25 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                         <QuestionMarkIcon />
                                     </IconButton>
                                 )}
-                                <Dialog maxWidth={'sm'} fullWidth={true} open={this.dataDoc.hintDialogueOpen} onClose={() => (this.dataDoc.hintDialogueOpen = false)}>
+                                <Dialog maxWidth={'sm'} fullWidth={true} open={BoolCast(this.dataDoc.hintDialogueOpen)} onClose={() => (this.dataDoc.hintDialogueOpen = false)}>
                                     <DialogTitle>Hints</DialogTitle>
                                     <DialogContent>
-                                        {this.dataDoc.selectedQuestion.hints &&
-                                            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>
-                                                );
-                                            })}
+                                        {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
@@ -1153,8 +1122,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </Dialog>
                                 <div className="wordProblemBox">
                                     <div className="question">
-                                        <p>{this.dataDoc.questionPartOne}</p>
-                                        <p>{this.dataDoc.questionPartTwo}</p>
+                                        <p>{StrCast(this.dataDoc.questionPartOne)}</p>
+                                        <p>{StrCast(this.dataDoc.questionPartTwo)}</p>
                                     </div>
                                     <div className="answers">
                                         {this.dataDoc.selectedQuestion.answerParts.includes('force of gravity') && (
@@ -1162,13 +1131,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 label={<p>Gravity magnitude</p>}
                                                 lowerBound={0}
                                                 dataDoc={this.dataDoc}
-                                                prop={'reviewGravityMagnitude'}
+                                                prop="review_GravityMagnitude"
                                                 step={0.1}
                                                 unit={'N'}
                                                 upperBound={50}
-                                                value={this.dataDoc.reviewGravityMagnitude}
-                                                showIcon={this.dataDoc.showIcon}
-                                                correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf('force of gravity')]}
+                                                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'}
                                             />
                                         )}
@@ -1177,14 +1146,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 label={<p>Gravity angle</p>}
                                                 lowerBound={0}
                                                 dataDoc={this.dataDoc}
-                                                prop={'reviewGravityAngle'}
+                                                prop="review_GravityAngle"
                                                 step={1}
                                                 unit={'°'}
                                                 upperBound={360}
-                                                value={this.dataDoc.reviewGravityAngle}
+                                                value={NumCast(this.dataDoc.review_GravityAngle)}
                                                 radianEquivalent={true}
-                                                showIcon={this.dataDoc.showIcon}
-                                                correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf('angle of gravity')]}
+                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
+                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('angle of gravity')]}
                                                 labelWidth={'7em'}
                                             />
                                         )}
@@ -1193,13 +1162,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 label={<p>Normal force magnitude</p>}
                                                 lowerBound={0}
                                                 dataDoc={this.dataDoc}
-                                                prop={'reviewNormalMagnitude'}
+                                                prop="review_NormalMagnitude"
                                                 step={0.1}
                                                 unit={'N'}
                                                 upperBound={50}
-                                                value={this.dataDoc.reviewNormalMagnitude}
-                                                showIcon={this.dataDoc.showIcon}
-                                                correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf('normal force')]}
+                                                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'}
                                             />
                                         )}
@@ -1208,14 +1177,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 label={<p>Normal force angle</p>}
                                                 lowerBound={0}
                                                 dataDoc={this.dataDoc}
-                                                prop={'reviewNormalAngle'}
+                                                prop="review_NormalAngle"
                                                 step={1}
                                                 unit={'°'}
                                                 upperBound={360}
-                                                value={this.dataDoc.reviewNormalAngle}
+                                                value={NumCast(this.dataDoc.review_NormalAngle)}
                                                 radianEquivalent={true}
-                                                showIcon={this.dataDoc.showIcon}
-                                                correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf('angle of normal force')]}
+                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
+                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('angle of normal force')]}
                                                 labelWidth={'7em'}
                                             />
                                         )}
@@ -1224,13 +1193,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 label={<p>Static friction magnitude</p>}
                                                 lowerBound={0}
                                                 dataDoc={this.dataDoc}
-                                                prop={'reviewStaticMagnitude'}
+                                                prop="review_StaticMagnitude"
                                                 step={0.1}
                                                 unit={'N'}
                                                 upperBound={50}
-                                                value={this.dataDoc.reviewStaticMagnitude}
-                                                showIcon={this.dataDoc.showIcon}
-                                                correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf('force of static friction')]}
+                                                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'}
                                             />
                                         )}
@@ -1239,14 +1208,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 label={<p>Static friction angle</p>}
                                                 lowerBound={0}
                                                 dataDoc={this.dataDoc}
-                                                prop={'reviewStaticAngle'}
+                                                prop="review_StaticAngle"
                                                 step={1}
                                                 unit={'°'}
                                                 upperBound={360}
-                                                value={this.dataDoc.reviewStaticAngle}
+                                                value={NumCast(this.dataDoc.review_StaticAngle)}
                                                 radianEquivalent={true}
-                                                showIcon={this.dataDoc.showIcon}
-                                                correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf('angle of static friction')]}
+                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
+                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('angle of static friction')]}
                                                 labelWidth={'7em'}
                                             />
                                         )}
@@ -1259,14 +1228,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 }
                                                 lowerBound={0}
                                                 dataDoc={this.dataDoc}
-                                                prop={'coefficientOfStaticFriction'}
+                                                prop="coefficientOfStaticFriction"
                                                 step={0.1}
                                                 unit={''}
                                                 upperBound={1}
-                                                value={this.dataDoc.coefficientOfStaticFriction}
+                                                value={NumCast(this.dataDoc.coefficientOfStaticFriction)}
                                                 effect={this.updateReviewForcesBasedOnCoefficient}
-                                                showIcon={this.dataDoc.showIcon}
-                                                correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf('coefficient of static friction')]}
+                                                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') && (
@@ -1274,18 +1243,18 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 label={<Box>&theta;</Box>}
                                                 lowerBound={0}
                                                 dataDoc={this.dataDoc}
-                                                prop={'wedgeAngle'}
+                                                prop="wedgeAngle"
                                                 step={1}
                                                 unit={'°'}
                                                 upperBound={49}
-                                                value={this.dataDoc.wedgeAngle ?? 26}
+                                                value={NumCast(this.dataDoc.wedgeAngle, 26)}
                                                 effect={(val: number) => {
                                                     this.changeWedgeBasedOnNewAngle(val);
                                                     this.updateReviewForcesBasedOnAngle(val);
                                                 }}
                                                 radianEquivalent={true}
-                                                showIcon={this.dataDoc.showIcon}
-                                                correctValue={this.dataDoc.answers[this.dataDoc.selectedQuestion.answerParts.indexOf('wedge angle')]}
+                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
+                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('wedge angle')]}
                                             />
                                         )}
                                     </div>
@@ -1306,40 +1275,40 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     }}>
                                     <IconButton
                                         onClick={() => {
-                                            let step = this.dataDoc.stepNumber - 1;
+                                            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.startForces = this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces);
+                                            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.showForceMagnitudes = this.dataDoc.selectedTutorial.steps[step].showMagnitude;
+                                            this.dataDoc.show_ForceMagnitudes = this.dataDoc.selectedTutorial.steps[step].show_Magnitude;
                                         }}
                                         disabled={this.dataDoc.stepNumber == 0}>
                                         <ArrowLeftIcon />
                                     </IconButton>
                                     <div>
                                         <h3>
-                                            Step {this.dataDoc.stepNumber + 1}: {this.dataDoc.selectedTutorial.steps[this.dataDoc.stepNumber].description}
+                                            Step {NumCast(this.dataDoc.stepNumber) + 1}: {this.dataDoc.selectedTutorial.steps[this.dataDoc.stepNumber].description}
                                         </h3>
-                                        <p>{this.dataDoc.selectedTutorial.steps[this.dataDoc.stepNumber].content}</p>
+                                        <p>{this.dataDoc.selectedTutorial.steps[NumCast(this.dataDoc.stepNumber)].content}</p>
                                     </div>
                                     <IconButton
                                         onClick={() => {
-                                            let step = this.dataDoc.stepNumber + 1;
+                                            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.startForces = this.getForceFromJSON(this.dataDoc.selectedTutorial.steps[step].forces);
+                                            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.showForceMagnitudes = this.dataDoc.selectedTutorial.steps[step].showMagnitude;
+                                            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.simulationType == 'One Weight' || this.dataDoc.simulationType == 'Inclined Plane' || this.dataDoc.simulationType == 'Pendulum') && <p>Resources</p>}
-                                    {this.dataDoc.simulationType == 'One Weight' && (
+                                    {(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
@@ -1367,7 +1336,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             </li>
                                         </ul>
                                     )}
-                                    {this.dataDoc.simulationType == 'Inclined Plane' && (
+                                    {this.dataDoc.simulation_Type == 'Inclined Plane' && (
                                         <ul>
                                             <li>
                                                 <a
@@ -1395,7 +1364,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             </li>
                                         </ul>
                                     )}
-                                    {this.dataDoc.simulationType == 'Pendulum' && (
+                                    {this.dataDoc.simulation_Type == 'Pendulum' && (
                                         <ul>
                                             <li>
                                                 <a
@@ -1414,7 +1383,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </div>
                             </div>
                         )}
-                        {this.dataDoc.mode == 'Review' && this.dataDoc.simulationType == 'Inclined Plane' && (
+                        {this.dataDoc.mode == 'Review' && this.dataDoc.simulation_Type == 'Inclined Plane' && (
                             <div
                                 style={{
                                     display: 'flex',
@@ -1434,9 +1403,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 <div style={{ display: 'flex', flexDirection: 'column' }}>
                                     <Button
                                         onClick={() => {
-                                            this.dataDoc.simulationReset = !this.dataDoc.simulationReset;
+                                            this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                             this.checkAnswers();
-                                            this.dataDoc.showIcon = true;
+                                            this.dataDoc.show_Icon = true;
                                         }}
                                         variant="outlined">
                                         <p>Submit</p>
@@ -1444,7 +1413,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     <Button
                                         onClick={() => {
                                             this.generateNewQuestion();
-                                            this.dataDoc.showIcon = false;
+                                            this.dataDoc.show_Icon = false;
                                         }}
                                         variant="outlined">
                                         <p>New question</p>
@@ -1456,123 +1425,127 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                             <div className="vars">
                                 <FormControl component="fieldset">
                                     <FormGroup>
-                                        {this.dataDoc.simulationType == 'One Weight' && (
+                                        {this.dataDoc.simulation_Type == 'One Weight' && (
                                             <FormControlLabel
-                                                control={<Checkbox checked={this.dataDoc.elasticCollisions} onChange={() => (this.dataDoc.elasticCollisions = !this.dataDoc.elasticCollisions)} />}
+                                                control={<Checkbox checked={BoolCast(this.dataDoc.elasticCollisions)} onChange={() => (this.dataDoc.elasticCollisions = !this.dataDoc.elasticCollisions)} />}
                                                 label="Make collisions elastic"
                                                 labelPlacement="start"
                                             />
                                         )}
-                                        <FormControlLabel control={<Checkbox checked={this.dataDoc.showForces} onChange={() => (this.dataDoc.showForces = !this.dataDoc.showForces)} />} label="Show force vectors" labelPlacement="start" />
-                                        {(this.dataDoc.simulationType == 'Inclined Plane' || this.dataDoc.simulationType == 'Pendulum') && (
+                                        <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={this.dataDoc.showForces} onChange={() => (this.dataDoc.showComponentForces = !this.dataDoc.showComponentForces)} />}
+                                                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={this.dataDoc.showAcceleration} onChange={() => (this.dataDoc.showAcceleration = !this.dataDoc.showAcceleration)} />}
+                                            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={this.dataDoc.showVelocity} onChange={() => (this.dataDoc.showVelocity = !this.dataDoc.showVelocity)} />} label="Show velocity vector" labelPlacement="start" />
-                                        <InputField label={<Box>Speed</Box>} lowerBound={1} dataDoc={this.dataDoc} prop={'simulationSpeed'} step={1} unit={'x'} upperBound={10} value={this.dataDoc.simulationSpeed ?? 2} labelWidth={'5em'} />
-                                        {this.dataDoc.simulationPaused && this.dataDoc.simulationType != 'Circular Motion' && (
+                                        <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'}
+                                                prop="gravity"
                                                 step={0.01}
                                                 unit={'m/s2'}
                                                 upperBound={0}
-                                                value={this.dataDoc.gravity ?? -9.81}
+                                                value={NumCast(this.dataDoc.gravity, -9.81)}
                                                 effect={(val: number) => {
-                                                    this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode);
+                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
                                                 }}
                                                 labelWidth={'5em'}
                                             />
                                         )}
-                                        {this.dataDoc.simulationPaused && this.dataDoc.simulationType != 'Pulley' && (
+                                        {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type != 'Pulley' && (
                                             <InputField
                                                 label={<Box>Mass</Box>}
                                                 lowerBound={1}
                                                 dataDoc={this.dataDoc}
-                                                prop={'mass'}
+                                                prop="mass"
                                                 step={0.1}
                                                 unit={'kg'}
                                                 upperBound={5}
-                                                value={this.dataDoc.mass ?? 1}
+                                                value={NumCast(this.dataDoc.mass) ?? 1}
                                                 effect={(val: number) => {
-                                                    this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode);
+                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
                                                 }}
                                                 labelWidth={'5em'}
                                             />
                                         )}
-                                        {this.dataDoc.simulationPaused && this.dataDoc.simulationType == 'Pulley' && (
+                                        {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type == 'Pulley' && (
                                             <InputField
                                                 label={<Box>Red mass</Box>}
                                                 lowerBound={1}
                                                 dataDoc={this.dataDoc}
-                                                prop={'mass'}
+                                                prop="mass"
                                                 step={0.1}
                                                 unit={'kg'}
                                                 upperBound={5}
-                                                value={this.dataDoc.mass ?? 1}
+                                                value={NumCast(this.dataDoc.mass) ?? 1}
                                                 effect={(val: number) => {
-                                                    this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode);
+                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
                                                 }}
                                                 labelWidth={'5em'}
                                             />
                                         )}
-                                        {this.dataDoc.simulationPaused && this.dataDoc.simulationType == 'Pulley' && (
+                                        {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type == 'Pulley' && (
                                             <InputField
                                                 label={<Box>Blue mass</Box>}
                                                 lowerBound={1}
                                                 dataDoc={this.dataDoc}
-                                                prop={'mass2'}
+                                                prop="mass2"
                                                 step={0.1}
                                                 unit={'kg'}
                                                 upperBound={5}
-                                                value={this.dataDoc.mass2 ?? 1}
+                                                value={NumCast(this.dataDoc.mass2) ?? 1}
                                                 effect={(val: number) => {
-                                                    this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode);
+                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
                                                 }}
                                                 labelWidth={'5em'}
                                             />
                                         )}
-                                        {this.dataDoc.simulationPaused && this.dataDoc.simulationType == 'Circular Motion' && (
+                                        {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type == 'Circular Motion' && (
                                             <InputField
                                                 label={<Box>Rod length</Box>}
                                                 lowerBound={100}
                                                 dataDoc={this.dataDoc}
-                                                prop={'circularMotionRadius'}
+                                                prop="circularMotionRadius"
                                                 step={5}
                                                 unit={'m'}
                                                 upperBound={250}
-                                                value={this.dataDoc.circularMotionRadius ?? 100}
+                                                value={NumCast(this.dataDoc.circularMotionRadius) ?? 100}
                                                 effect={(val: number) => {
-                                                    this.setupSimulation(this.dataDoc.simulationType, this.dataDoc.mode);
+                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
                                                 }}
                                                 labelWidth={'5em'}
                                             />
                                         )}
                                     </FormGroup>
                                 </FormControl>
-                                {this.dataDoc.simulationType == 'Spring' && this.dataDoc.simulationPaused && (
+                                {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'}
+                                            prop="springConstant"
                                             step={1}
                                             unit={'N/m'}
                                             upperBound={500}
-                                            value={this.dataDoc.springConstant ?? 0.5}
+                                            value={NumCast(this.dataDoc.springConstant) ?? 0.5}
                                             effect={(val: number) => {
-                                                this.dataDoc.simulationReset(!this.dataDoc.simulationReset);
+                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                             }}
                                             radianEquivalent={false}
                                             mode={'Freeform'}
@@ -1582,13 +1555,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             label={<Typography color="inherit">Rest length</Typography>}
                                             lowerBound={10}
                                             dataDoc={this.dataDoc}
-                                            prop={'springRestLength'}
+                                            prop="springRestLength"
                                             step={100}
                                             unit={''}
                                             upperBound={500}
-                                            value={this.dataDoc.springRestLength ?? 200}
+                                            value={NumCast(this.dataDoc.springRestLength) ?? 200}
                                             effect={(val: number) => {
-                                                this.dataDoc.simulationReset = !this.dataDoc.simulationReset;
+                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                             }}
                                             radianEquivalent={false}
                                             mode={'Freeform'}
@@ -1596,17 +1569,17 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                         />
                                         <InputField
                                             label={<Typography color="inherit">Starting displacement</Typography>}
-                                            lowerBound={-(this.dataDoc.springRestLength - 10)}
+                                            lowerBound={-(NumCast(this.dataDoc.springRestLength) - 10)}
                                             dataDoc={this.dataDoc}
-                                            prop={''}
+                                            prop=""
                                             step={10}
                                             unit={''}
-                                            upperBound={this.dataDoc.springRestLength}
-                                            value={this.dataDoc.springStartLength - this.dataDoc.springRestLength ?? 0}
+                                            upperBound={NumCast(this.dataDoc.springRestLength)}
+                                            value={NumCast(this.dataDoc.springStartLength) - NumCast(this.dataDoc.springRestLength)}
                                             effect={(val: number) => {
-                                                this.dataDoc.startPosY = this.dataDoc.springRestLength + val;
-                                                this.dataDoc.springStartLength = this.dataDoc.springRestLength + val;
-                                                this.dataDoc.simulationReset = !this.dataDoc.simulationReset;
+                                                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'}
@@ -1614,20 +1587,20 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                         />
                                     </div>
                                 )}
-                                {this.dataDoc.simulationType == 'Inclined Plane' && this.dataDoc.simulationPaused && (
+                                {this.dataDoc.simulation_Type == 'Inclined Plane' && this.dataDoc.simulation_Paused && (
                                     <div>
                                         <InputField
                                             label={<Box>&theta;</Box>}
                                             lowerBound={0}
                                             dataDoc={this.dataDoc}
-                                            prop={'wedgeAngle'}
+                                            prop="wedgeAngle"
                                             step={1}
                                             unit={'°'}
                                             upperBound={49}
-                                            value={this.dataDoc.wedgeAngle ?? 26}
+                                            value={NumCast(this.dataDoc.wedgeAngle, 26)}
                                             effect={(val: number) => {
                                                 this.changeWedgeBasedOnNewAngle(val);
-                                                this.dataDoc.simulationReset = !this.dataDoc.simulationReset;
+                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                             }}
                                             radianEquivalent={true}
                                             mode={'Freeform'}
@@ -1641,17 +1614,17 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             }
                                             lowerBound={0}
                                             dataDoc={this.dataDoc}
-                                            prop={'coefficientOfStaticFriction'}
+                                            prop="coefficientOfStaticFriction"
                                             step={0.1}
                                             unit={''}
                                             upperBound={1}
-                                            value={this.dataDoc.coefficientOfStaticFriction ?? 0}
+                                            value={NumCast(this.dataDoc.coefficientOfStaticFriction) ?? 0}
                                             effect={(val: number) => {
                                                 this.updateForcesWithFriction(val);
-                                                if (val < Number(this.dataDoc.coefficientOfKineticFriction)) {
+                                                if (val < NumCast(this.dataDoc.coefficientOfKineticFriction)) {
                                                     this.dataDoc.soefficientOfKineticFriction = val;
                                                 }
-                                                this.dataDoc.simulationReset = !this.dataDoc.simulationReset;
+                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                             }}
                                             mode={'Freeform'}
                                             labelWidth={'2em'}
@@ -1664,48 +1637,48 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             }
                                             lowerBound={0}
                                             dataDoc={this.dataDoc}
-                                            prop={'coefficientOfKineticFriction'}
+                                            prop="coefficientOfKineticFriction"
                                             step={0.1}
                                             unit={''}
-                                            upperBound={Number(this.dataDoc.coefficientOfStaticFriction)}
-                                            value={this.dataDoc.coefficientOfKineticFriction ?? 0}
+                                            upperBound={NumCast(this.dataDoc.coefficientOfStaticFriction)}
+                                            value={NumCast(this.dataDoc.coefficientOfKineticFriction) ?? 0}
                                             effect={(val: number) => {
-                                                this.dataDoc.simulationReset = !this.dataDoc.simulationReset;
+                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                             }}
                                             mode={'Freeform'}
                                             labelWidth={'2em'}
                                         />
                                     </div>
                                 )}
-                                {this.dataDoc.simulationType == 'Inclined Plane' && !this.dataDoc.simulationPaused && (
+                                {this.dataDoc.simulation_Type == 'Inclined Plane' && !this.dataDoc.simulation_Paused && (
                                     <Typography>
-                                        &theta;: {Math.round(Number(this.dataDoc.wedgeAngle) * 100) / 100}° ≈ {Math.round(((Number(this.dataDoc.wedgeAngle) * Math.PI) / 180) * 100) / 100} rad
+                                        &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.simulationType == 'Pendulum' && !this.dataDoc.simulationPaused && (
+                                {this.dataDoc.simulation_Type == 'Pendulum' && !this.dataDoc.simulation_Paused && (
                                     <Typography>
-                                        &theta;: {Math.round(this.dataDoc.pendulumAngle * 100) / 100}° ≈ {Math.round(((this.dataDoc.pendulumAngle * Math.PI) / 180) * 100) / 100} rad
+                                        &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.simulationType == 'Pendulum' && this.dataDoc.simulationPaused && (
+                                {this.dataDoc.simulation_Type == 'Pendulum' && this.dataDoc.simulation_Paused && (
                                     <div>
                                         <InputField
                                             label={<Box>Angle</Box>}
                                             lowerBound={0}
                                             dataDoc={this.dataDoc}
-                                            prop={'pendulumAngle'}
+                                            prop="pendulum_angle"
                                             step={1}
                                             unit={'°'}
                                             upperBound={59}
-                                            value={this.dataDoc.pendulumAngle ?? 30}
+                                            value={NumCast(this.dataDoc.pendulum_angle, 30)}
                                             effect={value => {
-                                                this.dataDoc.startPendulumAngle = value;
-                                                if (this.dataDoc.simulationType == 'Pendulum') {
-                                                    const mag = this.dataDoc.mass * Math.abs(this.dataDoc.gravity) * Math.cos((value * Math.PI) / 180);
+                                                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',
@@ -1722,29 +1695,29 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     };
                                                     const gravityParallel: IForce = {
                                                         description: 'Gravity Parallel Component',
-                                                        magnitude: Math.abs(this.dataDoc.gravity) * Math.cos((value * Math.PI) / 180),
+                                                        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(this.dataDoc.gravity) * Math.sin((value * Math.PI) / 180),
+                                                        magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * Math.sin((value * Math.PI) / 180),
                                                         directionInDegrees: -value,
                                                         component: true,
                                                     };
 
-                                                    const length = this.dataDoc.pendulumLength;
+                                                    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 - this.dataDoc.radius;
-                                                    const yPos = y - this.dataDoc.radius - 5;
-                                                    this.dataDoc.startPosX = xPos;
-                                                    this.dataDoc.startPosY = yPos;
+                                                    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.startForces = [
+                                                    this.dataDoc.start_Forces = [
                                                         {
                                                             description: 'Gravity',
-                                                            magnitude: Math.abs(this.dataDoc.gravity) * this.dataDoc.mass,
+                                                            magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
                                                             directionInDegrees: 270,
                                                             component: false,
                                                         },
@@ -1753,18 +1726,15 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     this.dataDoc.updatedForces = [
                                                         {
                                                             description: 'Gravity',
-                                                            magnitude: Math.abs(this.dataDoc.gravity) * this.dataDoc.mass,
+                                                            magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
                                                             directionInDegrees: 270,
                                                             component: false,
                                                         },
                                                         forceOfTension,
                                                     ];
                                                     this.dataDoc.componentForces = [tensionComponent, gravityParallel, gravityPerpendicular];
-                                                    this.dataDoc.adjustPendulumAngle = {
-                                                        angle: value,
-                                                        length: this.dataDoc.pendulumLength,
-                                                    };
-                                                    this.dataDoc.simulationReset = !this.dataDoc.simulationReset;
+                                                    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}
@@ -1775,18 +1745,16 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             label={<Box>Rod length</Box>}
                                             lowerBound={0}
                                             dataDoc={this.dataDoc}
-                                            prop={'pendulumLength'}
+                                            prop="pendulum_length"
                                             step={1}
                                             unit={'m'}
                                             upperBound={400}
-                                            value={Math.round(this.dataDoc.pendulumLength)}
+                                            value={Math.round(NumCast(this.dataDoc.pendulum_length))}
                                             effect={value => {
-                                                if (this.dataDoc.simulationType == 'Pendulum') {
-                                                    this.dataDoc.adjustPendulumAngle = {
-                                                        angle: this.dataDoc.pendulumAngle,
-                                                        length: value,
-                                                    };
-                                                    this.dataDoc.simulationReset = !this.dataDoc.simulationReset;
+                                                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}
@@ -1802,7 +1770,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 <table>
                                     <tbody>
                                         <tr>
-                                            <td>{this.dataDoc.simulationType == 'Pulley' ? 'Red Weight' : ''}</td>
+                                            <td>{this.dataDoc.simulation_Type == 'Pulley' ? 'Red Weight' : ''}</td>
                                             <td>X</td>
                                             <td>Y</td>
                                         </tr>
@@ -1817,36 +1785,34 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             >
                                                 <Box>Position</Box>
                                             </td>
-                                            {(!this.dataDoc.simulationPaused || this.dataDoc.simulationType == 'Inclined Plane' || this.dataDoc.simulationType == 'Circular Motion' || this.dataDoc.simulationType == 'Pulley') && (
-                                                <td style={{ cursor: 'default' }}>{this.dataDoc.positionXDisplay} 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' }}>{this.dataDoc.position_XDisplay} m</td>
                                             )}{' '}
-                                            {this.dataDoc.simulationPaused && this.dataDoc.simulationType != 'Inclined Plane' && this.dataDoc.simulationType != 'Circular Motion' && this.dataDoc.simulationType != 'Pulley' && (
+                                            {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.simulationType == 'Projectile' ? 1 : (this.xMax + this.xMin) / 4 - this.radius - 15}
+                                                        lowerBound={this.dataDoc.simulation_Type == 'Projectile' ? 1 : (this.xMax + this.xMin) / 4 - this.radius - 15}
                                                         dataDoc={this.dataDoc}
-                                                        prop={'positionXDisplay'}
+                                                        prop="position_XDisplay"
                                                         step={1}
                                                         unit={'m'}
-                                                        upperBound={this.dataDoc.simulationType == 'Projectile' ? this.xMax - 110 : (3 * (this.xMax + this.xMin)) / 4 - this.radius / 2 - 15}
-                                                        value={this.dataDoc.positionXDisplay}
+                                                        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.displayChange = {
-                                                                xDisplay: value,
-                                                                yDisplay: this.dataDoc.positionYDisplay,
-                                                            };
-                                                            if (this.dataDoc['simulationType'] == 'Suspension') {
+                                                            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(this.dataDoc.positionYDisplay) + 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 = (this.dataDoc.mass * Math.abs(this.dataDoc.gravity)) / ((-Math.cos(dir2T) / Math.cos(dir1T)) * Math.sin(dir1T) + Math.sin(dir2T));
+                                                                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;
@@ -1864,11 +1830,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                                 };
                                                                 const grav: IForce = {
                                                                     description: 'Gravity',
-                                                                    magnitude: this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
+                                                                    magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
                                                                     directionInDegrees: 270,
                                                                     component: false,
                                                                 };
-                                                                this.dataDoc['updatedForces'] = [tensionForce1, tensionForce2, grav];
+                                                                this.dataDoc.updatedForces = [tensionForce1, tensionForce2, grav];
                                                             }
                                                         }}
                                                         small={true}
@@ -1876,10 +1842,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     />
                                                 </td>
                                             )}{' '}
-                                            {(!this.dataDoc.simulationPaused || this.dataDoc.simulationType == 'Inclined Plane' || this.dataDoc.simulationType == 'Circular Motion' || this.dataDoc.simulationType == 'Pulley') && (
-                                                <td style={{ cursor: 'default' }}>{this.dataDoc.positionYDisplay} 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' }}>{`${NumCast(this.dataDoc.position_YDisplay)} m`}</td>
                                             )}{' '}
-                                            {this.dataDoc.simulationPaused && this.dataDoc.simulationType != 'Inclined Plane' && this.dataDoc.simulationType != 'Circular Motion' && this.dataDoc.simulationType != 'Pulley' && (
+                                            {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',
@@ -1887,25 +1853,23 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     <InputField
                                                         lowerBound={1}
                                                         dataDoc={this.dataDoc}
-                                                        prop={'positionYDisplay'}
+                                                        prop="position_YDisplay"
                                                         step={1}
                                                         unit={'m'}
                                                         upperBound={this.yMax - 110}
-                                                        value={this.dataDoc.positionYDisplay}
+                                                        value={NumCast(this.dataDoc.position_YDisplay)}
                                                         effect={value => {
-                                                            this.dataDoc.displayChange = {
-                                                                xDisplay: this.dataDoc.positionXDisplay,
-                                                                yDisplay: value,
-                                                            };
-                                                            if (this.dataDoc['simulationType'] == 'Suspension') {
+                                                            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 = this.dataDoc.positionXDisplay + this.radius - x1rod;
-                                                                let deltaX2 = x2rod - (this.dataDoc.positionXDisplay + 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 = (this.dataDoc.mass * Math.abs(this.dataDoc.gravity)) / ((-Math.cos(dir2T) / Math.cos(dir1T)) * Math.sin(dir1T) + Math.sin(dir2T));
+                                                                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;
@@ -1923,11 +1887,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                                 };
                                                                 const grav: IForce = {
                                                                     description: 'Gravity',
-                                                                    magnitude: this.dataDoc.mass * Math.abs(this.dataDoc.gravity),
+                                                                    magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
                                                                     directionInDegrees: 270,
                                                                     component: false,
                                                                 };
-                                                                this.dataDoc['updatedForces'] = [tensionForce1, tensionForce2, grav];
+                                                                this.dataDoc.updatedForces = [tensionForce1, tensionForce2, grav];
                                                             }
                                                         }}
                                                         small={true}
@@ -1947,10 +1911,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             >
                                                 <Box>Velocity</Box>
                                             </td>
-                                            {(!this.dataDoc.simulationPaused || (this.dataDoc.simulationType != 'One Weight' && this.dataDoc.simulationType != 'Circular Motion')) && (
-                                                <td style={{ cursor: 'default' }}>{this.dataDoc.velocityXDisplay} m/s</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.simulationPaused && (this.dataDoc.simulationType == 'One Weight' || this.dataDoc.simulationType == 'Circular Motion') && (
+                                            {this.dataDoc.simulation_Paused && (this.dataDoc.simulation_Type == 'One Weight' || this.dataDoc.simulation_Type == 'Circular Motion') && (
                                                 <td
                                                     style={{
                                                         cursor: 'default',
@@ -1958,22 +1922,22 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     <InputField
                                                         lowerBound={-50}
                                                         dataDoc={this.dataDoc}
-                                                        prop={'velocityXDisplay'}
+                                                        prop="velocity_XDisplay"
                                                         step={1}
                                                         unit={'m/s'}
                                                         upperBound={50}
-                                                        value={this.dataDoc.velocityXDisplay}
+                                                        value={this.dataDoc.velocity_XDisplay}
                                                         effect={value => {
-                                                            this.dataDoc.startVelX = value;
-                                                            this.dataDoc.simulationReset = !this.dataDoc.simulationReset;
+                                                            this.dataDoc.start_VelX = value;
+                                                            this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
                                                         }}
                                                         small={true}
                                                         mode={'Freeform'}
                                                     />
                                                 </td>
                                             )}{' '}
-                                            {(!this.dataDoc.simulationPaused || this.dataDoc.simulationType != 'One Weight') && <td style={{ cursor: 'default' }}>{this.dataDoc.velocityYDisplay} m/s</td>}{' '}
-                                            {this.dataDoc.simulationPaused && this.dataDoc.simulationType == 'One Weight' && (
+                                            {(!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',
@@ -1981,17 +1945,15 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     <InputField
                                                         lowerBound={-50}
                                                         dataDoc={this.dataDoc}
-                                                        prop={'velocityYDisplay'}
+                                                        prop="velocity_YDisplay"
                                                         step={1}
                                                         unit={'m/s'}
                                                         upperBound={50}
-                                                        value={this.dataDoc.velocityYDisplay}
+                                                        value={this.dataDoc.velocity_YDisplay}
                                                         effect={value => {
-                                                            this.dataDoc.startVelY = -value;
-                                                            this.dataDoc.displayChange = {
-                                                                xDisplay: this.dataDoc.positionXDisplay,
-                                                                yDisplay: this.dataDoc.positionYDisplay,
-                                                            };
+                                                            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'}
@@ -2011,23 +1973,23 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 <Box>Acceleration</Box>
                                             </td>
                                             <td style={{ cursor: 'default' }}>
-                                                {this.dataDoc.accelerationXDisplay} m/s<sup>2</sup>
+                                                {this.dataDoc.acceleration_XDisplay} m/s<sup>2</sup>
                                             </td>
                                             <td style={{ cursor: 'default' }}>
-                                                {this.dataDoc.accelerationYDisplay} m/s<sup>2</sup>
+                                                {this.dataDoc.acceleration_YDisplay} m/s<sup>2</sup>
                                             </td>
                                         </tr>
                                         <tr>
                                             <td>
                                                 <Box>Momentum</Box>
                                             </td>
-                                            <td>{Math.round(this.dataDoc.velocityXDisplay * this.dataDoc.mass * 10) / 10} kg*m/s</td>
-                                            <td>{Math.round(this.dataDoc.velocityYDisplay * this.dataDoc.mass * 10) / 10} kg*m/s</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.simulationType == 'Pulley' && (
+                            {this.dataDoc.mode == 'Freeform' && this.dataDoc.simulation_Type == 'Pulley' && (
                                 <table>
                                     <tbody>
                                         <tr>
@@ -2039,40 +2001,39 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             <td>
                                                 <Box>Position</Box>
                                             </td>
-                                            <td style={{ cursor: 'default' }}>{this.dataDoc.positionXDisplay2} m</td>
-                                            <td style={{ cursor: 'default' }}>{this.dataDoc.positionYDisplay2} m</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.velocityXDisplay2} m/s</td>
-
-                                            <td style={{ cursor: 'default' }}>{this.dataDoc.velocityYDisplay2} m/s</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.accelerationXDisplay2} m/s<sup>2</sup>
+                                                {this.dataDoc.acceleration_XDisplay2} m/s<sup>2</sup>
                                             </td>
                                             <td style={{ cursor: 'default' }}>
-                                                {this.dataDoc.accelerationYDisplay2} m/s<sup>2</sup>
+                                                {this.dataDoc.acceleration_YDisplay2} m/s<sup>2</sup>
                                             </td>
                                         </tr>
                                         <tr>
                                             <td>
                                                 <Box>Momentum</Box>
                                             </td>
-                                            <td>{Math.round(this.dataDoc.velocityXDisplay2 * this.dataDoc.mass * 10) / 10} kg*m/s</td>
-                                            <td>{Math.round(this.dataDoc.velocityYDisplay2 * this.dataDoc.mass * 10) / 10} kg*m/s</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.simulationType != 'Pendulum' && this.dataDoc.simulationType != 'Spring' && (
+                        {this.dataDoc.simulation_Type != 'Pendulum' && this.dataDoc.simulation_Type != 'Spring' && (
                             <div>
                                 <p>Kinematic Equations</p>
                                 <ul>
@@ -2089,7 +2050,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </ul>
                             </div>
                         )}
-                        {this.dataDoc.simulationType == 'Spring' && (
+                        {this.dataDoc.simulation_Type == 'Spring' && (
                             <div>
                                 <p>Harmonic Motion Equations: Spring</p>
                                 <ul>
@@ -2118,7 +2079,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </ul>
                             </div>
                         )}
-                        {this.dataDoc.simulationType == 'Pendulum' && (
+                        {this.dataDoc.simulation_Type == 'Pendulum' && (
                             <div>
                                 <p>Harmonic Motion Equations: Pendulum</p>
                                 <ul>
@@ -2153,7 +2114,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                             top: this.yMax - 120 + 40 + 'px',
                             left: this.xMin + 90 - 80 + 'px',
                         }}>
-                        {this.dataDoc.simulationType == 'Circular Motion' ? 'Z' : 'Y'}
+                        {this.dataDoc.simulation_Type == 'Circular Motion' ? 'Z' : 'Y'}
                     </p>
                     <p
                         style={{
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 88af37791..a2883e825 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -1,1674 +1,1352 @@
-import { Doc } from '../../../../fields/Doc';
+import { Doc, HeightSym, WidthSym } from '../../../../fields/Doc';
 import React = require('react');
-import "./PhysicsSimulationBox.scss";
+import './PhysicsSimulationBox.scss';
+import { NumCast } from '../../../../fields/Types';
 
 interface IWallProps {
-  length: number;
-  xPos: number;
-  yPos: number;
-  angleInDegrees: number;
+    length: number;
+    xPos: number;
+    yPos: number;
+    angleInDegrees: number;
 }
 interface IForce {
-  description: string;
-  magnitude: number;
-  directionInDegrees: number;
-  component: boolean;
+    description: string;
+    magnitude: number;
+    directionInDegrees: number;
+    component: boolean;
 }
 export interface IWeightProps {
-  dataDoc: Doc;
-  layoutDoc: Doc;
-  adjustPendulumAngle: { angle: number; length: number };
-  circularMotionRadius: number;
-  coefficientOfKineticFriction: number;
-  color: string;
-  componentForces: IForce[];
-  displayXVelocity: number;
-  displayYVelocity: number;
-  elasticCollisions: boolean;
-  gravity: number;
-  mass: number;
-  mode: string;
-  noMovement: boolean;
-  paused: boolean;
-  pendulumAngle: number;
-  pendulumLength: number;
-  radius: number;
-  reset: boolean;
-  showAcceleration: boolean;
-  showComponentForces: boolean;
-  showForceMagnitudes: boolean;
-  showForces: boolean;
-  showVelocity: boolean;
-  simulationSpeed: number;
-  simulationType: string;
-  springConstant: number;
-  springRestLength: number;
-  springStartLength: number;
-  startForces: IForce[];
-  startPendulumAngle: number;
-  startPosX: number;
-  startPosY: number;
-  startVelX: number;
-  startVelY: number;
-  timestepSize: number;
-  updateDisplay: { xDisplay: number; yDisplay: number };
-  updatedForces: IForce[];
-  wallPositions: IWallProps[];
-  wedgeHeight: number;
-  wedgeWidth: number;
-  xMax: number;
-  xMin: number;
-  yMax: number;
-  yMin: number;
+    dataDoc: Doc;
+    layoutDoc: Doc;
+    adjustPendulumAngle: number;
+    adjustPendulumLength: number;
+    circularMotionRadius: number;
+    coefficientOfKineticFriction: number;
+    color: string;
+    componentForces: IForce[];
+    displayXVelocity: number;
+    displayYVelocity: number;
+    elasticCollisions: boolean;
+    gravity: number;
+    mass: number;
+    mode: string;
+    noMovement: boolean;
+    paused: boolean;
+    pendulumAngle: number;
+    pendulumLength: number;
+    radius: number;
+    reset: boolean;
+    showAcceleration: boolean;
+    showComponentForces: boolean;
+    showForceMagnitudes: boolean;
+    showForces: boolean;
+    showVelocity: boolean;
+    simulationSpeed: number;
+    simulationType: string;
+    springConstant: number;
+    springRestLength: number;
+    springStartLength: number;
+    startForces: IForce[];
+    startPendulumAngle: number;
+    startPosX: number;
+    startPosY: number;
+    startVelX: number;
+    startVelY: number;
+    timestepSize: number;
+    updateXDisplay: number;
+    updateYDisplay: number;
+    updatedForces: IForce[];
+    wallPositions: IWallProps[];
+    wedgeHeight: number;
+    wedgeWidth: number;
+    xMax: number;
+    xMin: number;
+    yMax: number;
+    yMin: number;
 }
 
 interface IState {
-  angleLabel: number,
-  clickPositionX: number,
-  clickPositionY: number,
-  coordinates: string,
-  dragging: boolean,
-  kineticFriction: boolean,
-  maxPosYConservation: number,
-  timer: number,
-  updatedStartPosX: any,
-  updatedStartPosY: any,
-  walls: IWallProps[],
-  xPosition: any,
-  xVelocity: number,
-  yPosition: any,
-  yVelocity: number,
-  xAccel: number,
-  yAccel: number,
+    angleLabel: number;
+    clickPositionX: number;
+    clickPositionY: number;
+    coordinates: string;
+    dragging: boolean;
+    kineticFriction: boolean;
+    maxPosYConservation: number;
+    timer: number;
+    updatedStartPosX: any;
+    updatedStartPosY: any;
+    walls: IWallProps[];
+    xPosition: any;
+    xVelocity: number;
+    yPosition: any;
+    yVelocity: number;
+    xAccel: number;
+    yAccel: number;
 }
 
 export default class Weight extends React.Component<IWeightProps, IState> {
-
-  constructor(props: any) {
-    super(props)
-    this.state = {
-      angleLabel: 0,
-      clickPositionX: 0,
-      clickPositionY: 0,
-      coordinates: "",
-      dragging: false,
-      kineticFriction: false,
-      maxPosYConservation: 0,
-      timer: 0,
-      updatedStartPosX: this.props.startPosX ?? 0,
-      updatedStartPosY: this.props.startPosY ?? 0,
-      walls: [],
-      xPosition: this.props.startPosX ?? 0,
-      xVelocity: this.props.startVelX ? this.props.startVelX: 0,
-      yPosition: this.props.startPosY ?? 0,
-      yVelocity: this.props.startVelY ? this.props.startVelY: 0,
-      xAccel: 0,
-      yAccel: 0,
+    constructor(props: any) {
+        super(props);
+        this.state = {
+            angleLabel: 0,
+            clickPositionX: 0,
+            clickPositionY: 0,
+            coordinates: '',
+            dragging: false,
+            kineticFriction: false,
+            maxPosYConservation: 0,
+            timer: 0,
+            updatedStartPosX: this.props.startPosX ?? 0,
+            updatedStartPosY: this.props.startPosY ?? 0,
+            walls: [],
+            xPosition: this.props.startPosX ?? 0,
+            xVelocity: this.props.startVelX ? this.props.startVelX : 0,
+            yPosition: this.props.startPosY ?? 0,
+            yVelocity: this.props.startVelY ? this.props.startVelY : 0,
+            xAccel: 0,
+            yAccel: 0,
+        };
     }
-  }
-
-  componentDidMount() {
-    // Timer for animating the simulation
-    setInterval(() => {
-      this.setState({timer: this.state.timer + 1});
-    }, 50);
-  }
-
-  // Constants
-  draggable =
-    this.props.dataDoc['simulationType'] != "Inclined Plane" &&
-    this.props.dataDoc['simulationType'] != "Pendulum" &&
-    this.props.dataDoc['mode'] == "Freeform";
-  epsilon = 0.0001;
-  labelBackgroundColor = `rgba(255,255,255,0.5)`;
-
-  // Variables
-  weightStyle = {
-    alignItems: "center",
-    backgroundColor: this.props.color,
-    borderColor: "black",
-    borderRadius: 50 + "%",
-    borderStyle: "solid",
-    display: "flex",
-    height: 2 * this.props.radius + "px",
-    justifyContent: "center",
-    left: this.props.startPosX + "px",
-    position: "absolute" as "absolute",
-    top: this.props.startPosY + "px",
-    touchAction: "none",
-    width: 2 * this.props.radius + "px",
-    zIndex: 5,
-  };
-
-  // Helper function to go between display and real values
-  getDisplayYPos = (yPos: number) => {
-    return this.props.yMax - yPos - 2 * this.props.radius + 5;
-  };
-  getYPosFromDisplay = (yDisplay: number) => {
-    return this.props.yMax - yDisplay - 2 * this.props.radius + 5;
-  };
 
-  // Set display values based on real values
-  setYPosDisplay = (yPos: number) => {
-    const displayPos = this.getDisplayYPos(yPos);
-    if (this.props.color == 'red') {
-      this.props.dataDoc['positionYDisplay'] = Math.round(displayPos * 100) / 100
-    } else {
-      this.props.dataDoc['positionYDisplay2'] = Math.round(displayPos * 100) / 100
+    componentDidMount() {
+        // Timer for animating the simulation
+        setInterval(() => {
+            this.setState({ timer: this.state.timer + 1 });
+        }, 50);
     }
-  };
-  setXPosDisplay = (xPos: number) => {
-    if (this.props.color == 'red') {
-      this.props.dataDoc['positionXDisplay'] = Math.round(xPos * 100) / 100;
-    } else {
-      this.props.dataDoc['positionXDisplay2'] = Math.round(xPos * 100) / 100;}
-  };
-  setYVelDisplay = (yVel: number) => {
-    if (this.props.color == 'red') {
-      this.props.dataDoc['velocityYDisplay'] = (-1 * Math.round(yVel * 100)) / 100;
-    } else {
-      this.props.dataDoc['velocityYDisplay2'] = (-1 * Math.round(yVel * 100)) / 100;}
-  };
-  setXVelDisplay = (xVel: number) => {
-    if (this.props.color == 'red') {
-      this.props.dataDoc['velocityXDisplay'] = Math.round(xVel * 100) / 100;
-    } else {
-      this.props.dataDoc['velocityXDisplay2'] = Math.round(xVel * 100) / 100;}
-  };
 
-  // Update display values when simulation updates
-  setDisplayValues = (
-    xPos: number = this.state.xPosition,
-    yPos: number = this.state.yPosition,
-    xVel: number = this.state.xVelocity,
-    yVel: number = this.state.yVelocity
-  ) => {
-    this.setYPosDisplay(yPos);
-    this.setXPosDisplay(xPos);
-    this.setYVelDisplay(yVel);
-    this.setXVelDisplay(xVel);
-    if (this.props.color == 'red') {
-      this.props.dataDoc['accelerationYDisplay'] = 
-        (-1 * Math.round(this.getNewAccelerationY(this.props.updatedForces) * 100)) / 100
-      ;
-      this.props.dataDoc['accelerationXDisplay'] = 
-        Math.round(this.getNewAccelerationX(this.props.updatedForces) * 100) / 100
-      ;
-    } else {
-      this.props.dataDoc['accelerationYDisplay2'] = 
-        (-1 * Math.round(this.getNewAccelerationY(this.props.updatedForces) * 100)) / 100
-      ;
-      this.props.dataDoc['accelerationXDisplay2'] = 
-        Math.round(this.getNewAccelerationX(this.props.updatedForces) * 100) / 100
-      ;}
+    // Constants
+    draggable = this.props.dataDoc.simulation_Type != 'Inclined Plane' && this.props.dataDoc.simulation_Type != 'Pendulum' && this.props.dataDoc.mode == 'Freeform';
+    epsilon = 0.0001;
+    labelBackgroundColor = `rgba(255,255,255,0.5)`;
 
-    this.setState({xAccel : (Math.round(this.getNewAccelerationX(this.props.updatedForces) * 100) / 100)})
-    this.setState({yAccel :
-      (-1 * Math.round(this.getNewAccelerationY(this.props.updatedForces) * 100)) / 100
-    });
-  };
+    // Variables
+    weightStyle = {
+        alignItems: 'center',
+        backgroundColor: this.props.color,
+        borderColor: 'black',
+        borderRadius: 50 + '%',
+        borderStyle: 'solid',
+        display: 'flex',
+        height: 2 * this.props.radius + 'px',
+        justifyContent: 'center',
+        left: this.props.startPosX + 'px',
+        position: 'absolute' as 'absolute',
+        top: this.props.startPosY + 'px',
+        touchAction: 'none',
+        width: 2 * this.props.radius + 'px',
+        zIndex: 5,
+    };
 
-  componentDidUpdate(prevProps: Readonly<IWeightProps>, prevState: Readonly<IState>, snapshot?: any): void {
-    // Change pendulum angle from input field
-    if (prevProps.adjustPendulumAngle != this.props.adjustPendulumAngle) {
-      let length = this.props.adjustPendulumAngle.length;
-      const x =
-        length * Math.cos(((90 - this.props.adjustPendulumAngle.angle) * Math.PI) / 180);
-      const y =
-        length * Math.sin(((90 - this.props.adjustPendulumAngle.angle) * Math.PI) / 180);
-      const xPos = this.props.xMax / 2 - x - this.props.radius;
-      const yPos = y - this.props.radius - 5;
-      this.setState({xPosition: xPos})
-      this.setState({yPosition: yPos})
-      this.setState({updatedStartPosX: xPos})
-      this.setState({updatedStartPosY: yPos})
-      this.props.dataDoc['pendulumAngle'] = this.props.adjustPendulumAngle.angle
-      this.props.dataDoc['pendulumLength'] = this.props.adjustPendulumAngle.length
-    }
+    // Helper function to go between display and real values
+    getDisplayYPos = (yPos: number) => {
+        return this.props.yMax - yPos - 2 * this.props.radius + 5;
+    };
+    getYPosFromDisplay = (yDisplay: number) => {
+        return this.props.yMax - yDisplay - 2 * this.props.radius + 5;
+    };
 
-    // When display values updated by user, update real values
-    if (prevProps.updateDisplay != this.props.updateDisplay) {
-      if (this.props.updateDisplay.xDisplay != this.state.xPosition) {
-        let x = this.props.updateDisplay.xDisplay;
-        x = Math.max(0, x);
-        x = Math.min(x, this.props.xMax - 2 * this.props.radius);
-        this.setState({updatedStartPosX: x})
-        this.setState({xPosition: x})
+    // Set display values based on real values
+    setYPosDisplay = (yPos: number) => {
+        const displayPos = this.getDisplayYPos(yPos);
         if (this.props.color == 'red') {
-        this.props.dataDoc['positionXDisplay'] = x
+            this.props.dataDoc.position_YDisplay = Math.round(displayPos * 100) / 100;
         } else {
-          this.props.dataDoc['positionXDisplay2'] = x
+            this.props.dataDoc.position_YDisplay2 = Math.round(displayPos * 100) / 100;
         }
-      }
-  
-      if (this.props.updateDisplay.yDisplay != this.getDisplayYPos(this.state.yPosition)) {
-        let y = this.props.updateDisplay.yDisplay;
-        y = Math.max(0, y);
-        y = Math.min(y, this.props.yMax - 2 * this.props.radius);
-        let coordinatePosition = this.getYPosFromDisplay(y);
-        this.setState({updatedStartPosY: coordinatePosition})
-        this.setState({yPosition: coordinatePosition})
+    };
+    setXPosDisplay = (xPos: number) => {
         if (this.props.color == 'red') {
-        this.props.dataDoc['positionYDisplay'] = y
+            this.props.dataDoc.position_XDisplay = Math.round(xPos * 100) / 100;
         } else {
-          this.props.dataDoc['positionYDisplay2'] = y
+            this.props.dataDoc.position_XDisplay2 = Math.round(xPos * 100) / 100;
         }
-      }
-  
-      if (this.props.displayXVelocity != this.state.xVelocity) {
-        let x = this.props.displayXVelocity;
-        this.setState({xVelocity: x})
+    };
+    setYVelDisplay = (yVel: number) => {
         if (this.props.color == 'red') {
-          this.props.dataDoc['velocityXDisplay'] = x
+            this.props.dataDoc.velocity_YDisplay = (-1 * Math.round(yVel * 100)) / 100;
         } else {
-          this.props.dataDoc['velocityXDisplay2'] = x
+            this.props.dataDoc.velocity_YDisplay2 = (-1 * Math.round(yVel * 100)) / 100;
         }
-      }
-  
-      if (this.props.displayYVelocity != -this.state.yVelocity) {
-        let y = this.props.displayYVelocity;
-        this.setState({yVelocity: -y})
+    };
+    setXVelDisplay = (xVel: number) => {
         if (this.props.color == 'red') {
-          this.props.dataDoc['velocityYDisplay'] = y
+            this.props.dataDoc.velocity_XDisplay = Math.round(xVel * 100) / 100;
         } else {
-          this.props.dataDoc['velocityYDisplay2'] = y
+            this.props.dataDoc.velocity_XDisplay2 = Math.round(xVel * 100) / 100;
         }
-      }
-    }
-    
-    // Prevent bug when switching between sims
-    if (prevProps.startForces != this.props.startForces) {
-      this.setState({xVelocity: this.props.startVelX})
-      this.setState({yVelocity: this.props.startVelY})
-      this.setDisplayValues();
-    }
+    };
 
-    // Make sure weight doesn't go above max height 
-    if ((prevState.updatedStartPosY != this.state.updatedStartPosY || prevProps.startVelY != this.props.startVelY) && !isNaN(this.state.updatedStartPosY) && !isNaN(this.props.startVelY)){
-      if (this.props.dataDoc['simulationType'] == "One Weight") {
-        let maxYPos = this.state.updatedStartPosY;
-        if (this.props.startVelY != 0) {
-          maxYPos -= (this.props.startVelY * this.props.startVelY) / (2 * Math.abs(this.props.gravity));
+    // Update display values when simulation updates
+    setDisplayValues = (xPos: number = this.state.xPosition, yPos: number = this.state.yPosition, xVel: number = this.state.xVelocity, yVel: number = this.state.yVelocity) => {
+        this.setYPosDisplay(yPos);
+        this.setXPosDisplay(xPos);
+        this.setYVelDisplay(yVel);
+        this.setXVelDisplay(xVel);
+        if (this.props.color == 'red') {
+            this.props.dataDoc.acceleration_YDisplay = (-1 * Math.round(this.getNewAccelerationY(this.props.updatedForces) * 100)) / 100;
+            this.props.dataDoc.acceleration_XDisplay = Math.round(this.getNewAccelerationX(this.props.updatedForces) * 100) / 100;
+        } else {
+            this.props.dataDoc.acceleration_YDisplay2 = (-1 * Math.round(this.getNewAccelerationY(this.props.updatedForces) * 100)) / 100;
+            this.props.dataDoc.acceleration_XDisplay2 = Math.round(this.getNewAccelerationX(this.props.updatedForces) * 100) / 100;
         }
-        if (maxYPos < 0) {
-          maxYPos = 0;
+
+        this.setState({ xAccel: Math.round(this.getNewAccelerationX(this.props.updatedForces) * 100) / 100 });
+        this.setState({ yAccel: (-1 * Math.round(this.getNewAccelerationY(this.props.updatedForces) * 100)) / 100 });
+    };
+
+    componentDidUpdate(prevProps: Readonly<IWeightProps>, prevState: Readonly<IState>, snapshot?: any): void {
+        // Change pendulum angle from input field
+        if (prevProps.adjustPendulumAngle != this.props.adjustPendulumAngle || prevProps.adjustPendulumLength !== this.props.adjustPendulumLength) {
+            let length = this.props.adjustPendulumLength;
+            const x = length * Math.cos(((90 - this.props.adjustPendulumAngle) * Math.PI) / 180);
+            const y = length * Math.sin(((90 - this.props.adjustPendulumAngle) * Math.PI) / 180);
+            const xPos = this.props.xMax / 2 - x - this.props.radius;
+            const yPos = y - this.props.radius - 5;
+            this.setState({ xPosition: xPos });
+            this.setState({ yPosition: yPos });
+            this.setState({ updatedStartPosX: xPos });
+            this.setState({ updatedStartPosY: yPos });
+            this.props.dataDoc.pendulum_angle = this.props.adjustPendulumAngle;
+            this.props.dataDoc.pendulum_length = this.props.adjustPendulumLength;
         }
-        this.setState({maxPosYConservation: maxYPos})
-      }
-    }
 
-    // Check for collisions and update
-    if (!this.props.paused) {
-      if (prevState.timer != this.state.timer) {
-        if (!this.props.noMovement) {
-          let collisions = false;
-          if (
-            this.props.dataDoc['simulationType'] == "One Weight" ||
-            this.props.dataDoc['simulationType'] == "Inclined Plane"
-          ) {
-            const collisionsWithGround = this.checkForCollisionsWithGround();
-            const collisionsWithWalls = this.checkForCollisionsWithWall();
-            collisions = collisionsWithGround || collisionsWithWalls;
-          }
-          if (this.props.dataDoc['simulationType'] == "Pulley") {
-            if (this.state.yPosition <= this.props.yMin + 100 || this.state.yPosition >= this.props.yMax - 100) {
-              collisions = true;
+        // When display values updated by user, update real value
+        if (prevProps.updateYDisplay != this.props.updateYDisplay || prevProps.updateXDisplay !== this.props.updateXDisplay) {
+            if (this.props.updateXDisplay != this.state.xPosition) {
+                let x = this.props.updateXDisplay;
+                x = Math.max(0, x);
+                x = Math.min(x, this.props.xMax - 2 * this.props.radius);
+                this.setState({ updatedStartPosX: x });
+                this.setState({ xPosition: x });
+                if (this.props.color == 'red') {
+                    this.props.dataDoc.position_XDisplay = x;
+                } else {
+                    this.props.dataDoc.position_XDisplay2 = x;
+                }
+            }
+
+            if (this.props.updateYDisplay != this.getDisplayYPos(this.state.yPosition)) {
+                let y = this.props.updateYDisplay;
+                y = Math.max(0, y);
+                y = Math.min(y, this.props.yMax - 2 * this.props.radius);
+                let coordinatePosition = this.getYPosFromDisplay(y);
+                this.setState({ updatedStartPosY: coordinatePosition });
+                this.setState({ yPosition: coordinatePosition });
+                if (this.props.color == 'red') {
+                    this.props.dataDoc.position_YDisplay = y;
+                } else {
+                    this.props.dataDoc.position_YDisplay2 = y;
+                }
+            }
+
+            if (this.props.displayXVelocity != this.state.xVelocity) {
+                let x = this.props.displayXVelocity;
+                this.setState({ xVelocity: x });
+                if (this.props.color == 'red') {
+                    this.props.dataDoc.velocity_XDisplay = x;
+                } else {
+                    this.props.dataDoc.velocity_XDisplay2 = x;
+                }
+            }
+
+            if (this.props.displayYVelocity != -this.state.yVelocity) {
+                let y = this.props.displayYVelocity;
+                this.setState({ yVelocity: -y });
+                if (this.props.color == 'red') {
+                    this.props.dataDoc.velocity_YDisplay = y;
+                } else {
+                    this.props.dataDoc.velocity_YDisplay2 = y;
+                }
             }
-          }
-          if (!collisions) {
-            this.update();
-          }
-          this.setDisplayValues();
         }
-      }
-    }
 
-    // Reset everything on reset button click
-    if (prevProps.reset != this.props.reset) {
-      this.resetEverything();
-    }
-    
-    // Convert from static to kinetic friction if/when weight slips on inclined plane
-    if (prevState.xVelocity != this.state.xVelocity) {
-      if (
-        this.props.dataDoc['simulationType'] == "Inclined Plane" &&
-        Math.abs(this.state.xVelocity) > 0.1 &&
-        this.props.dataDoc['mode'] != "Review" &&
-        !this.state.kineticFriction
-      ) {
-        this.setState({kineticFriction: true})
-        const normalForce: IForce = {
-          description: "Normal Force",
-          magnitude:
-            this.props.mass *
-            Math.abs(this.props.gravity) *
-            Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
-          directionInDegrees:
-            180 - 90 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
-          component: false,
-        };
-        let frictionForce: IForce = {
-          description: "Kinetic Friction Force",
-          magnitude:
-            this.props.mass *
-            this.props.coefficientOfKineticFriction *
-            Math.abs(this.props.gravity) *
-            Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
-          directionInDegrees:
-            180 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
-          component: false,
-        };
-        // reduce magnitude of friction force if necessary such that block cannot slide up plane
-        let yForce = -Math.abs(this.props.gravity);
-        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(this.props.gravity)) /
-            Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
+        // Prevent bug when switching between sims
+        if (prevProps.startForces != this.props.startForces) {
+            this.setState({ xVelocity: this.props.startVelX });
+            this.setState({ yVelocity: this.props.startVelY });
+            this.setDisplayValues();
         }
 
-        const frictionForceComponent: IForce = {
-          description: "Kinetic Friction Force",
+        // Make sure weight doesn't go above max height
+        if ((prevState.updatedStartPosY != this.state.updatedStartPosY || prevProps.startVelY != this.props.startVelY) && !isNaN(this.state.updatedStartPosY) && !isNaN(this.props.startVelY)) {
+            if (this.props.dataDoc.simulation_Type == 'One Weight') {
+                let maxYPos = this.state.updatedStartPosY;
+                if (this.props.startVelY != 0) {
+                    maxYPos -= (this.props.startVelY * this.props.startVelY) / (2 * Math.abs(this.props.gravity));
+                }
+                if (maxYPos < 0) {
+                    maxYPos = 0;
+                }
+                this.setState({ maxPosYConservation: maxYPos });
+            }
+        }
 
-          magnitude:
-            this.props.mass *
-            this.props.coefficientOfKineticFriction *
-            Math.abs(this.props.gravity) *
-            Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
-          directionInDegrees:
-            180 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
-          component: true,
-        };
-        const normalForceComponent: IForce = {
-          description: "Normal Force",
-          magnitude:
-            this.props.mass *
-            Math.abs(this.props.gravity) *
-            Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
-          directionInDegrees:
-            180 - 90 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
-          component: true,
-        };
-        const gravityParallel: IForce = {
-          description: "Gravity Parallel Component",
-          magnitude:
-            this.props.mass *
-            Math.abs(this.props.gravity) *
-            Math.sin(Math.PI / 2 - Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
-          directionInDegrees:
-            180 -
-            90 -
-            (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI +
-            180,
-          component: true,
-        };
-        const gravityPerpendicular: IForce = {
-          description: "Gravity Perpendicular Component",
-          magnitude:
-            this.props.mass *
-            Math.abs(this.props.gravity) *
-            Math.cos(Math.PI / 2 - Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
-          directionInDegrees:
-            360 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
-          component: true,
-        };
-        const gravityForce: IForce = {
-          description: "Gravity",
-          magnitude: this.props.mass * Math.abs(this.props.gravity),
-          directionInDegrees: 270,
-          component: false,
-        };
-        if (this.props.coefficientOfKineticFriction != 0) {
-          this.props.dataDoc['updatedForces'] = ([gravityForce, normalForce, frictionForce]);
-          this.props.dataDoc['componentForces'] = ([
-            frictionForceComponent,
-            normalForceComponent,
-            gravityParallel,
-            gravityPerpendicular,
-          ]);
-        } else {
-          this.props.dataDoc['updatedForces'] = ([gravityForce, normalForce]);
-          this.props.dataDoc['componentForces'] = ([
-            normalForceComponent,
-            gravityParallel,
-            gravityPerpendicular,
-          ]);
+        // Check for collisions and update
+        if (!this.props.paused) {
+            if (prevState.timer != this.state.timer) {
+                if (!this.props.noMovement) {
+                    let collisions = false;
+                    if (this.props.dataDoc.simulation_Type == 'One Weight' || this.props.dataDoc.simulation_Type == 'Inclined Plane') {
+                        const collisionsWithGround = this.checkForCollisionsWithGround();
+                        const collisionsWithWalls = this.checkForCollisionsWithWall();
+                        collisions = collisionsWithGround || collisionsWithWalls;
+                    }
+                    if (this.props.dataDoc.simulation_Type == 'Pulley') {
+                        if (this.state.yPosition <= this.props.yMin + 100 || this.state.yPosition >= this.props.yMax - 100) {
+                            collisions = true;
+                        }
+                    }
+                    if (!collisions) {
+                        this.update();
+                    }
+                    this.setDisplayValues();
+                }
+            }
         }
-      }
-    }
 
-    // Add/remove walls when simulation type changes
-    if (prevProps.simulationType != this.props.simulationType) {
-      let w: IWallProps[] = [];
-      if (this.props.dataDoc['simulationType'] == "One Weight" || this.props.dataDoc['simulationType'] == "Inclined Plane") {
-        w = this.props.wallPositions
-      }
-      this.setState({walls: w})
-    }
+        // Reset everything on reset button click
+        if (prevProps.reset != this.props.reset) {
+            this.resetEverything();
+        }
 
-    // Update x position when start pos x changes
-    if (prevProps.startPosX != this.props.startPosX) {
-      if (this.props.paused && !isNaN(this.props.startPosX)) {
-        this.setState({xPosition: this.props.startPosX})
-        this.setState({updatedStartPosX: this.props.startPosX})
-        this.setXPosDisplay(this.props.startPosX)
-      }
-    }
+        // Convert from static to kinetic friction if/when weight slips on inclined plane
+        if (prevState.xVelocity != this.state.xVelocity) {
+            if (this.props.dataDoc.simulation_Type == 'Inclined Plane' && Math.abs(this.state.xVelocity) > 0.1 && this.props.dataDoc.mode != 'Review' && !this.state.kineticFriction) {
+                this.setState({ kineticFriction: true });
+                const normalForce: IForce = {
+                    description: 'Normal Force',
+                    magnitude: this.props.mass * Math.abs(this.props.gravity) * Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
+                    directionInDegrees: 180 - 90 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
+                    component: false,
+                };
+                let frictionForce: IForce = {
+                    description: 'Kinetic Friction Force',
+                    magnitude: this.props.mass * this.props.coefficientOfKineticFriction * Math.abs(this.props.gravity) * Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
+                    directionInDegrees: 180 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
+                    component: false,
+                };
+                // reduce magnitude of friction force if necessary such that block cannot slide up plane
+                let yForce = -Math.abs(this.props.gravity);
+                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(this.props.gravity)) / Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
+                }
 
-    // Update y position when start pos y changes TODO debug
-    if (prevProps.startPosY != this.props.startPosY) {
-       if (this.props.paused && !isNaN(this.props.startPosY)) {
-        this.setState({yPosition: this.props.startPosY})
-        this.setState({updatedStartPosY: this.props.startPosY ?? 0})
-        this.setYPosDisplay(this.props.startPosY ?? 0)
-      }
-    }
+                const frictionForceComponent: IForce = {
+                    description: 'Kinetic Friction Force',
 
-    // Update wedge coordinates
-    if (prevProps.wedgeWidth != this.props.wedgeWidth || prevProps.wedgeHeight != this.props.wedgeHeight) {
-      const left = this.props.xMax * 0.25;
-      const coordinatePair1 = Math.round(left) + "," + this.props.yMax + " ";
-      const coordinatePair2 = Math.round(left + this.props.wedgeWidth) + "," + this.props.yMax + " ";
-      const coordinatePair3 = Math.round(left) + "," + (this.props.yMax - this.props.wedgeHeight);
-      const coord = coordinatePair1 + coordinatePair2 + coordinatePair3;
-      this.setState({coordinates: coord})
-    } 
+                    magnitude: this.props.mass * this.props.coefficientOfKineticFriction * Math.abs(this.props.gravity) * Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
+                    directionInDegrees: 180 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
+                    component: true,
+                };
+                const normalForceComponent: IForce = {
+                    description: 'Normal Force',
+                    magnitude: this.props.mass * Math.abs(this.props.gravity) * Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
+                    directionInDegrees: 180 - 90 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
+                    component: true,
+                };
+                const gravityParallel: IForce = {
+                    description: 'Gravity Parallel Component',
+                    magnitude: this.props.mass * Math.abs(this.props.gravity) * Math.sin(Math.PI / 2 - Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
+                    directionInDegrees: 180 - 90 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI + 180,
+                    component: true,
+                };
+                const gravityPerpendicular: IForce = {
+                    description: 'Gravity Perpendicular Component',
+                    magnitude: this.props.mass * Math.abs(this.props.gravity) * Math.cos(Math.PI / 2 - Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
+                    directionInDegrees: 360 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
+                    component: true,
+                };
+                const gravityForce: IForce = {
+                    description: 'Gravity',
+                    magnitude: this.props.mass * Math.abs(this.props.gravity),
+                    directionInDegrees: 270,
+                    component: false,
+                };
+                if (this.props.coefficientOfKineticFriction != 0) {
+                    this.props.dataDoc.updatedForces = [gravityForce, normalForce, frictionForce];
+                    this.props.dataDoc.componentForces = [frictionForceComponent, normalForceComponent, gravityParallel, gravityPerpendicular];
+                } else {
+                    this.props.dataDoc.updatedForces = [gravityForce, normalForce];
+                    this.props.dataDoc.componentForces = [normalForceComponent, gravityParallel, gravityPerpendicular];
+                }
+            }
+        }
 
-    if (this.state.xPosition != prevState.xPosition || this.state.yPosition != prevState.yPosition) {
-      this.weightStyle = {
-        alignItems: "center",
-        backgroundColor: this.props.color,
-        borderColor: "black",
-        borderRadius: 50 + "%",
-        borderStyle: "solid",
-        display: "flex",
-        height: 2 * this.props.radius + "px",
-        justifyContent: "center",
-        left: this.state.xPosition + "px",
-        position: "absolute" as "absolute",
-        top: this.state.yPosition + "px",
-        touchAction: "none",
-        width: 2 * this.props.radius + "px",
-        zIndex: 5,
-      };
-    }
-  }
+        // Add/remove walls when simulation type changes
+        if (prevProps.simulationType != this.props.simulationType) {
+            let w: IWallProps[] = [];
+            if (this.props.dataDoc.simulation_Type == 'One Weight' || this.props.dataDoc.simulation_Type == 'Inclined Plane') {
+                w = this.props.wallPositions;
+            }
+            this.setState({ walls: w });
+        }
 
-  // Reset simulation on reset button click
-  resetEverything = () => {
-    this.setState({kineticFriction: false})
-    this.setState({xPosition: this.state.updatedStartPosX})
-    this.setState({yPosition: this.state.updatedStartPosY})
-    this.setState({xVelocity: this.props.startVelX ?? 0})
-    this.setState({yVelocity: this.props.startVelY ?? 0})
-    this.props.dataDoc['pendulumAngle'] = this.props.dataDoc['startPendulumAngle']
-    this.props.dataDoc['updatedForces'] = (this.props.dataDoc['startForces'])
-    this.props.dataDoc['updatedForces2'] = (this.props.dataDoc['startForces2'])
-    if (this.props.color == 'red') {
-      this.props.dataDoc['positionXDisplay'] = this.state.updatedStartPosX
-      this.props.dataDoc['positionYDisplay'] = this.state.updatedStartPosY
-      this.props.dataDoc['velocityXDisplay'] = this.props.startVelX ?? 0
-      this.props.dataDoc['velocityYDisplay'] = this.props.startVelY ?? 0
-      this.props.dataDoc['accelerationXDisplay'] = 0
-      this.props.dataDoc['accelerationYDisplay'] = 0
-    } else {
-      this.props.dataDoc['positionXDisplay2'] = this.state.updatedStartPosX
-      this.props.dataDoc['positionYDisplay2'] = this.state.updatedStartPosY
-      this.props.dataDoc['velocityXDisplay2'] = this.props.startVelX ?? 0
-      this.props.dataDoc['velocityYDisplay2'] = this.props.startVelY ?? 0
-      this.props.dataDoc['accelerationXDisplay2'] = 0
-      this.props.dataDoc['accelerationYDisplay2'] = 0
-    }
-    this.setState({angleLabel: Math.round(this.props.dataDoc['pendulumAngle'] ?? 0 * 100) / 100})
-  };
+        // Update x position when start pos x changes
+        if (prevProps.startPosX != this.props.startPosX) {
+            if (this.props.paused && !isNaN(this.props.startPosX)) {
+                this.setState({ xPosition: this.props.startPosX });
+                this.setState({ updatedStartPosX: this.props.startPosX });
+                this.setXPosDisplay(this.props.startPosX);
+            }
+        }
 
-  // Compute x acceleration from forces, F=ma
-  getNewAccelerationX = (forceList: IForce[]) => {
-    let newXAcc = 0;
-    if (forceList) {
-      forceList.forEach((force) => {
-        newXAcc +=
-          (force.magnitude *
-            Math.cos((force.directionInDegrees * Math.PI) / 180)) /
-          this.props.mass;
-      });
-    }
-    return newXAcc;
-  };
+        // Update y position when start pos y changes TODO debug
+        if (prevProps.startPosY != this.props.startPosY) {
+            if (this.props.paused && !isNaN(this.props.startPosY)) {
+                this.setState({ yPosition: this.props.startPosY });
+                this.setState({ updatedStartPosY: this.props.startPosY ?? 0 });
+                this.setYPosDisplay(this.props.startPosY ?? 0);
+            }
+        }
 
+        // Update wedge coordinates
+        if (this.state.coordinates === '' || prevProps.wedgeWidth != this.props.wedgeWidth || prevProps.wedgeHeight != this.props.wedgeHeight) {
+            const left = this.props.xMax * 0.25;
+            const coordinatePair1 = Math.round(left) + ',' + this.props.yMax + ' ';
+            const coordinatePair2 = Math.round(left + this.props.wedgeWidth) + ',' + this.props.yMax + ' ';
+            const coordinatePair3 = Math.round(left) + ',' + (this.props.yMax - this.props.wedgeHeight);
+            const coord = coordinatePair1 + coordinatePair2 + coordinatePair3;
+            this.setState({ coordinates: coord });
+        }
 
-  // Compute y acceleration from forces, F=ma
-  getNewAccelerationY = (forceList: IForce[]) => {
-    let newYAcc = 0;
-    if (forceList) {
-      forceList.forEach((force) => {
-        newYAcc +=
-          (-1 *
-            (force.magnitude *
-              Math.sin((force.directionInDegrees * Math.PI) / 180))) /
-            this.props.mass;
-      });
+        if (this.state.xPosition != prevState.xPosition || this.state.yPosition != prevState.yPosition) {
+            this.weightStyle = {
+                alignItems: 'center',
+                backgroundColor: this.props.color,
+                borderColor: 'black',
+                borderRadius: 50 + '%',
+                borderStyle: 'solid',
+                display: 'flex',
+                height: 2 * this.props.radius + 'px',
+                justifyContent: 'center',
+                left: this.state.xPosition + 'px',
+                position: 'absolute' as 'absolute',
+                top: this.state.yPosition + 'px',
+                touchAction: 'none',
+                width: 2 * this.props.radius + 'px',
+                zIndex: 5,
+            };
+        }
     }
-    return newYAcc;
-  };
 
-  // Compute uniform circular motion forces given x, y positions
-  getNewCircularMotionForces = (xPos: number, yPos: number) => {
-    let deltaX = (this.props.xMin + this.props.xMax) / 2 - (xPos + this.props.radius);
-    let deltaY = yPos + this.props.radius - (this.props.yMin + this.props.yMax) / 2;
-    let dir = (Math.atan2(deltaY, deltaX) * 180) / Math.PI;
-    const tensionForce: IForce = {
-      description: "Centripetal Force",
-      magnitude: (this.props.startVelX ** 2 * this.props.mass) / this.props.circularMotionRadius,
-      directionInDegrees: dir,
-      component: false,
+    // Reset simulation on reset button click
+    resetEverything = () => {
+        this.setState({ kineticFriction: false });
+        this.setState({ xPosition: this.state.updatedStartPosX });
+        this.setState({ yPosition: this.state.updatedStartPosY });
+        this.setState({ xVelocity: this.props.startVelX ?? 0 });
+        this.setState({ yVelocity: this.props.startVelY ?? 0 });
+        this.props.dataDoc.pendulum_angle = this.props.dataDoc.start_PendulumAngle;
+        this.props.dataDoc.updatedForces = this.props.dataDoc.start_Forces;
+        this.props.dataDoc.updatedForces2 = this.props.dataDoc.start_Forces2;
+        if (this.props.color == 'red') {
+            this.props.dataDoc.position_XDisplay = this.state.updatedStartPosX;
+            this.props.dataDoc.position_YDisplay = this.state.updatedStartPosY;
+            this.props.dataDoc.velocity_XDisplay = this.props.startVelX ?? 0;
+            this.props.dataDoc.velocity_YDisplay = this.props.startVelY ?? 0;
+            this.props.dataDoc.acceleration_XDisplay = 0;
+            this.props.dataDoc.acceleration_YDisplay = 0;
+        } else {
+            this.props.dataDoc.position_XDisplay2 = this.state.updatedStartPosX;
+            this.props.dataDoc.position_YDisplay2 = this.state.updatedStartPosY;
+            this.props.dataDoc.velocity_XDisplay2 = this.props.startVelX ?? 0;
+            this.props.dataDoc.velocity_YDisplay2 = this.props.startVelY ?? 0;
+            this.props.dataDoc.acceleration_XDisplay2 = 0;
+            this.props.dataDoc.acceleration_YDisplay2 = 0;
+        }
+        this.setState({ angleLabel: Math.round(NumCast(this.props.dataDoc.pendulum_angle) ?? 0 * 100) / 100 });
     };
-    return [tensionForce];
-  };
 
-  // Compute spring forces given y position
-  getNewSpringForces = (yPos: number) => {
-    let springForce: IForce = {
-      description: "Spring Force",
-      magnitude: 0,
-      directionInDegrees: 90,
-      component: false,
+    // Compute x acceleration from forces, F=ma
+    getNewAccelerationX = (forceList: IForce[]) => {
+        let newXAcc = 0;
+        if (forceList) {
+            forceList.forEach(force => {
+                newXAcc += (force.magnitude * Math.cos((force.directionInDegrees * Math.PI) / 180)) / this.props.mass;
+            });
+        }
+        return newXAcc;
     };
-    if (yPos - this.props.springRestLength > 0) {
-      springForce = {
-        description: "Spring Force",
-        magnitude: this.props.springConstant * (yPos - this.props.springRestLength),
-        directionInDegrees: 90,
-        component: false,
-      };
-    } else if (yPos - this.props.springRestLength < 0) {
-      springForce = {
-        description: "Spring Force",
-        magnitude: this.props.springConstant * (this.props.springRestLength - yPos),
-        directionInDegrees: 270,
-        component: false,
-      };
-    }
-    return [
-      {
-        description: "Gravity",
-        magnitude: Math.abs(this.props.gravity) * this.props.mass,
-        directionInDegrees: 270,
-        component: false,
-      },
-      springForce,
-    ];
-  };
-
-  // Compute pendulum forces given position, velocity
-  getNewPendulumForces = (
-    xPos: number,
-    yPos: number,
-    xVel: number,
-    yVel: number
-  ) => {
-    const x = this.props.xMax / 2 - xPos - this.props.radius;
-    const y = yPos + this.props.radius + 5;
-    let angle = (Math.atan(y / x) * 180) / Math.PI;
-    if (angle < 0) {
-      angle += 180;
-    }
-    let oppositeAngle = 90 - angle;
-    if (oppositeAngle < 0) {
-      oppositeAngle = 90 - (180 - angle);
-    }
-
-    const pendulumLength = Math.sqrt(x * x + y * y);
-    this.props.dataDoc['pendulumAngle'] = oppositeAngle;
 
-    const mag =
-      this.props.mass  * Math.abs(this.props.gravity) * Math.cos((oppositeAngle * Math.PI) / 180) +
-      (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength;
-
-    const forceOfTension: IForce = {
-      description: "Tension",
-      magnitude: mag,
-      directionInDegrees: angle,
-      component: false,
+    // Compute y acceleration from forces, F=ma
+    getNewAccelerationY = (forceList: IForce[]) => {
+        let newYAcc = 0;
+        if (forceList) {
+            forceList.forEach(force => {
+                newYAcc += (-1 * (force.magnitude * Math.sin((force.directionInDegrees * Math.PI) / 180))) / this.props.mass;
+            });
+        }
+        return newYAcc;
     };
 
-    return [
-      {
-        description: "Gravity",
-        magnitude: Math.abs(this.props.gravity) * this.props.mass,
-        directionInDegrees: 270,
-        component: false,
-      },
-      forceOfTension,
-    ];
-  };
+    // Compute uniform circular motion forces given x, y positions
+    getNewCircularMotionForces = (xPos: number, yPos: number) => {
+        let deltaX = (this.props.xMin + this.props.xMax) / 2 - (xPos + this.props.radius);
+        let deltaY = yPos + this.props.radius - (this.props.yMin + this.props.yMax) / 2;
+        let dir = (Math.atan2(deltaY, deltaX) * 180) / Math.PI;
+        const tensionForce: IForce = {
+            description: 'Centripetal Force',
+            magnitude: (this.props.startVelX ** 2 * this.props.mass) / this.props.circularMotionRadius,
+            directionInDegrees: dir,
+            component: false,
+        };
+        return [tensionForce];
+    };
 
-  // Check for collisions in x direction
-  checkForCollisionsWithWall = () => {
-    let collision = false;
-    const minX = this.state.xPosition;
-    const maxX = this.state.xPosition + 2 * this.props.radius;
-    if (this.state.xVelocity != 0) {
-      this.state.walls.forEach((wall) => {
-        if (wall.angleInDegrees == 90) {
-          const wallX = (wall.xPos / 100) * this.props.layoutDoc._width;
-          if (wall.xPos < 0.35) {
-            if (minX <= wallX) {
-              this.setState({xPosition: wallX+0.01});
-              if (this.props.elasticCollisions) {
-                this.setState({xVelocity: -this.state.xVelocity});
-              } else {
-                this.setState({xVelocity: 0});
-              }
-              collision = true;
-            }
-          } else {
-            if (maxX >= wallX) {
-              this.setState({xPosition: wallX- 2 * this.props.radius-0.01});
-              if (this.props.elasticCollisions) {
-                this.setState({xVelocity: -this.state.xVelocity});
-              } else {
-                this.setState({xVelocity: 0});
-              }
-              collision = true;
-            }
-          }
+    // Compute spring forces given y position
+    getNewSpringForces = (yPos: number) => {
+        let springForce: IForce = {
+            description: 'Spring Force',
+            magnitude: 0,
+            directionInDegrees: 90,
+            component: false,
+        };
+        if (yPos - this.props.springRestLength > 0) {
+            springForce = {
+                description: 'Spring Force',
+                magnitude: this.props.springConstant * (yPos - this.props.springRestLength),
+                directionInDegrees: 90,
+                component: false,
+            };
+        } else if (yPos - this.props.springRestLength < 0) {
+            springForce = {
+                description: 'Spring Force',
+                magnitude: this.props.springConstant * (this.props.springRestLength - yPos),
+                directionInDegrees: 270,
+                component: false,
+            };
         }
-      });
-    }
-    return collision;
-  };
+        return [
+            {
+                description: 'Gravity',
+                magnitude: Math.abs(this.props.gravity) * this.props.mass,
+                directionInDegrees: 270,
+                component: false,
+            },
+            springForce,
+        ];
+    };
 
-  // Check for collisions in y direction
-  checkForCollisionsWithGround = () => {
-    let collision = false;
-    const minY = this.state.yPosition;
-    const maxY = this.state.yPosition + 2 * this.props.radius;
-    if (this.state.yVelocity > 0) {
-      this.state.walls.forEach((wall) => {
-        if (wall.angleInDegrees == 0 && wall.yPos > 0.4) {
-          const groundY = (wall.yPos / 100) * this.props.layoutDoc._height;
-          if (maxY > groundY) {
-            this.setState({yPosition: groundY- 2 * this.props.radius-0.01});
-            if (this.props.elasticCollisions) {
-              this.setState({yVelocity: -this.state.yVelocity});
-            } else {
-              this.setState({yVelocity: 0});
-              if (this.props.dataDoc['simulationType'] != "Two Weights") {
-                const forceOfGravity: IForce = {
-                  description: "Gravity",
-                  magnitude: Math.abs(this.props.gravity) * this.props.mass,
-                  directionInDegrees: 270,
-                  component: false,
-                };
-                const normalForce: IForce = {
-                  description: "Normal force",
-                  magnitude: Math.abs(this.props.gravity) * this.props.mass,
-                  directionInDegrees: wall.angleInDegrees + 90,
-                  component: false,
-                };
-                this.props.dataDoc['updatedForces'] = ([forceOfGravity, normalForce]);
-                if (this.props.dataDoc['simulationType'] == "Inclined Plane") {
-                  const forceOfGravityC: IForce = {
-                    description: "Gravity",
-                    magnitude: Math.abs(this.props.gravity) * this.props.mass,
-                    directionInDegrees: 270,
-                    component: true,
-                  };
-                  const normalForceC: IForce = {
-                    description: "Normal force",
-                    magnitude: Math.abs(this.props.gravity) * this.props.mass,
-                    directionInDegrees: wall.angleInDegrees + 90,
-                    component: true,
-                  };
-                  this.props.dataDoc['componentForces'] = ([forceOfGravityC, normalForceC]);
-                }
-              }
-            }
-            collision = true;
-          }
+    // Compute pendulum forces given position, velocity
+    getNewPendulumForces = (xPos: number, yPos: number, xVel: number, yVel: number) => {
+        const x = this.props.xMax / 2 - xPos - this.props.radius;
+        const y = yPos + this.props.radius + 5;
+        let angle = (Math.atan(y / x) * 180) / Math.PI;
+        if (angle < 0) {
+            angle += 180;
         }
-      });
-    }
-    if (this.state.yVelocity < 0) {
-      this.state.walls.forEach((wall) => {
-        if (wall.angleInDegrees == 0 && wall.yPos < 0.4) {
-          const groundY = (wall.yPos / 100) * this.props.layoutDoc._height;
-          if (minY < groundY) {
-            this.setState({yPosition: groundY + 0.01});
-            if (this.props.elasticCollisions) {
-              this.setState({yVelocity: -this.state.yVelocity});
-            } else {
-              this.setState({yVelocity: 0});
-            }
-            collision = true;
-          }
+        let oppositeAngle = 90 - angle;
+        if (oppositeAngle < 0) {
+            oppositeAngle = 90 - (180 - angle);
         }
-      });
-    }
-    return collision;
-  };
 
-  // Called at each RK4 step
-  evaluate = (
-    currentXPos: number,
-    currentYPos: number,
-    currentXVel: number,
-    currentYVel: number,
-    deltaXPos: number,
-    deltaYPos: number,
-    deltaXVel: number,
-    deltaYVel: number,
-    dt: number
-  ) => {
-    const newXPos = currentXPos + deltaXPos * dt;
-    const newYPos = currentYPos + deltaYPos * dt;
-    const newXVel = currentXVel + deltaXVel * dt;
-    const newYVel = currentYVel + deltaYVel * dt;
-    const newDeltaXPos = newXVel;
-    const newDeltaYPos = newYVel;
-    let forces = this.props.updatedForces;
-    if (this.props.dataDoc['simulationType'] == "Pendulum") {
-      forces = this.getNewPendulumForces(newXPos, newYPos, newXVel, newYVel);
-    } else if (this.props.dataDoc['simulationType'] == "Spring") {
-      forces = this.getNewSpringForces(newYPos);
-    } else if (this.props.dataDoc['simulationType'] == "Circular Motion") {
-      forces = this.getNewCircularMotionForces(newXPos, newYPos);
-    }
-    const newDeltaXVel = this.getNewAccelerationX(forces);
-    const newDeltaYVel = this.getNewAccelerationY(forces);
-    return {
-      xPos: newXPos,
-      yPos: newYPos,
-      xVel: newXVel,
-      yVel: newYVel,
-      deltaXPos: newDeltaXPos,
-      deltaYPos: newDeltaYPos,
-      deltaXVel: newDeltaXVel,
-      deltaYVel: newDeltaYVel,
+        const pendulumLength = Math.sqrt(x * x + y * y);
+        this.props.dataDoc.pendulum_angle = oppositeAngle;
+
+        const mag = this.props.mass * Math.abs(this.props.gravity) * Math.cos((oppositeAngle * Math.PI) / 180) + (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength;
+
+        const forceOfTension: IForce = {
+            description: 'Tension',
+            magnitude: mag,
+            directionInDegrees: angle,
+            component: false,
+        };
+
+        return [
+            {
+                description: 'Gravity',
+                magnitude: Math.abs(this.props.gravity) * this.props.mass,
+                directionInDegrees: 270,
+                component: false,
+            },
+            forceOfTension,
+        ];
     };
-  };
 
-  // Update position, velocity using RK4 method
-  update = () => {
-    let startXVel = this.state.xVelocity;
-    let startYVel = this.state.yVelocity;
-    let xPos = this.state.xPosition;
-    let yPos = this.state.yPosition;
-    let xVel = this.state.xVelocity;
-    let yVel = this.state.yVelocity;
-    let forces: IForce[] = this.props.dataDoc['updatedForces'];
-    if (this.props.dataDoc['simulationType'] == "Pendulum") {
-      forces = this.getNewPendulumForces(xPos, yPos, xVel, yVel);
-    } else if (this.props.dataDoc['simulationType'] == "Spring") {
-      forces = this.getNewSpringForces(yPos);
-    } else if (this.props.dataDoc['simulationType'] == "Circular Motion") {
-      forces = this.getNewCircularMotionForces(xPos, yPos);
-    }
-    const xAcc = this.getNewAccelerationX(forces);
-    const yAcc = this.getNewAccelerationY(forces);
-    for (let i = 0; i < this.props.simulationSpeed; i++) {
-      const k1 = this.evaluate(xPos, yPos, xVel, yVel, xVel, yVel, xAcc, yAcc, 0);
-      const k2 = this.evaluate(
-        xPos,
-        yPos,
-        xVel,
-        yVel,
-        k1.deltaXPos,
-        k1.deltaYPos,
-        k1.deltaXVel,
-        k1.deltaYVel,
-        this.props.timestepSize * 0.5
-      );
-      const k3 = this.evaluate(
-        xPos,
-        yPos,
-        xVel,
-        yVel,
-        k2.deltaXPos,
-        k2.deltaYPos,
-        k2.deltaXVel,
-        k2.deltaYVel,
-        this.props.timestepSize * 0.5
-      );
-      const k4 = this.evaluate(
-        xPos,
-        yPos,
-        xVel,
-        yVel,
-        k3.deltaXPos,
-        k3.deltaYPos,
-        k3.deltaXVel,
-        k3.deltaYVel,
-        this.props.timestepSize
-      );
+    // Check for collisions in x direction
+    checkForCollisionsWithWall = () => {
+        let collision = false;
+        const minX = this.state.xPosition;
+        const maxX = this.state.xPosition + 2 * this.props.radius;
+        if (this.state.xVelocity != 0) {
+            this.state.walls.forEach(wall => {
+                if (wall.angleInDegrees == 90) {
+                    const wallX = (wall.xPos / 100) * this.props.layoutDoc[WidthSym]();
+                    if (wall.xPos < 0.35) {
+                        if (minX <= wallX) {
+                            this.setState({ xPosition: wallX + 0.01 });
+                            if (this.props.elasticCollisions) {
+                                this.setState({ xVelocity: -this.state.xVelocity });
+                            } else {
+                                this.setState({ xVelocity: 0 });
+                            }
+                            collision = true;
+                        }
+                    } else {
+                        if (maxX >= wallX) {
+                            this.setState({ xPosition: wallX - 2 * this.props.radius - 0.01 });
+                            if (this.props.elasticCollisions) {
+                                this.setState({ xVelocity: -this.state.xVelocity });
+                            } else {
+                                this.setState({ xVelocity: 0 });
+                            }
+                            collision = true;
+                        }
+                    }
+                }
+            });
+        }
+        return collision;
+    };
 
-      xVel +=
-        ((this.props.timestepSize * 1.0) / 6.0) *
-        (k1.deltaXVel + 2 * (k2.deltaXVel + k3.deltaXVel) + k4.deltaXVel);
-      yVel +=
-        ((this.props.timestepSize * 1.0) / 6.0) *
-        (k1.deltaYVel + 2 * (k2.deltaYVel + k3.deltaYVel) + k4.deltaYVel);
-      xPos +=
-        ((this.props.timestepSize * 1.0) / 6.0) *
-        (k1.deltaXPos + 2 * (k2.deltaXPos + k3.deltaXPos) + k4.deltaXPos);
-      yPos +=
-        ((this.props.timestepSize * 1.0) / 6.0) *
-        (k1.deltaYPos + 2 * (k2.deltaYPos + k3.deltaYPos) + k4.deltaYPos);
-    }
-    // make sure harmonic motion maintained and errors don't propagate
-    if (this.props.dataDoc['simulationType'] == "Spring") {
-      if (startYVel < 0 && yVel > 0 && yPos < this.props.springRestLength) {
-        let equilibriumPos =
-        this.props.springRestLength + (this.props.mass * Math.abs(this.props.gravity)) / this.props.springConstant;
-        let amplitude = Math.abs(equilibriumPos - this.props.springStartLength);
-        yPos = equilibriumPos - amplitude;
-      } else if (startYVel > 0 && yVel < 0 && yPos > this.props.springRestLength) {
-        let equilibriumPos =
-        this.props.springRestLength + (this.props.mass * Math.abs(this.props.gravity)) / this.props.springConstant;
-        let amplitude = Math.abs(equilibriumPos - this.props.springStartLength);
-        yPos = equilibriumPos + amplitude;
-      }
-    }
-    if (this.props.dataDoc['simulationType'] == "Pendulum") {
-      let startX = this.state.updatedStartPosX;
-      if (startXVel <= 0 && xVel > 0) {
-        xPos = this.state.updatedStartPosX;
-        if (this.state.updatedStartPosX > this.props.xMax / 2) {
-          xPos = this.props.xMax / 2 + (this.props.xMax / 2 - startX) - 2 * this.props.radius;
+    // Check for collisions in y direction
+    checkForCollisionsWithGround = () => {
+        let collision = false;
+        const minY = this.state.yPosition;
+        const maxY = this.state.yPosition + 2 * this.props.radius;
+        if (this.state.yVelocity > 0) {
+            this.state.walls.forEach(wall => {
+                if (wall.angleInDegrees == 0 && wall.yPos > 0.4) {
+                    const groundY = (wall.yPos / 100) * this.props.layoutDoc[HeightSym]();
+                    if (maxY > groundY) {
+                        this.setState({ yPosition: groundY - 2 * this.props.radius - 0.01 });
+                        if (this.props.elasticCollisions) {
+                            this.setState({ yVelocity: -this.state.yVelocity });
+                        } else {
+                            this.setState({ yVelocity: 0 });
+                            if (this.props.dataDoc.simulation_Type != 'Two Weights') {
+                                const forceOfGravity: IForce = {
+                                    description: 'Gravity',
+                                    magnitude: Math.abs(this.props.gravity) * this.props.mass,
+                                    directionInDegrees: 270,
+                                    component: false,
+                                };
+                                const normalForce: IForce = {
+                                    description: 'Normal force',
+                                    magnitude: Math.abs(this.props.gravity) * this.props.mass,
+                                    directionInDegrees: wall.angleInDegrees + 90,
+                                    component: false,
+                                };
+                                this.props.dataDoc.updatedForces = [forceOfGravity, normalForce];
+                                if (this.props.dataDoc.simulation_Type == 'Inclined Plane') {
+                                    const forceOfGravityC: IForce = {
+                                        description: 'Gravity',
+                                        magnitude: Math.abs(this.props.gravity) * this.props.mass,
+                                        directionInDegrees: 270,
+                                        component: true,
+                                    };
+                                    const normalForceC: IForce = {
+                                        description: 'Normal force',
+                                        magnitude: Math.abs(this.props.gravity) * this.props.mass,
+                                        directionInDegrees: wall.angleInDegrees + 90,
+                                        component: true,
+                                    };
+                                    this.props.dataDoc.componentForces = [forceOfGravityC, normalForceC];
+                                }
+                            }
+                        }
+                        collision = true;
+                    }
+                }
+            });
         }
-        yPos = this.props.startPosY;
-      } else if (startXVel >= 0 && xVel < 0) {
-        xPos = this.state.updatedStartPosX;
-        if (this.state.updatedStartPosX < this.props.xMax / 2) {
-          xPos = this.props.xMax / 2 + (this.props.xMax / 2 - startX) - 2 * this.props.radius;
+        if (this.state.yVelocity < 0) {
+            this.state.walls.forEach(wall => {
+                if (wall.angleInDegrees == 0 && wall.yPos < 0.4) {
+                    const groundY = (wall.yPos / 100) * this.props.layoutDoc[HeightSym]();
+                    if (minY < groundY) {
+                        this.setState({ yPosition: groundY + 0.01 });
+                        if (this.props.elasticCollisions) {
+                            this.setState({ yVelocity: -this.state.yVelocity });
+                        } else {
+                            this.setState({ yVelocity: 0 });
+                        }
+                        collision = true;
+                    }
+                }
+            });
         }
-        yPos = this.props.startPosY;
-      }
-    }
-    if (this.props.dataDoc['simulationType'] == "One Weight") {
-      if (yPos < this.state.maxPosYConservation) {
-        yPos = this.state.maxPosYConservation;
-      }
-    }
-    this.setState({xVelocity: xVel});
-    this.setState({yVelocity: yVel});
-    this.setState({xPosition: xPos});
-    this.setState({yPosition: yPos});
-    let forcesn = this.props.dataDoc['updatedForces']
-    if (this.props.dataDoc['simulationType'] == "Pendulum") {
-      forcesn = this.getNewPendulumForces(xPos, yPos, xVel, yVel);
-    } else if (this.props.dataDoc['simulationType'] == "Spring") {
-      forcesn = this.getNewSpringForces(yPos);
-    } else if (this.props.dataDoc['simulationType'] == "Circular Motion") {
-      forcesn = this.getNewCircularMotionForces(xPos, yPos);
-    }
-    this.props.dataDoc['updatedForces'] = (forcesn);
-
-    // set component forces if they change
-    if (this.props.dataDoc['simulationType'] == "Pendulum") {
-      let x = this.props.xMax / 2 - xPos - this.props.radius;
-      let y = yPos + this.props.radius + 5;
-      let angle = (Math.atan(y / x) * 180) / Math.PI;
-      if (angle < 0) {
-        angle += 180;
-      }
-      let oppositeAngle = 90 - angle;
-      if (oppositeAngle < 0) {
-        oppositeAngle = 90 - (180 - angle);
-      }
-
-      const pendulumLength = Math.sqrt(x * x + y * y);
+        return collision;
+    };
 
-      const mag =
-      this.props.mass * Math.abs(this.props.gravity) * Math.cos((oppositeAngle * Math.PI) / 180) +
-        (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength;
+    // Called at each RK4 step
+    evaluate = (currentXPos: number, currentYPos: number, currentXVel: number, currentYVel: number, deltaXPos: number, deltaYPos: number, deltaXVel: number, deltaYVel: number, dt: number) => {
+        const newXPos = currentXPos + deltaXPos * dt;
+        const newYPos = currentYPos + deltaYPos * dt;
+        const newXVel = currentXVel + deltaXVel * dt;
+        const newYVel = currentYVel + deltaYVel * dt;
+        const newDeltaXPos = newXVel;
+        const newDeltaYPos = newYVel;
+        let forces = this.props.updatedForces;
+        if (this.props.dataDoc.simulation_Type == 'Pendulum') {
+            forces = this.getNewPendulumForces(newXPos, newYPos, newXVel, newYVel);
+        } else if (this.props.dataDoc.simulation_Type == 'Spring') {
+            forces = this.getNewSpringForces(newYPos);
+        } else if (this.props.dataDoc.simulation_Type == 'Circular Motion') {
+            forces = this.getNewCircularMotionForces(newXPos, newYPos);
+        }
+        const newDeltaXVel = this.getNewAccelerationX(forces);
+        const newDeltaYVel = this.getNewAccelerationY(forces);
+        return {
+            xPos: newXPos,
+            yPos: newYPos,
+            xVel: newXVel,
+            yVel: newYVel,
+            deltaXPos: newDeltaXPos,
+            deltaYPos: newDeltaYPos,
+            deltaXVel: newDeltaXVel,
+            deltaYVel: newDeltaYVel,
+        };
+    };
 
-      const tensionComponent: IForce = {
-        description: "Tension",
-        magnitude: mag,
-        directionInDegrees: angle,
-        component: true,
-      };
-      const gravityParallel: IForce = {
-        description: "Gravity Parallel Component",
-        magnitude: Math.abs(this.props.gravity) * Math.cos(((90 - angle) * Math.PI) / 180),
-        directionInDegrees: 270 - (90 - angle),
-        component: true,
-      };
-      const gravityPerpendicular: IForce = {
-        description: "Gravity Perpendicular Component",
-        magnitude: Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180),
-        directionInDegrees: -(90 - angle),
-        component: true,
-      };
-      if (Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180) < 0) {
-        gravityPerpendicular.magnitude = Math.abs(
-          Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180)
-        );
-        gravityPerpendicular.directionInDegrees = 180 - (90 - angle);
-      }
-      this.props.dataDoc['componentForces'] = ([
-        tensionComponent,
-        gravityParallel,
-        gravityPerpendicular,
-      ]);
-    }
-  };
+    // Update position, velocity using RK4 method
+    update = () => {
+        let startXVel = this.state.xVelocity;
+        let startYVel = this.state.yVelocity;
+        let xPos = this.state.xPosition;
+        let yPos = this.state.yPosition;
+        let xVel = this.state.xVelocity;
+        let yVel = this.state.yVelocity;
+        let forces: IForce[] = this.props.dataDoc.updatedForces;
+        if (this.props.dataDoc.simulation_Type == 'Pendulum') {
+            forces = this.getNewPendulumForces(xPos, yPos, xVel, yVel);
+        } else if (this.props.dataDoc.simulation_Type == 'Spring') {
+            forces = this.getNewSpringForces(yPos);
+        } else if (this.props.dataDoc.simulation_Type == 'Circular Motion') {
+            forces = this.getNewCircularMotionForces(xPos, yPos);
+        }
+        const xAcc = this.getNewAccelerationX(forces);
+        const yAcc = this.getNewAccelerationY(forces);
+        for (let i = 0; i < this.props.simulationSpeed; i++) {
+            const k1 = this.evaluate(xPos, yPos, xVel, yVel, xVel, yVel, xAcc, yAcc, 0);
+            const k2 = this.evaluate(xPos, yPos, xVel, yVel, k1.deltaXPos, k1.deltaYPos, k1.deltaXVel, k1.deltaYVel, this.props.timestepSize * 0.5);
+            const k3 = this.evaluate(xPos, yPos, xVel, yVel, k2.deltaXPos, k2.deltaYPos, k2.deltaXVel, k2.deltaYVel, this.props.timestepSize * 0.5);
+            const k4 = this.evaluate(xPos, yPos, xVel, yVel, k3.deltaXPos, k3.deltaYPos, k3.deltaXVel, k3.deltaYVel, this.props.timestepSize);
 
-  // Render weight, spring, rod(s), vectors
-  render () { 
-    return (
-    <div>
-      <div
-        className="weightContainer"
-        onPointerDown={(e) => {
-          if (this.draggable) {
-            this.props.dataDoc['paused'] = true;
-            this.setState({dragging: true});
-            this.setState({clickPositionX: e.clientX});
-            this.setState({clickPositionY: e.clientY});
-          } 
-        }}
-        onPointerMove={(e) => {
-          if (this.state.dragging) {
-            let newY = this.state.yPosition + e.clientY - this.state.clickPositionY;
-            if (newY > this.props.yMax - 2 * this.props.radius - 10) {
-              newY = this.props.yMax - 2 * this.props.radius - 10;
-            } else if (newY < 10) {
-              newY = 10;
+            xVel += ((this.props.timestepSize * 1.0) / 6.0) * (k1.deltaXVel + 2 * (k2.deltaXVel + k3.deltaXVel) + k4.deltaXVel);
+            yVel += ((this.props.timestepSize * 1.0) / 6.0) * (k1.deltaYVel + 2 * (k2.deltaYVel + k3.deltaYVel) + k4.deltaYVel);
+            xPos += ((this.props.timestepSize * 1.0) / 6.0) * (k1.deltaXPos + 2 * (k2.deltaXPos + k3.deltaXPos) + k4.deltaXPos);
+            yPos += ((this.props.timestepSize * 1.0) / 6.0) * (k1.deltaYPos + 2 * (k2.deltaYPos + k3.deltaYPos) + k4.deltaYPos);
+        }
+        // make sure harmonic motion maintained and errors don't propagate
+        if (this.props.dataDoc.simulation_Type == 'Spring') {
+            if (startYVel < 0 && yVel > 0 && yPos < this.props.springRestLength) {
+                let equilibriumPos = this.props.springRestLength + (this.props.mass * Math.abs(this.props.gravity)) / this.props.springConstant;
+                let amplitude = Math.abs(equilibriumPos - this.props.springStartLength);
+                yPos = equilibriumPos - amplitude;
+            } else if (startYVel > 0 && yVel < 0 && yPos > this.props.springRestLength) {
+                let equilibriumPos = this.props.springRestLength + (this.props.mass * Math.abs(this.props.gravity)) / this.props.springConstant;
+                let amplitude = Math.abs(equilibriumPos - this.props.springStartLength);
+                yPos = equilibriumPos + amplitude;
             }
-
-            let newX = this.state.xPosition + e.clientX - this.state.clickPositionX;
-            if (newX > this.props.xMax - 2 * this.props.radius - 10) {
-              newX = this.props.xMax - 2 * this.props.radius - 10;
-            } else if (newX < 10) {
-              newX = 10;
+        }
+        if (this.props.dataDoc.simulation_Type == 'Pendulum') {
+            let startX = this.state.updatedStartPosX;
+            if (startXVel <= 0 && xVel > 0) {
+                xPos = this.state.updatedStartPosX;
+                if (this.state.updatedStartPosX > this.props.xMax / 2) {
+                    xPos = this.props.xMax / 2 + (this.props.xMax / 2 - startX) - 2 * this.props.radius;
+                }
+                yPos = this.props.startPosY;
+            } else if (startXVel >= 0 && xVel < 0) {
+                xPos = this.state.updatedStartPosX;
+                if (this.state.updatedStartPosX < this.props.xMax / 2) {
+                    xPos = this.props.xMax / 2 + (this.props.xMax / 2 - startX) - 2 * this.props.radius;
+                }
+                yPos = this.props.startPosY;
             }
-            if (this.props.dataDoc['simulationType'] == "Suspension") {
-              if (newX < (this.props.xMax + this.props.xMin) / 4 - this.props.radius - 15) {
-                newX = (this.props.xMax + this.props.xMin) / 4 - this.props.radius - 15;
-              } else if (newX > (3 * (this.props.xMax + this.props.xMin)) / 4 - this.props.radius / 2 - 15) {
-                newX = (3 * (this.props.xMax + this.props.xMin)) / 4 - this.props.radius / 2 - 15;
-              }
+        }
+        if (this.props.dataDoc.simulation_Type == 'One Weight') {
+            if (yPos < this.state.maxPosYConservation) {
+                yPos = this.state.maxPosYConservation;
             }
+        }
+        this.setState({ xVelocity: xVel });
+        this.setState({ yVelocity: yVel });
+        this.setState({ xPosition: xPos });
+        this.setState({ yPosition: yPos });
+        let forcesn = this.props.dataDoc.updatedForces;
+        if (this.props.dataDoc.simulation_Type == 'Pendulum') {
+            forcesn = this.getNewPendulumForces(xPos, yPos, xVel, yVel);
+        } else if (this.props.dataDoc.simulation_Type == 'Spring') {
+            forcesn = this.getNewSpringForces(yPos);
+        } else if (this.props.dataDoc.simulation_Type == 'Circular Motion') {
+            forcesn = this.getNewCircularMotionForces(xPos, yPos);
+        }
+        this.props.dataDoc.updatedForces = forcesn;
 
-            this.setState({yPosition: newY});
-            this.props.dataDoc['positionYDisplay'] = 
-              Math.round((this.props.yMax - 2 * this.props.radius - newY + 5) * 100) / 100
-            if (this.props.dataDoc['simulationType'] != "Pulley") {
-              this.setState({xPosition: newX});
-              this.props.dataDoc['positionXDisplay'] = newX
-            }
-            if (this.props.dataDoc['simulationType'] != "Suspension") {
-              if (this.props.dataDoc['simulationType'] != "Pulley") {
-                this.setState({updatedStartPosX: newX});
-              }
-              this.setState({updatedStartPosY: newY});
-            }
-            this.setState({clickPositionX: e.clientX});
-            this.setState({clickPositionY: e.clientY});
-            this.setDisplayValues();
-          }
-        }}
-        onPointerUp={(e) => {
-          if (this.state.dragging) {
-            if (
-              this.props.dataDoc['simulationType'] != "Pendulum" &&
-              this.props.dataDoc['simulationType'] != "Suspension"
-            ) {
-              this.resetEverything();
+        // set component forces if they change
+        if (this.props.dataDoc.simulation_Type == 'Pendulum') {
+            let x = this.props.xMax / 2 - xPos - this.props.radius;
+            let y = yPos + this.props.radius + 5;
+            let angle = (Math.atan(y / x) * 180) / Math.PI;
+            if (angle < 0) {
+                angle += 180;
             }
-            this.setState({dragging: false});
-            let newY = this.state.yPosition + e.clientY - this.state.clickPositionY;
-            if (newY > this.props.yMax - 2 * this.props.radius - 10) {
-              newY = this.props.yMax - 2 * this.props.radius - 10;
-            } else if (newY < 10) {
-              newY = 10;
+            let oppositeAngle = 90 - angle;
+            if (oppositeAngle < 0) {
+                oppositeAngle = 90 - (180 - angle);
             }
 
-            let newX = this.state.xPosition + e.clientX - this.state.clickPositionX;
-            if (newX > this.props.xMax - 2 * this.props.radius - 10) {
-              newX = this.props.xMax - 2 * this.props.radius - 10;
-            } else if (newX < 10) {
-              newX = 10;
-            }
-            if (this.props.dataDoc['simulationType'] == "Spring") {
-              this.props.dataDoc.springStartLength = newY
-            }
-            if (this.props.dataDoc['simulationType'] == "Suspension") {
-              let x1rod = (this.props.xMax + this.props.xMin) / 2 - this.props.radius - this.props.yMin - 200;
-              let x2rod = (this.props.xMax + this.props.xMin) / 2 + this.props.yMin + 200 + this.props.radius;
-              let deltaX1 = this.state.xPosition + this.props.radius - x1rod;
-              let deltaX2 = x2rod - (this.state.xPosition + this.props.radius);
-              let deltaY = this.state.yPosition + this.props.radius;
-              let dir1T = Math.PI - Math.atan(deltaY / deltaX1);
-              let dir2T = Math.atan(deltaY / deltaX2);
-              let tensionMag2 =
-                (this.props.mass * Math.abs(this.props.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: this.props.mass * Math.abs(this.props.gravity),
-                directionInDegrees: 270,
-                component: false,
-              };
-              this.props.dataDoc['updatedForces'] = ([tensionForce1, tensionForce2, grav]);
+            const pendulumLength = Math.sqrt(x * x + y * y);
+
+            const mag = this.props.mass * Math.abs(this.props.gravity) * Math.cos((oppositeAngle * Math.PI) / 180) + (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength;
+
+            const tensionComponent: IForce = {
+                description: 'Tension',
+                magnitude: mag,
+                directionInDegrees: angle,
+                component: true,
+            };
+            const gravityParallel: IForce = {
+                description: 'Gravity Parallel Component',
+                magnitude: Math.abs(this.props.gravity) * Math.cos(((90 - angle) * Math.PI) / 180),
+                directionInDegrees: 270 - (90 - angle),
+                component: true,
+            };
+            const gravityPerpendicular: IForce = {
+                description: 'Gravity Perpendicular Component',
+                magnitude: Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180),
+                directionInDegrees: -(90 - angle),
+                component: true,
+            };
+            if (Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180) < 0) {
+                gravityPerpendicular.magnitude = Math.abs(Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180));
+                gravityPerpendicular.directionInDegrees = 180 - (90 - angle);
             }
-          }
-        }}
-      >
-        <div className="weight" style={this.weightStyle}>
-          <p className="weightLabel">{this.props.mass} kg</p>
-        </div>
-      </div>
-      {this.props.dataDoc['simulationType'] == "Spring" && (
-        <div
-          className="spring"
-          style={{
-            pointerEvents: "none",
-            position: "absolute",
-            left: 0,
-            top: 0,
-          }}
-        >
-          <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
-            {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map((val) => {
-              const count = 10;
-              let xPos1;
-              let yPos1;
-              let xPos2;
-              let yPos2;
-              if (val % 2 == 0) {
-                xPos1 = this.state.xPosition + this.props.radius - 20;
-                xPos2 = this.state.xPosition + this.props.radius + 20;
-              } else {
-                xPos1 = this.state.xPosition + this.props.radius + 20;
-                xPos2 = this.state.xPosition + this.props.radius - 20;
-              }
-              yPos1 = (val * this.state.yPosition) / count;
-              yPos2 = ((val + 1) * this.state.yPosition) / count;
-              return (
-                <line
-                  key={val}
-                  x1={xPos1}
-                  y1={yPos1}
-                  x2={xPos2}
-                  y2={yPos2}
-                  stroke={"#808080"}
-                  strokeWidth="10"
-                />
-              );
-            })}
-          </svg>
-        </div>
-      )}
-      
-      {this.props.dataDoc['simulationType'] == "Pulley" && (
-        <div
-          className="rod"
-          style={{
-            pointerEvents: "none",
-            position: "absolute",
-            left: 0,
-            top: 0,
-          }}
-        >
-          <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
-            <line
-              x1={this.state.xPosition + this.props.radius}
-              y1={this.state.yPosition + this.props.radius}
-              x2={this.state.xPosition + this.props.radius}
-              y2={this.props.yMin}
-              stroke={"#deb887"}
-              strokeWidth="10"
-            />
-          </svg>
-        </div>
-      )}
-      {this.props.dataDoc['simulationType'] == "Pulley" && (
-        <div
-          className="wheel"
-          style={{
-            pointerEvents: "none",
-            position: "absolute",
-            left: 0,
-            top: 0,
-          }}
-        >
-          <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
-            <circle
-              cx={(this.props.xMax + this.props.xMin) / 2}
-              cy={this.props.radius}
-              r={this.props.radius * 1.5}
-              fill={"#808080"}
-            />
-          </svg>
-        </div>
-      )}
-      {this.props.dataDoc['simulationType'] == "Suspension" && (
-        <div
-          className="rod"
-          style={{
-            pointerEvents: "none",
-            position: "absolute",
-            left: 0,
-            top: 0,
-          }}
-        >
-          <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
-            <line
-              x1={this.state.xPosition + this.props.radius}
-              y1={this.state.yPosition + this.props.radius}
-              x2={(this.props.xMax + this.props.xMin) / 2 - this.props.radius - this.props.yMin - 200}
-              y2={this.props.yMin}
-              stroke={"#deb887"}
-              strokeWidth="10"
-            />
-          </svg>
-          <p
-            style={{
-              position: "absolute",
-              left: (this.props.xMax + this.props.xMin) / 2 - this.props.radius - this.props.yMin - 200 + 80 + "px",
-              top: 10 + "px",
-              backgroundColor: this.labelBackgroundColor,
-            }}
-          >
-            {Math.round(
-              ((Math.atan(
-                (this.state.yPosition + this.props.radius) /
-                  (this.state.xPosition +
-                    this.props.radius -
-                    ((this.props.xMax + this.props.xMin) / 2 - this.props.radius - this.props.yMin - 200))
-              ) *
-                180) /
-                Math.PI) *
-                100
-            ) / 100}
-            °
-          </p>
-          <svg width={this.props.layoutDoc._width + "px"} height={this.props.layoutDoc._height + "px"}>
-            <line
-              x1={this.state.xPosition + this.props.radius}
-              y1={this.state.yPosition + this.props.radius}
-              x2={(this.props.xMax + this.props.xMin) / 2 + this.props.yMin + 200 + this.props.radius}
-              y2={this.props.yMin}
-              stroke={"#deb887"}
-              strokeWidth="10"
-            />
-          </svg>
+            this.props.dataDoc.componentForces = [tensionComponent, gravityParallel, gravityPerpendicular];
+        }
+    };
 
-          <p
-            style={{
-              position: "absolute",
-              left: (this.props.xMax + this.props.xMin) / 2 + this.props.yMin + 200 + this.props.radius - 80 + "px",
-              top: 10 + "px",
-              backgroundColor: this.labelBackgroundColor,
-            }}
-          >
-            {Math.round(
-              ((Math.atan(
-                (this.state.yPosition + this.props.radius) /
-                  ((this.props.xMax + this.props.xMin) / 2 +
-                  this.props.yMin +
-                    200 +
-                    this.props.radius -
-                    (this.state.xPosition + this.props.radius))
-              ) *
-                180) /
-                Math.PI) *
-                100
-            ) / 100}
-            °
-          </p>
-        </div>
-      )}
-      {this.props.dataDoc['simulationType'] == "Circular Motion" && (
-        <div
-          className="rod"
-          style={{
-            pointerEvents: "none",
-            position: "absolute",
-            left: 0,
-            top: 0,
-          }}
-        >
-          <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
-            <line
-              x1={this.state.xPosition + this.props.radius}
-              y1={this.state.yPosition + this.props.radius}
-              x2={(this.props.xMin + this.props.xMax) / 2}
-              y2={(this.props.yMin + this.props.yMax) / 2}
-              stroke={"#deb887"}
-              strokeWidth="10"
-            />
-          </svg>
-        </div>
-      )}
-      {this.props.dataDoc['simulationType'] == "Pendulum" && (
-        <div
-          className="rod"
-          style={{
-            pointerEvents: "none",
-            position: "absolute",
-            left: 0,
-            top: 0,
-          }}
-        >
-          <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
-            <line
-              x1={this.state.xPosition + this.props.radius}
-              y1={this.state.yPosition + this.props.radius}
-              x2={this.props.xMax / 2}
-              y2={-5}
-              stroke={"#deb887"}
-              strokeWidth="10"
-            />
-          </svg>
-          {!this.state.dragging && (
+    // Render weight, spring, rod(s), vectors
+    render() {
+        return (
             <div>
-              <p
-                style={{
-                  position: "absolute",
-                  zIndex: 5,
-                  left: this.state.xPosition + "px",
-                  top: this.state.yPosition - 70 + "px",
-                  backgroundColor: this.labelBackgroundColor,
-                }}
-              >
-                {Math.round(this.props.pendulumLength)} m
-              </p>
-              <p
-                style={{
-                  position: "absolute",
-                  left: this.props.xMax / 2 + "px",
-                  top: 30 + "px",
-                  backgroundColor: this.labelBackgroundColor,
-                }}
-              >
-                {Math.round(this.props.pendulumAngle * 100) / 100}°
-              </p>
-            </div>
-          )}
-        </div>
-      )}
-      {this.props.dataDoc['simulationType'] == "Inclined Plane" && (
-        <div>
-          <div
-            style={{ position: "absolute", left: "0", top: "0" }}
-          >
-            <svg width={this.props.xMax + "px"} height={this.props.yMax + "px"}>
-              <polygon points={this.state.coordinates} style={{ fill: "burlywood" }} />
-            </svg>
-          </div>
-
-          <p
-            style={{
-              position: "absolute",
-              left: Math.round(this.props.xMax * 0.5 - 200 + this.props.wedgeWidth - 80) + "px",
-              top: Math.round(this.props.yMax - 40) + "px",
-            }}
-          >
-            {Math.round(
-              ((Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI) * 100
-            ) / 100}
-            °
-          </p>
-        </div>
-      )}
-      {!this.state.dragging && this.props.showAcceleration && (
-        <div>
-          <div
-            style={{
-              pointerEvents: "none",
-              position: "absolute",
-              left: 0,
-              top: 0,
-            }}
-          >
-            <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
-              <defs>
-                <marker
-                  id="accArrow"
-                  markerWidth="10"
-                  markerHeight="10"
-                  refX="0"
-                  refY="3"
-                  orient="auto"
-                  markerUnits="strokeWidth"
-                >
-                  <path d="M0,0 L0,6 L9,3 z" fill="green" />
-                </marker>
-              </defs>
-              <line
-                x1={this.state.xPosition + this.props.radius}
-                y1={this.state.yPosition + this.props.radius}
-                x2={this.state.xPosition + this.props.radius + this.getNewAccelerationX(this.props.updatedForces) * 15}
-                y2={this.state.yPosition + this.props.radius + this.getNewAccelerationY(this.props.updatedForces) * 15}
-                stroke={"green"}
-                strokeWidth="5"
-                markerEnd="url(#accArrow)"
-              />
-            </svg>
-            <div
-              style={{
-                pointerEvents: "none",
-                position: "absolute",
-                left: this.state.xPosition + this.props.radius + this.state.xAccel * 15 + 25 + "px",
-                top: this.state.yPosition + this.props.radius + this.state.yAccel * 15 + 70 + "px",
-                lineHeight: 1,
-              }}
-            >
-              <p>
-                {Math.round(
-                  100 * Math.sqrt(this.state.xAccel * this.state.xAccel + this.state.yAccel * this.state.yAccel)
-                ) / 100}{" "}
-                m/s
-                <sup>2</sup>
-              </p>
-            </div>
-          </div>
-        </div>
-      )}
-      {!this.state.dragging && this.props.showVelocity && (
-        <div>
-          <div
-            style={{
-              pointerEvents: "none",
-              position: "absolute",
-              left: 0,
-              top: 0,
-            }}
-          >
-            <svg width={this.props.xMax + "px"} height={this.props.layoutDoc._height + "px"}>
-              <defs>
-                <marker
-                  id="velArrow"
-                  markerWidth="10"
-                  markerHeight="10"
-                  refX="0"
-                  refY="3"
-                  orient="auto"
-                  markerUnits="strokeWidth"
-                >
-                  <path d="M0,0 L0,6 L9,3 z" fill="blue" />
-                </marker>
-              </defs>
-              <line
-                x1={this.state.xPosition + this.props.radius}
-                y1={this.state.yPosition + this.props.radius}
-                x2={this.state.xPosition + this.props.radius + this.state.xVelocity * 7}
-                y2={this.state.yPosition + this.props.radius + this.state.yVelocity * 7}
-                stroke={"blue"}
-                strokeWidth="5"
-                markerEnd="url(#velArrow)"
-              />
-            </svg>
-            <div
-              style={{
-                pointerEvents: "none",
-                position: "absolute",
-                left: this.state.xPosition + this.props.radius + this.state.xVelocity * 7 + 25 + "px",
-                top: this.state.yPosition +  this.props.radius + this.state.yVelocity * 7 + "px",
-                lineHeight: 1,
-              }}
-            >
-              <p>
-                {Math.round(
-                  100 *
-                    Math.sqrt(
-                      this.props.displayXVelocity * this.props.displayXVelocity +
-                      this.props.displayYVelocity * this.props.displayYVelocity
-                    )
-                ) / 100}{" "}
-                m/s
-              </p>
-            </div>
-          </div>
-        </div>
-      )}
-      {!this.state.dragging &&
-        this.props.showComponentForces &&
-        this.props.componentForces.map((force, index) => {
-          if (force.magnitude < this.epsilon) {
-            return;
-          }
-          let arrowStartY: number = this.state.yPosition + this.props.radius;
-          const arrowStartX: number = this.state.xPosition + this.props.radius;
-          let arrowEndY: number =
-            arrowStartY -
-            Math.abs(force.magnitude) *
-              20 *
-              Math.sin((force.directionInDegrees * Math.PI) / 180);
-          const arrowEndX: number =
-            arrowStartX +
-            Math.abs(force.magnitude) *
-              20 *
-              Math.cos((force.directionInDegrees * Math.PI) / 180);
+                <div
+                    className="weightContainer"
+                    onPointerDown={e => {
+                        if (this.draggable) {
+                            this.props.dataDoc.paused = true;
+                            this.setState({ dragging: true });
+                            this.setState({ clickPositionX: e.clientX });
+                            this.setState({ clickPositionY: e.clientY });
+                        }
+                    }}
+                    onPointerMove={e => {
+                        if (this.state.dragging) {
+                            let newY = this.state.yPosition + e.clientY - this.state.clickPositionY;
+                            if (newY > this.props.yMax - 2 * this.props.radius - 10) {
+                                newY = this.props.yMax - 2 * this.props.radius - 10;
+                            } else if (newY < 10) {
+                                newY = 10;
+                            }
 
-          let color = "#0d0d0d";
+                            let newX = this.state.xPosition + e.clientX - this.state.clickPositionX;
+                            if (newX > this.props.xMax - 2 * this.props.radius - 10) {
+                                newX = this.props.xMax - 2 * this.props.radius - 10;
+                            } else if (newX < 10) {
+                                newX = 10;
+                            }
+                            if (this.props.dataDoc.simulation_Type == 'Suspension') {
+                                if (newX < (this.props.xMax + this.props.xMin) / 4 - this.props.radius - 15) {
+                                    newX = (this.props.xMax + this.props.xMin) / 4 - this.props.radius - 15;
+                                } else if (newX > (3 * (this.props.xMax + this.props.xMin)) / 4 - this.props.radius / 2 - 15) {
+                                    newX = (3 * (this.props.xMax + this.props.xMin)) / 4 - this.props.radius / 2 - 15;
+                                }
+                            }
 
-          let labelTop = arrowEndY;
-          let labelLeft = arrowEndX;
-          if (force.directionInDegrees > 90 && force.directionInDegrees < 270) {
-            labelLeft -= 120;
-          } else {
-            labelLeft += 30;
-          }
-          if (force.directionInDegrees >= 0 && force.directionInDegrees < 180) {
-            labelTop += 40;
-          } else {
-            labelTop -= 40;
-          }
-          labelTop = Math.min(labelTop, this.props.yMax + 50);
-          labelTop = Math.max(labelTop, this.props.yMin);
-          labelLeft = Math.min(labelLeft, this.props.xMax - 60);
-          labelLeft = Math.max(labelLeft, this.props.xMin);
+                            this.setState({ yPosition: newY });
+                            this.props.dataDoc.position_YDisplay = Math.round((this.props.yMax - 2 * this.props.radius - newY + 5) * 100) / 100;
+                            if (this.props.dataDoc.simulation_Type != 'Pulley') {
+                                this.setState({ xPosition: newX });
+                                this.props.dataDoc.position_XDisplay = newX;
+                            }
+                            if (this.props.dataDoc.simulation_Type != 'Suspension') {
+                                if (this.props.dataDoc.simulation_Type != 'Pulley') {
+                                    this.setState({ updatedStartPosX: newX });
+                                }
+                                this.setState({ updatedStartPosY: newY });
+                            }
+                            this.setState({ clickPositionX: e.clientX });
+                            this.setState({ clickPositionY: e.clientY });
+                            this.setDisplayValues();
+                        }
+                    }}
+                    onPointerUp={e => {
+                        if (this.state.dragging) {
+                            if (this.props.dataDoc.simulation_Type != 'Pendulum' && this.props.dataDoc.simulation_Type != 'Suspension') {
+                                this.resetEverything();
+                            }
+                            this.setState({ dragging: false });
+                            let newY = this.state.yPosition + e.clientY - this.state.clickPositionY;
+                            if (newY > this.props.yMax - 2 * this.props.radius - 10) {
+                                newY = this.props.yMax - 2 * this.props.radius - 10;
+                            } else if (newY < 10) {
+                                newY = 10;
+                            }
 
-          return (
-            <div key={index}>
-              <div
-                style={{
-                  pointerEvents: "none",
-                  position: "absolute",
-                  left: this.props.xMin,
-                  top: this.props.yMin,
-                }}
-              >
-                <svg
-                  width={this.props.xMax - this.props.xMin + "px"}
-                  height={this.props.layoutDoc._height + "px"}
-                >
-                  <defs>
-                    <marker
-                      id="forceArrow"
-                      markerWidth="10"
-                      markerHeight="10"
-                      refX="0"
-                      refY="3"
-                      orient="auto"
-                      markerUnits="strokeWidth"
-                    >
-                      <path d="M0,0 L0,6 L9,3 z" fill={color} />
-                    </marker>
-                  </defs>
-                  {force.component == true && (
-                    <line
-                      x1={arrowStartX}
-                      y1={arrowStartY}
-                      x2={arrowEndX}
-                      y2={arrowEndY}
-                      stroke={color}
-                      strokeWidth="5"
-                      strokeDasharray="10,10"
-                      markerEnd="url(#forceArrow)"
-                    />
-                  )}
-                  {force.component == false && (
-                    <line
-                      x1={arrowStartX}
-                      y1={arrowStartY}
-                      x2={arrowEndX}
-                      y2={arrowEndY}
-                      stroke={color}
-                      strokeWidth="5"
-                      markerEnd="url(#forceArrow)"
-                    />
-                  )}
-                </svg>
-              </div>
-              <div
-                style={{
-                  pointerEvents: "none",
-                  position: "absolute",
-                  left: labelLeft + "px",
-                  top: labelTop + "px",
-                  lineHeight: 1,
-                  backgroundColor: this.labelBackgroundColor,
-                }}
-              >
-                {force.description && <p>{force.description}</p>}
-                {!force.description && <p>Force</p>}
-                {this.props.showForceMagnitudes && (
-                  <p>{Math.round(100 * force.magnitude) / 100} N</p>
+                            let newX = this.state.xPosition + e.clientX - this.state.clickPositionX;
+                            if (newX > this.props.xMax - 2 * this.props.radius - 10) {
+                                newX = this.props.xMax - 2 * this.props.radius - 10;
+                            } else if (newX < 10) {
+                                newX = 10;
+                            }
+                            if (this.props.dataDoc.simulation_Type == 'Spring') {
+                                this.props.dataDoc.springStartLength = newY;
+                            }
+                            if (this.props.dataDoc.simulation_Type == 'Suspension') {
+                                let x1rod = (this.props.xMax + this.props.xMin) / 2 - this.props.radius - this.props.yMin - 200;
+                                let x2rod = (this.props.xMax + this.props.xMin) / 2 + this.props.yMin + 200 + this.props.radius;
+                                let deltaX1 = this.state.xPosition + this.props.radius - x1rod;
+                                let deltaX2 = x2rod - (this.state.xPosition + this.props.radius);
+                                let deltaY = this.state.yPosition + this.props.radius;
+                                let dir1T = Math.PI - Math.atan(deltaY / deltaX1);
+                                let dir2T = Math.atan(deltaY / deltaX2);
+                                let tensionMag2 = (this.props.mass * Math.abs(this.props.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: this.props.mass * Math.abs(this.props.gravity),
+                                    directionInDegrees: 270,
+                                    component: false,
+                                };
+                                this.props.dataDoc.updatedForces = [tensionForce1, tensionForce2, grav];
+                            }
+                        }
+                    }}>
+                    <div className="weight" style={this.weightStyle}>
+                        <p className="weightLabel">{this.props.mass} kg</p>
+                    </div>
+                </div>
+                {this.props.dataDoc.simulation_Type == 'Spring' && (
+                    <div
+                        className="spring"
+                        style={{
+                            pointerEvents: 'none',
+                            position: 'absolute',
+                            left: 0,
+                            top: 0,
+                        }}>
+                        <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                            {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(val => {
+                                const count = 10;
+                                let xPos1;
+                                let yPos1;
+                                let xPos2;
+                                let yPos2;
+                                if (val % 2 == 0) {
+                                    xPos1 = this.state.xPosition + this.props.radius - 20;
+                                    xPos2 = this.state.xPosition + this.props.radius + 20;
+                                } else {
+                                    xPos1 = this.state.xPosition + this.props.radius + 20;
+                                    xPos2 = this.state.xPosition + this.props.radius - 20;
+                                }
+                                yPos1 = (val * this.state.yPosition) / count;
+                                yPos2 = ((val + 1) * this.state.yPosition) / count;
+                                return <line key={val} x1={xPos1} y1={yPos1} x2={xPos2} y2={yPos2} stroke={'#808080'} strokeWidth="10" />;
+                            })}
+                        </svg>
+                    </div>
                 )}
-              </div>
-            </div>
-          );
-        })}
-      {!this.state.dragging &&
-        this.props.showForces && this.props.updatedForces &&
-        this.props.updatedForces.map((force, index) => {
-          if (force.magnitude < this.epsilon) {
-            return;
-          }
-          let arrowStartY: number = this.state.yPosition + this.props.radius;
-          const arrowStartX: number = this.state.xPosition + this.props.radius;
-          let arrowEndY: number =
-            arrowStartY -
-            Math.abs(force.magnitude) *
-              20 *
-              Math.sin((force.directionInDegrees * Math.PI) / 180);
-          const arrowEndX: number =
-            arrowStartX +
-            Math.abs(force.magnitude) *
-              20 *
-              Math.cos((force.directionInDegrees * Math.PI) / 180);
 
-          let color = "#0d0d0d";
+                {this.props.dataDoc.simulation_Type == 'Pulley' && (
+                    <div
+                        className="rod"
+                        style={{
+                            pointerEvents: 'none',
+                            position: 'absolute',
+                            left: 0,
+                            top: 0,
+                        }}>
+                        <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                            <line x1={this.state.xPosition + this.props.radius} y1={this.state.yPosition + this.props.radius} x2={this.state.xPosition + this.props.radius} y2={this.props.yMin} stroke={'#deb887'} strokeWidth="10" />
+                        </svg>
+                    </div>
+                )}
+                {this.props.dataDoc.simulation_Type == 'Pulley' && (
+                    <div
+                        className="wheel"
+                        style={{
+                            pointerEvents: 'none',
+                            position: 'absolute',
+                            left: 0,
+                            top: 0,
+                        }}>
+                        <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                            <circle cx={(this.props.xMax + this.props.xMin) / 2} cy={this.props.radius} r={this.props.radius * 1.5} fill={'#808080'} />
+                        </svg>
+                    </div>
+                )}
+                {this.props.dataDoc.simulation_Type == 'Suspension' && (
+                    <div
+                        className="rod"
+                        style={{
+                            pointerEvents: 'none',
+                            position: 'absolute',
+                            left: 0,
+                            top: 0,
+                        }}>
+                        <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                            <line
+                                x1={this.state.xPosition + this.props.radius}
+                                y1={this.state.yPosition + this.props.radius}
+                                x2={(this.props.xMax + this.props.xMin) / 2 - this.props.radius - this.props.yMin - 200}
+                                y2={this.props.yMin}
+                                stroke={'#deb887'}
+                                strokeWidth="10"
+                            />
+                        </svg>
+                        <p
+                            style={{
+                                position: 'absolute',
+                                left: (this.props.xMax + this.props.xMin) / 2 - this.props.radius - this.props.yMin - 200 + 80 + 'px',
+                                top: 10 + 'px',
+                                backgroundColor: this.labelBackgroundColor,
+                            }}>
+                            {Math.round(
+                                ((Math.atan((this.state.yPosition + this.props.radius) / (this.state.xPosition + this.props.radius - ((this.props.xMax + this.props.xMin) / 2 - this.props.radius - this.props.yMin - 200))) * 180) / Math.PI) * 100
+                            ) / 100}
+                            °
+                        </p>
+                        <div
+                            className="rod"
+                            style={{
+                                pointerEvents: 'none',
+                                position: 'absolute',
+                                left: 0,
+                                top: 0,
+                            }}>
+                            <svg width={this.props.layoutDoc._width + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                                <line
+                                    x1={this.state.xPosition + this.props.radius}
+                                    y1={this.state.yPosition + this.props.radius}
+                                    x2={(this.props.xMax + this.props.xMin) / 2 + this.props.yMin + 200 + this.props.radius}
+                                    y2={this.props.yMin}
+                                    stroke={'#deb887'}
+                                    strokeWidth="10"
+                                />
+                            </svg>
+                        </div>
 
-          let labelTop = arrowEndY;
-          let labelLeft = arrowEndX;
-          if (force.directionInDegrees > 90 && force.directionInDegrees < 270) {
-            labelLeft -= 120;
-          } else {
-            labelLeft += 30;
-          }
-          if (force.directionInDegrees >= 0 && force.directionInDegrees < 180) {
-            labelTop += 40;
-          } else {
-            labelTop -= 40;
-          }
-          labelTop = Math.min(labelTop, this.props.yMax + 50);
-          labelTop = Math.max(labelTop, this.props.yMin);
-          labelLeft = Math.min(labelLeft, this.props.xMax - 60);
-          labelLeft = Math.max(labelLeft, this.props.xMin);
+                        <p
+                            style={{
+                                position: 'absolute',
+                                left: (this.props.xMax + this.props.xMin) / 2 + this.props.yMin + 200 + this.props.radius - 80 + 'px',
+                                top: 10 + 'px',
+                                backgroundColor: this.labelBackgroundColor,
+                            }}>
+                            {Math.round(
+                                ((Math.atan((this.state.yPosition + this.props.radius) / ((this.props.xMax + this.props.xMin) / 2 + this.props.yMin + 200 + this.props.radius - (this.state.xPosition + this.props.radius))) * 180) / Math.PI) * 100
+                            ) / 100}
+                            °
+                        </p>
+                    </div>
+                )}
+                {this.props.dataDoc.simulation_Type == 'Circular Motion' && (
+                    <div
+                        className="rod"
+                        style={{
+                            pointerEvents: 'none',
+                            position: 'absolute',
+                            left: 0,
+                            top: 0,
+                        }}>
+                        <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                            <line
+                                x1={this.state.xPosition + this.props.radius}
+                                y1={this.state.yPosition + this.props.radius}
+                                x2={(this.props.xMin + this.props.xMax) / 2}
+                                y2={(this.props.yMin + this.props.yMax) / 2}
+                                stroke={'#deb887'}
+                                strokeWidth="10"
+                            />
+                        </svg>
+                    </div>
+                )}
+                {this.props.dataDoc.simulation_Type == 'Pendulum' && (
+                    <div
+                        className="rod"
+                        style={{
+                            pointerEvents: 'none',
+                            position: 'absolute',
+                            left: 0,
+                            top: 0,
+                        }}>
+                        <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                            <line x1={this.state.xPosition + this.props.radius} y1={this.state.yPosition + this.props.radius} x2={this.props.xMax / 2} y2={-5} stroke={'#deb887'} strokeWidth="10" />
+                        </svg>
+                        {!this.state.dragging && (
+                            <div>
+                                <p
+                                    style={{
+                                        position: 'absolute',
+                                        zIndex: 5,
+                                        left: this.state.xPosition + 'px',
+                                        top: this.state.yPosition - 70 + 'px',
+                                        backgroundColor: this.labelBackgroundColor,
+                                    }}>
+                                    {Math.round(this.props.pendulumLength)} m
+                                </p>
+                                <p
+                                    style={{
+                                        position: 'absolute',
+                                        left: this.props.xMax / 2 + 'px',
+                                        top: 30 + 'px',
+                                        backgroundColor: this.labelBackgroundColor,
+                                    }}>
+                                    {Math.round(this.props.pendulum_angle * 100) / 100}°
+                                </p>
+                            </div>
+                        )}
+                    </div>
+                )}
+                {this.props.dataDoc.simulation_Type == 'Inclined Plane' && (
+                    <div>
+                        <div style={{ position: 'absolute', left: '0', top: '0' }}>
+                            <svg width={this.props.xMax + 'px'} height={this.props.yMax + 'px'}>
+                                <polygon points={this.state.coordinates} style={{ fill: 'burlywood' }} />
+                            </svg>
+                        </div>
 
-          return (
-            <div key={index}>
-              <div
-                style={{
-                  pointerEvents: "none",
-                  position: "absolute",
-                  left: this.props.xMin,
-                  top: this.props.yMin,
-                }}
-              >
-                <svg
-                  width={this.props.xMax - this.props.xMin + "px"}
-                  height={this.props.layoutDoc._height + "px"}
-                >
-                  <defs>
-                    <marker
-                      id="forceArrow"
-                      markerWidth="10"
-                      markerHeight="10"
-                      refX="0"
-                      refY="3"
-                      orient="auto"
-                      markerUnits="strokeWidth"
-                    >
-                      <path d="M0,0 L0,6 L9,3 z" fill={color} />
-                    </marker>
-                  </defs>
-                  {force.component == true && (
-                    <line
-                      x1={arrowStartX}
-                      y1={arrowStartY}
-                      x2={arrowEndX}
-                      y2={arrowEndY}
-                      stroke={color}
-                      strokeWidth="5"
-                      strokeDasharray="10,10"
-                      markerEnd="url(#forceArrow)"
-                    />
-                  )}
-                  {force.component == false && (
-                    <line
-                      x1={arrowStartX}
-                      y1={arrowStartY}
-                      x2={arrowEndX}
-                      y2={arrowEndY}
-                      stroke={color}
-                      strokeWidth="5"
-                      markerEnd="url(#forceArrow)"
-                    />
-                  )}
-                </svg>
-              </div>
-              <div
-                style={{
-                  pointerEvents: "none",
-                  position: "absolute",
-                  left: labelLeft + "px",
-                  top: labelTop + "px",
-                  lineHeight: 1,
-                  backgroundColor: this.labelBackgroundColor,
-                }}
-              >
-                {force.description && <p>{force.description}</p>}
-                {!force.description && <p>Force</p>}
-                {this.props.showForceMagnitudes && (
-                  <p>{Math.round(100 * force.magnitude) / 100} N</p>
+                        <p
+                            style={{
+                                position: 'absolute',
+                                left: Math.round(this.props.xMax * 0.5 - 200 + this.props.wedgeWidth - 80) + 'px',
+                                top: Math.round(this.props.yMax - 40) + 'px',
+                            }}>
+                            {Math.round(((Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI) * 100) / 100}°
+                        </p>
+                    </div>
                 )}
-              </div>
+                {!this.state.dragging && this.props.showAcceleration && (
+                    <div>
+                        <div
+                            style={{
+                                pointerEvents: 'none',
+                                position: 'absolute',
+                                left: 0,
+                                top: 0,
+                            }}>
+                            <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                                <defs>
+                                    <marker id="accArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
+                                        <path d="M0,0 L0,6 L9,3 z" fill="green" />
+                                    </marker>
+                                </defs>
+                                <line
+                                    x1={this.state.xPosition + this.props.radius}
+                                    y1={this.state.yPosition + this.props.radius}
+                                    x2={this.state.xPosition + this.props.radius + this.getNewAccelerationX(this.props.updatedForces) * 15}
+                                    y2={this.state.yPosition + this.props.radius + this.getNewAccelerationY(this.props.updatedForces) * 15}
+                                    stroke={'green'}
+                                    strokeWidth="5"
+                                    markerEnd="url(#accArrow)"
+                                />
+                            </svg>
+                            <div
+                                style={{
+                                    pointerEvents: 'none',
+                                    position: 'absolute',
+                                    left: this.state.xPosition + this.props.radius + this.state.xAccel * 15 + 25 + 'px',
+                                    top: this.state.yPosition + this.props.radius + this.state.yAccel * 15 + 70 + 'px',
+                                    lineHeight: 1,
+                                }}>
+                                <p>
+                                    {Math.round(100 * Math.sqrt(this.state.xAccel * this.state.xAccel + this.state.yAccel * this.state.yAccel)) / 100} m/s
+                                    <sup>2</sup>
+                                </p>
+                            </div>
+                        </div>
+                    </div>
+                )}
+                {!this.state.dragging && this.props.showVelocity && (
+                    <div>
+                        <div
+                            style={{
+                                pointerEvents: 'none',
+                                position: 'absolute',
+                                left: 0,
+                                top: 0,
+                            }}>
+                            <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                                <defs>
+                                    <marker id="velArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
+                                        <path d="M0,0 L0,6 L9,3 z" fill="blue" />
+                                    </marker>
+                                </defs>
+                                <line
+                                    x1={this.state.xPosition + this.props.radius}
+                                    y1={this.state.yPosition + this.props.radius}
+                                    x2={this.state.xPosition + this.props.radius + this.state.xVelocity * 7}
+                                    y2={this.state.yPosition + this.props.radius + this.state.yVelocity * 7}
+                                    stroke={'blue'}
+                                    strokeWidth="5"
+                                    markerEnd="url(#velArrow)"
+                                />
+                            </svg>
+                            <div
+                                style={{
+                                    pointerEvents: 'none',
+                                    position: 'absolute',
+                                    left: this.state.xPosition + this.props.radius + this.state.xVelocity * 7 + 25 + 'px',
+                                    top: this.state.yPosition + this.props.radius + this.state.yVelocity * 7 + 'px',
+                                    lineHeight: 1,
+                                }}>
+                                <p>{Math.round(100 * Math.sqrt(this.props.displayXVelocity * this.props.displayXVelocity + this.props.displayYVelocity * this.props.displayYVelocity)) / 100} m/s</p>
+                            </div>
+                        </div>
+                    </div>
+                )}
+                {!this.state.dragging &&
+                    this.props.showComponentForces &&
+                    this.props.componentForces.map((force, index) => {
+                        if (force.magnitude < this.epsilon) {
+                            return;
+                        }
+                        let arrowStartY: number = this.state.yPosition + this.props.radius;
+                        const arrowStartX: number = this.state.xPosition + this.props.radius;
+                        let arrowEndY: number = arrowStartY - Math.abs(force.magnitude) * 20 * Math.sin((force.directionInDegrees * Math.PI) / 180);
+                        const arrowEndX: number = arrowStartX + Math.abs(force.magnitude) * 20 * Math.cos((force.directionInDegrees * Math.PI) / 180);
+
+                        let color = '#0d0d0d';
+
+                        let labelTop = arrowEndY;
+                        let labelLeft = arrowEndX;
+                        if (force.directionInDegrees > 90 && force.directionInDegrees < 270) {
+                            labelLeft -= 120;
+                        } else {
+                            labelLeft += 30;
+                        }
+                        if (force.directionInDegrees >= 0 && force.directionInDegrees < 180) {
+                            labelTop += 40;
+                        } else {
+                            labelTop -= 40;
+                        }
+                        labelTop = Math.min(labelTop, this.props.yMax + 50);
+                        labelTop = Math.max(labelTop, this.props.yMin);
+                        labelLeft = Math.min(labelLeft, this.props.xMax - 60);
+                        labelLeft = Math.max(labelLeft, this.props.xMin);
+
+                        return (
+                            <div key={index}>
+                                <div
+                                    style={{
+                                        pointerEvents: 'none',
+                                        position: 'absolute',
+                                        left: this.props.xMin,
+                                        top: this.props.yMin,
+                                    }}>
+                                    <svg width={this.props.xMax - this.props.xMin + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                                        <defs>
+                                            <marker id="forceArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
+                                                <path d="M0,0 L0,6 L9,3 z" fill={color} />
+                                            </marker>
+                                        </defs>
+                                        {force.component == true && <line x1={arrowStartX} y1={arrowStartY} x2={arrowEndX} y2={arrowEndY} stroke={color} strokeWidth="5" strokeDasharray="10,10" markerEnd="url(#forceArrow)" />}
+                                        {force.component == false && <line x1={arrowStartX} y1={arrowStartY} x2={arrowEndX} y2={arrowEndY} stroke={color} strokeWidth="5" markerEnd="url(#forceArrow)" />}
+                                    </svg>
+                                </div>
+                                <div
+                                    style={{
+                                        pointerEvents: 'none',
+                                        position: 'absolute',
+                                        left: labelLeft + 'px',
+                                        top: labelTop + 'px',
+                                        lineHeight: 1,
+                                        backgroundColor: this.labelBackgroundColor,
+                                    }}>
+                                    {force.description && <p>{force.description}</p>}
+                                    {!force.description && <p>Force</p>}
+                                    {this.props.showForceMagnitudes && <p>{Math.round(100 * force.magnitude) / 100} N</p>}
+                                </div>
+                            </div>
+                        );
+                    })}
+                {!this.state.dragging &&
+                    this.props.showForces &&
+                    this.props.updatedForces &&
+                    this.props.updatedForces.map((force, index) => {
+                        if (force.magnitude < this.epsilon) {
+                            return;
+                        }
+                        let arrowStartY: number = this.state.yPosition + this.props.radius;
+                        const arrowStartX: number = this.state.xPosition + this.props.radius;
+                        let arrowEndY: number = arrowStartY - Math.abs(force.magnitude) * 20 * Math.sin((force.directionInDegrees * Math.PI) / 180);
+                        const arrowEndX: number = arrowStartX + Math.abs(force.magnitude) * 20 * Math.cos((force.directionInDegrees * Math.PI) / 180);
+
+                        let color = '#0d0d0d';
+
+                        let labelTop = arrowEndY;
+                        let labelLeft = arrowEndX;
+                        if (force.directionInDegrees > 90 && force.directionInDegrees < 270) {
+                            labelLeft -= 120;
+                        } else {
+                            labelLeft += 30;
+                        }
+                        if (force.directionInDegrees >= 0 && force.directionInDegrees < 180) {
+                            labelTop += 40;
+                        } else {
+                            labelTop -= 40;
+                        }
+                        labelTop = Math.min(labelTop, this.props.yMax + 50);
+                        labelTop = Math.max(labelTop, this.props.yMin);
+                        labelLeft = Math.min(labelLeft, this.props.xMax - 60);
+                        labelLeft = Math.max(labelLeft, this.props.xMin);
+
+                        return (
+                            <div key={index}>
+                                <div
+                                    style={{
+                                        pointerEvents: 'none',
+                                        position: 'absolute',
+                                        left: this.props.xMin,
+                                        top: this.props.yMin,
+                                    }}>
+                                    <svg width={this.props.xMax - this.props.xMin + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                                        <defs>
+                                            <marker id="forceArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
+                                                <path d="M0,0 L0,6 L9,3 z" fill={color} />
+                                            </marker>
+                                        </defs>
+                                        {force.component == true && <line x1={arrowStartX} y1={arrowStartY} x2={arrowEndX} y2={arrowEndY} stroke={color} strokeWidth="5" strokeDasharray="10,10" markerEnd="url(#forceArrow)" />}
+                                        {force.component == false && <line x1={arrowStartX} y1={arrowStartY} x2={arrowEndX} y2={arrowEndY} stroke={color} strokeWidth="5" markerEnd="url(#forceArrow)" />}
+                                    </svg>
+                                </div>
+                                <div
+                                    style={{
+                                        pointerEvents: 'none',
+                                        position: 'absolute',
+                                        left: labelLeft + 'px',
+                                        top: labelTop + 'px',
+                                        lineHeight: 1,
+                                        backgroundColor: this.labelBackgroundColor,
+                                    }}>
+                                    {force.description && <p>{force.description}</p>}
+                                    {!force.description && <p>Force</p>}
+                                    {this.props.showForceMagnitudes && <p>{Math.round(100 * force.magnitude) / 100} N</p>}
+                                </div>
+                            </div>
+                        );
+                    })}
             </div>
-          );
-        })}
-    </div>
-  )}
-};
+        );
+    }
+}
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 8dd322e05..d0e5d03b3 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -382,7 +382,7 @@ export class Doc extends RefField {
     public get [LayoutSym]() {
         return this[SelfProxy].__LAYOUT__;
     }
-    public get [DataSym]() {
+    public get [DataSym](): Doc {
         const self = this[SelfProxy];
         return self.resolvedDataDoc && !self.isTemplateForField ? self : Doc.GetProto(Cast(Doc.Layout(self).resolvedDataDoc, Doc, null) || self);
     }
-- 
cgit v1.2.3-70-g09d2


From 90479323c4476c1c87f10ec2ca42339246414ca0 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 23 May 2023 00:35:00 -0400
Subject: more physics cleanup

---
 src/client/documents/Documents.ts                  |   2 +-
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 914 ++++++++++-----------
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   | 187 ++---
 3 files changed, 551 insertions(+), 552 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 4ee3368ab..1a2409508 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -690,7 +690,7 @@ export namespace Docs {
                 {
                     data: '',
                     layout: { view: PhysicsSimulationBox, dataField: defaultDataKey },
-                    options: { _height: 100, position: '', velocity: '', acceleration: '', pendulum: '',  simulation: '', review: '', show: '', start: '' },
+                    options: { _height: 100, position: '', acceleration: '', pendulum: '', spring: '', wedge: '', simulation: '', review: '' },
                 },
             ],
         ]);
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index db15c9a5c..0f5bdf316 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -19,6 +19,7 @@ import Weight from './PhysicsSimulationWeight';
 import React = require('react');
 import { BoolCast, NumCast, StrCast } from '../../../../fields/Types';
 import { List } from '../../../../fields/List';
+import { computed } from 'mobx';
 
 interface IWallProps {
     length: number;
@@ -79,6 +80,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         super(props);
     }
 
+    @computed get circularMotionRadius() {
+        return NumCast(this.dataDoc.circularMotionRadius, 150);
+    }
+    @computed get gravity() {
+        return NumCast(this.dataDoc.simulation_gravity, -9.81);
+    }
+
     // Constants
     xMin = 0;
     yMin = 0;
@@ -95,65 +103,49 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         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 ?? [];
+        this.dataDoc.simulation_gravity = NumCast(this.dataDoc.simulation_gravity, -9.81);
+        this.dataDoc.mass1 = NumCast(this.dataDoc.mass1, 1);
+        this.dataDoc.simulation_mode = 'Freeform';
+        this.dataDoc.simulation_showComponentForces = this.dataDoc.simulation_showComponentForces ?? false;
+        this.dataDoc.simulation_speed = NumCast(this.dataDoc.simulation_speed, 2);
+        this.dataDoc.simulation_type = StrCast(this.dataDoc.simulation_type, 'Inclined Plane');
+        this.dataDoc.mass1_forcesStart = this.dataDoc.mass1_forcesStart ?? [];
+        this.dataDoc.mass1_positionXstart = this.dataDoc.mass1_positionXstart ?? Math.round((this.xMax * 0.5 - 200) * 10) / 10;
+        this.dataDoc.mass1_positionYstart = this.dataDoc.mass1_positionYstart ?? this.getDisplayYPos((400 - 0.08 * this.layoutDoc._height) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26));
+        this.dataDoc.mass1_forcesUpdated = this.dataDoc.mass1_forcesUpdated ?? [];
 
         // 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;
+        this.dataDoc.tutorial = this.dataDoc.tutorial ?? tutorials.inclinePlane;
 
         // 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);
+        this.dataDoc.spring_constant = NumCast(this.dataDoc.spring_constant, 0.5);
+        this.dataDoc.spring_lengthRest = NumCast(this.dataDoc.spring_lengthRest, 200);
+        this.dataDoc.spring_lengthStart = NumCast(this.dataDoc.spring_lengthStart, 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);
+        this.dataDoc.wedge_angle = NumCast(this.dataDoc.wedge_angle, 26);
+        this.dataDoc.wedge_height = NumCast(this.dataDoc.wedge_height, Math.tan((26 * Math.PI) / 180) * this.xMax * 0.5);
+        this.dataDoc.wedge_width = NumCast(this.dataDoc.wedge_width, 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));
+        this.setupSimulation(StrCast(this.dataDoc.simulation_type), StrCast(this.dataDoc.simulation_mode));
 
         // Create walls
         let walls = [];
@@ -170,49 +162,49 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             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));
+            this.setupSimulation(StrCast(this.dataDoc.simulation_type), StrCast(this.dataDoc.simulation_mode));
         }
     }
 
     setupSimulation = (simulationType: string, mode: string) => {
-        this.dataDoc.simulation_Paused = true;
+        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;
+            this.dataDoc.mass1_velocityXstart = 0;
+            this.dataDoc.mass1_velocityYstart = 0;
+            this.dataDoc.mass1_velocityX = 0;
+            this.dataDoc.mass1_velocityY = 0;
         }
         if (mode == 'Freeform') {
-            this.dataDoc.show_ForceMagnitudes = true;
+            this.dataDoc.simulation_showForceMagnitudes = 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 = [
+                this.dataDoc.simulation_showComponentForces = false;
+                this.dataDoc.mass1_positionYstart = this.yMin + 0.08 * this.layoutDoc[HeightSym]();
+                this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
+                this.dataDoc.mass1_positionY = this.getDisplayYPos(this.yMin + 0.08 * this.layoutDoc[HeightSym]());
+                this.dataDoc.mass1_positionX = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
+                this.dataDoc.mass1_forcesUpdated = [
                     {
                         description: 'Gravity',
-                        magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
+                        magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
                         directionInDegrees: 270,
                         component: false,
                     },
                 ];
-                this.dataDoc.start_Forces = [
+                this.dataDoc.mass1_forcesStart = [
                     {
                         description: 'Gravity',
-                        magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
+                        magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
                         directionInDegrees: 270,
                         component: false,
                     },
                 ];
-                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
+                this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
             } else if (simulationType == 'Inclined Plane') {
                 this.changeWedgeBasedOnNewAngle(26);
-                this.dataDoc.start_Forces = [
+                this.dataDoc.mass1_forcesStart = [
                     {
                         description: 'Gravity',
-                        magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
+                        magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
                         directionInDegrees: 270,
                         component: false,
                     },
@@ -230,11 +222,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 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.dataDoc.simulation_showComponentForces = false;
+            this.dataDoc.simulation_showForceMagnitudes = true;
+            this.dataDoc.simulation_showAcceleration = false;
+            this.dataDoc.simulation_showVelocity = false;
+            this.dataDoc.simulation_showForces = true;
             this.generateNewQuestion();
             if (simulationType == 'One Weight') {
                 // TODO - one weight review problems
@@ -242,8 +234,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.setupSpring();
                 // TODO - spring review problems
             } else if (simulationType == 'Inclined Plane') {
-                this.dataDoc.updatedForces = [];
-                this.dataDoc.start_Forces = [];
+                this.dataDoc.mass1_forcesUpdated = [];
+                this.dataDoc.mass1_forcesStart = [];
             } else if (simulationType == 'Pendulum') {
                 this.setupPendulum();
                 // TODO - pendulum review problems
@@ -258,78 +250,78 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 // 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;
+            this.dataDoc.simulation_showComponentForces = false;
+            this.dataDoc.tutorial_stepNumber = 0;
+            this.dataDoc.simulation_showAcceleration = false;
+            if (this.dataDoc.simulation_type != 'Circular Motion') {
+                this.dataDoc.mass1_velocityX = 0;
+                this.dataDoc.mass1_velocityY = 0;
+                this.dataDoc.simulation_showVelocity = false;
             } else {
-                this.dataDoc.velocity_XDisplay = 20;
-                this.dataDoc.velocity_YDisplay = 0;
-                this.dataDoc.show_Velocity = true;
+                this.dataDoc.mass1_velocityX = 20;
+                this.dataDoc.mass1_velocityY = 0;
+                this.dataDoc.simulation_showVelocity = 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;
+            if (this.dataDoc.simulation_type == 'One Weight') {
+                this.dataDoc.simulation_showForces = true;
+                this.dataDoc.mass1_positionYstart = this.yMax - 100;
+                this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
+                this.dataDoc.tutorial = tutorials.freeWeight;
+                this.dataDoc.mass1_forcesStart = this.getForceFromJSON(tutorials.freeWeight.steps[0].forces);
+                this.dataDoc.simulation_showForceMagnitudes = tutorials.freeWeight.steps[0].showMagnitude;
+            } else if (this.dataDoc.simulation_type == 'Spring') {
+                this.dataDoc.simulation_showForces = 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;
+                this.dataDoc.mass1_positionYstart = this.yMin + 200 + 19.62;
+                this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
+                this.dataDoc.tutorial = tutorials.spring;
+                this.dataDoc.mass1_forcesStart = this.getForceFromJSON(tutorials.spring.steps[0].forces);
+                this.dataDoc.simulation_showForceMagnitudes = tutorials.spring.steps[0].showMagnitude;
+            } else if (this.dataDoc.simulation_type == 'Pendulum') {
+                this.dataDoc.simulation_showForces = 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.mass1_positionXstart = xPos;
+                this.dataDoc.mass1_positionYstart = yPos;
+                this.dataDoc.tutorial = tutorials.pendulum;
+                this.dataDoc.mass1_forcesStart = this.getForceFromJSON(tutorials.pendulum.steps[0].forces);
+                this.dataDoc.simulation_showForceMagnitudes = 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;
+            } else if (this.dataDoc.simulation_type == 'Inclined Plane') {
+                this.dataDoc.simulation_showForces = true;
+                this.dataDoc.wedge_angle = 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.dataDoc.tutorial = tutorials.inclinePlane;
+                this.dataDoc.mass1_forcesStart = this.getForceFromJSON(tutorials.inclinePlane.steps[0].forces);
+                this.dataDoc.simulation_showForceMagnitudes = tutorials.inclinePlane.steps[0].showMagnitude;
+            } else if (this.dataDoc.simulation_type == 'Circular Motion') {
+                this.dataDoc.simulation_showForces = 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.dataDoc.tutorial = tutorials.circular;
+                this.dataDoc.mass1_forcesStart = this.getForceFromJSON(tutorials.circular.steps[0].forces);
+                this.dataDoc.simulation_showForceMagnitudes = tutorials.circular.steps[0].showMagnitude;
+            } else if (this.dataDoc.simulation_type == 'Pulley') {
+                this.dataDoc.simulation_showForces = 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.dataDoc.tutorial = tutorials.pulley;
+                this.dataDoc.mass1_forcesStart = this.getForceFromJSON(tutorials.pulley.steps[0].forces);
+                this.dataDoc.simulation_showForceMagnitudes = tutorials.pulley.steps[0].showMagnitude;
+            } else if (this.dataDoc.simulation_type == 'Suspension') {
+                this.dataDoc.simulation_showForces = 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.tutorial = tutorials.suspension;
+                this.dataDoc.mass1_forcesStart = this.getForceFromJSON(tutorials.suspension.steps[0].forces);
+                this.dataDoc.simulation_showForceMagnitudes = tutorials.suspension.steps[0].showMagnitude;
             }
-            this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
+            this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
         }
     };
 
@@ -342,72 +334,71 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     };
 
     // 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)) => {
+    updateForcesWithFriction = (coefficient: number, width: number = NumCast(this.dataDoc.wedge_width), height: number = NumCast(this.dataDoc.wedge_height)) => {
         const normalForce: IForce = {
             description: 'Normal Force',
-            magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos(Math.atan(height / width)) * NumCast(this.dataDoc.mass),
+            magnitude: Math.abs(this.gravity) * Math.cos(Math.atan(height / width)) * NumCast(this.dataDoc.mass1),
             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),
+            magnitude: coefficient * Math.abs(this.gravity) * Math.cos(Math.atan(height / width)) * NumCast(this.dataDoc.mass1),
             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);
+        let yForce = -Math.abs(this.gravity) * NumCast(this.dataDoc.mass1);
         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);
+            frictionForce.magnitude = (-normalForce.magnitude * Math.sin((normalForce.directionInDegrees * Math.PI) / 180) + Math.abs(this.gravity) * NumCast(this.dataDoc.mass1)) / 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)),
+            magnitude: coefficient * Math.abs(this.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)),
+            magnitude: Math.abs(this.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)),
+            magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.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)),
+            magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.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)),
+            magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity),
             directionInDegrees: 270,
             component: false,
         };
         if (coefficient != 0) {
-            this.dataDoc.start_Forces = [gravityForce, normalForce, frictionForce];
-            this.dataDoc.updatedForces = [gravityForce, normalForce, frictionForce];
+            this.dataDoc.mass1_forcesStart = [gravityForce, normalForce, frictionForce];
+            this.dataDoc.mass1_forcesUpdated = [gravityForce, normalForce, frictionForce];
             this.dataDoc.componentForces = [frictionForceComponent, normalForceComponent, gravityParallel, gravityPerpendicular];
         } else {
-            this.dataDoc.start_Forces = [gravityForce, normalForce];
-            this.dataDoc.updatedForces = [gravityForce, normalForce];
+            this.dataDoc.mass1_forcesStart = [gravityForce, normalForce];
+            this.dataDoc.mass1_forcesUpdated = [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;
+        this.dataDoc.wedge_width = this.xMax * 0.5;
+        this.dataDoc.wedge_height = 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;
@@ -433,16 +424,16 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             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.dataDoc.mass1_positionXstart = this.xMax * 0.25;
+        this.dataDoc.mass1_positionYstart = yPos;
+        if (this.dataDoc.simulation_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 theta: number = NumCast(this.dataDoc.wedge_angle);
         let index = this.dataDoc.selectedQuestion.variablesForQuestionSetup.indexOf('theta - max 45');
         if (index >= 0) {
             theta = NumListCast(this.dataDoc.questionVariables)[index];
@@ -450,16 +441,16 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         if (isNaN(theta)) {
             return;
         }
-        this.dataDoc.review_GravityMagnitude = Math.abs(NumCast(this.dataDoc.gravity));
+        this.dataDoc.review_GravityMagnitude = Math.abs(this.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_NormalMagnitude = Math.abs(this.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);
+        let yForce = -Math.abs(this.gravity);
+        yForce += Math.abs(this.gravity) * Math.cos((theta * Math.PI) / 180) * Math.sin(((90 - theta) * Math.PI) / 180);
+        yForce += coefficient * Math.abs(this.gravity) * Math.cos((theta * Math.PI) / 180) * Math.sin(((180 - theta) * Math.PI) / 180);
+        let friction = coefficient * Math.abs(this.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);
+            friction = (-(Math.abs(this.gravity) * Math.cos((theta * Math.PI) / 180)) * Math.sin(((90 - theta) * Math.PI) / 180) + Math.abs(this.gravity)) / Math.sin(((180 - theta) * Math.PI) / 180);
         }
         this.dataDoc.review_StaticMagnitude = friction;
         this.dataDoc.review_StaticAngle = 180 - theta;
@@ -467,16 +458,16 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
 
     // 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_GravityMagnitude = Math.abs(this.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_NormalMagnitude = Math.abs(this.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);
+        let yForce = -Math.abs(this.gravity);
+        yForce += Math.abs(this.gravity) * Math.cos((angle * Math.PI) / 180) * Math.sin(((90 - angle) * Math.PI) / 180);
+        yForce += NumCast(this.dataDoc.review_Coefficient) * Math.abs(this.gravity) * Math.cos((angle * Math.PI) / 180) * Math.sin(((180 - angle) * Math.PI) / 180);
+        let friction = NumCast(this.dataDoc.review_Coefficient) * Math.abs(this.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);
+            friction = (-(Math.abs(this.gravity) * Math.cos((angle * Math.PI) / 180)) * Math.sin(((90 - angle) * Math.PI) / 180) + Math.abs(this.gravity)) / Math.sin(((180 - angle) * Math.PI) / 180);
         }
         this.dataDoc.review_StaticMagnitude = friction;
         this.dataDoc.review_StaticAngle = 180 - angle;
@@ -486,7 +477,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     getAnswersToQuestion = (question: QuestionTemplate, questionVars: number[]) => {
         const solutions: number[] = [];
 
-        let theta: number = NumCast(this.dataDoc.wedgeAngle);
+        let theta: number = NumCast(this.dataDoc.wedge_angle);
         let index = question.variablesForQuestionSetup.indexOf('theta - max 45');
         if (index >= 0) {
             theta = questionVars[index];
@@ -504,20 +495,20 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             } 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));
+                solutions.push(Math.abs(this.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 normalForceMagnitude = Math.abs(this.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 frictionForceMagnitude = (-normalForceMagnitude * Math.sin((normalForceAngle * Math.PI) / 180) + Math.abs(this.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 normalForceMagnitude = Math.abs(this.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 frictionForceMagnitude = (-normalForceMagnitude * Math.sin((normalForceAngle * Math.PI) / 180) + Math.abs(this.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') {
@@ -563,7 +554,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                         error = true;
                     }
                 } else if (this.dataDoc.selectedQuestion.answerParts[i] == 'wedge angle') {
-                    if (Math.abs(NumCast(this.dataDoc.wedgeAngle) - this.dataDoc.selectedSolutions[i]) > epsilon) {
+                    if (Math.abs(NumCast(this.dataDoc.wedge_angle) - this.dataDoc.selectedSolutions[i]) > epsilon) {
                         error = true;
                     }
                 }
@@ -571,14 +562,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         }
         if (showAlert) {
             if (!error) {
-                this.dataDoc.simulation_Paused = false;
+                this.dataDoc.simulation_paused = false;
                 setTimeout(() => {
-                    this.dataDoc.simulation_Paused = true;
+                    this.dataDoc.simulation_paused = true;
                 }, 3000);
             } else {
-                this.dataDoc.simulation_Paused = false;
+                this.dataDoc.simulation_paused = false;
                 setTimeout(() => {
-                    this.dataDoc.simulation_Paused = true;
+                    this.dataDoc.simulation_paused = true;
                 }, 3000);
             }
         }
@@ -600,7 +591,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.review_StaticMagnitude = 0;
         this.dataDoc.review_StaticAngle = 0;
         this.dataDoc.coefficientOfKineticFriction = 0;
-        this.dataDoc.simulation_Paused = true;
+        this.dataDoc.simulation_paused = true;
     };
 
     // In review mode, reset problem variables and generate a new question
@@ -610,7 +601,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         const vars: number[] = [];
         let question: QuestionTemplate = questions.inclinePlane[0];
 
-        if (this.dataDoc.simulation_Type == 'Inclined Plane') {
+        if (this.dataDoc.simulation_type == 'Inclined Plane') {
             if (this.dataDoc.questionNumber === questions.inclinePlane.length - 1) {
                 this.dataDoc.questionNumber = 0;
             } else {
@@ -619,21 +610,21 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             question = questions.inclinePlane[NumCast(this.dataDoc.questionNumber)];
 
             let coefficient = 0;
-            let wedgeAngle = 0;
+            let wedge_angle = 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;
+                    wedge_angle = 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.wedge_angle = wedge_angle;
+            this.changeWedgeBasedOnNewAngle(wedge_angle);
             this.dataDoc.coefficientOfStaticFriction = coefficient;
             this.dataDoc.review_Coefficient = coefficient;
         }
@@ -652,27 +643,27 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         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);
+        //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;
+        this.dataDoc.simulation_showComponentForces = false;
+        this.dataDoc.mass1_velocityYstart = 0;
+        this.dataDoc.mass1_velocityXstart = 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;
+        let yPos = (this.yMax + this.yMin) / 2 + this.circularMotionRadius - 0.08 * this.layoutDoc[HeightSym]();
+        this.dataDoc.mass1_positionYstart = yPos;
+        this.dataDoc.mass1_positionXstart = xPos;
         const tensionForce: IForce = {
             description: 'Centripetal Force',
-            magnitude: (this.dataDoc.start_VelX ** 2 * NumCast(this.dataDoc.mass)) / NumCast(this.dataDoc.circularMotionRadius),
+            magnitude: (this.dataDoc.mass1_velocityXstart ** 2 * NumCast(this.dataDoc.mass1)) / this.circularMotionRadius,
             directionInDegrees: 90,
             component: false,
         };
-        this.dataDoc.updatedForces = [tensionForce];
-        this.dataDoc.start_Forces = [tensionForce];
-        this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
+        this.dataDoc.mass1_forcesUpdated = [tensionForce];
+        this.dataDoc.mass1_forcesStart = [tensionForce];
+        this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
     };
 
     // Default setup for pendulum simulation
@@ -683,9 +674,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         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);
+        this.dataDoc.mass1_positionXstart = xPos;
+        this.dataDoc.mass1_positionYstart = yPos;
+        const mag = NumCast(this.dataDoc.mass1) * Math.abs(this.gravity) * Math.sin((60 * Math.PI) / 180);
         const forceOfTension: IForce = {
             description: 'Tension',
             magnitude: mag,
@@ -701,37 +692,37 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         };
         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),
+            magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.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),
+            magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity) * Math.cos(((90 - angle) * Math.PI) / 180),
             directionInDegrees: -angle,
             component: true,
         };
 
         this.dataDoc.componentForces = [tensionComponent, gravityParallel, gravityPerpendicular];
-        this.dataDoc.updatedForces = [
+        this.dataDoc.mass1_forcesUpdated = [
             {
                 description: 'Gravity',
-                magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
+                magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity),
                 directionInDegrees: 270,
                 component: false,
             },
             forceOfTension,
         ];
-        this.dataDoc.start_Forces = [
+        this.dataDoc.mass1_forcesStart = [
             {
                 description: 'Gravity',
-                magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
+                magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity),
                 directionInDegrees: 270,
                 component: false,
             },
             forceOfTension,
         ];
-        this.dataDoc.start_PendulumAngle = 30;
+        this.dataDoc.pendulum_angleStart = 30;
         this.dataDoc.pendulum_angle = 30;
         this.dataDoc.pendulum_length = 300;
         this.dataDoc.pendulum_angle_adjust = 30;
@@ -740,32 +731,32 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
 
     // Default setup for spring simulation
     setupSpring = () => {
-        this.dataDoc.show_ComponentForces = false;
+        this.dataDoc.simulation_showComponentForces = false;
         const gravityForce: IForce = {
             description: 'Gravity',
-            magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
+            magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
             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;
+        this.dataDoc.mass1_forcesUpdated = [gravityForce];
+        this.dataDoc.mass1_forcesStart = [gravityForce];
+        this.dataDoc.mass1_positionXstart = this.xMax / 2 - 0.08 * this.layoutDoc[HeightSym]();
+        this.dataDoc.mass1_positionYstart = 200;
+        this.dataDoc.spring_constant = 0.5;
+        this.dataDoc.spring_lengthRest = 200;
+        this.dataDoc.spring_lengthStart = 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));
+        this.dataDoc.mass1_positionYstart = yPos;
+        this.dataDoc.mass1_positionXstart = xPos;
+        this.dataDoc.mass1_positionY = this.getDisplayYPos(yPos);
+        this.dataDoc.mass1_positionX = xPos;
+        let tensionMag = (NumCast(this.dataDoc.mass1) * Math.abs(this.gravity)) / (2 * Math.sin(Math.PI / 4));
         const tensionForce1: IForce = {
             description: 'Tension',
             magnitude: tensionMag,
@@ -780,59 +771,59 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         };
         const grav: IForce = {
             description: 'Gravity',
-            magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
+            magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.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;
+        this.dataDoc.mass1_forcesUpdated = [tensionForce1, tensionForce2, grav];
+        this.dataDoc.mass1_forcesStart = [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));
+        this.dataDoc.simulation_showComponentForces = false;
+        this.dataDoc.mass1_positionYstart = (this.yMax + this.yMin) / 2;
+        this.dataDoc.mass1_positionXstart = (this.xMin + this.xMax) / 2 - 2 * (0.08 * this.layoutDoc[HeightSym]()) - 5;
+        this.dataDoc.mass1_positionY = this.getDisplayYPos((this.yMax + this.yMin) / 2);
+        this.dataDoc.mass1_positionX = (this.xMin + this.xMax) / 2 - 2 * (0.08 * this.layoutDoc[HeightSym]()) - 5;
+        let a = (-1 * ((NumCast(this.dataDoc.mass1) - NumCast(this.dataDoc.mass2)) * Math.abs(this.gravity))) / (NumCast(this.dataDoc.mass1) + NumCast(this.dataDoc.mass2));
         const gravityForce1: IForce = {
             description: 'Gravity',
-            magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
+            magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.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)),
+            magnitude: NumCast(this.dataDoc.mass1) * a + NumCast(this.dataDoc.mass1) * Math.abs(this.gravity),
             directionInDegrees: 90,
             component: false,
         };
         a *= -1;
         const gravityForce2: IForce = {
             description: 'Gravity',
-            magnitude: NumCast(this.dataDoc.mass2) * Math.abs(NumCast(this.dataDoc.gravity)),
+            magnitude: NumCast(this.dataDoc.mass2) * Math.abs(this.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)),
+            magnitude: NumCast(this.dataDoc.mass2) * a + NumCast(this.dataDoc.mass2) * Math.abs(this.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.mass1_forcesUpdated = [gravityForce1, tensionForce1];
+        this.dataDoc.mass1_forcesStart = [gravityForce1, tensionForce1];
+        this.dataDoc.mass2_positionYstart = (this.yMax + this.yMin) / 2;
+        this.dataDoc.mass2_positionXstart = (this.xMin + this.xMax) / 2 + 5;
+        this.dataDoc.mass2_positionY = this.getDisplayYPos((this.yMax + this.yMin) / 2);
+        this.dataDoc.mass2_positionX = (this.xMin + this.xMax) / 2 + 5;
+        this.dataDoc.mass2_forcesUpdated = [gravityForce2, tensionForce2];
+        this.dataDoc.mass2_forcesStart = [gravityForce2, tensionForce2];
 
-        this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
+        this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
     };
 
     // Helper function used for tutorial and review mode
@@ -877,8 +868,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             directionInDegrees: NumCast(this.dataDoc.review_StaticAngle),
             component: false,
         };
-        this.dataDoc.start_Forces = [forceOfGravityReview, normalForceReview, staticFrictionForceReview];
-        this.dataDoc.updatedForces = [forceOfGravityReview, normalForceReview, staticFrictionForceReview];
+        this.dataDoc.mass1_forcesStart = [forceOfGravityReview, normalForceReview, staticFrictionForceReview];
+        this.dataDoc.mass1_forcesUpdated = [forceOfGravityReview, normalForceReview, staticFrictionForceReview];
     };
 
     render() {
@@ -888,7 +879,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                     <div className="mechanicsSimulationContentContainer">
                         <div className="mechanicsSimulationButtonsAndElements">
                             <div className="mechanicsSimulationButtons">
-                                {!this.dataDoc.simulation_Paused && (
+                                {!this.dataDoc.simulation_paused && (
                                     <div
                                         style={{
                                             position: 'fixed',
@@ -907,94 +898,94 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     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)}
+                                    gravity={this.gravity}
+                                    circularMotionRadius={this.circularMotionRadius}
                                     componentForces={this.dataDoc.componentForces}
-                                    showComponentForces={BoolCast(this.dataDoc.show_ComponentForces)}
+                                    showComponentForces={BoolCast(this.dataDoc.simulation_showComponentForces)}
                                     color={'red'}
                                     coefficientOfKineticFriction={NumCast(this.dataDoc.coefficientOfKineticFriction)}
-                                    displayXVelocity={NumCast(this.dataDoc.velocity_XDisplay)}
-                                    displayYVelocity={NumCast(this.dataDoc.velocity_YDisplay)}
+                                    displayXVelocity={NumCast(this.dataDoc.mass1_velocityX)}
+                                    displayYVelocity={NumCast(this.dataDoc.mass1_velocityY)}
                                     elasticCollisions={BoolCast(this.dataDoc.elasticCollisions)}
-                                    mass={NumCast(this.dataDoc.mass)}
-                                    mode={StrCast(this.dataDoc.mode)}
+                                    mass={NumCast(this.dataDoc.mass1)}
+                                    simulationMode={StrCast(this.dataDoc.simulation_mode)}
                                     noMovement={BoolCast(this.dataDoc.noMovement)}
-                                    paused={BoolCast(this.dataDoc.simulation_Paused)}
+                                    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)}
+                                    reset={BoolCast(this.dataDoc.simulation_reset)}
+                                    simulationSpeed={NumCast(this.dataDoc.simulation_speed)}
+                                    startPendulumAngle={NumCast(this.dataDoc.pendulum_angleStart)}
+                                    showAcceleration={BoolCast(this.dataDoc.simulation_showAcceleration)}
+                                    showForceMagnitudes={BoolCast(this.dataDoc.simulation_showForceMagnitudes)}
+                                    showForces={BoolCast(this.dataDoc.simulation_showForces)}
+                                    showVelocity={BoolCast(this.dataDoc.simulation_showVelocity)}
+                                    simulationType={StrCast(this.dataDoc.simulation_type)}
+                                    springConstant={NumCast(this.dataDoc.spring_constant)}
+                                    springStartLength={NumCast(this.dataDoc.spring_lengthStart)}
+                                    springRestLength={NumCast(this.dataDoc.spring_lengthRest)}
+                                    startForces={this.dataDoc.mass1_forcesStart}
+                                    startPosX={NumCast(this.dataDoc.mass1_positionXstart)}
+                                    startPosY={NumCast(this.dataDoc.mass1_positionYstart)}
+                                    startVelX={NumCast(this.dataDoc.mass1_velocityXstart)}
+                                    startVelY={NumCast(this.dataDoc.mass1_velocityYstart)}
                                     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)}
+                                    updateXmass={NumCast(this.dataDoc.mass1_xChange)}
+                                    updateYmass={NumCast(this.dataDoc.mass1_yChange)}
+                                    forcesUpdated={this.dataDoc.mass1_forcesUpdated}
+                                    wedgeHeight={NumCast(this.dataDoc.wedge_height)}
+                                    wedgeWidth={NumCast(this.dataDoc.wedge_width)}
                                     xMax={this.xMax}
                                     xMin={this.xMin}
                                     yMax={this.yMax}
                                     yMin={this.yMin}
                                 />
-                                {this.dataDoc.simulation_Type == 'Pulley' && (
+                                {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)}
+                                        circularMotionRadius={this.circularMotionRadius}
+                                        gravity={this.gravity}
                                         componentForces={this.dataDoc.componentForces}
-                                        showComponentForces={BoolCast(this.dataDoc.show_ComponentForces)}
+                                        showComponentForces={BoolCast(this.dataDoc.simulation_showComponentForces)}
                                         color={'blue'}
                                         coefficientOfKineticFriction={NumCast(this.dataDoc.coefficientOfKineticFriction)}
-                                        displayXVelocity={NumCast(this.dataDoc.velocity_XDisplay)}
-                                        displayYVelocity={NumCast(this.dataDoc.velocity_YDisplay)}
+                                        displayXVelocity={NumCast(this.dataDoc.mass1_velocityX)}
+                                        displayYVelocity={NumCast(this.dataDoc.mass1_velocityY)}
                                         elasticCollisions={BoolCast(this.dataDoc.elasticCollisions)}
                                         mass={NumCast(this.dataDoc.mass2)}
-                                        mode={StrCast(this.dataDoc.mode)}
+                                        simulationMode={StrCast(this.dataDoc.simulation_mode)}
                                         noMovement={BoolCast(this.dataDoc.noMovement)}
-                                        paused={BoolCast(this.dataDoc.simulation_Paused)}
+                                        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)}
+                                        reset={BoolCast(this.dataDoc.simulation_reset)}
+                                        simulationSpeed={NumCast(this.dataDoc.simulation_speed)}
+                                        startPendulumAngle={NumCast(this.dataDoc.pendulum_angleStart)}
+                                        showAcceleration={BoolCast(this.dataDoc.simulation_showAcceleration)}
+                                        showForceMagnitudes={BoolCast(this.dataDoc.simulation_showForceMagnitudes)}
+                                        showForces={BoolCast(this.dataDoc.simulation_showForces)}
+                                        showVelocity={BoolCast(this.dataDoc.simulation_showVelocity)}
+                                        simulationType={this.dataDoc.simulation_type}
+                                        springConstant={NumCast(this.dataDoc.spring_constant)}
+                                        springStartLength={NumCast(this.dataDoc.spring_lengthStart)}
+                                        springRestLength={NumCast(this.dataDoc.spring_lengthRest)}
+                                        startForces={this.dataDoc.mass2_forcesStart}
+                                        startPosX={NumCast(this.dataDoc.mass2_positionXstart)}
+                                        startPosY={NumCast(this.dataDoc.mass2_positionYstart)}
+                                        startVelX={NumCast(this.dataDoc.mass1_velocityXstart)}
+                                        startVelY={NumCast(this.dataDoc.mass1_velocityYstart)}
                                         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)}
+                                        updateXmass={NumCast(this.dataDoc.mass2_xChange)}
+                                        updateYmass={NumCast(this.dataDoc.mass2_yChange)}
+                                        forcesUpdated={this.dataDoc.mass2_forcesUpdated}
+                                        wedgeHeight={NumCast(this.dataDoc.wedge_height)}
+                                        wedgeWidth={NumCast(this.dataDoc.wedge_width)}
                                         xMax={this.xMax}
                                         xMin={this.xMin}
                                         yMax={this.yMax}
@@ -1003,7 +994,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 )}
                             </div>
                             <div>
-                                {(this.dataDoc.simulation_Type == 'One Weight' || this.dataDoc.simulation_Type == 'Inclined Plane') &&
+                                {(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} />;
@@ -1014,26 +1005,26 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                     <div className="mechanicsSimulationEquationContainer">
                         <div className="mechanicsSimulationControls">
                             <Stack direction="row" spacing={1}>
-                                {this.dataDoc.simulation_Paused && this.dataDoc.mode != 'Tutorial' && (
+                                {this.dataDoc.simulation_paused && this.dataDoc.simulation_mode != 'Tutorial' && (
                                     <IconButton
                                         onClick={() => {
-                                            this.dataDoc.simulation_Paused = false;
+                                            this.dataDoc.simulation_paused = false;
                                         }}>
                                         <PlayArrowIcon />
                                     </IconButton>
                                 )}
-                                {!this.dataDoc.simulation_Paused && this.dataDoc.mode != 'Tutorial' && (
+                                {!this.dataDoc.simulation_paused && this.dataDoc.simulation_mode != 'Tutorial' && (
                                     <IconButton
                                         onClick={() => {
-                                            this.dataDoc.simulation_Paused = true;
+                                            this.dataDoc.simulation_paused = true;
                                         }}>
                                         <PauseIcon />
                                     </IconButton>
                                 )}
-                                {this.dataDoc.simulation_Paused && this.dataDoc.mode != 'Tutorial' && (
+                                {this.dataDoc.simulation_paused && this.dataDoc.simulation_mode != 'Tutorial' && (
                                     <IconButton
                                         onClick={() => {
-                                            this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
+                                            this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                                         }}>
                                         <ReplayIcon />
                                     </IconButton>
@@ -1041,10 +1032,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                             </Stack>
                             <div className="dropdownMenu">
                                 <select
-                                    value={StrCast(this.dataDoc.simulation_Type)}
+                                    value={StrCast(this.dataDoc.simulation_type)}
                                     onChange={event => {
-                                        this.dataDoc.simulation_Type = event.target.value;
-                                        this.setupSimulation(event.target.value, StrCast(this.dataDoc.mode));
+                                        this.dataDoc.simulation_type = event.target.value;
+                                        this.setupSimulation(event.target.value, StrCast(this.dataDoc.simulation_mode));
                                     }}
                                     style={{ height: '2em', width: '100%', fontSize: '16px' }}>
                                     <option value="One Weight">Projectile</option>
@@ -1058,10 +1049,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                             </div>
                             <div className="dropdownMenu">
                                 <select
-                                    value={StrCast(this.dataDoc.mode)}
+                                    value={StrCast(this.dataDoc.simulation_mode)}
                                     onChange={event => {
-                                        this.dataDoc.mode = event.target.value;
-                                        this.setupSimulation(StrCast(this.dataDoc.simulation_Type), event.target.value);
+                                        this.dataDoc.simulation_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>
@@ -1070,13 +1061,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </select>
                             </div>
                         </div>
-                        {this.dataDoc.mode == 'Review' && this.dataDoc.simulation_Type != 'Inclined Plane' && (
+                        {this.dataDoc.simulation_mode == 'Review' && this.dataDoc.simulation_type != 'Inclined Plane' && (
                             <div className="wordProblemBox">
-                                <p>{this.dataDoc.simulation_Type} review problems in progress!</p>
+                                <p>{this.dataDoc.simulation_type} review problems in progress!</p>
                                 <hr />
                             </div>
                         )}
-                        {this.dataDoc.mode == 'Review' && this.dataDoc.simulation_Type == 'Inclined Plane' && (
+                        {this.dataDoc.simulation_mode == 'Review' && this.dataDoc.simulation_type == 'Inclined Plane' && (
                             <div>
                                 {!this.dataDoc.hintDialogueOpen && (
                                     <IconButton
@@ -1136,7 +1127,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 unit={'N'}
                                                 upperBound={50}
                                                 value={NumCast(this.dataDoc.review_GravityMagnitude)}
-                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
+                                                showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
                                                 correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('force of gravity')]}
                                                 labelWidth={'7em'}
                                             />
@@ -1152,7 +1143,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 upperBound={360}
                                                 value={NumCast(this.dataDoc.review_GravityAngle)}
                                                 radianEquivalent={true}
-                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
+                                                showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
                                                 correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('angle of gravity')]}
                                                 labelWidth={'7em'}
                                             />
@@ -1167,7 +1158,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 unit={'N'}
                                                 upperBound={50}
                                                 value={NumCast(this.dataDoc.review_NormalMagnitude)}
-                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
+                                                showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
                                                 correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('normal force')]}
                                                 labelWidth={'7em'}
                                             />
@@ -1183,7 +1174,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 upperBound={360}
                                                 value={NumCast(this.dataDoc.review_NormalAngle)}
                                                 radianEquivalent={true}
-                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
+                                                showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
                                                 correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('angle of normal force')]}
                                                 labelWidth={'7em'}
                                             />
@@ -1198,7 +1189,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 unit={'N'}
                                                 upperBound={50}
                                                 value={NumCast(this.dataDoc.review_StaticMagnitude)}
-                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
+                                                showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
                                                 correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('force of static friction')]}
                                                 labelWidth={'7em'}
                                             />
@@ -1214,7 +1205,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 upperBound={360}
                                                 value={NumCast(this.dataDoc.review_StaticAngle)}
                                                 radianEquivalent={true}
-                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
+                                                showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
                                                 correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('angle of static friction')]}
                                                 labelWidth={'7em'}
                                             />
@@ -1234,7 +1225,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 upperBound={1}
                                                 value={NumCast(this.dataDoc.coefficientOfStaticFriction)}
                                                 effect={this.updateReviewForcesBasedOnCoefficient}
-                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
+                                                showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
                                                 correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('coefficient of static friction')]}
                                             />
                                         )}
@@ -1243,17 +1234,17 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 label={<Box>&theta;</Box>}
                                                 lowerBound={0}
                                                 dataDoc={this.dataDoc}
-                                                prop="wedgeAngle"
+                                                prop="wedge_angle"
                                                 step={1}
                                                 unit={'°'}
                                                 upperBound={49}
-                                                value={NumCast(this.dataDoc.wedgeAngle, 26)}
+                                                value={NumCast(this.dataDoc.wedge_angle, 26)}
                                                 effect={(val: number) => {
                                                     this.changeWedgeBasedOnNewAngle(val);
                                                     this.updateReviewForcesBasedOnAngle(val);
                                                 }}
                                                 radianEquivalent={true}
-                                                showIcon={BoolCast(this.dataDoc.show_Icon)}
+                                                showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
                                                 correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('wedge angle')]}
                                             />
                                         )}
@@ -1261,11 +1252,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </div>
                             </div>
                         )}
-                        {this.dataDoc.mode == 'Tutorial' && (
+                        {this.dataDoc.simulation_mode == 'Tutorial' && (
                             <div className="wordProblemBox">
                                 <div className="question">
                                     <h2>Problem</h2>
-                                    <p>{this.dataDoc.selectedTutorial.question}</p>
+                                    <p>{this.dataDoc.tutorial.question}</p>
                                 </div>
                                 <div
                                     style={{
@@ -1275,40 +1266,40 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     }}>
                                     <IconButton
                                         onClick={() => {
-                                            let step = NumCast(this.dataDoc.stepNumber) - 1;
+                                            let step = NumCast(this.dataDoc.tutorial_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;
+                                            step = Math.min(step, this.dataDoc.tutorial.steps.length - 1);
+                                            this.dataDoc.tutorial_stepNumber = step;
+                                            this.dataDoc.mass1_forcesStart = this.getForceFromJSON(this.dataDoc.tutorial.steps[step].forces);
+                                            this.dataDoc.mass1_forcesUpdated = this.getForceFromJSON(this.dataDoc.tutorial.steps[step].forces);
+                                            this.dataDoc.simulation_showForceMagnitudes = this.dataDoc.tutorial.steps[step].show_Magnitude;
                                         }}
-                                        disabled={this.dataDoc.stepNumber == 0}>
+                                        disabled={this.dataDoc.tutorial_stepNumber == 0}>
                                         <ArrowLeftIcon />
                                     </IconButton>
                                     <div>
                                         <h3>
-                                            Step {NumCast(this.dataDoc.stepNumber) + 1}: {this.dataDoc.selectedTutorial.steps[this.dataDoc.stepNumber].description}
+                                            Step {NumCast(this.dataDoc.tutorial_stepNumber) + 1}: {this.dataDoc.tutorial.steps[this.dataDoc.tutorial_stepNumber].description}
                                         </h3>
-                                        <p>{this.dataDoc.selectedTutorial.steps[NumCast(this.dataDoc.stepNumber)].content}</p>
+                                        <p>{this.dataDoc.tutorial.steps[NumCast(this.dataDoc.tutorial_stepNumber)].content}</p>
                                     </div>
                                     <IconButton
                                         onClick={() => {
-                                            let step = NumCast(this.dataDoc.stepNumber) + 1;
+                                            let step = NumCast(this.dataDoc.tutorial_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;
+                                            step = Math.min(step, this.dataDoc.tutorial.steps.length - 1);
+                                            this.dataDoc.tutorial_stepNumber = step;
+                                            this.dataDoc.mass1_forcesStart = this.getForceFromJSON(this.dataDoc.tutorial.steps[step].forces);
+                                            this.dataDoc.mass1_forcesUpdated = this.getForceFromJSON(this.dataDoc.tutorial.steps[step].forces);
+                                            this.dataDoc.simulation_showForceMagnitudes = this.dataDoc.tutorial.steps[step].show_Magnitude;
                                         }}
-                                        disabled={this.dataDoc.stepNumber == this.dataDoc.selectedTutorial.steps.length - 1}>
+                                        disabled={this.dataDoc.tutorial_stepNumber == this.dataDoc.tutorial.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' && (
+                                    {(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
@@ -1336,7 +1327,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             </li>
                                         </ul>
                                     )}
-                                    {this.dataDoc.simulation_Type == 'Inclined Plane' && (
+                                    {this.dataDoc.simulation_type == 'Inclined Plane' && (
                                         <ul>
                                             <li>
                                                 <a
@@ -1364,7 +1355,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             </li>
                                         </ul>
                                     )}
-                                    {this.dataDoc.simulation_Type == 'Pendulum' && (
+                                    {this.dataDoc.simulation_type == 'Pendulum' && (
                                         <ul>
                                             <li>
                                                 <a
@@ -1383,7 +1374,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </div>
                             </div>
                         )}
-                        {this.dataDoc.mode == 'Review' && this.dataDoc.simulation_Type == 'Inclined Plane' && (
+                        {this.dataDoc.simulation_mode == 'Review' && this.dataDoc.simulation_type == 'Inclined Plane' && (
                             <div
                                 style={{
                                     display: 'flex',
@@ -1396,16 +1387,16 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                         textDecoration: 'underline',
                                         cursor: 'pointer',
                                     }}
-                                    onClick={() => (this.dataDoc.mode = 'Tutorial')}>
+                                    onClick={() => (this.dataDoc.simulation_mode = 'Tutorial')}>
                                     {' '}
                                     Go to walkthrough{' '}
                                 </p>
                                 <div style={{ display: 'flex', flexDirection: 'column' }}>
                                     <Button
                                         onClick={() => {
-                                            this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
+                                            this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                                             this.checkAnswers();
-                                            this.dataDoc.show_Icon = true;
+                                            this.dataDoc.simulation_showIcon = true;
                                         }}
                                         variant="outlined">
                                         <p>Submit</p>
@@ -1413,7 +1404,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     <Button
                                         onClick={() => {
                                             this.generateNewQuestion();
-                                            this.dataDoc.show_Icon = false;
+                                            this.dataDoc.simulation_showIcon = false;
                                         }}
                                         variant="outlined">
                                         <p>New question</p>
@@ -1421,37 +1412,41 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </div>
                             </div>
                         )}
-                        {this.dataDoc.mode == 'Freeform' && (
+                        {this.dataDoc.simulation_mode == 'Freeform' && (
                             <div className="vars">
                                 <FormControl component="fieldset">
                                     <FormGroup>
-                                        {this.dataDoc.simulation_Type == 'One Weight' && (
+                                        {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.simulation_showForces)} onChange={() => (this.dataDoc.simulation_showForces = !this.dataDoc.simulation_showForces)} />}
+                                            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)} />}
+                                                control={<Checkbox checked={BoolCast(this.dataDoc.simulation_showForces)} onChange={() => (this.dataDoc.simulation_showComponentForces = !this.dataDoc.simulation_showComponentForces)} />}
                                                 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)} />}
+                                            control={<Checkbox checked={BoolCast(this.dataDoc.simulation_showAcceleration)} onChange={() => (this.dataDoc.simulation_showAcceleration = !this.dataDoc.simulation_showAcceleration)} />}
                                             label="Show acceleration vector"
                                             labelPlacement="start"
                                         />
                                         <FormControlLabel
-                                            control={<Checkbox checked={BoolCast(this.dataDoc.show_Velocity)} onChange={() => (this.dataDoc.show_Velocity = !this.dataDoc.show_Velocity)} />}
+                                            control={<Checkbox checked={BoolCast(this.dataDoc.simulation_showVelocity)} onChange={() => (this.dataDoc.simulation_showVelocity = !this.dataDoc.simulation_showVelocity)} />}
                                             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>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}
@@ -1460,46 +1455,46 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 step={0.01}
                                                 unit={'m/s2'}
                                                 upperBound={0}
-                                                value={NumCast(this.dataDoc.gravity, -9.81)}
+                                                value={NumCast(this.dataDoc.simulation_gravity, -9.81)}
                                                 effect={(val: number) => {
-                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
+                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_type), StrCast(this.dataDoc.simulation_mode));
                                                 }}
                                                 labelWidth={'5em'}
                                             />
                                         )}
-                                        {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type != 'Pulley' && (
+                                        {this.dataDoc.simulation_paused && this.dataDoc.simulation_type != 'Pulley' && (
                                             <InputField
                                                 label={<Box>Mass</Box>}
                                                 lowerBound={1}
                                                 dataDoc={this.dataDoc}
-                                                prop="mass"
+                                                prop="mass1"
                                                 step={0.1}
                                                 unit={'kg'}
                                                 upperBound={5}
-                                                value={NumCast(this.dataDoc.mass) ?? 1}
+                                                value={NumCast(this.dataDoc.mass1) ?? 1}
                                                 effect={(val: number) => {
-                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
+                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_type), StrCast(this.dataDoc.simulation_mode));
                                                 }}
                                                 labelWidth={'5em'}
                                             />
                                         )}
-                                        {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type == 'Pulley' && (
+                                        {this.dataDoc.simulation_paused && this.dataDoc.simulation_type == 'Pulley' && (
                                             <InputField
                                                 label={<Box>Red mass</Box>}
                                                 lowerBound={1}
                                                 dataDoc={this.dataDoc}
-                                                prop="mass"
+                                                prop="mass1"
                                                 step={0.1}
                                                 unit={'kg'}
                                                 upperBound={5}
-                                                value={NumCast(this.dataDoc.mass) ?? 1}
+                                                value={NumCast(this.dataDoc.mass1) ?? 1}
                                                 effect={(val: number) => {
-                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
+                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_type), StrCast(this.dataDoc.simulation_mode));
                                                 }}
                                                 labelWidth={'5em'}
                                             />
                                         )}
-                                        {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type == 'Pulley' && (
+                                        {this.dataDoc.simulation_paused && this.dataDoc.simulation_type == 'Pulley' && (
                                             <InputField
                                                 label={<Box>Blue mass</Box>}
                                                 lowerBound={1}
@@ -1510,12 +1505,12 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 upperBound={5}
                                                 value={NumCast(this.dataDoc.mass2) ?? 1}
                                                 effect={(val: number) => {
-                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
+                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_type), StrCast(this.dataDoc.simulation_mode));
                                                 }}
                                                 labelWidth={'5em'}
                                             />
                                         )}
-                                        {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type == 'Circular Motion' && (
+                                        {this.dataDoc.simulation_paused && this.dataDoc.simulation_type == 'Circular Motion' && (
                                             <InputField
                                                 label={<Box>Rod length</Box>}
                                                 lowerBound={100}
@@ -1524,28 +1519,28 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 step={5}
                                                 unit={'m'}
                                                 upperBound={250}
-                                                value={NumCast(this.dataDoc.circularMotionRadius) ?? 100}
+                                                value={this.circularMotionRadius}
                                                 effect={(val: number) => {
-                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_Type), StrCast(this.dataDoc.mode));
+                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_type), StrCast(this.dataDoc.simulation_mode));
                                                 }}
                                                 labelWidth={'5em'}
                                             />
                                         )}
                                     </FormGroup>
                                 </FormControl>
-                                {this.dataDoc.simulation_Type == 'Spring' && this.dataDoc.simulation_Paused && (
+                                {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"
+                                            prop="spring_constant"
                                             step={1}
                                             unit={'N/m'}
                                             upperBound={500}
-                                            value={NumCast(this.dataDoc.springConstant) ?? 0.5}
+                                            value={NumCast(this.dataDoc.spring_constant) ?? 0.5}
                                             effect={(val: number) => {
-                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
+                                                this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                                             }}
                                             radianEquivalent={false}
                                             mode={'Freeform'}
@@ -1555,13 +1550,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             label={<Typography color="inherit">Rest length</Typography>}
                                             lowerBound={10}
                                             dataDoc={this.dataDoc}
-                                            prop="springRestLength"
+                                            prop="spring_lengthRest"
                                             step={100}
                                             unit={''}
                                             upperBound={500}
-                                            value={NumCast(this.dataDoc.springRestLength) ?? 200}
+                                            value={NumCast(this.dataDoc.spring_lengthRest) ?? 200}
                                             effect={(val: number) => {
-                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
+                                                this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                                             }}
                                             radianEquivalent={false}
                                             mode={'Freeform'}
@@ -1569,17 +1564,17 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                         />
                                         <InputField
                                             label={<Typography color="inherit">Starting displacement</Typography>}
-                                            lowerBound={-(NumCast(this.dataDoc.springRestLength) - 10)}
+                                            lowerBound={-(NumCast(this.dataDoc.spring_lengthRest) - 10)}
                                             dataDoc={this.dataDoc}
                                             prop=""
                                             step={10}
                                             unit={''}
-                                            upperBound={NumCast(this.dataDoc.springRestLength)}
-                                            value={NumCast(this.dataDoc.springStartLength) - NumCast(this.dataDoc.springRestLength)}
+                                            upperBound={NumCast(this.dataDoc.spring_lengthRest)}
+                                            value={NumCast(this.dataDoc.spring_lengthStart) - NumCast(this.dataDoc.spring_lengthRest)}
                                             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;
+                                                this.dataDoc.mass1_positionYstart = NumCast(this.dataDoc.spring_lengthRest) + val;
+                                                this.dataDoc.spring_lengthStart = NumCast(this.dataDoc.spring_lengthRest) + val;
+                                                this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                                             }}
                                             radianEquivalent={false}
                                             mode={'Freeform'}
@@ -1587,20 +1582,20 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                         />
                                     </div>
                                 )}
-                                {this.dataDoc.simulation_Type == 'Inclined Plane' && this.dataDoc.simulation_Paused && (
+                                {this.dataDoc.simulation_type == 'Inclined Plane' && this.dataDoc.simulation_paused && (
                                     <div>
                                         <InputField
                                             label={<Box>&theta;</Box>}
                                             lowerBound={0}
                                             dataDoc={this.dataDoc}
-                                            prop="wedgeAngle"
+                                            prop="wedge_angle"
                                             step={1}
                                             unit={'°'}
                                             upperBound={49}
-                                            value={NumCast(this.dataDoc.wedgeAngle, 26)}
+                                            value={NumCast(this.dataDoc.wedge_angle, 26)}
                                             effect={(val: number) => {
                                                 this.changeWedgeBasedOnNewAngle(val);
-                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
+                                                this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                                             }}
                                             radianEquivalent={true}
                                             mode={'Freeform'}
@@ -1624,7 +1619,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 if (val < NumCast(this.dataDoc.coefficientOfKineticFriction)) {
                                                     this.dataDoc.soefficientOfKineticFriction = val;
                                                 }
-                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
+                                                this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                                             }}
                                             mode={'Freeform'}
                                             labelWidth={'2em'}
@@ -1643,28 +1638,28 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             upperBound={NumCast(this.dataDoc.coefficientOfStaticFriction)}
                                             value={NumCast(this.dataDoc.coefficientOfKineticFriction) ?? 0}
                                             effect={(val: number) => {
-                                                this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
+                                                this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                                             }}
                                             mode={'Freeform'}
                                             labelWidth={'2em'}
                                         />
                                     </div>
                                 )}
-                                {this.dataDoc.simulation_Type == 'Inclined Plane' && !this.dataDoc.simulation_Paused && (
+                                {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
+                                        &theta;: {Math.round(NumCast(this.dataDoc.wedge_angle) * 100) / 100}° ≈ {Math.round(((NumCast(this.dataDoc.wedge_angle) * 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 && (
+                                {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 && (
+                                {this.dataDoc.simulation_type == 'Pendulum' && this.dataDoc.simulation_paused && (
                                     <div>
                                         <InputField
                                             label={<Box>Angle</Box>}
@@ -1676,9 +1671,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             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);
+                                                this.dataDoc.pendulum_angleStart = value;
+                                                if (this.dataDoc.simulation_type == 'Pendulum') {
+                                                    const mag = NumCast(this.dataDoc.mass1) * Math.abs(this.gravity) * Math.cos((value * Math.PI) / 180);
 
                                                     const forceOfTension: IForce = {
                                                         description: 'Tension',
@@ -1695,13 +1690,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     };
                                                     const gravityParallel: IForce = {
                                                         description: 'Gravity Parallel Component',
-                                                        magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * Math.cos((value * Math.PI) / 180),
+                                                        magnitude: Math.abs(this.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),
+                                                        magnitude: Math.abs(this.gravity) * Math.sin((value * Math.PI) / 180),
                                                         directionInDegrees: -value,
                                                         component: true,
                                                     };
@@ -1711,22 +1706,22 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     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.mass1_positionXstart = xPos;
+                                                    this.dataDoc.mass1_positionYstart = yPos;
 
-                                                    this.dataDoc.start_Forces = [
+                                                    this.dataDoc.mass1_forcesStart = [
                                                         {
                                                             description: 'Gravity',
-                                                            magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
+                                                            magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
                                                             directionInDegrees: 270,
                                                             component: false,
                                                         },
                                                         forceOfTension,
                                                     ];
-                                                    this.dataDoc.updatedForces = [
+                                                    this.dataDoc.mass1_forcesUpdated = [
                                                         {
                                                             description: 'Gravity',
-                                                            magnitude: Math.abs(NumCast(this.dataDoc.gravity)) * NumCast(this.dataDoc.mass),
+                                                            magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
                                                             directionInDegrees: 270,
                                                             component: false,
                                                         },
@@ -1734,7 +1729,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     ];
                                                     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);
+                                                    this.dataDoc.pendulum_length_adjust = this.dataDoc.pendulum_length;
+                                                    this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                                                 }
                                             }}
                                             radianEquivalent={true}
@@ -1751,10 +1747,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             upperBound={400}
                                             value={Math.round(NumCast(this.dataDoc.pendulum_length))}
                                             effect={value => {
-                                                if (this.dataDoc.simulation_Type == 'Pendulum') {
+                                                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;
+                                                    this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                                                 }
                                             }}
                                             radianEquivalent={false}
@@ -1766,11 +1762,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                             </div>
                         )}
                         <div className="mechanicsSimulationEquation">
-                            {this.dataDoc.mode == 'Freeform' && (
+                            {this.dataDoc.simulation_mode == 'Freeform' && (
                                 <table>
                                     <tbody>
                                         <tr>
-                                            <td>{this.dataDoc.simulation_Type == 'Pulley' ? 'Red Weight' : ''}</td>
+                                            <td>{this.dataDoc.simulation_type == 'Pulley' ? 'Red Weight' : ''}</td>
                                             <td>X</td>
                                             <td>Y</td>
                                         </tr>
@@ -1785,34 +1781,34 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             >
                                                 <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' }}>{this.dataDoc.mass1_positionX} m</td>
                                             )}{' '}
-                                            {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type != 'Inclined Plane' && this.dataDoc.simulation_Type != 'Circular Motion' && this.dataDoc.simulation_Type != 'Pulley' && (
+                                            {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}
+                                                        lowerBound={this.dataDoc.simulation_type == 'Projectile' ? 1 : (this.xMax + this.xMin) / 4 - this.radius - 15}
                                                         dataDoc={this.dataDoc}
-                                                        prop="position_XDisplay"
+                                                        prop="mass1_positionX"
                                                         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)}
+                                                        upperBound={this.dataDoc.simulation_type == 'Projectile' ? this.xMax - 110 : (3 * (this.xMax + this.xMin)) / 4 - this.radius / 2 - 15}
+                                                        value={NumCast(this.dataDoc.mass1_positionX)}
                                                         effect={value => {
-                                                            this.dataDoc.display_xChange = value;
-                                                            this.dataDoc.display_yChange = this.dataDoc.position_YDisplay;
-                                                            if (this.dataDoc.simulation_Type == 'Suspension') {
+                                                            this.dataDoc.mass1_xChange = value;
+                                                            this.dataDoc.mass1_yChange = this.dataDoc.mass1_positionY;
+                                                            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 deltaY = this.getYPosFromDisplay(NumCast(this.dataDoc.mass1_positionY)) + 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 tensionMag2 = (NumCast(this.dataDoc.mass1) * Math.abs(this.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;
@@ -1830,11 +1826,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                                 };
                                                                 const grav: IForce = {
                                                                     description: 'Gravity',
-                                                                    magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
+                                                                    magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity),
                                                                     directionInDegrees: 270,
                                                                     component: false,
                                                                 };
-                                                                this.dataDoc.updatedForces = [tensionForce1, tensionForce2, grav];
+                                                                this.dataDoc.mass1_forcesUpdated = [tensionForce1, tensionForce2, grav];
                                                             }
                                                         }}
                                                         small={true}
@@ -1842,10 +1838,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     />
                                                 </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' }}>{`${NumCast(this.dataDoc.mass1_positionY)} m`}</td>
                                             )}{' '}
-                                            {this.dataDoc.simulation_Paused && this.dataDoc.simulation_Type != 'Inclined Plane' && this.dataDoc.simulation_Type != 'Circular Motion' && this.dataDoc.simulation_Type != 'Pulley' && (
+                                            {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',
@@ -1853,23 +1849,23 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     <InputField
                                                         lowerBound={1}
                                                         dataDoc={this.dataDoc}
-                                                        prop="position_YDisplay"
+                                                        prop="mass1_positionY"
                                                         step={1}
                                                         unit={'m'}
                                                         upperBound={this.yMax - 110}
-                                                        value={NumCast(this.dataDoc.position_YDisplay)}
+                                                        value={NumCast(this.dataDoc.mass1_positionY)}
                                                         effect={value => {
-                                                            this.dataDoc.display_xChange = NumCast(this.dataDoc.position_XDisplay);
-                                                            this.dataDoc.display_yChange = value;
-                                                            if (this.dataDoc.simulation_Type == 'Suspension') {
+                                                            this.dataDoc.mass1_xChange = NumCast(this.dataDoc.mass1_positionX);
+                                                            this.dataDoc.mass1_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 deltaX1 = NumCast(this.dataDoc.mass1_positionX) + this.radius - x1rod;
+                                                                let deltaX2 = x2rod - (NumCast(this.dataDoc.mass1_positionX) + 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 tensionMag2 = (NumCast(this.dataDoc.mass1) * Math.abs(this.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;
@@ -1887,11 +1883,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                                 };
                                                                 const grav: IForce = {
                                                                     description: 'Gravity',
-                                                                    magnitude: NumCast(this.dataDoc.mass) * Math.abs(NumCast(this.dataDoc.gravity)),
+                                                                    magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity),
                                                                     directionInDegrees: 270,
                                                                     component: false,
                                                                 };
-                                                                this.dataDoc.updatedForces = [tensionForce1, tensionForce2, grav];
+                                                                this.dataDoc.mass1_forcesUpdated = [tensionForce1, tensionForce2, grav];
                                                             }
                                                         }}
                                                         small={true}
@@ -1911,10 +1907,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             >
                                                 <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' }}>{`${NumCast(this.dataDoc.mass1_velocityX)} m/s`}</td>
                                             )}{' '}
-                                            {this.dataDoc.simulation_Paused && (this.dataDoc.simulation_Type == 'One Weight' || this.dataDoc.simulation_Type == 'Circular Motion') && (
+                                            {this.dataDoc.simulation_paused && (this.dataDoc.simulation_type == 'One Weight' || this.dataDoc.simulation_type == 'Circular Motion') && (
                                                 <td
                                                     style={{
                                                         cursor: 'default',
@@ -1922,22 +1918,22 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     <InputField
                                                         lowerBound={-50}
                                                         dataDoc={this.dataDoc}
-                                                        prop="velocity_XDisplay"
+                                                        prop="mass1_velocityX"
                                                         step={1}
                                                         unit={'m/s'}
                                                         upperBound={50}
-                                                        value={this.dataDoc.velocity_XDisplay}
+                                                        value={this.dataDoc.mass1_velocityX}
                                                         effect={value => {
-                                                            this.dataDoc.start_VelX = value;
-                                                            this.dataDoc.simulation_Reset = !this.dataDoc.simulation_Reset;
+                                                            this.dataDoc.mass1_velocityXstart = 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' && (
+                                            {(!this.dataDoc.simulation_paused || this.dataDoc.simulation_type != 'One Weight') && <td style={{ cursor: 'default' }}>{this.dataDoc.mass1_velocityY} m/s</td>}{' '}
+                                            {this.dataDoc.simulation_paused && this.dataDoc.simulation_type == 'One Weight' && (
                                                 <td
                                                     style={{
                                                         cursor: 'default',
@@ -1945,15 +1941,15 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     <InputField
                                                         lowerBound={-50}
                                                         dataDoc={this.dataDoc}
-                                                        prop="velocity_YDisplay"
+                                                        prop="mass1_velocityY"
                                                         step={1}
                                                         unit={'m/s'}
                                                         upperBound={50}
-                                                        value={this.dataDoc.velocity_YDisplay}
+                                                        value={this.dataDoc.mass1_velocityY}
                                                         effect={value => {
-                                                            this.dataDoc.start_VelY = -value;
-                                                            this.dataDoc.display_xChange = this.dataDoc.position_XDisplay;
-                                                            this.dataDoc.display_yChange = this.dataDoc.position_YDisplay;
+                                                            this.dataDoc.mass1_velocityYstart = -value;
+                                                            this.dataDoc.mass1_xChange = this.dataDoc.mass1_positionX;
+                                                            this.dataDoc.mass1_yChange = this.dataDoc.mass1_positionY;
                                                         }}
                                                         small={true}
                                                         mode={'Freeform'}
@@ -1973,23 +1969,23 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 <Box>Acceleration</Box>
                                             </td>
                                             <td style={{ cursor: 'default' }}>
-                                                {this.dataDoc.acceleration_XDisplay} m/s<sup>2</sup>
+                                                {this.dataDoc.mass1_accelerationX} m/s<sup>2</sup>
                                             </td>
                                             <td style={{ cursor: 'default' }}>
-                                                {this.dataDoc.acceleration_YDisplay} m/s<sup>2</sup>
+                                                {this.dataDoc.mass1_accelerationY} 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>
+                                            <td>{Math.round(NumCast(this.dataDoc.mass1_velocityX) * NumCast(this.dataDoc.mass1) * 10) / 10} kg*m/s</td>
+                                            <td>{Math.round(NumCast(this.dataDoc.mass1_velocityY) * NumCast(this.dataDoc.mass1) * 10) / 10} kg*m/s</td>
                                         </tr>
                                     </tbody>
                                 </table>
                             )}
-                            {this.dataDoc.mode == 'Freeform' && this.dataDoc.simulation_Type == 'Pulley' && (
+                            {this.dataDoc.simulation_mode == 'Freeform' && this.dataDoc.simulation_type == 'Pulley' && (
                                 <table>
                                     <tbody>
                                         <tr>
@@ -2001,39 +1997,39 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             <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>
+                                            <td style={{ cursor: 'default' }}>{`${this.dataDoc.mass2_positionX} m`}</td>
+                                            <td style={{ cursor: 'default' }}>{`${this.dataDoc.mass2_positionY} 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>
+                                            <td style={{ cursor: 'default' }}>{`${this.dataDoc.mass2_positionX} m/s`}</td>
+                                            <td style={{ cursor: 'default' }}>{`${this.dataDoc.mass2_positionY} m/s`}</td>
                                         </tr>
                                         <tr>
                                             <td>
                                                 <Box>Acceleration</Box>
                                             </td>
                                             <td style={{ cursor: 'default' }}>
-                                                {this.dataDoc.acceleration_XDisplay2} m/s<sup>2</sup>
+                                                {this.dataDoc.mass2_accelerationX} m/s<sup>2</sup>
                                             </td>
                                             <td style={{ cursor: 'default' }}>
-                                                {this.dataDoc.acceleration_YDisplay2} m/s<sup>2</sup>
+                                                {this.dataDoc.mass2_accelerationY} 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>
+                                            <td>{Math.round(NumCast(this.dataDoc.mass2_velocityX) * NumCast(this.dataDoc.mass1) * 10) / 10} kg*m/s</td>
+                                            <td>{Math.round(NumCast(this.dataDoc.mass2_velocityY) * NumCast(this.dataDoc.mass1) * 10) / 10} kg*m/s</td>
                                         </tr>
                                     </tbody>
                                 </table>
                             )}
                         </div>
-                        {this.dataDoc.simulation_Type != 'Pendulum' && this.dataDoc.simulation_Type != 'Spring' && (
+                        {this.dataDoc.simulation_type != 'Pendulum' && this.dataDoc.simulation_type != 'Spring' && (
                             <div>
                                 <p>Kinematic Equations</p>
                                 <ul>
@@ -2050,7 +2046,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </ul>
                             </div>
                         )}
-                        {this.dataDoc.simulation_Type == 'Spring' && (
+                        {this.dataDoc.simulation_type == 'Spring' && (
                             <div>
                                 <p>Harmonic Motion Equations: Spring</p>
                                 <ul>
@@ -2079,7 +2075,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </ul>
                             </div>
                         )}
-                        {this.dataDoc.simulation_Type == 'Pendulum' && (
+                        {this.dataDoc.simulation_type == 'Pendulum' && (
                             <div>
                                 <p>Harmonic Motion Equations: Pendulum</p>
                                 <ul>
@@ -2114,7 +2110,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                             top: this.yMax - 120 + 40 + 'px',
                             left: this.xMin + 90 - 80 + 'px',
                         }}>
-                        {this.dataDoc.simulation_Type == 'Circular Motion' ? 'Z' : 'Y'}
+                        {this.dataDoc.simulation_type == 'Circular Motion' ? 'Z' : 'Y'}
                     </p>
                     <p
                         style={{
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index a2883e825..1d980ebf4 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -2,6 +2,7 @@ import { Doc, HeightSym, WidthSym } from '../../../../fields/Doc';
 import React = require('react');
 import './PhysicsSimulationBox.scss';
 import { NumCast } from '../../../../fields/Types';
+import { computed } from 'mobx';
 
 interface IWallProps {
     length: number;
@@ -29,7 +30,7 @@ export interface IWeightProps {
     elasticCollisions: boolean;
     gravity: number;
     mass: number;
-    mode: string;
+    simulationMode: string;
     noMovement: boolean;
     paused: boolean;
     pendulumAngle: number;
@@ -55,7 +56,7 @@ export interface IWeightProps {
     timestepSize: number;
     updateXDisplay: number;
     updateYDisplay: number;
-    updatedForces: IForce[];
+    forcesUpdated: IForce[];
     wallPositions: IWallProps[];
     wedgeHeight: number;
     wedgeWidth: number;
@@ -117,7 +118,9 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     }
 
     // Constants
-    draggable = this.props.dataDoc.simulation_Type != 'Inclined Plane' && this.props.dataDoc.simulation_Type != 'Pendulum' && this.props.dataDoc.mode == 'Freeform';
+    @computed get draggable() {
+        return this.props.simulationType != 'Inclined Plane' && this.props.simulationType != 'Pendulum' && this.props.simulationMode == 'Freeform';
+    }
     epsilon = 0.0001;
     labelBackgroundColor = `rgba(255,255,255,0.5)`;
 
@@ -151,30 +154,30 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     setYPosDisplay = (yPos: number) => {
         const displayPos = this.getDisplayYPos(yPos);
         if (this.props.color == 'red') {
-            this.props.dataDoc.position_YDisplay = Math.round(displayPos * 100) / 100;
+            this.props.dataDoc.mass1_positionY = Math.round(displayPos * 100) / 100;
         } else {
-            this.props.dataDoc.position_YDisplay2 = Math.round(displayPos * 100) / 100;
+            this.props.dataDoc.mass2_positionY = Math.round(displayPos * 100) / 100;
         }
     };
     setXPosDisplay = (xPos: number) => {
         if (this.props.color == 'red') {
-            this.props.dataDoc.position_XDisplay = Math.round(xPos * 100) / 100;
+            this.props.dataDoc.mass1_positionX = Math.round(xPos * 100) / 100;
         } else {
-            this.props.dataDoc.position_XDisplay2 = Math.round(xPos * 100) / 100;
+            this.props.dataDoc.mass2_positionX = Math.round(xPos * 100) / 100;
         }
     };
     setYVelDisplay = (yVel: number) => {
         if (this.props.color == 'red') {
-            this.props.dataDoc.velocity_YDisplay = (-1 * Math.round(yVel * 100)) / 100;
+            this.props.dataDoc.mass1_velocityY = (-1 * Math.round(yVel * 100)) / 100;
         } else {
-            this.props.dataDoc.velocity_YDisplay2 = (-1 * Math.round(yVel * 100)) / 100;
+            this.props.dataDoc.mass2_velocityY = (-1 * Math.round(yVel * 100)) / 100;
         }
     };
     setXVelDisplay = (xVel: number) => {
         if (this.props.color == 'red') {
-            this.props.dataDoc.velocity_XDisplay = Math.round(xVel * 100) / 100;
+            this.props.dataDoc.mass1_velocityX = Math.round(xVel * 100) / 100;
         } else {
-            this.props.dataDoc.velocity_XDisplay2 = Math.round(xVel * 100) / 100;
+            this.props.dataDoc.mass2_velocityX = Math.round(xVel * 100) / 100;
         }
     };
 
@@ -185,15 +188,15 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         this.setYVelDisplay(yVel);
         this.setXVelDisplay(xVel);
         if (this.props.color == 'red') {
-            this.props.dataDoc.acceleration_YDisplay = (-1 * Math.round(this.getNewAccelerationY(this.props.updatedForces) * 100)) / 100;
-            this.props.dataDoc.acceleration_XDisplay = Math.round(this.getNewAccelerationX(this.props.updatedForces) * 100) / 100;
+            this.props.dataDoc.mass1_accelerationY = (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated) * 100)) / 100;
+            this.props.dataDoc.mass1_accelerationX = Math.round(this.getNewAccelerationX(this.props.forcesUpdated) * 100) / 100;
         } else {
-            this.props.dataDoc.acceleration_YDisplay2 = (-1 * Math.round(this.getNewAccelerationY(this.props.updatedForces) * 100)) / 100;
-            this.props.dataDoc.acceleration_XDisplay2 = Math.round(this.getNewAccelerationX(this.props.updatedForces) * 100) / 100;
+            this.props.dataDoc.mass2_accelerationY = (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated) * 100)) / 100;
+            this.props.dataDoc.mass2_accelerationX = Math.round(this.getNewAccelerationX(this.props.forcesUpdated) * 100) / 100;
         }
 
-        this.setState({ xAccel: Math.round(this.getNewAccelerationX(this.props.updatedForces) * 100) / 100 });
-        this.setState({ yAccel: (-1 * Math.round(this.getNewAccelerationY(this.props.updatedForces) * 100)) / 100 });
+        this.setState({ xAccel: Math.round(this.getNewAccelerationX(this.props.forcesUpdated) * 100) / 100 });
+        this.setState({ yAccel: (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated) * 100)) / 100 });
     };
 
     componentDidUpdate(prevProps: Readonly<IWeightProps>, prevState: Readonly<IState>, snapshot?: any): void {
@@ -221,9 +224,9 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 this.setState({ updatedStartPosX: x });
                 this.setState({ xPosition: x });
                 if (this.props.color == 'red') {
-                    this.props.dataDoc.position_XDisplay = x;
+                    this.props.dataDoc.mass1_positionX = x;
                 } else {
-                    this.props.dataDoc.position_XDisplay2 = x;
+                    this.props.dataDoc.mass2_positionX = x;
                 }
             }
 
@@ -235,9 +238,9 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 this.setState({ updatedStartPosY: coordinatePosition });
                 this.setState({ yPosition: coordinatePosition });
                 if (this.props.color == 'red') {
-                    this.props.dataDoc.position_YDisplay = y;
+                    this.props.dataDoc.mass1_positionY = y;
                 } else {
-                    this.props.dataDoc.position_YDisplay2 = y;
+                    this.props.dataDoc.mass2_positionY = y;
                 }
             }
 
@@ -245,9 +248,9 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 let x = this.props.displayXVelocity;
                 this.setState({ xVelocity: x });
                 if (this.props.color == 'red') {
-                    this.props.dataDoc.velocity_XDisplay = x;
+                    this.props.dataDoc.mass1_velocityX = x;
                 } else {
-                    this.props.dataDoc.velocity_XDisplay2 = x;
+                    this.props.dataDoc.mass2_velocityX = x;
                 }
             }
 
@@ -255,9 +258,9 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 let y = this.props.displayYVelocity;
                 this.setState({ yVelocity: -y });
                 if (this.props.color == 'red') {
-                    this.props.dataDoc.velocity_YDisplay = y;
+                    this.props.dataDoc.mass1_velocityY = y;
                 } else {
-                    this.props.dataDoc.velocity_YDisplay2 = y;
+                    this.props.dataDoc.mass2_velocityY = y;
                 }
             }
         }
@@ -271,7 +274,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
 
         // Make sure weight doesn't go above max height
         if ((prevState.updatedStartPosY != this.state.updatedStartPosY || prevProps.startVelY != this.props.startVelY) && !isNaN(this.state.updatedStartPosY) && !isNaN(this.props.startVelY)) {
-            if (this.props.dataDoc.simulation_Type == 'One Weight') {
+            if (this.props.simulationType == 'One Weight') {
                 let maxYPos = this.state.updatedStartPosY;
                 if (this.props.startVelY != 0) {
                     maxYPos -= (this.props.startVelY * this.props.startVelY) / (2 * Math.abs(this.props.gravity));
@@ -288,12 +291,12 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             if (prevState.timer != this.state.timer) {
                 if (!this.props.noMovement) {
                     let collisions = false;
-                    if (this.props.dataDoc.simulation_Type == 'One Weight' || this.props.dataDoc.simulation_Type == 'Inclined Plane') {
+                    if (this.props.simulationType == 'One Weight' || this.props.simulationType == 'Inclined Plane') {
                         const collisionsWithGround = this.checkForCollisionsWithGround();
                         const collisionsWithWalls = this.checkForCollisionsWithWall();
                         collisions = collisionsWithGround || collisionsWithWalls;
                     }
-                    if (this.props.dataDoc.simulation_Type == 'Pulley') {
+                    if (this.props.simulationType == 'Pulley') {
                         if (this.state.yPosition <= this.props.yMin + 100 || this.state.yPosition >= this.props.yMax - 100) {
                             collisions = true;
                         }
@@ -313,7 +316,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
 
         // Convert from static to kinetic friction if/when weight slips on inclined plane
         if (prevState.xVelocity != this.state.xVelocity) {
-            if (this.props.dataDoc.simulation_Type == 'Inclined Plane' && Math.abs(this.state.xVelocity) > 0.1 && this.props.dataDoc.mode != 'Review' && !this.state.kineticFriction) {
+            if (this.props.simulationType == 'Inclined Plane' && Math.abs(this.state.xVelocity) > 0.1 && this.props.simulationMode != 'Review' && !this.state.kineticFriction) {
                 this.setState({ kineticFriction: true });
                 const normalForce: IForce = {
                     description: 'Normal Force',
@@ -367,10 +370,10 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                     component: false,
                 };
                 if (this.props.coefficientOfKineticFriction != 0) {
-                    this.props.dataDoc.updatedForces = [gravityForce, normalForce, frictionForce];
+                    this.props.dataDoc.mass1_forcesUpdated = [gravityForce, normalForce, frictionForce];
                     this.props.dataDoc.componentForces = [frictionForceComponent, normalForceComponent, gravityParallel, gravityPerpendicular];
                 } else {
-                    this.props.dataDoc.updatedForces = [gravityForce, normalForce];
+                    this.props.dataDoc.mass1_forcesUpdated = [gravityForce, normalForce];
                     this.props.dataDoc.componentForces = [normalForceComponent, gravityParallel, gravityPerpendicular];
                 }
             }
@@ -379,7 +382,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         // Add/remove walls when simulation type changes
         if (prevProps.simulationType != this.props.simulationType) {
             let w: IWallProps[] = [];
-            if (this.props.dataDoc.simulation_Type == 'One Weight' || this.props.dataDoc.simulation_Type == 'Inclined Plane') {
+            if (this.props.simulationType == 'One Weight' || this.props.simulationType == 'Inclined Plane') {
                 w = this.props.wallPositions;
             }
             this.setState({ walls: w });
@@ -438,27 +441,27 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         this.setState({ kineticFriction: false });
         this.setState({ xPosition: this.state.updatedStartPosX });
         this.setState({ yPosition: this.state.updatedStartPosY });
-        this.setState({ xVelocity: this.props.startVelX ?? 0 });
-        this.setState({ yVelocity: this.props.startVelY ?? 0 });
-        this.props.dataDoc.pendulum_angle = this.props.dataDoc.start_PendulumAngle;
-        this.props.dataDoc.updatedForces = this.props.dataDoc.start_Forces;
-        this.props.dataDoc.updatedForces2 = this.props.dataDoc.start_Forces2;
+        this.setState({ xVelocity: this.props.startVelX });
+        this.setState({ yVelocity: this.props.startVelY });
+        this.props.dataDoc.pendulum_angle = this.props.startPendulumAngle;
+        this.props.dataDoc.mass1_forcesUpdated = this.props.dataDoc.mass1_forcesStart;
+        this.props.dataDoc.mass2_forcesUpdated = this.props.dataDoc.mass2_forcesStart;
         if (this.props.color == 'red') {
-            this.props.dataDoc.position_XDisplay = this.state.updatedStartPosX;
-            this.props.dataDoc.position_YDisplay = this.state.updatedStartPosY;
-            this.props.dataDoc.velocity_XDisplay = this.props.startVelX ?? 0;
-            this.props.dataDoc.velocity_YDisplay = this.props.startVelY ?? 0;
-            this.props.dataDoc.acceleration_XDisplay = 0;
-            this.props.dataDoc.acceleration_YDisplay = 0;
+            this.props.dataDoc.mass1_positionX = this.state.updatedStartPosX;
+            this.props.dataDoc.mass1_positionY = this.state.updatedStartPosY;
+            this.props.dataDoc.mass1_velocityX = this.props.startVelX;
+            this.props.dataDoc.mass1_velocityY = this.props.startVelY;
+            this.props.dataDoc.mass1_accelerationX = 0;
+            this.props.dataDoc.mass1_accelerationY = 0;
         } else {
-            this.props.dataDoc.position_XDisplay2 = this.state.updatedStartPosX;
-            this.props.dataDoc.position_YDisplay2 = this.state.updatedStartPosY;
-            this.props.dataDoc.velocity_XDisplay2 = this.props.startVelX ?? 0;
-            this.props.dataDoc.velocity_YDisplay2 = this.props.startVelY ?? 0;
-            this.props.dataDoc.acceleration_XDisplay2 = 0;
-            this.props.dataDoc.acceleration_YDisplay2 = 0;
+            this.props.dataDoc.mass2_positionX = this.state.updatedStartPosX;
+            this.props.dataDoc.mass2_positionY = this.state.updatedStartPosY;
+            this.props.dataDoc.mass2_velocityX = this.props.startVelX;
+            this.props.dataDoc.mass2_velocityY = this.props.startVelY;
+            this.props.dataDoc.mass2_accelerationX = 0;
+            this.props.dataDoc.mass2_accelerationY = 0;
         }
-        this.setState({ angleLabel: Math.round(NumCast(this.props.dataDoc.pendulum_angle) ?? 0 * 100) / 100 });
+        this.setState({ angleLabel: Math.round(this.props.pendulumAngle * 100) / 100 });
     };
 
     // Compute x acceleration from forces, F=ma
@@ -618,7 +621,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             this.setState({ yVelocity: -this.state.yVelocity });
                         } else {
                             this.setState({ yVelocity: 0 });
-                            if (this.props.dataDoc.simulation_Type != 'Two Weights') {
+                            if (this.props.simulationType != 'Two Weights') {
                                 const forceOfGravity: IForce = {
                                     description: 'Gravity',
                                     magnitude: Math.abs(this.props.gravity) * this.props.mass,
@@ -631,8 +634,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                     directionInDegrees: wall.angleInDegrees + 90,
                                     component: false,
                                 };
-                                this.props.dataDoc.updatedForces = [forceOfGravity, normalForce];
-                                if (this.props.dataDoc.simulation_Type == 'Inclined Plane') {
+                                this.props.dataDoc.mass1_forcesUpdated = [forceOfGravity, normalForce];
+                                if (this.props.simulationType == 'Inclined Plane') {
                                     const forceOfGravityC: IForce = {
                                         description: 'Gravity',
                                         magnitude: Math.abs(this.props.gravity) * this.props.mass,
@@ -681,12 +684,12 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         const newYVel = currentYVel + deltaYVel * dt;
         const newDeltaXPos = newXVel;
         const newDeltaYPos = newYVel;
-        let forces = this.props.updatedForces;
-        if (this.props.dataDoc.simulation_Type == 'Pendulum') {
+        let forces = this.props.forcesUpdated;
+        if (this.props.simulationType == 'Pendulum') {
             forces = this.getNewPendulumForces(newXPos, newYPos, newXVel, newYVel);
-        } else if (this.props.dataDoc.simulation_Type == 'Spring') {
+        } else if (this.props.simulationType == 'Spring') {
             forces = this.getNewSpringForces(newYPos);
-        } else if (this.props.dataDoc.simulation_Type == 'Circular Motion') {
+        } else if (this.props.simulationType == 'Circular Motion') {
             forces = this.getNewCircularMotionForces(newXPos, newYPos);
         }
         const newDeltaXVel = this.getNewAccelerationX(forces);
@@ -711,12 +714,12 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         let yPos = this.state.yPosition;
         let xVel = this.state.xVelocity;
         let yVel = this.state.yVelocity;
-        let forces: IForce[] = this.props.dataDoc.updatedForces;
-        if (this.props.dataDoc.simulation_Type == 'Pendulum') {
+        let forces: IForce[] = this.props.dataDoc.mass1_forcesUpdated;
+        if (this.props.simulationType == 'Pendulum') {
             forces = this.getNewPendulumForces(xPos, yPos, xVel, yVel);
-        } else if (this.props.dataDoc.simulation_Type == 'Spring') {
+        } else if (this.props.simulationType == 'Spring') {
             forces = this.getNewSpringForces(yPos);
-        } else if (this.props.dataDoc.simulation_Type == 'Circular Motion') {
+        } else if (this.props.simulationType == 'Circular Motion') {
             forces = this.getNewCircularMotionForces(xPos, yPos);
         }
         const xAcc = this.getNewAccelerationX(forces);
@@ -733,7 +736,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             yPos += ((this.props.timestepSize * 1.0) / 6.0) * (k1.deltaYPos + 2 * (k2.deltaYPos + k3.deltaYPos) + k4.deltaYPos);
         }
         // make sure harmonic motion maintained and errors don't propagate
-        if (this.props.dataDoc.simulation_Type == 'Spring') {
+        if (this.props.simulationType == 'Spring') {
             if (startYVel < 0 && yVel > 0 && yPos < this.props.springRestLength) {
                 let equilibriumPos = this.props.springRestLength + (this.props.mass * Math.abs(this.props.gravity)) / this.props.springConstant;
                 let amplitude = Math.abs(equilibriumPos - this.props.springStartLength);
@@ -744,7 +747,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 yPos = equilibriumPos + amplitude;
             }
         }
-        if (this.props.dataDoc.simulation_Type == 'Pendulum') {
+        if (this.props.simulationType == 'Pendulum') {
             let startX = this.state.updatedStartPosX;
             if (startXVel <= 0 && xVel > 0) {
                 xPos = this.state.updatedStartPosX;
@@ -760,7 +763,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 yPos = this.props.startPosY;
             }
         }
-        if (this.props.dataDoc.simulation_Type == 'One Weight') {
+        if (this.props.simulationType == 'One Weight') {
             if (yPos < this.state.maxPosYConservation) {
                 yPos = this.state.maxPosYConservation;
             }
@@ -769,18 +772,18 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         this.setState({ yVelocity: yVel });
         this.setState({ xPosition: xPos });
         this.setState({ yPosition: yPos });
-        let forcesn = this.props.dataDoc.updatedForces;
-        if (this.props.dataDoc.simulation_Type == 'Pendulum') {
+        let forcesn = this.props.dataDoc.mass1_forcesUpdated;
+        if (this.props.simulationType == 'Pendulum') {
             forcesn = this.getNewPendulumForces(xPos, yPos, xVel, yVel);
-        } else if (this.props.dataDoc.simulation_Type == 'Spring') {
+        } else if (this.props.simulationType == 'Spring') {
             forcesn = this.getNewSpringForces(yPos);
-        } else if (this.props.dataDoc.simulation_Type == 'Circular Motion') {
+        } else if (this.props.simulationType == 'Circular Motion') {
             forcesn = this.getNewCircularMotionForces(xPos, yPos);
         }
-        this.props.dataDoc.updatedForces = forcesn;
+        this.props.dataDoc.mass1_forcesUpdated = forcesn;
 
         // set component forces if they change
-        if (this.props.dataDoc.simulation_Type == 'Pendulum') {
+        if (this.props.simulationType == 'Pendulum') {
             let x = this.props.xMax / 2 - xPos - this.props.radius;
             let y = yPos + this.props.radius + 5;
             let angle = (Math.atan(y / x) * 180) / Math.PI;
@@ -851,7 +854,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             } else if (newX < 10) {
                                 newX = 10;
                             }
-                            if (this.props.dataDoc.simulation_Type == 'Suspension') {
+                            if (this.props.simulationType == 'Suspension') {
                                 if (newX < (this.props.xMax + this.props.xMin) / 4 - this.props.radius - 15) {
                                     newX = (this.props.xMax + this.props.xMin) / 4 - this.props.radius - 15;
                                 } else if (newX > (3 * (this.props.xMax + this.props.xMin)) / 4 - this.props.radius / 2 - 15) {
@@ -860,13 +863,13 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             }
 
                             this.setState({ yPosition: newY });
-                            this.props.dataDoc.position_YDisplay = Math.round((this.props.yMax - 2 * this.props.radius - newY + 5) * 100) / 100;
-                            if (this.props.dataDoc.simulation_Type != 'Pulley') {
+                            this.props.dataDoc.mass1_positionY = Math.round((this.props.yMax - 2 * this.props.radius - newY + 5) * 100) / 100;
+                            if (this.props.simulationType != 'Pulley') {
                                 this.setState({ xPosition: newX });
-                                this.props.dataDoc.position_XDisplay = newX;
+                                this.props.dataDoc.mass1_positionX = newX;
                             }
-                            if (this.props.dataDoc.simulation_Type != 'Suspension') {
-                                if (this.props.dataDoc.simulation_Type != 'Pulley') {
+                            if (this.props.simulationType != 'Suspension') {
+                                if (this.props.simulationType != 'Pulley') {
                                     this.setState({ updatedStartPosX: newX });
                                 }
                                 this.setState({ updatedStartPosY: newY });
@@ -878,7 +881,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                     }}
                     onPointerUp={e => {
                         if (this.state.dragging) {
-                            if (this.props.dataDoc.simulation_Type != 'Pendulum' && this.props.dataDoc.simulation_Type != 'Suspension') {
+                            if (this.props.simulationType != 'Pendulum' && this.props.simulationType != 'Suspension') {
                                 this.resetEverything();
                             }
                             this.setState({ dragging: false });
@@ -895,10 +898,10 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             } else if (newX < 10) {
                                 newX = 10;
                             }
-                            if (this.props.dataDoc.simulation_Type == 'Spring') {
-                                this.props.dataDoc.springStartLength = newY;
+                            if (this.props.simulationType == 'Spring') {
+                                this.props.dataDoc.spring_lengthStart = newY;
                             }
-                            if (this.props.dataDoc.simulation_Type == 'Suspension') {
+                            if (this.props.simulationType == 'Suspension') {
                                 let x1rod = (this.props.xMax + this.props.xMin) / 2 - this.props.radius - this.props.yMin - 200;
                                 let x2rod = (this.props.xMax + this.props.xMin) / 2 + this.props.yMin + 200 + this.props.radius;
                                 let deltaX1 = this.state.xPosition + this.props.radius - x1rod;
@@ -928,7 +931,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                     directionInDegrees: 270,
                                     component: false,
                                 };
-                                this.props.dataDoc.updatedForces = [tensionForce1, tensionForce2, grav];
+                                this.props.dataDoc.mass1_forcesUpdated = [tensionForce1, tensionForce2, grav];
                             }
                         }
                     }}>
@@ -936,7 +939,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                         <p className="weightLabel">{this.props.mass} kg</p>
                     </div>
                 </div>
-                {this.props.dataDoc.simulation_Type == 'Spring' && (
+                {this.props.simulationType == 'Spring' && (
                     <div
                         className="spring"
                         style={{
@@ -967,7 +970,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                     </div>
                 )}
 
-                {this.props.dataDoc.simulation_Type == 'Pulley' && (
+                {this.props.simulationType == 'Pulley' && (
                     <div
                         className="rod"
                         style={{
@@ -981,7 +984,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                         </svg>
                     </div>
                 )}
-                {this.props.dataDoc.simulation_Type == 'Pulley' && (
+                {this.props.simulationType == 'Pulley' && (
                     <div
                         className="wheel"
                         style={{
@@ -995,7 +998,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                         </svg>
                     </div>
                 )}
-                {this.props.dataDoc.simulation_Type == 'Suspension' && (
+                {this.props.simulationType == 'Suspension' && (
                     <div
                         className="rod"
                         style={{
@@ -1060,7 +1063,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                         </p>
                     </div>
                 )}
-                {this.props.dataDoc.simulation_Type == 'Circular Motion' && (
+                {this.props.simulationType == 'Circular Motion' && (
                     <div
                         className="rod"
                         style={{
@@ -1081,7 +1084,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                         </svg>
                     </div>
                 )}
-                {this.props.dataDoc.simulation_Type == 'Pendulum' && (
+                {this.props.simulationType == 'Pendulum' && (
                     <div
                         className="rod"
                         style={{
@@ -1118,7 +1121,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                         )}
                     </div>
                 )}
-                {this.props.dataDoc.simulation_Type == 'Inclined Plane' && (
+                {this.props.simulationType == 'Inclined Plane' && (
                     <div>
                         <div style={{ position: 'absolute', left: '0', top: '0' }}>
                             <svg width={this.props.xMax + 'px'} height={this.props.yMax + 'px'}>
@@ -1154,8 +1157,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                 <line
                                     x1={this.state.xPosition + this.props.radius}
                                     y1={this.state.yPosition + this.props.radius}
-                                    x2={this.state.xPosition + this.props.radius + this.getNewAccelerationX(this.props.updatedForces) * 15}
-                                    y2={this.state.yPosition + this.props.radius + this.getNewAccelerationY(this.props.updatedForces) * 15}
+                                    x2={this.state.xPosition + this.props.radius + this.getNewAccelerationX(this.props.forcesUpdated) * 15}
+                                    y2={this.state.yPosition + this.props.radius + this.getNewAccelerationY(this.props.forcesUpdated) * 15}
                                     stroke={'green'}
                                     strokeWidth="5"
                                     markerEnd="url(#accArrow)"
@@ -1282,8 +1285,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                     })}
                 {!this.state.dragging &&
                     this.props.showForces &&
-                    this.props.updatedForces &&
-                    this.props.updatedForces.map((force, index) => {
+                    this.props.forcesUpdated &&
+                    this.props.forcesUpdated.map((force, index) => {
                         if (force.magnitude < this.epsilon) {
                             return;
                         }
-- 
cgit v1.2.3-70-g09d2


From 4832bb8e9589a786ac08d24b6e55bb23d19ce855 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 23 May 2023 11:31:49 -0400
Subject: fixed physics force assignment to fields

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 164 ++++++++++-----------
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   |  66 ++++-----
 2 files changed, 107 insertions(+), 123 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 0f5bdf316..9d75944f4 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -102,26 +102,21 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         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.simulation_gravity = NumCast(this.dataDoc.simulation_gravity, -9.81);
         this.dataDoc.mass1 = NumCast(this.dataDoc.mass1, 1);
         this.dataDoc.simulation_mode = 'Freeform';
         this.dataDoc.simulation_showComponentForces = this.dataDoc.simulation_showComponentForces ?? false;
         this.dataDoc.simulation_speed = NumCast(this.dataDoc.simulation_speed, 2);
         this.dataDoc.simulation_type = StrCast(this.dataDoc.simulation_type, 'Inclined Plane');
-        this.dataDoc.mass1_forcesStart = this.dataDoc.mass1_forcesStart ?? [];
         this.dataDoc.mass1_positionXstart = this.dataDoc.mass1_positionXstart ?? Math.round((this.xMax * 0.5 - 200) * 10) / 10;
         this.dataDoc.mass1_positionYstart = this.dataDoc.mass1_positionYstart ?? this.getDisplayYPos((400 - 0.08 * this.layoutDoc._height) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26));
-        this.dataDoc.mass1_forcesUpdated = this.dataDoc.mass1_forcesUpdated ?? [];
 
         // 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.questionPartOne = '';
         this.dataDoc.questionPartTwo = '';
-        this.dataDoc.selectedSolutions = [];
         this.dataDoc.selectedQuestion = this.dataDoc.selectedQuestion ?? questions.inclinePlane[0];
         // this.dataDoc.sketching = this.dataDoc.sketching ?? false;
 
@@ -182,33 +177,33 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
                 this.dataDoc.mass1_positionY = this.getDisplayYPos(this.yMin + 0.08 * this.layoutDoc[HeightSym]());
                 this.dataDoc.mass1_positionX = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
-                this.dataDoc.mass1_forcesUpdated = [
+                this.dataDoc.mass1_forcesUpdated = JSON.stringify([
                     {
                         description: 'Gravity',
                         magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
                         directionInDegrees: 270,
                         component: false,
                     },
-                ];
-                this.dataDoc.mass1_forcesStart = [
+                ]);
+                this.dataDoc.mass1_forcesStart = JSON.stringify([
                     {
                         description: 'Gravity',
                         magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
                         directionInDegrees: 270,
                         component: false,
                     },
-                ];
+                ]);
                 this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
             } else if (simulationType == 'Inclined Plane') {
                 this.changeWedgeBasedOnNewAngle(26);
-                this.dataDoc.mass1_forcesStart = [
+                this.dataDoc.mass1_forcesStart = JSON.stringify([
                     {
                         description: 'Gravity',
                         magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
                         directionInDegrees: 270,
                         component: false,
                     },
-                ];
+                ]);
                 this.updateForcesWithFriction(NumCast(this.dataDoc.coefficientOfStaticFriction));
             } else if (simulationType == 'Pendulum') {
                 this.setupPendulum();
@@ -234,8 +229,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.setupSpring();
                 // TODO - spring review problems
             } else if (simulationType == 'Inclined Plane') {
-                this.dataDoc.mass1_forcesUpdated = [];
-                this.dataDoc.mass1_forcesStart = [];
+                this.dataDoc.mass1_forcesUpdated = '';
+                this.dataDoc.mass1_forcesStart = '';
             } else if (simulationType == 'Pendulum') {
                 this.setupPendulum();
                 // TODO - pendulum review problems
@@ -268,7 +263,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.dataDoc.mass1_positionYstart = this.yMax - 100;
                 this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
                 this.dataDoc.tutorial = tutorials.freeWeight;
-                this.dataDoc.mass1_forcesStart = this.getForceFromJSON(tutorials.freeWeight.steps[0].forces);
+                this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.freeWeight.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.freeWeight.steps[0].showMagnitude;
             } else if (this.dataDoc.simulation_type == 'Spring') {
                 this.dataDoc.simulation_showForces = true;
@@ -276,7 +271,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.dataDoc.mass1_positionYstart = this.yMin + 200 + 19.62;
                 this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
                 this.dataDoc.tutorial = tutorials.spring;
-                this.dataDoc.mass1_forcesStart = this.getForceFromJSON(tutorials.spring.steps[0].forces);
+                this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.spring.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.spring.steps[0].showMagnitude;
             } else if (this.dataDoc.simulation_type == 'Pendulum') {
                 this.dataDoc.simulation_showForces = true;
@@ -289,7 +284,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.dataDoc.mass1_positionXstart = xPos;
                 this.dataDoc.mass1_positionYstart = yPos;
                 this.dataDoc.tutorial = tutorials.pendulum;
-                this.dataDoc.mass1_forcesStart = this.getForceFromJSON(tutorials.pendulum.steps[0].forces);
+                this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.pendulum.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.pendulum.steps[0].showMagnitude;
                 this.dataDoc.pendulum_angle = 30;
                 this.dataDoc.pendulum_length = 300;
@@ -300,25 +295,25 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.dataDoc.wedge_angle = 26;
                 this.changeWedgeBasedOnNewAngle(26);
                 this.dataDoc.tutorial = tutorials.inclinePlane;
-                this.dataDoc.mass1_forcesStart = this.getForceFromJSON(tutorials.inclinePlane.steps[0].forces);
+                this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.inclinePlane.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.inclinePlane.steps[0].showMagnitude;
             } else if (this.dataDoc.simulation_type == 'Circular Motion') {
                 this.dataDoc.simulation_showForces = true;
                 this.setupCircular(40);
                 this.dataDoc.tutorial = tutorials.circular;
-                this.dataDoc.mass1_forcesStart = this.getForceFromJSON(tutorials.circular.steps[0].forces);
+                this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.circular.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.circular.steps[0].showMagnitude;
             } else if (this.dataDoc.simulation_type == 'Pulley') {
                 this.dataDoc.simulation_showForces = true;
                 this.setupPulley();
                 this.dataDoc.tutorial = tutorials.pulley;
-                this.dataDoc.mass1_forcesStart = this.getForceFromJSON(tutorials.pulley.steps[0].forces);
+                this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.pulley.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.pulley.steps[0].showMagnitude;
             } else if (this.dataDoc.simulation_type == 'Suspension') {
                 this.dataDoc.simulation_showForces = true;
                 this.setupSuspension();
                 this.dataDoc.tutorial = tutorials.suspension;
-                this.dataDoc.mass1_forcesStart = this.getForceFromJSON(tutorials.suspension.steps[0].forces);
+                this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.suspension.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.suspension.steps[0].showMagnitude;
             }
             this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
@@ -385,13 +380,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             component: false,
         };
         if (coefficient != 0) {
-            this.dataDoc.mass1_forcesStart = [gravityForce, normalForce, frictionForce];
-            this.dataDoc.mass1_forcesUpdated = [gravityForce, normalForce, frictionForce];
-            this.dataDoc.componentForces = [frictionForceComponent, normalForceComponent, gravityParallel, gravityPerpendicular];
+            this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce, normalForce, frictionForce]);
+            this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce, normalForce, frictionForce]);
+            this.dataDoc.mass1_componentForces = JSON.stringify([frictionForceComponent, normalForceComponent, gravityParallel, gravityPerpendicular]);
         } else {
-            this.dataDoc.mass1_forcesStart = [gravityForce, normalForce];
-            this.dataDoc.mass1_forcesUpdated = [gravityForce, normalForce];
-            this.dataDoc.componentForces = [normalForceComponent, gravityParallel, gravityPerpendicular];
+            this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce, normalForce]);
+            this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce, normalForce]);
+            this.dataDoc.mass1_componentForces = JSON.stringify([normalForceComponent, gravityParallel, gravityPerpendicular]);
         }
     };
 
@@ -661,8 +656,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             directionInDegrees: 90,
             component: false,
         };
-        this.dataDoc.mass1_forcesUpdated = [tensionForce];
-        this.dataDoc.mass1_forcesStart = [tensionForce];
+        this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce]);
+        this.dataDoc.mass1_forcesStart = JSON.stringify([tensionForce]);
         this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
     };
 
@@ -703,8 +698,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             component: true,
         };
 
-        this.dataDoc.componentForces = [tensionComponent, gravityParallel, gravityPerpendicular];
-        this.dataDoc.mass1_forcesUpdated = [
+        this.dataDoc.mass1_componentForces = JSON.stringify([tensionComponent, gravityParallel, gravityPerpendicular]);
+        this.dataDoc.mass1_forcesUpdated = JSON.stringify([
             {
                 description: 'Gravity',
                 magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity),
@@ -712,8 +707,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 component: false,
             },
             forceOfTension,
-        ];
-        this.dataDoc.mass1_forcesStart = [
+        ]);
+        this.dataDoc.mass1_forcesStart = JSON.stringify([
             {
                 description: 'Gravity',
                 magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity),
@@ -721,7 +716,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 component: false,
             },
             forceOfTension,
-        ];
+        ]);
         this.dataDoc.pendulum_angleStart = 30;
         this.dataDoc.pendulum_angle = 30;
         this.dataDoc.pendulum_length = 300;
@@ -738,8 +733,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             directionInDegrees: 270,
             component: false,
         };
-        this.dataDoc.mass1_forcesUpdated = [gravityForce];
-        this.dataDoc.mass1_forcesStart = [gravityForce];
+        this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce]);
+        this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce]);
         this.dataDoc.mass1_positionXstart = this.xMax / 2 - 0.08 * this.layoutDoc[HeightSym]();
         this.dataDoc.mass1_positionYstart = 200;
         this.dataDoc.spring_constant = 0.5;
@@ -775,8 +770,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             directionInDegrees: 270,
             component: false,
         };
-        this.dataDoc.mass1_forcesUpdated = [tensionForce1, tensionForce2, grav];
-        this.dataDoc.mass1_forcesStart = [tensionForce1, tensionForce2, grav];
+        this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, grav]);
+        this.dataDoc.mass1_forcesStart = JSON.stringify([tensionForce1, tensionForce2, grav]);
         this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
     };
 
@@ -814,39 +809,21 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             component: false,
         };
 
-        this.dataDoc.mass1_forcesUpdated = [gravityForce1, tensionForce1];
-        this.dataDoc.mass1_forcesStart = [gravityForce1, tensionForce1];
+        this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce1, tensionForce1]);
+        this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce1, tensionForce1]);
         this.dataDoc.mass2_positionYstart = (this.yMax + this.yMin) / 2;
         this.dataDoc.mass2_positionXstart = (this.xMin + this.xMax) / 2 + 5;
         this.dataDoc.mass2_positionY = this.getDisplayYPos((this.yMax + this.yMin) / 2);
         this.dataDoc.mass2_positionX = (this.xMin + this.xMax) / 2 + 5;
-        this.dataDoc.mass2_forcesUpdated = [gravityForce2, tensionForce2];
-        this.dataDoc.mass2_forcesStart = [gravityForce2, tensionForce2];
+        this.dataDoc.mass2_forcesUpdated = JSON.stringify([gravityForce2, tensionForce2]);
+        this.dataDoc.mass2_forcesStart = JSON.stringify([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;
-    };
+    public static parseJSON(json: string) {
+        return !json ? [] : (JSON.parse(json) as IForce[]);
+    }
 
     // Handle force change in review mode
     updateReviewModeValues = () => {
@@ -868,10 +845,21 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             directionInDegrees: NumCast(this.dataDoc.review_StaticAngle),
             component: false,
         };
-        this.dataDoc.mass1_forcesStart = [forceOfGravityReview, normalForceReview, staticFrictionForceReview];
-        this.dataDoc.mass1_forcesUpdated = [forceOfGravityReview, normalForceReview, staticFrictionForceReview];
+        this.dataDoc.mass1_forcesStart = JSON.stringify([forceOfGravityReview, normalForceReview, staticFrictionForceReview]);
+        this.dataDoc.mass1_forcesUpdated = JSON.stringify([forceOfGravityReview, normalForceReview, staticFrictionForceReview]);
     };
 
+    componentForces1 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass1_componentForces));
+    setComponentForces1 = (forces: IForce[]) => (this.dataDoc.mass1_componentForces = JSON.stringify(forces));
+    componentForces2 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass2_componentForces));
+    setComponentForces2 = (forces: IForce[]) => (this.dataDoc.mass2_componentForces = JSON.stringify(forces));
+    startForces1 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass1_forcesStart));
+    startForces2 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass2_forcesStart));
+    forcesUpdated1 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass1_forcesUpdated));
+    setForcesUpdated1 = (forces: IForce[]) => (this.dataDoc.mass1_forcesUpdated = JSON.stringify(forces));
+    forcesUpdated2 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass2_forcesUpdated));
+    setForcesUpdated2 = (forces: IForce[]) => (this.dataDoc.mass2_forcesUpdated = JSON.stringify(forces));
+
     render() {
         return (
             <div className="physicsSimApp">
@@ -900,7 +888,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     adjustPendulumLength={NumCast(this.dataDoc.pendulum_length_adjust)}
                                     gravity={this.gravity}
                                     circularMotionRadius={this.circularMotionRadius}
-                                    componentForces={this.dataDoc.componentForces}
+                                    componentForces={this.componentForces1}
+                                    setComponentForces={this.setComponentForces1}
                                     showComponentForces={BoolCast(this.dataDoc.simulation_showComponentForces)}
                                     color={'red'}
                                     coefficientOfKineticFriction={NumCast(this.dataDoc.coefficientOfKineticFriction)}
@@ -925,15 +914,16 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     springConstant={NumCast(this.dataDoc.spring_constant)}
                                     springStartLength={NumCast(this.dataDoc.spring_lengthStart)}
                                     springRestLength={NumCast(this.dataDoc.spring_lengthRest)}
-                                    startForces={this.dataDoc.mass1_forcesStart}
+                                    startForces={this.startForces1}
                                     startPosX={NumCast(this.dataDoc.mass1_positionXstart)}
                                     startPosY={NumCast(this.dataDoc.mass1_positionYstart)}
                                     startVelX={NumCast(this.dataDoc.mass1_velocityXstart)}
                                     startVelY={NumCast(this.dataDoc.mass1_velocityYstart)}
                                     timestepSize={0.05}
-                                    updateXmass={NumCast(this.dataDoc.mass1_xChange)}
-                                    updateYmass={NumCast(this.dataDoc.mass1_yChange)}
-                                    forcesUpdated={this.dataDoc.mass1_forcesUpdated}
+                                    updateXDisplay={NumCast(this.dataDoc.mass1_xChange)}
+                                    updateYDisplay={NumCast(this.dataDoc.mass1_yChange)}
+                                    forcesUpdated={this.forcesUpdated1}
+                                    setForcesUpdated={this.setForcesUpdated1}
                                     wedgeHeight={NumCast(this.dataDoc.wedge_height)}
                                     wedgeWidth={NumCast(this.dataDoc.wedge_width)}
                                     xMax={this.xMax}
@@ -950,7 +940,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                         adjustPendulumLength={NumCast(this.dataDoc.pendulum_length_adjust)}
                                         circularMotionRadius={this.circularMotionRadius}
                                         gravity={this.gravity}
-                                        componentForces={this.dataDoc.componentForces}
+                                        componentForces={this.componentForces2}
+                                        setComponentForces={this.setComponentForces2}
                                         showComponentForces={BoolCast(this.dataDoc.simulation_showComponentForces)}
                                         color={'blue'}
                                         coefficientOfKineticFriction={NumCast(this.dataDoc.coefficientOfKineticFriction)}
@@ -975,15 +966,16 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                         springConstant={NumCast(this.dataDoc.spring_constant)}
                                         springStartLength={NumCast(this.dataDoc.spring_lengthStart)}
                                         springRestLength={NumCast(this.dataDoc.spring_lengthRest)}
-                                        startForces={this.dataDoc.mass2_forcesStart}
+                                        startForces={this.startForces2}
                                         startPosX={NumCast(this.dataDoc.mass2_positionXstart)}
                                         startPosY={NumCast(this.dataDoc.mass2_positionYstart)}
-                                        startVelX={NumCast(this.dataDoc.mass1_velocityXstart)}
-                                        startVelY={NumCast(this.dataDoc.mass1_velocityYstart)}
+                                        startVelX={NumCast(this.dataDoc.mass2_velocityXstart)}
+                                        startVelY={NumCast(this.dataDoc.mass2_velocityYstart)}
                                         timestepSize={0.05}
-                                        updateXmass={NumCast(this.dataDoc.mass2_xChange)}
-                                        updateYmass={NumCast(this.dataDoc.mass2_yChange)}
-                                        forcesUpdated={this.dataDoc.mass2_forcesUpdated}
+                                        updateXDisplay={NumCast(this.dataDoc.mass2_xChange)}
+                                        updateYDisplay={NumCast(this.dataDoc.mass2_yChange)}
+                                        forcesUpdated={this.forcesUpdated2}
+                                        setForcesUpdated={this.setForcesUpdated2}
                                         wedgeHeight={NumCast(this.dataDoc.wedge_height)}
                                         wedgeWidth={NumCast(this.dataDoc.wedge_width)}
                                         xMax={this.xMax}
@@ -1270,8 +1262,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             step = Math.max(step, 0);
                                             step = Math.min(step, this.dataDoc.tutorial.steps.length - 1);
                                             this.dataDoc.tutorial_stepNumber = step;
-                                            this.dataDoc.mass1_forcesStart = this.getForceFromJSON(this.dataDoc.tutorial.steps[step].forces);
-                                            this.dataDoc.mass1_forcesUpdated = this.getForceFromJSON(this.dataDoc.tutorial.steps[step].forces);
+                                            this.dataDoc.mass1_forcesStart = this.dataDoc.tutorial.steps[step].forces;
+                                            this.dataDoc.mass1_forcesUpdated = this.dataDoc.tutorial.steps[step].forces;
                                             this.dataDoc.simulation_showForceMagnitudes = this.dataDoc.tutorial.steps[step].show_Magnitude;
                                         }}
                                         disabled={this.dataDoc.tutorial_stepNumber == 0}>
@@ -1289,11 +1281,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             step = Math.max(step, 0);
                                             step = Math.min(step, this.dataDoc.tutorial.steps.length - 1);
                                             this.dataDoc.tutorial_stepNumber = step;
-                                            this.dataDoc.mass1_forcesStart = this.getForceFromJSON(this.dataDoc.tutorial.steps[step].forces);
-                                            this.dataDoc.mass1_forcesUpdated = this.getForceFromJSON(this.dataDoc.tutorial.steps[step].forces);
+                                            this.dataDoc.mass1_forcesStart = this.dataDoc.tutorial.steps[step].forces;
+                                            this.dataDoc.mass1_forcesUpdated = this.dataDoc.tutorial.steps[step].forces;
                                             this.dataDoc.simulation_showForceMagnitudes = this.dataDoc.tutorial.steps[step].show_Magnitude;
                                         }}
-                                        disabled={this.dataDoc.tutorial_stepNumber == this.dataDoc.tutorial.steps.length - 1}>
+                                        disabled={this.dataDoc.tutorial_stepNumber === this.dataDoc.tutorial.steps.length - 1}>
                                         <ArrowRightIcon />
                                     </IconButton>
                                 </div>
@@ -1709,7 +1701,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     this.dataDoc.mass1_positionXstart = xPos;
                                                     this.dataDoc.mass1_positionYstart = yPos;
 
-                                                    this.dataDoc.mass1_forcesStart = [
+                                                    this.dataDoc.mass1_forcesStart = JSON.stringify([
                                                         {
                                                             description: 'Gravity',
                                                             magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
@@ -1717,8 +1709,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                             component: false,
                                                         },
                                                         forceOfTension,
-                                                    ];
-                                                    this.dataDoc.mass1_forcesUpdated = [
+                                                    ]);
+                                                    this.dataDoc.mass1_forcesUpdated = JSON.stringify([
                                                         {
                                                             description: 'Gravity',
                                                             magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
@@ -1726,8 +1718,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                             component: false,
                                                         },
                                                         forceOfTension,
-                                                    ];
-                                                    this.dataDoc.componentForces = [tensionComponent, gravityParallel, gravityPerpendicular];
+                                                    ]);
+                                                    this.dataDoc.mass1_componentForces = JSON.stringify([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;
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 1d980ebf4..94e101490 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -1,7 +1,6 @@
 import { Doc, HeightSym, WidthSym } from '../../../../fields/Doc';
 import React = require('react');
 import './PhysicsSimulationBox.scss';
-import { NumCast } from '../../../../fields/Types';
 import { computed } from 'mobx';
 
 interface IWallProps {
@@ -24,7 +23,8 @@ export interface IWeightProps {
     circularMotionRadius: number;
     coefficientOfKineticFriction: number;
     color: string;
-    componentForces: IForce[];
+    componentForces: () => IForce[];
+    setComponentForces: (x: IForce[]) => {};
     displayXVelocity: number;
     displayYVelocity: number;
     elasticCollisions: boolean;
@@ -47,7 +47,7 @@ export interface IWeightProps {
     springConstant: number;
     springRestLength: number;
     springStartLength: number;
-    startForces: IForce[];
+    startForces: () => IForce[];
     startPendulumAngle: number;
     startPosX: number;
     startPosY: number;
@@ -56,7 +56,8 @@ export interface IWeightProps {
     timestepSize: number;
     updateXDisplay: number;
     updateYDisplay: number;
-    forcesUpdated: IForce[];
+    forcesUpdated: () => IForce[];
+    setForcesUpdated: (x: IForce[]) => {};
     wallPositions: IWallProps[];
     wedgeHeight: number;
     wedgeWidth: number;
@@ -188,15 +189,15 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         this.setYVelDisplay(yVel);
         this.setXVelDisplay(xVel);
         if (this.props.color == 'red') {
-            this.props.dataDoc.mass1_accelerationY = (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated) * 100)) / 100;
-            this.props.dataDoc.mass1_accelerationX = Math.round(this.getNewAccelerationX(this.props.forcesUpdated) * 100) / 100;
+            this.props.dataDoc.mass1_accelerationY = (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated()) * 100)) / 100;
+            this.props.dataDoc.mass1_accelerationX = Math.round(this.getNewAccelerationX(this.props.forcesUpdated()) * 100) / 100;
         } else {
-            this.props.dataDoc.mass2_accelerationY = (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated) * 100)) / 100;
-            this.props.dataDoc.mass2_accelerationX = Math.round(this.getNewAccelerationX(this.props.forcesUpdated) * 100) / 100;
+            this.props.dataDoc.mass2_accelerationY = (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated()) * 100)) / 100;
+            this.props.dataDoc.mass2_accelerationX = Math.round(this.getNewAccelerationX(this.props.forcesUpdated()) * 100) / 100;
         }
 
-        this.setState({ xAccel: Math.round(this.getNewAccelerationX(this.props.forcesUpdated) * 100) / 100 });
-        this.setState({ yAccel: (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated) * 100)) / 100 });
+        this.setState({ xAccel: Math.round(this.getNewAccelerationX(this.props.forcesUpdated()) * 100) / 100 });
+        this.setState({ yAccel: (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated()) * 100)) / 100 });
     };
 
     componentDidUpdate(prevProps: Readonly<IWeightProps>, prevState: Readonly<IState>, snapshot?: any): void {
@@ -265,13 +266,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             }
         }
 
-        // Prevent bug when switching between sims
-        if (prevProps.startForces != this.props.startForces) {
-            this.setState({ xVelocity: this.props.startVelX });
-            this.setState({ yVelocity: this.props.startVelY });
-            this.setDisplayValues();
-        }
-
         // Make sure weight doesn't go above max height
         if ((prevState.updatedStartPosY != this.state.updatedStartPosY || prevProps.startVelY != this.props.startVelY) && !isNaN(this.state.updatedStartPosY) && !isNaN(this.props.startVelY)) {
             if (this.props.simulationType == 'One Weight') {
@@ -370,11 +364,11 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                     component: false,
                 };
                 if (this.props.coefficientOfKineticFriction != 0) {
-                    this.props.dataDoc.mass1_forcesUpdated = [gravityForce, normalForce, frictionForce];
-                    this.props.dataDoc.componentForces = [frictionForceComponent, normalForceComponent, gravityParallel, gravityPerpendicular];
+                    this.props.setForcesUpdated([gravityForce, normalForce, frictionForce]);
+                    this.props.setComponentForces([frictionForceComponent, normalForceComponent, gravityParallel, gravityPerpendicular]);
                 } else {
-                    this.props.dataDoc.mass1_forcesUpdated = [gravityForce, normalForce];
-                    this.props.dataDoc.componentForces = [normalForceComponent, gravityParallel, gravityPerpendicular];
+                    this.props.setForcesUpdated([gravityForce, normalForce]);
+                    this.props.setComponentForces([normalForceComponent, gravityParallel, gravityPerpendicular]);
                 }
             }
         }
@@ -444,8 +438,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         this.setState({ xVelocity: this.props.startVelX });
         this.setState({ yVelocity: this.props.startVelY });
         this.props.dataDoc.pendulum_angle = this.props.startPendulumAngle;
-        this.props.dataDoc.mass1_forcesUpdated = this.props.dataDoc.mass1_forcesStart;
-        this.props.dataDoc.mass2_forcesUpdated = this.props.dataDoc.mass2_forcesStart;
+        this.props.setForcesUpdated(this.props.startForces());
         if (this.props.color == 'red') {
             this.props.dataDoc.mass1_positionX = this.state.updatedStartPosX;
             this.props.dataDoc.mass1_positionY = this.state.updatedStartPosY;
@@ -634,7 +627,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                     directionInDegrees: wall.angleInDegrees + 90,
                                     component: false,
                                 };
-                                this.props.dataDoc.mass1_forcesUpdated = [forceOfGravity, normalForce];
+                                this.props.setForcesUpdated([forceOfGravity, normalForce]);
                                 if (this.props.simulationType == 'Inclined Plane') {
                                     const forceOfGravityC: IForce = {
                                         description: 'Gravity',
@@ -648,7 +641,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                         directionInDegrees: wall.angleInDegrees + 90,
                                         component: true,
                                     };
-                                    this.props.dataDoc.componentForces = [forceOfGravityC, normalForceC];
+                                    this.props.setComponentForces([forceOfGravityC, normalForceC]);
                                 }
                             }
                         }
@@ -684,7 +677,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         const newYVel = currentYVel + deltaYVel * dt;
         const newDeltaXPos = newXVel;
         const newDeltaYPos = newYVel;
-        let forces = this.props.forcesUpdated;
+        let forces = this.props.forcesUpdated();
         if (this.props.simulationType == 'Pendulum') {
             forces = this.getNewPendulumForces(newXPos, newYPos, newXVel, newYVel);
         } else if (this.props.simulationType == 'Spring') {
@@ -714,7 +707,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         let yPos = this.state.yPosition;
         let xVel = this.state.xVelocity;
         let yVel = this.state.yVelocity;
-        let forces: IForce[] = this.props.dataDoc.mass1_forcesUpdated;
+        let forces = this.props.forcesUpdated();
         if (this.props.simulationType == 'Pendulum') {
             forces = this.getNewPendulumForces(xPos, yPos, xVel, yVel);
         } else if (this.props.simulationType == 'Spring') {
@@ -772,7 +765,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         this.setState({ yVelocity: yVel });
         this.setState({ xPosition: xPos });
         this.setState({ yPosition: yPos });
-        let forcesn = this.props.dataDoc.mass1_forcesUpdated;
+        let forcesn = this.props.forcesUpdated();
         if (this.props.simulationType == 'Pendulum') {
             forcesn = this.getNewPendulumForces(xPos, yPos, xVel, yVel);
         } else if (this.props.simulationType == 'Spring') {
@@ -780,7 +773,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         } else if (this.props.simulationType == 'Circular Motion') {
             forcesn = this.getNewCircularMotionForces(xPos, yPos);
         }
-        this.props.dataDoc.mass1_forcesUpdated = forcesn;
+        this.props.setForcesUpdated(forcesn);
 
         // set component forces if they change
         if (this.props.simulationType == 'Pendulum') {
@@ -821,7 +814,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 gravityPerpendicular.magnitude = Math.abs(Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180));
                 gravityPerpendicular.directionInDegrees = 180 - (90 - angle);
             }
-            this.props.dataDoc.componentForces = [tensionComponent, gravityParallel, gravityPerpendicular];
+            this.props.setComponentForces([tensionComponent, gravityParallel, gravityPerpendicular]);
         }
     };
 
@@ -931,7 +924,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                     directionInDegrees: 270,
                                     component: false,
                                 };
-                                this.props.dataDoc.mass1_forcesUpdated = [tensionForce1, tensionForce2, grav];
+                                this.props.setForcesUpdated([tensionForce1, tensionForce2, grav]);
                             }
                         }
                     }}>
@@ -1115,7 +1108,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                         top: 30 + 'px',
                                         backgroundColor: this.labelBackgroundColor,
                                     }}>
-                                    {Math.round(this.props.pendulum_angle * 100) / 100}°
+                                    {Math.round(this.props.pendulumAngle * 100) / 100}°
                                 </p>
                             </div>
                         )}
@@ -1157,8 +1150,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                 <line
                                     x1={this.state.xPosition + this.props.radius}
                                     y1={this.state.yPosition + this.props.radius}
-                                    x2={this.state.xPosition + this.props.radius + this.getNewAccelerationX(this.props.forcesUpdated) * 15}
-                                    y2={this.state.yPosition + this.props.radius + this.getNewAccelerationY(this.props.forcesUpdated) * 15}
+                                    x2={this.state.xPosition + this.props.radius + this.getNewAccelerationX(this.props.forcesUpdated()) * 15}
+                                    y2={this.state.yPosition + this.props.radius + this.getNewAccelerationY(this.props.forcesUpdated()) * 15}
                                     stroke={'green'}
                                     strokeWidth="5"
                                     markerEnd="url(#accArrow)"
@@ -1220,7 +1213,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 )}
                 {!this.state.dragging &&
                     this.props.showComponentForces &&
-                    this.props.componentForces.map((force, index) => {
+                    this.props.componentForces().map((force, index) => {
                         if (force.magnitude < this.epsilon) {
                             return;
                         }
@@ -1285,8 +1278,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                     })}
                 {!this.state.dragging &&
                     this.props.showForces &&
-                    this.props.forcesUpdated &&
-                    this.props.forcesUpdated.map((force, index) => {
+                    this.props.forcesUpdated().map((force, index) => {
                         if (force.magnitude < this.epsilon) {
                             return;
                         }
-- 
cgit v1.2.3-70-g09d2


From 18e458603d1c672b412c18237be73f6581d58137 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 23 May 2023 12:49:24 -0400
Subject: more physics fixes

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      |  66 ++++++----
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   | 136 +++++++++------------
 2 files changed, 95 insertions(+), 107 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 9d75944f4..35e9c189f 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -19,7 +19,7 @@ import Weight from './PhysicsSimulationWeight';
 import React = require('react');
 import { BoolCast, NumCast, StrCast } from '../../../../fields/Types';
 import { List } from '../../../../fields/List';
-import { computed } from 'mobx';
+import { computed, trace } from 'mobx';
 
 interface IWallProps {
     length: number;
@@ -920,8 +920,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     startVelX={NumCast(this.dataDoc.mass1_velocityXstart)}
                                     startVelY={NumCast(this.dataDoc.mass1_velocityYstart)}
                                     timestepSize={0.05}
-                                    updateXDisplay={NumCast(this.dataDoc.mass1_xChange)}
-                                    updateYDisplay={NumCast(this.dataDoc.mass1_yChange)}
+                                    updateMassPosX={NumCast(this.dataDoc.mass1_xChange)}
+                                    updateMassPosY={NumCast(this.dataDoc.mass1_yChange)}
                                     forcesUpdated={this.forcesUpdated1}
                                     setForcesUpdated={this.setForcesUpdated1}
                                     wedgeHeight={NumCast(this.dataDoc.wedge_height)}
@@ -972,8 +972,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                         startVelX={NumCast(this.dataDoc.mass2_velocityXstart)}
                                         startVelY={NumCast(this.dataDoc.mass2_velocityYstart)}
                                         timestepSize={0.05}
-                                        updateXDisplay={NumCast(this.dataDoc.mass2_xChange)}
-                                        updateYDisplay={NumCast(this.dataDoc.mass2_yChange)}
+                                        updateMassPosX={NumCast(this.dataDoc.mass2_xChange)}
+                                        updateMassPosY={NumCast(this.dataDoc.mass2_yChange)}
                                         forcesUpdated={this.forcesUpdated2}
                                         setForcesUpdated={this.setForcesUpdated2}
                                         wedgeHeight={NumCast(this.dataDoc.wedge_height)}
@@ -1055,7 +1055,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                         </div>
                         {this.dataDoc.simulation_mode == 'Review' && this.dataDoc.simulation_type != 'Inclined Plane' && (
                             <div className="wordProblemBox">
-                                <p>{this.dataDoc.simulation_type} review problems in progress!</p>
+                                <p>
+                                    <>{this.dataDoc.simulation_type} review problems in progress!</>
+                                </p>
                                 <hr />
                             </div>
                         )}
@@ -1437,7 +1439,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             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'} />
+                                        <InputField label={<Box>Speed</Box>} lowerBound={1} dataDoc={this.dataDoc} prop="simulation_speed" step={1} unit={'x'} upperBound={10} value={NumCast(this.dataDoc.simulation_speed, 2)} labelWidth={'5em'} />
                                         {this.dataDoc.simulation_paused && this.dataDoc.simulation_type != 'Circular Motion' && (
                                             <InputField
                                                 label={<Box>Gravity</Box>}
@@ -1639,11 +1641,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 )}
                                 {this.dataDoc.simulation_type == 'Inclined Plane' && !this.dataDoc.simulation_paused && (
                                     <Typography>
-                                        &theta;: {Math.round(NumCast(this.dataDoc.wedge_angle) * 100) / 100}° ≈ {Math.round(((NumCast(this.dataDoc.wedge_angle) * Math.PI) / 180) * 100) / 100} rad
-                                        <br />
-                                        &mu; <sub>s</sub>: {this.dataDoc.coefficientOfStaticFriction}
-                                        <br />
-                                        &mu; <sub>k</sub>: {this.dataDoc.coefficientOfKineticFriction}
+                                        <>
+                                            &theta;: {Math.round(NumCast(this.dataDoc.wedge_angle) * 100) / 100}° ≈ {Math.round(((NumCast(this.dataDoc.wedge_angle) * 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 && (
@@ -1774,7 +1778,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 <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.mass1_positionX} m</td>
+                                                <td style={{ cursor: 'default' }}>
+                                                    <>{this.dataDoc.mass1_positionX} m</>
+                                                </td>
                                             )}{' '}
                                             {this.dataDoc.simulation_paused && this.dataDoc.simulation_type != 'Inclined Plane' && this.dataDoc.simulation_type != 'Circular Motion' && this.dataDoc.simulation_type != 'Pulley' && (
                                                 <td
@@ -1791,7 +1797,6 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                         value={NumCast(this.dataDoc.mass1_positionX)}
                                                         effect={value => {
                                                             this.dataDoc.mass1_xChange = value;
-                                                            this.dataDoc.mass1_yChange = this.dataDoc.mass1_positionY;
                                                             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;
@@ -1822,7 +1827,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                                     directionInDegrees: 270,
                                                                     component: false,
                                                                 };
-                                                                this.dataDoc.mass1_forcesUpdated = [tensionForce1, tensionForce2, grav];
+                                                                this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, grav]);
                                                             }
                                                         }}
                                                         small={true}
@@ -1847,7 +1852,6 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                         upperBound={this.yMax - 110}
                                                         value={NumCast(this.dataDoc.mass1_positionY)}
                                                         effect={value => {
-                                                            this.dataDoc.mass1_xChange = NumCast(this.dataDoc.mass1_positionX);
                                                             this.dataDoc.mass1_yChange = value;
                                                             if (this.dataDoc.simulation_type == 'Suspension') {
                                                                 let x1rod = (this.xMax + this.xMin) / 2 - this.radius - this.yMin - 200;
@@ -1879,7 +1883,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                                     directionInDegrees: 270,
                                                                     component: false,
                                                                 };
-                                                                this.dataDoc.mass1_forcesUpdated = [tensionForce1, tensionForce2, grav];
+                                                                this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, grav]);
                                                             }
                                                         }}
                                                         small={true}
@@ -1914,7 +1918,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                         step={1}
                                                         unit={'m/s'}
                                                         upperBound={50}
-                                                        value={this.dataDoc.mass1_velocityX}
+                                                        value={NumCast(this.dataDoc.mass1_velocityX)}
                                                         effect={value => {
                                                             this.dataDoc.mass1_velocityXstart = value;
                                                             this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
@@ -1924,7 +1928,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     />
                                                 </td>
                                             )}{' '}
-                                            {(!this.dataDoc.simulation_paused || this.dataDoc.simulation_type != 'One Weight') && <td style={{ cursor: 'default' }}>{this.dataDoc.mass1_velocityY} m/s</td>}{' '}
+                                            {(!this.dataDoc.simulation_paused || this.dataDoc.simulation_type != 'One Weight') && (
+                                                <td style={{ cursor: 'default' }}>
+                                                    <>{this.dataDoc.mass1_velocityY} m/s</>
+                                                </td>
+                                            )}{' '}
                                             {this.dataDoc.simulation_paused && this.dataDoc.simulation_type == 'One Weight' && (
                                                 <td
                                                     style={{
@@ -1937,11 +1945,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                         step={1}
                                                         unit={'m/s'}
                                                         upperBound={50}
-                                                        value={this.dataDoc.mass1_velocityY}
+                                                        value={NumCast(this.dataDoc.mass1_velocityY)}
                                                         effect={value => {
                                                             this.dataDoc.mass1_velocityYstart = -value;
-                                                            this.dataDoc.mass1_xChange = this.dataDoc.mass1_positionX;
-                                                            this.dataDoc.mass1_yChange = this.dataDoc.mass1_positionY;
                                                         }}
                                                         small={true}
                                                         mode={'Freeform'}
@@ -1961,10 +1967,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 <Box>Acceleration</Box>
                                             </td>
                                             <td style={{ cursor: 'default' }}>
-                                                {this.dataDoc.mass1_accelerationX} m/s<sup>2</sup>
+                                                <>
+                                                    {this.dataDoc.mass1_accelerationX} m/s<sup>2</sup>
+                                                </>
                                             </td>
                                             <td style={{ cursor: 'default' }}>
-                                                {this.dataDoc.mass1_accelerationY} m/s<sup>2</sup>
+                                                <>
+                                                    {this.dataDoc.mass1_accelerationY} m/s<sup>2</sup>
+                                                </>
                                             </td>
                                         </tr>
                                         <tr>
@@ -2004,10 +2014,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 <Box>Acceleration</Box>
                                             </td>
                                             <td style={{ cursor: 'default' }}>
-                                                {this.dataDoc.mass2_accelerationX} m/s<sup>2</sup>
+                                                <>
+                                                    {this.dataDoc.mass2_accelerationX} m/s<sup>2</sup>
+                                                </>
                                             </td>
                                             <td style={{ cursor: 'default' }}>
-                                                {this.dataDoc.mass2_accelerationY} m/s<sup>2</sup>
+                                                <>
+                                                    {this.dataDoc.mass2_accelerationY} m/s<sup>2</sup>
+                                                </>
                                             </td>
                                         </tr>
                                         <tr>
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 94e101490..025c757c9 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -1,7 +1,8 @@
+import { computed, trace } from 'mobx';
+import { observer } from 'mobx-react';
 import { Doc, HeightSym, WidthSym } from '../../../../fields/Doc';
-import React = require('react');
 import './PhysicsSimulationBox.scss';
-import { computed } from 'mobx';
+import React = require('react');
 
 interface IWallProps {
     length: number;
@@ -54,8 +55,8 @@ export interface IWeightProps {
     startVelX: number;
     startVelY: number;
     timestepSize: number;
-    updateXDisplay: number;
-    updateYDisplay: number;
+    updateMassPosX: number;
+    updateMassPosY: number;
     forcesUpdated: () => IForce[];
     setForcesUpdated: (x: IForce[]) => {};
     wallPositions: IWallProps[];
@@ -86,7 +87,7 @@ interface IState {
     xAccel: number;
     yAccel: number;
 }
-
+@observer
 export default class Weight extends React.Component<IWeightProps, IState> {
     constructor(props: any) {
         super(props);
@@ -144,63 +145,54 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     };
 
     // Helper function to go between display and real values
-    getDisplayYPos = (yPos: number) => {
-        return this.props.yMax - yPos - 2 * this.props.radius + 5;
-    };
-    getYPosFromDisplay = (yDisplay: number) => {
-        return this.props.yMax - yDisplay - 2 * this.props.radius + 5;
-    };
+    getDisplayYPos = (yPos: number) => this.props.yMax - yPos - 2 * this.props.radius + 5;
 
     // Set display values based on real values
-    setYPosDisplay = (yPos: number) => {
-        const displayPos = this.getDisplayYPos(yPos);
+    setPosition = (xPos: number | undefined, yPos: number | undefined) => {
         if (this.props.color == 'red') {
-            this.props.dataDoc.mass1_positionY = Math.round(displayPos * 100) / 100;
+            yPos !== undefined && (this.props.dataDoc.mass1_positionY = Math.round(this.getDisplayYPos(yPos) * 100) / 100);
+            xPos !== undefined && (this.props.dataDoc.mass1_positionX = Math.round(xPos * 100) / 100);
         } else {
-            this.props.dataDoc.mass2_positionY = Math.round(displayPos * 100) / 100;
+            yPos !== undefined && (this.props.dataDoc.mass2_positionY = Math.round(this.getDisplayYPos(yPos) * 100) / 100);
+            xPos !== undefined && (this.props.dataDoc.mass2_positionX = Math.round(xPos * 100) / 100);
         }
     };
-    setXPosDisplay = (xPos: number) => {
+    setVelocity = (xVel: number | undefined, yVel: number | undefined) => {
         if (this.props.color == 'red') {
-            this.props.dataDoc.mass1_positionX = Math.round(xPos * 100) / 100;
+            yVel !== undefined && (this.props.dataDoc.mass1_velocityY = (-1 * Math.round(yVel * 100)) / 100);
+            xVel !== undefined && (this.props.dataDoc.mass1_velocityX = Math.round(xVel * 100) / 100);
         } else {
-            this.props.dataDoc.mass2_positionX = Math.round(xPos * 100) / 100;
+            yVel !== undefined && (this.props.dataDoc.mass2_velocityY = (-1 * Math.round(yVel * 100)) / 100);
+            xVel !== undefined && (this.props.dataDoc.mass2_velocityX = Math.round(xVel * 100) / 100);
         }
     };
-    setYVelDisplay = (yVel: number) => {
+    setAcceleration = (xAccel: number, yAccel: number) => {
         if (this.props.color == 'red') {
-            this.props.dataDoc.mass1_velocityY = (-1 * Math.round(yVel * 100)) / 100;
+            this.props.dataDoc.mass1_accelerationY = yAccel;
+            this.props.dataDoc.mass1_accelerationX = xAccel;
         } else {
-            this.props.dataDoc.mass2_velocityY = (-1 * Math.round(yVel * 100)) / 100;
-        }
-    };
-    setXVelDisplay = (xVel: number) => {
-        if (this.props.color == 'red') {
-            this.props.dataDoc.mass1_velocityX = Math.round(xVel * 100) / 100;
-        } else {
-            this.props.dataDoc.mass2_velocityX = Math.round(xVel * 100) / 100;
+            this.props.dataDoc.mass2_accelerationY = yAccel;
+            this.props.dataDoc.mass2_accelerationX = xAccel;
         }
+
+        this.setState({ xAccel });
+        this.setState({ yAccel });
     };
 
     // Update display values when simulation updates
     setDisplayValues = (xPos: number = this.state.xPosition, yPos: number = this.state.yPosition, xVel: number = this.state.xVelocity, yVel: number = this.state.yVelocity) => {
-        this.setYPosDisplay(yPos);
-        this.setXPosDisplay(xPos);
-        this.setYVelDisplay(yVel);
-        this.setXVelDisplay(xVel);
-        if (this.props.color == 'red') {
-            this.props.dataDoc.mass1_accelerationY = (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated()) * 100)) / 100;
-            this.props.dataDoc.mass1_accelerationX = Math.round(this.getNewAccelerationX(this.props.forcesUpdated()) * 100) / 100;
-        } else {
-            this.props.dataDoc.mass2_accelerationY = (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated()) * 100)) / 100;
-            this.props.dataDoc.mass2_accelerationX = Math.round(this.getNewAccelerationX(this.props.forcesUpdated()) * 100) / 100;
-        }
-
-        this.setState({ xAccel: Math.round(this.getNewAccelerationX(this.props.forcesUpdated()) * 100) / 100 });
-        this.setState({ yAccel: (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated()) * 100)) / 100 });
+        this.setPosition(xPos, yPos);
+        this.setVelocity(xVel, yVel);
+        this.setAcceleration(Math.round(this.getNewAccelerationX(this.props.forcesUpdated()) * 100) / 100, (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated()) * 100)) / 100);
     };
 
     componentDidUpdate(prevProps: Readonly<IWeightProps>, prevState: Readonly<IState>, snapshot?: any): void {
+        if (prevProps.simulationType != this.props.simulationType) {
+            this.setState({ xVelocity: this.props.startVelX });
+            this.setState({ yVelocity: this.props.startVelY });
+            this.setDisplayValues();
+        }
+
         // Change pendulum angle from input field
         if (prevProps.adjustPendulumAngle != this.props.adjustPendulumAngle || prevProps.adjustPendulumLength !== this.props.adjustPendulumLength) {
             let length = this.props.adjustPendulumLength;
@@ -217,52 +209,33 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         }
 
         // When display values updated by user, update real value
-        if (prevProps.updateYDisplay != this.props.updateYDisplay || prevProps.updateXDisplay !== this.props.updateXDisplay) {
-            if (this.props.updateXDisplay != this.state.xPosition) {
-                let x = this.props.updateXDisplay;
-                x = Math.max(0, x);
-                x = Math.min(x, this.props.xMax - 2 * this.props.radius);
-                this.setState({ updatedStartPosX: x });
-                this.setState({ xPosition: x });
-                if (this.props.color == 'red') {
-                    this.props.dataDoc.mass1_positionX = x;
-                } else {
-                    this.props.dataDoc.mass2_positionX = x;
-                }
-            }
-
-            if (this.props.updateYDisplay != this.getDisplayYPos(this.state.yPosition)) {
-                let y = this.props.updateYDisplay;
-                y = Math.max(0, y);
-                y = Math.min(y, this.props.yMax - 2 * this.props.radius);
-                let coordinatePosition = this.getYPosFromDisplay(y);
-                this.setState({ updatedStartPosY: coordinatePosition });
-                this.setState({ yPosition: coordinatePosition });
-                if (this.props.color == 'red') {
-                    this.props.dataDoc.mass1_positionY = y;
-                } else {
-                    this.props.dataDoc.mass2_positionY = y;
-                }
-            }
+        if (prevProps.updateMassPosX !== this.props.updateMassPosX) {
+            let x = this.props.updateMassPosX;
+            x = Math.max(0, x);
+            x = Math.min(x, this.props.xMax - 2 * this.props.radius);
+            this.setState({ updatedStartPosX: x });
+            this.setState({ xPosition: x });
+            this.setPosition(x, undefined);
+        }
+        if (prevProps.updateMassPosY != this.props.updateMassPosY) {
+            let y = this.props.updateMassPosY;
+            y = Math.max(0, y);
+            y = Math.min(y, this.props.yMax - 2 * this.props.radius);
+            let coordinatePosition = this.getDisplayYPos(y);
+            this.setState({ updatedStartPosY: coordinatePosition });
+            this.setState({ yPosition: coordinatePosition });
+            this.setPosition(undefined, y);
 
             if (this.props.displayXVelocity != this.state.xVelocity) {
                 let x = this.props.displayXVelocity;
                 this.setState({ xVelocity: x });
-                if (this.props.color == 'red') {
-                    this.props.dataDoc.mass1_velocityX = x;
-                } else {
-                    this.props.dataDoc.mass2_velocityX = x;
-                }
+                this.setVelocity(x, undefined);
             }
 
             if (this.props.displayYVelocity != -this.state.yVelocity) {
                 let y = this.props.displayYVelocity;
                 this.setState({ yVelocity: -y });
-                if (this.props.color == 'red') {
-                    this.props.dataDoc.mass1_velocityY = y;
-                } else {
-                    this.props.dataDoc.mass2_velocityY = y;
-                }
+                this.setVelocity(undefined, y);
             }
         }
 
@@ -387,7 +360,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             if (this.props.paused && !isNaN(this.props.startPosX)) {
                 this.setState({ xPosition: this.props.startPosX });
                 this.setState({ updatedStartPosX: this.props.startPosX });
-                this.setXPosDisplay(this.props.startPosX);
+                this.setPosition(this.props.startPosX, undefined);
             }
         }
 
@@ -396,7 +369,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             if (this.props.paused && !isNaN(this.props.startPosY)) {
                 this.setState({ yPosition: this.props.startPosY });
                 this.setState({ updatedStartPosY: this.props.startPosY ?? 0 });
-                this.setYPosDisplay(this.props.startPosY ?? 0);
+                this.setPosition(undefined, this.props.startPosY ?? 0);
             }
         }
 
@@ -820,6 +793,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
 
     // Render weight, spring, rod(s), vectors
     render() {
+        trace();
         return (
             <div>
                 <div
-- 
cgit v1.2.3-70-g09d2


From 2c7c450f646dff3ec771f10f0fe323ae761670aa Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 23 May 2023 14:57:38 -0400
Subject: more phys cleanup

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 660 +++++++++++----------
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   | 137 ++---
 2 files changed, 385 insertions(+), 412 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index 35e9c189f..fa47a218b 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -86,6 +86,78 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     @computed get gravity() {
         return NumCast(this.dataDoc.simulation_gravity, -9.81);
     }
+    @computed get simulationType() {
+        return StrCast(this.dataDoc.simulation_type, 'Inclined Plane');
+    }
+    @computed get simulationMode() {
+        return StrCast(this.dataDoc.simulation_mode, 'Freeform');
+    }
+    // Used for spring simulation
+    @computed get springConstant() {
+        return NumCast(this.dataDoc.spring_constant, 0.5);
+    }
+    @computed get springLengthRest() {
+        return NumCast(this.dataDoc.spring_lengthRest, 200);
+    }
+    @computed get springLengthStart() {
+        return NumCast(this.dataDoc.spring_lengthStart, 200);
+    }
+
+    @computed get pendulumAngle() {
+        return NumCast(this.dataDoc.pendulum_angle);
+    }
+    @computed get pendulumAngleStart() {
+        return NumCast(this.dataDoc.pendulum_angleStart);
+    }
+    @computed get pendulumLength() {
+        return NumCast(this.dataDoc.pendulum_length);
+    }
+    @computed get pendulumLengthStart() {
+        return NumCast(this.dataDoc.pendulum_lengthStart);
+    }
+
+    // Used for wedge simulation
+    @computed get wedgeAngle() {
+        return NumCast(this.dataDoc.wedge_angle, 26);
+    }
+    @computed get wedgeHeight() {
+        return NumCast(this.dataDoc.wedge_height, Math.tan((26 * Math.PI) / 180) * this.xMax * 0.5);
+    }
+    @computed get wedgeWidth() {
+        return NumCast(this.dataDoc.wedge_width, this.xMax * 0.5);
+    }
+    @computed get mass1() {
+        return NumCast(this.dataDoc.mass1, 1);
+    }
+    @computed get mass2() {
+        return NumCast(this.dataDoc.mass2, 1);
+    }
+
+    @computed get mass1PosXStart() {
+        return NumCast(this.dataDoc.mass1_positionXstart, Math.round((this.xMax * 0.5 - 200) * 10) / 10);
+    }
+    @computed get mass1PosYStart() {
+        return NumCast(this.dataDoc.mass1_positionYstart, this.getDisplayYPos((400 - 0.08 * this.layoutDoc[HeightSym]()) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26)));
+    }
+    @computed get mass1VelXStart() {
+        return NumCast(this.dataDoc.mass1_velocityXstart);
+    }
+    @computed get mass1VelYStart() {
+        return NumCast(this.dataDoc.mass1_velocityYstart);
+    }
+
+    @computed get mass2PosXStart() {
+        return NumCast(this.dataDoc.mass2_positionXstart);
+    }
+    @computed get mass2PosYStart() {
+        return NumCast(this.dataDoc.mass2_positionYstart, this.getDisplayYPos((400 - 0.08 * this.layoutDoc[HeightSym]()) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26)));
+    }
+    @computed get mass2VelXStart() {
+        return NumCast(this.dataDoc.mass2_velocityXstart);
+    }
+    @computed get mass2VelYStart() {
+        return NumCast(this.dataDoc.mass2_velocityYstart);
+    }
 
     // Constants
     xMin = 0;
@@ -102,15 +174,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.layoutDoc._height = 800;
         this.xMax = this.layoutDoc._width * 0.6;
         this.yMax = this.layoutDoc._height * 0.9;
-        this.dataDoc.simulation_gravity = NumCast(this.dataDoc.simulation_gravity, -9.81);
-        this.dataDoc.mass1 = NumCast(this.dataDoc.mass1, 1);
-        this.dataDoc.simulation_mode = 'Freeform';
         this.dataDoc.simulation_showComponentForces = this.dataDoc.simulation_showComponentForces ?? false;
         this.dataDoc.simulation_speed = NumCast(this.dataDoc.simulation_speed, 2);
-        this.dataDoc.simulation_type = StrCast(this.dataDoc.simulation_type, 'Inclined Plane');
-        this.dataDoc.mass1_positionXstart = this.dataDoc.mass1_positionXstart ?? Math.round((this.xMax * 0.5 - 200) * 10) / 10;
-        this.dataDoc.mass1_positionYstart = this.dataDoc.mass1_positionYstart ?? this.getDisplayYPos((400 - 0.08 * this.layoutDoc._height) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26));
-
         // Used for review mode
         // this.dataDoc.currentForceSketch = this.dataDoc.currentForceSketch ?? null;
         // this.dataDoc.deleteMode = this.dataDoc.deleteMode ?? false;
@@ -123,24 +188,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         // Used for tutorial mode
         this.dataDoc.tutorial = this.dataDoc.tutorial ?? tutorials.inclinePlane;
 
-        // Used for spring simulation
-        this.dataDoc.spring_constant = NumCast(this.dataDoc.spring_constant, 0.5);
-        this.dataDoc.spring_lengthRest = NumCast(this.dataDoc.spring_lengthRest, 200);
-        this.dataDoc.spring_lengthStart = NumCast(this.dataDoc.spring_lengthStart, 200);
-
-        // Used for pendulum simulation
-        this.dataDoc.pendulum_length = NumCast(this.dataDoc.pendulum_length, 300);
-
-        // Used for wedge simulation
-        this.dataDoc.wedge_angle = NumCast(this.dataDoc.wedge_angle, 26);
-        this.dataDoc.wedge_height = NumCast(this.dataDoc.wedge_height, Math.tan((26 * Math.PI) / 180) * this.xMax * 0.5);
-        this.dataDoc.wedge_width = NumCast(this.dataDoc.wedge_width, this.xMax * 0.5);
-
-        // Used for pulley simulation
-        this.dataDoc.mass2 = NumCast(this.dataDoc.mass2, 1);
-
         // Setup simulation
-        this.setupSimulation(StrCast(this.dataDoc.simulation_type), StrCast(this.dataDoc.simulation_mode));
+        this.setupSimulation();
 
         // Create walls
         let walls = [];
@@ -157,11 +206,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             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.simulation_mode));
+            this.setupSimulation();
         }
     }
 
-    setupSimulation = (simulationType: string, mode: string) => {
+    setupSimulation = () => {
+        const simulationType = this.simulationType;
+        const mode = this.simulationMode;
         this.dataDoc.simulation_paused = true;
         if (simulationType != 'Circular Motion') {
             this.dataDoc.mass1_velocityXstart = 0;
@@ -180,7 +231,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.dataDoc.mass1_forcesUpdated = JSON.stringify([
                     {
                         description: 'Gravity',
-                        magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
+                        magnitude: Math.abs(this.gravity) * this.mass1,
                         directionInDegrees: 270,
                         component: false,
                     },
@@ -188,18 +239,19 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.dataDoc.mass1_forcesStart = JSON.stringify([
                     {
                         description: 'Gravity',
-                        magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
+                        magnitude: Math.abs(this.gravity) * this.mass1,
                         directionInDegrees: 270,
                         component: false,
                     },
                 ]);
                 this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
+                ``;
             } else if (simulationType == 'Inclined Plane') {
                 this.changeWedgeBasedOnNewAngle(26);
                 this.dataDoc.mass1_forcesStart = JSON.stringify([
                     {
                         description: 'Gravity',
-                        magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
+                        magnitude: Math.abs(this.gravity) * this.mass1,
                         directionInDegrees: 270,
                         component: false,
                     },
@@ -248,7 +300,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             this.dataDoc.simulation_showComponentForces = false;
             this.dataDoc.tutorial_stepNumber = 0;
             this.dataDoc.simulation_showAcceleration = false;
-            if (this.dataDoc.simulation_type != 'Circular Motion') {
+            if (this.simulationType != 'Circular Motion') {
                 this.dataDoc.mass1_velocityX = 0;
                 this.dataDoc.mass1_velocityY = 0;
                 this.dataDoc.simulation_showVelocity = false;
@@ -258,14 +310,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.dataDoc.simulation_showVelocity = true;
             }
 
-            if (this.dataDoc.simulation_type == 'One Weight') {
+            if (this.simulationType == 'One Weight') {
                 this.dataDoc.simulation_showForces = true;
                 this.dataDoc.mass1_positionYstart = this.yMax - 100;
                 this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
                 this.dataDoc.tutorial = tutorials.freeWeight;
                 this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.freeWeight.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.freeWeight.steps[0].showMagnitude;
-            } else if (this.dataDoc.simulation_type == 'Spring') {
+            } else if (this.simulationType == 'Spring') {
                 this.dataDoc.simulation_showForces = true;
                 this.setupSpring();
                 this.dataDoc.mass1_positionYstart = this.yMin + 200 + 19.62;
@@ -273,43 +325,31 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.dataDoc.tutorial = tutorials.spring;
                 this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.spring.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.spring.steps[0].showMagnitude;
-            } else if (this.dataDoc.simulation_type == 'Pendulum') {
-                this.dataDoc.simulation_showForces = 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.mass1_positionXstart = xPos;
-                this.dataDoc.mass1_positionYstart = yPos;
+            } else if (this.simulationType == 'Pendulum') {
+                this.setupPendulum();
                 this.dataDoc.tutorial = tutorials.pendulum;
                 this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.pendulum.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = 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') {
+            } else if (this.simulationType == 'Inclined Plane') {
                 this.dataDoc.simulation_showForces = true;
                 this.dataDoc.wedge_angle = 26;
                 this.changeWedgeBasedOnNewAngle(26);
                 this.dataDoc.tutorial = tutorials.inclinePlane;
                 this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.inclinePlane.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.inclinePlane.steps[0].showMagnitude;
-            } else if (this.dataDoc.simulation_type == 'Circular Motion') {
+            } else if (this.simulationType == 'Circular Motion') {
                 this.dataDoc.simulation_showForces = true;
                 this.setupCircular(40);
                 this.dataDoc.tutorial = tutorials.circular;
                 this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.circular.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.circular.steps[0].showMagnitude;
-            } else if (this.dataDoc.simulation_type == 'Pulley') {
+            } else if (this.simulationType == 'Pulley') {
                 this.dataDoc.simulation_showForces = true;
                 this.setupPulley();
                 this.dataDoc.tutorial = tutorials.pulley;
                 this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.pulley.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.pulley.steps[0].showMagnitude;
-            } else if (this.dataDoc.simulation_type == 'Suspension') {
+            } else if (this.simulationType == 'Suspension') {
                 this.dataDoc.simulation_showForces = true;
                 this.setupSuspension();
                 this.dataDoc.tutorial = tutorials.suspension;
@@ -329,25 +369,25 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     };
 
     // Update forces when coefficient of static friction changes in freeform mode
-    updateForcesWithFriction = (coefficient: number, width: number = NumCast(this.dataDoc.wedge_width), height: number = NumCast(this.dataDoc.wedge_height)) => {
+    updateForcesWithFriction = (coefficient: number, width = this.wedgeWidth, height = this.wedgeHeight) => {
         const normalForce: IForce = {
             description: 'Normal Force',
-            magnitude: Math.abs(this.gravity) * Math.cos(Math.atan(height / width)) * NumCast(this.dataDoc.mass1),
+            magnitude: Math.abs(this.gravity) * Math.cos(Math.atan(height / width)) * this.mass1,
             directionInDegrees: 180 - 90 - (Math.atan(height / width) * 180) / Math.PI,
             component: false,
         };
         let frictionForce: IForce = {
             description: 'Static Friction Force',
-            magnitude: coefficient * Math.abs(this.gravity) * Math.cos(Math.atan(height / width)) * NumCast(this.dataDoc.mass1),
+            magnitude: coefficient * Math.abs(this.gravity) * Math.cos(Math.atan(height / width)) * this.mass1,
             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(this.gravity) * NumCast(this.dataDoc.mass1);
+        let yForce = -Math.abs(this.gravity) * this.mass1;
         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(this.gravity) * NumCast(this.dataDoc.mass1)) / Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
+            frictionForce.magnitude = (-normalForce.magnitude * Math.sin((normalForce.directionInDegrees * Math.PI) / 180) + Math.abs(this.gravity) * this.mass1) / Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
         }
         const frictionForceComponent: IForce = {
             description: 'Static Friction Force',
@@ -363,19 +403,19 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         };
         const gravityParallel: IForce = {
             description: 'Gravity Parallel Component',
-            magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity) * Math.sin(Math.PI / 2 - Math.atan(height / width)),
+            magnitude: this.mass1 * Math.abs(this.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.mass1) * Math.abs(this.gravity) * Math.cos(Math.PI / 2 - Math.atan(height / width)),
+            magnitude: this.mass1 * Math.abs(this.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.mass1) * Math.abs(this.gravity),
+            magnitude: this.mass1 * Math.abs(this.gravity),
             directionInDegrees: 270,
             component: false,
         };
@@ -421,14 +461,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
 
         this.dataDoc.mass1_positionXstart = this.xMax * 0.25;
         this.dataDoc.mass1_positionYstart = yPos;
-        if (this.dataDoc.simulation_mode == 'Freeform') {
+        if (this.simulationMode == '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.wedge_angle);
+        let theta = this.wedgeAngle;
         let index = this.dataDoc.selectedQuestion.variablesForQuestionSetup.indexOf('theta - max 45');
         if (index >= 0) {
             theta = NumListCast(this.dataDoc.questionVariables)[index];
@@ -472,7 +512,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     getAnswersToQuestion = (question: QuestionTemplate, questionVars: number[]) => {
         const solutions: number[] = [];
 
-        let theta: number = NumCast(this.dataDoc.wedge_angle);
+        let theta = this.wedgeAngle;
         let index = question.variablesForQuestionSetup.indexOf('theta - max 45');
         if (index >= 0) {
             theta = questionVars[index];
@@ -549,7 +589,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                         error = true;
                     }
                 } else if (this.dataDoc.selectedQuestion.answerParts[i] == 'wedge angle') {
-                    if (Math.abs(NumCast(this.dataDoc.wedge_angle) - this.dataDoc.selectedSolutions[i]) > epsilon) {
+                    if (Math.abs(this.wedgeAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
                         error = true;
                     }
                 }
@@ -596,7 +636,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         const vars: number[] = [];
         let question: QuestionTemplate = questions.inclinePlane[0];
 
-        if (this.dataDoc.simulation_type == 'Inclined Plane') {
+        if (this.simulationType === 'Inclined Plane') {
             if (this.dataDoc.questionNumber === questions.inclinePlane.length - 1) {
                 this.dataDoc.questionNumber = 0;
             } else {
@@ -652,7 +692,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.mass1_positionXstart = xPos;
         const tensionForce: IForce = {
             description: 'Centripetal Force',
-            magnitude: (this.dataDoc.mass1_velocityXstart ** 2 * NumCast(this.dataDoc.mass1)) / this.circularMotionRadius,
+            magnitude: (this.dataDoc.mass1_velocityXstart ** 2 * this.mass1) / this.circularMotionRadius,
             directionInDegrees: 90,
             component: false,
         };
@@ -671,7 +711,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         const yPos = y - 0.08 * this.layoutDoc[HeightSym]() - 5;
         this.dataDoc.mass1_positionXstart = xPos;
         this.dataDoc.mass1_positionYstart = yPos;
-        const mag = NumCast(this.dataDoc.mass1) * Math.abs(this.gravity) * Math.sin((60 * Math.PI) / 180);
+        const mag = this.mass1 * Math.abs(this.gravity) * Math.sin((60 * Math.PI) / 180);
         const forceOfTension: IForce = {
             description: 'Tension',
             magnitude: mag,
@@ -687,13 +727,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         };
         const gravityParallel: IForce = {
             description: 'Gravity Parallel Component',
-            magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity) * Math.sin(((90 - angle) * Math.PI) / 180),
+            magnitude: this.mass1 * Math.abs(this.gravity) * Math.sin(((90 - angle) * Math.PI) / 180),
             directionInDegrees: -angle - 90,
             component: true,
         };
         const gravityPerpendicular: IForce = {
             description: 'Gravity Perpendicular Component',
-            magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity) * Math.cos(((90 - angle) * Math.PI) / 180),
+            magnitude: this.mass1 * Math.abs(this.gravity) * Math.cos(((90 - angle) * Math.PI) / 180),
             directionInDegrees: -angle,
             component: true,
         };
@@ -702,7 +742,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.mass1_forcesUpdated = JSON.stringify([
             {
                 description: 'Gravity',
-                magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity),
+                magnitude: this.mass1 * Math.abs(this.gravity),
                 directionInDegrees: 270,
                 component: false,
             },
@@ -711,17 +751,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.mass1_forcesStart = JSON.stringify([
             {
                 description: 'Gravity',
-                magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity),
+                magnitude: this.mass1 * Math.abs(this.gravity),
                 directionInDegrees: 270,
                 component: false,
             },
             forceOfTension,
         ]);
-        this.dataDoc.pendulum_angleStart = 30;
-        this.dataDoc.pendulum_angle = 30;
-        this.dataDoc.pendulum_length = 300;
-        this.dataDoc.pendulum_angle_adjust = 30;
-        this.dataDoc.pendulum_length_adjust = 300;
+        this.dataDoc.pendulum_angle = this.dataDoc.pendulum_angleStart = 30;
+        this.dataDoc.pendulum_length = this.dataDoc.pendulum_lengthStart = 300;
     };
 
     // Default setup for spring simulation
@@ -729,7 +766,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.simulation_showComponentForces = false;
         const gravityForce: IForce = {
             description: 'Gravity',
-            magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
+            magnitude: Math.abs(this.gravity) * this.mass1,
             directionInDegrees: 270,
             component: false,
         };
@@ -751,7 +788,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.mass1_positionXstart = xPos;
         this.dataDoc.mass1_positionY = this.getDisplayYPos(yPos);
         this.dataDoc.mass1_positionX = xPos;
-        let tensionMag = (NumCast(this.dataDoc.mass1) * Math.abs(this.gravity)) / (2 * Math.sin(Math.PI / 4));
+        let tensionMag = (this.mass1 * Math.abs(this.gravity)) / (2 * Math.sin(Math.PI / 4));
         const tensionForce1: IForce = {
             description: 'Tension',
             magnitude: tensionMag,
@@ -766,7 +803,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         };
         const grav: IForce = {
             description: 'Gravity',
-            magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity),
+            magnitude: this.mass1 * Math.abs(this.gravity),
             directionInDegrees: 270,
             component: false,
         };
@@ -782,29 +819,29 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.mass1_positionXstart = (this.xMin + this.xMax) / 2 - 2 * (0.08 * this.layoutDoc[HeightSym]()) - 5;
         this.dataDoc.mass1_positionY = this.getDisplayYPos((this.yMax + this.yMin) / 2);
         this.dataDoc.mass1_positionX = (this.xMin + this.xMax) / 2 - 2 * (0.08 * this.layoutDoc[HeightSym]()) - 5;
-        let a = (-1 * ((NumCast(this.dataDoc.mass1) - NumCast(this.dataDoc.mass2)) * Math.abs(this.gravity))) / (NumCast(this.dataDoc.mass1) + NumCast(this.dataDoc.mass2));
+        let a = (-1 * ((this.mass1 - this.mass2) * Math.abs(this.gravity))) / (this.mass1 + this.mass2);
         const gravityForce1: IForce = {
             description: 'Gravity',
-            magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity),
+            magnitude: this.mass1 * Math.abs(this.gravity),
             directionInDegrees: 270,
             component: false,
         };
         const tensionForce1: IForce = {
             description: 'Tension',
-            magnitude: NumCast(this.dataDoc.mass1) * a + NumCast(this.dataDoc.mass1) * Math.abs(this.gravity),
+            magnitude: this.mass1 * a + this.mass1 * Math.abs(this.gravity),
             directionInDegrees: 90,
             component: false,
         };
         a *= -1;
         const gravityForce2: IForce = {
             description: 'Gravity',
-            magnitude: NumCast(this.dataDoc.mass2) * Math.abs(this.gravity),
+            magnitude: this.mass2 * Math.abs(this.gravity),
             directionInDegrees: 270,
             component: false,
         };
         const tensionForce2: IForce = {
             description: 'Tension',
-            magnitude: NumCast(this.dataDoc.mass2) * a + NumCast(this.dataDoc.mass2) * Math.abs(this.gravity),
+            magnitude: this.mass2 * a + this.mass2 * Math.abs(this.gravity),
             directionInDegrees: 90,
             component: false,
         };
@@ -849,6 +886,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.mass1_forcesUpdated = JSON.stringify([forceOfGravityReview, normalForceReview, staticFrictionForceReview]);
     };
 
+    pause = () => (this.dataDoc.paused = true);
     componentForces1 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass1_componentForces));
     setComponentForces1 = (forces: IForce[]) => (this.dataDoc.mass1_componentForces = JSON.stringify(forces));
     componentForces2 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass2_componentForces));
@@ -859,8 +897,76 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     setForcesUpdated1 = (forces: IForce[]) => (this.dataDoc.mass1_forcesUpdated = JSON.stringify(forces));
     forcesUpdated2 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass2_forcesUpdated));
     setForcesUpdated2 = (forces: IForce[]) => (this.dataDoc.mass2_forcesUpdated = JSON.stringify(forces));
-
+    setPosition1 = (xPos: number | undefined, yPos: number | undefined) => {
+        yPos !== undefined && (this.dataDoc.mass1_positionY = Math.round(yPos * 100) / 100);
+        xPos !== undefined && (this.dataDoc.mass1_positionX = Math.round(xPos * 100) / 100);
+    };
+    setPosition2 = (xPos: number | undefined, yPos: number | undefined) => {
+        yPos !== undefined && (this.dataDoc.mass2_positionY = Math.round(yPos * 100) / 100);
+        xPos !== undefined && (this.dataDoc.mass2_positionX = Math.round(xPos * 100) / 100);
+    };
+    setVelocity1 = (xVel: number | undefined, yVel: number | undefined) => {
+        yVel !== undefined && (this.dataDoc.mass1_velocityY = (-1 * Math.round(yVel * 100)) / 100);
+        xVel !== undefined && (this.dataDoc.mass1_velocityX = Math.round(xVel * 100) / 100);
+    };
+    setVelocity2 = (xVel: number | undefined, yVel: number | undefined) => {
+        yVel !== undefined && (this.dataDoc.mass2_velocityY = (-1 * Math.round(yVel * 100)) / 100);
+        xVel !== undefined && (this.dataDoc.mass2_velocityX = Math.round(xVel * 100) / 100);
+    };
+    setAcceleration1 = (xAccel: number, yAccel: number) => {
+        this.dataDoc.mass1_accelerationY = yAccel;
+        this.dataDoc.mass1_accelerationX = xAccel;
+    };
+    setAcceleration2 = (xAccel: number, yAccel: number) => {
+        this.dataDoc.mass2_accelerationY = yAccel;
+        this.dataDoc.mass2_accelerationX = xAccel;
+    };
+    setPendulumAngle = (angle: number | undefined, length: number | undefined) => {
+        angle !== undefined && (this.dataDoc.pendulum_angle = angle);
+        length !== undefined && (this.dataDoc.pendulum_length = length);
+    };
+    setSpringLength = (length: number) => {
+        this.dataDoc.spring_lengthStart = length;
+    };
     render() {
+        const commonWeightProps = {
+            pause: this.pause,
+            paused: BoolCast(this.dataDoc.simulation_paused),
+            panelWidth: this.layoutDoc[WidthSym],
+            panelHeight: this.layoutDoc[HeightSym],
+            xMax: this.xMax,
+            xMin: this.xMin,
+            yMax: this.yMax,
+            yMin: this.yMin,
+            wallPositions: this.wallPositions,
+            gravity: this.gravity,
+            timestepSize: 0.05,
+            showComponentForces: BoolCast(this.dataDoc.simulation_showComponentForces),
+            coefficientOfKineticFriction: NumCast(this.dataDoc.coefficientOfKineticFriction),
+            elasticCollisions: BoolCast(this.dataDoc.elasticCollisions),
+            simulationMode: this.simulationMode,
+            noMovement: BoolCast(this.dataDoc.noMovement),
+            circularMotionRadius: this.circularMotionRadius,
+            wedgeHeight: this.wedgeHeight,
+            wedgeWidth: this.wedgeWidth,
+            springConstant: this.springConstant,
+            springStartLength: this.springLengthStart,
+            springRestLength: this.springLengthRest,
+            setSpringLength: this.setSpringLength,
+            setPendulumAngle: this.setPendulumAngle,
+            pendulumAngle: this.pendulumAngle,
+            pendulumLength: this.pendulumLength,
+            startPendulumAngle: this.pendulumAngleStart,
+            startPendulumLength: this.pendulumLengthStart,
+            radius: 0.08 * this.layoutDoc[HeightSym](),
+            reset: BoolCast(this.dataDoc.simulation_reset),
+            simulationSpeed: NumCast(this.dataDoc.simulation_speed),
+            showAcceleration: BoolCast(this.dataDoc.simulation_showAcceleration),
+            showForceMagnitudes: BoolCast(this.dataDoc.simulation_showForceMagnitudes),
+            showForces: BoolCast(this.dataDoc.simulation_showForces),
+            showVelocity: BoolCast(this.dataDoc.simulation_showVelocity),
+            simulationType: this.simulationType,
+        };
         return (
             <div className="physicsSimApp">
                 <div className="mechanicsSimulationContainer">
@@ -881,153 +987,81 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                             </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={this.gravity}
-                                    circularMotionRadius={this.circularMotionRadius}
+                                    {...commonWeightProps}
+                                    color="red"
                                     componentForces={this.componentForces1}
                                     setComponentForces={this.setComponentForces1}
-                                    showComponentForces={BoolCast(this.dataDoc.simulation_showComponentForces)}
-                                    color={'red'}
-                                    coefficientOfKineticFriction={NumCast(this.dataDoc.coefficientOfKineticFriction)}
                                     displayXVelocity={NumCast(this.dataDoc.mass1_velocityX)}
                                     displayYVelocity={NumCast(this.dataDoc.mass1_velocityY)}
-                                    elasticCollisions={BoolCast(this.dataDoc.elasticCollisions)}
-                                    mass={NumCast(this.dataDoc.mass1)}
-                                    simulationMode={StrCast(this.dataDoc.simulation_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.pendulum_angleStart)}
-                                    showAcceleration={BoolCast(this.dataDoc.simulation_showAcceleration)}
-                                    showForceMagnitudes={BoolCast(this.dataDoc.simulation_showForceMagnitudes)}
-                                    showForces={BoolCast(this.dataDoc.simulation_showForces)}
-                                    showVelocity={BoolCast(this.dataDoc.simulation_showVelocity)}
-                                    simulationType={StrCast(this.dataDoc.simulation_type)}
-                                    springConstant={NumCast(this.dataDoc.spring_constant)}
-                                    springStartLength={NumCast(this.dataDoc.spring_lengthStart)}
-                                    springRestLength={NumCast(this.dataDoc.spring_lengthRest)}
+                                    mass={this.mass1}
                                     startForces={this.startForces1}
-                                    startPosX={NumCast(this.dataDoc.mass1_positionXstart)}
-                                    startPosY={NumCast(this.dataDoc.mass1_positionYstart)}
-                                    startVelX={NumCast(this.dataDoc.mass1_velocityXstart)}
-                                    startVelY={NumCast(this.dataDoc.mass1_velocityYstart)}
-                                    timestepSize={0.05}
+                                    startPosX={this.mass1PosXStart}
+                                    startPosY={this.mass1PosYStart}
+                                    startVelX={this.mass1VelXStart}
+                                    startVelY={this.mass1VelYStart}
                                     updateMassPosX={NumCast(this.dataDoc.mass1_xChange)}
                                     updateMassPosY={NumCast(this.dataDoc.mass1_yChange)}
                                     forcesUpdated={this.forcesUpdated1}
                                     setForcesUpdated={this.setForcesUpdated1}
-                                    wedgeHeight={NumCast(this.dataDoc.wedge_height)}
-                                    wedgeWidth={NumCast(this.dataDoc.wedge_width)}
-                                    xMax={this.xMax}
-                                    xMin={this.xMin}
-                                    yMax={this.yMax}
-                                    yMin={this.yMin}
+                                    setPosition={this.setPosition1}
+                                    setVelocity={this.setVelocity1}
+                                    setAcceleration={this.setAcceleration1}
                                 />
-                                {this.dataDoc.simulation_type == 'Pulley' && (
+                                {this.simulationType == '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={this.circularMotionRadius}
-                                        gravity={this.gravity}
+                                        {...commonWeightProps}
+                                        color="green"
                                         componentForces={this.componentForces2}
                                         setComponentForces={this.setComponentForces2}
-                                        showComponentForces={BoolCast(this.dataDoc.simulation_showComponentForces)}
-                                        color={'blue'}
-                                        coefficientOfKineticFriction={NumCast(this.dataDoc.coefficientOfKineticFriction)}
-                                        displayXVelocity={NumCast(this.dataDoc.mass1_velocityX)}
-                                        displayYVelocity={NumCast(this.dataDoc.mass1_velocityY)}
-                                        elasticCollisions={BoolCast(this.dataDoc.elasticCollisions)}
-                                        mass={NumCast(this.dataDoc.mass2)}
-                                        simulationMode={StrCast(this.dataDoc.simulation_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.pendulum_angleStart)}
-                                        showAcceleration={BoolCast(this.dataDoc.simulation_showAcceleration)}
-                                        showForceMagnitudes={BoolCast(this.dataDoc.simulation_showForceMagnitudes)}
-                                        showForces={BoolCast(this.dataDoc.simulation_showForces)}
-                                        showVelocity={BoolCast(this.dataDoc.simulation_showVelocity)}
-                                        simulationType={this.dataDoc.simulation_type}
-                                        springConstant={NumCast(this.dataDoc.spring_constant)}
-                                        springStartLength={NumCast(this.dataDoc.spring_lengthStart)}
-                                        springRestLength={NumCast(this.dataDoc.spring_lengthRest)}
+                                        displayXVelocity={NumCast(this.dataDoc.mass2_velocityX)}
+                                        displayYVelocity={NumCast(this.dataDoc.mass2_velocityY)}
+                                        mass={this.mass2}
                                         startForces={this.startForces2}
-                                        startPosX={NumCast(this.dataDoc.mass2_positionXstart)}
-                                        startPosY={NumCast(this.dataDoc.mass2_positionYstart)}
-                                        startVelX={NumCast(this.dataDoc.mass2_velocityXstart)}
-                                        startVelY={NumCast(this.dataDoc.mass2_velocityYstart)}
-                                        timestepSize={0.05}
+                                        startPosX={this.mass2PosXStart}
+                                        startPosY={this.mass2PosYStart}
+                                        startVelX={this.mass2VelXStart}
+                                        startVelY={this.mass2VelYStart}
                                         updateMassPosX={NumCast(this.dataDoc.mass2_xChange)}
                                         updateMassPosY={NumCast(this.dataDoc.mass2_yChange)}
                                         forcesUpdated={this.forcesUpdated2}
                                         setForcesUpdated={this.setForcesUpdated2}
-                                        wedgeHeight={NumCast(this.dataDoc.wedge_height)}
-                                        wedgeWidth={NumCast(this.dataDoc.wedge_width)}
-                                        xMax={this.xMax}
-                                        xMin={this.xMin}
-                                        yMax={this.yMax}
-                                        yMin={this.yMin}
+                                        setPosition={this.setPosition2}
+                                        setVelocity={this.setVelocity2}
+                                        setAcceleration={this.setAcceleration2}
                                     />
                                 )}
                             </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} />;
-                                    })}
+                                {(this.simulationType == 'One Weight' || this.simulationType == 'Inclined Plane') &&
+                                    this.wallPositions?.map((element, index) => <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.simulation_mode != 'Tutorial' && (
-                                    <IconButton
-                                        onClick={() => {
-                                            this.dataDoc.simulation_paused = false;
-                                        }}>
+                                {this.dataDoc.simulation_paused && this.simulationMode != 'Tutorial' && (
+                                    <IconButton onClick={() => (this.dataDoc.simulation_paused = false)}>
                                         <PlayArrowIcon />
                                     </IconButton>
                                 )}
-                                {!this.dataDoc.simulation_paused && this.dataDoc.simulation_mode != 'Tutorial' && (
-                                    <IconButton
-                                        onClick={() => {
-                                            this.dataDoc.simulation_paused = true;
-                                        }}>
+                                {!this.dataDoc.simulation_paused && this.simulationMode != 'Tutorial' && (
+                                    <IconButton onClick={() => (this.dataDoc.simulation_paused = true)}>
                                         <PauseIcon />
                                     </IconButton>
                                 )}
-                                {this.dataDoc.simulation_paused && this.dataDoc.simulation_mode != 'Tutorial' && (
-                                    <IconButton
-                                        onClick={() => {
-                                            this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
-                                        }}>
+                                {this.dataDoc.simulation_paused && this.simulationMode != 'Tutorial' && (
+                                    <IconButton onClick={() => (this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset)}>
                                         <ReplayIcon />
                                     </IconButton>
                                 )}
                             </Stack>
                             <div className="dropdownMenu">
                                 <select
-                                    value={StrCast(this.dataDoc.simulation_type)}
+                                    value={StrCast(this.simulationType)}
                                     onChange={event => {
                                         this.dataDoc.simulation_type = event.target.value;
-                                        this.setupSimulation(event.target.value, StrCast(this.dataDoc.simulation_mode));
+                                        this.setupSimulation();
                                     }}
                                     style={{ height: '2em', width: '100%', fontSize: '16px' }}>
                                     <option value="One Weight">Projectile</option>
@@ -1041,10 +1075,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                             </div>
                             <div className="dropdownMenu">
                                 <select
-                                    value={StrCast(this.dataDoc.simulation_mode)}
+                                    value={this.simulationMode}
                                     onChange={event => {
                                         this.dataDoc.simulation_mode = event.target.value;
-                                        this.setupSimulation(StrCast(this.dataDoc.simulation_type), event.target.value);
+                                        this.setupSimulation();
                                     }}
                                     style={{ height: '2em', width: '100%', fontSize: '16px' }}>
                                     <option value="Tutorial">Tutorial Mode</option>
@@ -1053,21 +1087,19 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </select>
                             </div>
                         </div>
-                        {this.dataDoc.simulation_mode == 'Review' && this.dataDoc.simulation_type != 'Inclined Plane' && (
+                        {this.simulationMode == 'Review' && this.simulationType != 'Inclined Plane' && (
                             <div className="wordProblemBox">
                                 <p>
-                                    <>{this.dataDoc.simulation_type} review problems in progress!</>
+                                    <>{this.simulationType} review problems in progress!</>
                                 </p>
                                 <hr />
                             </div>
                         )}
-                        {this.dataDoc.simulation_mode == 'Review' && this.dataDoc.simulation_type == 'Inclined Plane' && (
+                        {this.simulationMode == 'Review' && this.simulationType == 'Inclined Plane' && (
                             <div>
                                 {!this.dataDoc.hintDialogueOpen && (
                                     <IconButton
-                                        onClick={() => {
-                                            this.dataDoc.hintDialogueOpen = true;
-                                        }}
+                                        onClick={() => (this.dataDoc.hintDialogueOpen = true)}
                                         sx={{
                                             position: 'fixed',
                                             left: this.xMax - 50 + 'px',
@@ -1079,30 +1111,23 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 <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>
-                                            );
-                                        })}
+                                        {this.dataDoc.selectedQuestion.hints?.map((hint: any, index: number) => (
+                                            <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>
+                                        <Button onClick={() => (this.dataDoc.hintDialogueOpen = false)}>Close</Button>
                                     </DialogActions>
                                 </Dialog>
                                 <div className="wordProblemBox">
@@ -1232,7 +1257,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 step={1}
                                                 unit={'°'}
                                                 upperBound={49}
-                                                value={NumCast(this.dataDoc.wedge_angle, 26)}
+                                                value={this.wedgeAngle}
                                                 effect={(val: number) => {
                                                     this.changeWedgeBasedOnNewAngle(val);
                                                     this.updateReviewForcesBasedOnAngle(val);
@@ -1246,7 +1271,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </div>
                             </div>
                         )}
-                        {this.dataDoc.simulation_mode == 'Tutorial' && (
+                        {this.simulationMode == 'Tutorial' && (
                             <div className="wordProblemBox">
                                 <div className="question">
                                     <h2>Problem</h2>
@@ -1292,8 +1317,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     </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' && (
+                                    {(this.simulationType == 'One Weight' || this.simulationType == 'Inclined Plane' || this.simulationType == 'Pendulum') && <p>Resources</p>}
+                                    {this.simulationType == 'One Weight' && (
                                         <ul>
                                             <li>
                                                 <a
@@ -1321,7 +1346,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             </li>
                                         </ul>
                                     )}
-                                    {this.dataDoc.simulation_type == 'Inclined Plane' && (
+                                    {this.simulationType == 'Inclined Plane' && (
                                         <ul>
                                             <li>
                                                 <a
@@ -1349,7 +1374,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             </li>
                                         </ul>
                                     )}
-                                    {this.dataDoc.simulation_type == 'Pendulum' && (
+                                    {this.simulationType == 'Pendulum' && (
                                         <ul>
                                             <li>
                                                 <a
@@ -1368,7 +1393,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </div>
                             </div>
                         )}
-                        {this.dataDoc.simulation_mode == 'Review' && this.dataDoc.simulation_type == 'Inclined Plane' && (
+                        {this.simulationMode == 'Review' && this.simulationType == 'Inclined Plane' && (
                             <div
                                 style={{
                                     display: 'flex',
@@ -1406,11 +1431,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </div>
                             </div>
                         )}
-                        {this.dataDoc.simulation_mode == 'Freeform' && (
+                        {this.simulationMode == 'Freeform' && (
                             <div className="vars">
                                 <FormControl component="fieldset">
                                     <FormGroup>
-                                        {this.dataDoc.simulation_type == 'One Weight' && (
+                                        {this.simulationType == 'One Weight' && (
                                             <FormControlLabel
                                                 control={<Checkbox checked={BoolCast(this.dataDoc.elasticCollisions)} onChange={() => (this.dataDoc.elasticCollisions = !this.dataDoc.elasticCollisions)} />}
                                                 label="Make collisions elastic"
@@ -1422,7 +1447,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             label="Show force vectors"
                                             labelPlacement="start"
                                         />
-                                        {(this.dataDoc.simulation_type == 'Inclined Plane' || this.dataDoc.simulation_type == 'Pendulum') && (
+                                        {(this.simulationType == 'Inclined Plane' || this.simulationType == 'Pendulum') && (
                                             <FormControlLabel
                                                 control={<Checkbox checked={BoolCast(this.dataDoc.simulation_showForces)} onChange={() => (this.dataDoc.simulation_showComponentForces = !this.dataDoc.simulation_showComponentForces)} />}
                                                 label="Show component force vectors"
@@ -1440,7 +1465,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             labelPlacement="start"
                                         />
                                         <InputField label={<Box>Speed</Box>} lowerBound={1} dataDoc={this.dataDoc} prop="simulation_speed" step={1} unit={'x'} upperBound={10} value={NumCast(this.dataDoc.simulation_speed, 2)} labelWidth={'5em'} />
-                                        {this.dataDoc.simulation_paused && this.dataDoc.simulation_type != 'Circular Motion' && (
+                                        {this.dataDoc.simulation_paused && this.simulationType != 'Circular Motion' && (
                                             <InputField
                                                 label={<Box>Gravity</Box>}
                                                 lowerBound={-30}
@@ -1450,13 +1475,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 unit={'m/s2'}
                                                 upperBound={0}
                                                 value={NumCast(this.dataDoc.simulation_gravity, -9.81)}
-                                                effect={(val: number) => {
-                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_type), StrCast(this.dataDoc.simulation_mode));
-                                                }}
+                                                effect={(val: number) => this.setupSimulation()}
                                                 labelWidth={'5em'}
                                             />
                                         )}
-                                        {this.dataDoc.simulation_paused && this.dataDoc.simulation_type != 'Pulley' && (
+                                        {this.dataDoc.simulation_paused && this.simulationType != 'Pulley' && (
                                             <InputField
                                                 label={<Box>Mass</Box>}
                                                 lowerBound={1}
@@ -1465,14 +1488,12 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 step={0.1}
                                                 unit={'kg'}
                                                 upperBound={5}
-                                                value={NumCast(this.dataDoc.mass1) ?? 1}
-                                                effect={(val: number) => {
-                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_type), StrCast(this.dataDoc.simulation_mode));
-                                                }}
+                                                value={this.mass1 ?? 1}
+                                                effect={(val: number) => this.setupSimulation()}
                                                 labelWidth={'5em'}
                                             />
                                         )}
-                                        {this.dataDoc.simulation_paused && this.dataDoc.simulation_type == 'Pulley' && (
+                                        {this.dataDoc.simulation_paused && this.simulationType == 'Pulley' && (
                                             <InputField
                                                 label={<Box>Red mass</Box>}
                                                 lowerBound={1}
@@ -1481,14 +1502,12 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 step={0.1}
                                                 unit={'kg'}
                                                 upperBound={5}
-                                                value={NumCast(this.dataDoc.mass1) ?? 1}
-                                                effect={(val: number) => {
-                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_type), StrCast(this.dataDoc.simulation_mode));
-                                                }}
+                                                value={this.mass1 ?? 1}
+                                                effect={(val: number) => this.setupSimulation()}
                                                 labelWidth={'5em'}
                                             />
                                         )}
-                                        {this.dataDoc.simulation_paused && this.dataDoc.simulation_type == 'Pulley' && (
+                                        {this.dataDoc.simulation_paused && this.simulationType == 'Pulley' && (
                                             <InputField
                                                 label={<Box>Blue mass</Box>}
                                                 lowerBound={1}
@@ -1497,14 +1516,12 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 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.simulation_mode));
-                                                }}
+                                                value={this.mass2 ?? 1}
+                                                effect={(val: number) => this.setupSimulation()}
                                                 labelWidth={'5em'}
                                             />
                                         )}
-                                        {this.dataDoc.simulation_paused && this.dataDoc.simulation_type == 'Circular Motion' && (
+                                        {this.dataDoc.simulation_paused && this.simulationType == 'Circular Motion' && (
                                             <InputField
                                                 label={<Box>Rod length</Box>}
                                                 lowerBound={100}
@@ -1514,15 +1531,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 unit={'m'}
                                                 upperBound={250}
                                                 value={this.circularMotionRadius}
-                                                effect={(val: number) => {
-                                                    this.setupSimulation(StrCast(this.dataDoc.simulation_type), StrCast(this.dataDoc.simulation_mode));
-                                                }}
+                                                effect={(val: number) => this.setupSimulation()}
                                                 labelWidth={'5em'}
                                             />
                                         )}
                                     </FormGroup>
                                 </FormControl>
-                                {this.dataDoc.simulation_type == 'Spring' && this.dataDoc.simulation_paused && (
+                                {this.simulationType == 'Spring' && this.dataDoc.simulation_paused && (
                                     <div>
                                         <InputField
                                             label={<Typography color="inherit">Spring stiffness</Typography>}
@@ -1532,10 +1547,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             step={1}
                                             unit={'N/m'}
                                             upperBound={500}
-                                            value={NumCast(this.dataDoc.spring_constant) ?? 0.5}
-                                            effect={(val: number) => {
-                                                this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
-                                            }}
+                                            value={this.springConstant}
+                                            effect={(val: number) => (this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset)}
                                             radianEquivalent={false}
                                             mode={'Freeform'}
                                             labelWidth={'7em'}
@@ -1546,37 +1559,35 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             dataDoc={this.dataDoc}
                                             prop="spring_lengthRest"
                                             step={100}
-                                            unit={''}
+                                            unit=""
                                             upperBound={500}
-                                            value={NumCast(this.dataDoc.spring_lengthRest) ?? 200}
-                                            effect={(val: number) => {
-                                                this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
-                                            }}
+                                            value={this.springLengthRest}
+                                            effect={(val: number) => (this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset)}
                                             radianEquivalent={false}
-                                            mode={'Freeform'}
+                                            mode="Freeform"
                                             labelWidth={'7em'}
                                         />
                                         <InputField
                                             label={<Typography color="inherit">Starting displacement</Typography>}
-                                            lowerBound={-(NumCast(this.dataDoc.spring_lengthRest) - 10)}
+                                            lowerBound={-(this.springLengthRest - 10)}
                                             dataDoc={this.dataDoc}
                                             prop=""
                                             step={10}
-                                            unit={''}
-                                            upperBound={NumCast(this.dataDoc.spring_lengthRest)}
-                                            value={NumCast(this.dataDoc.spring_lengthStart) - NumCast(this.dataDoc.spring_lengthRest)}
+                                            unit=""
+                                            upperBound={this.springLengthRest}
+                                            value={this.springLengthStart - this.springLengthRest}
                                             effect={(val: number) => {
-                                                this.dataDoc.mass1_positionYstart = NumCast(this.dataDoc.spring_lengthRest) + val;
-                                                this.dataDoc.spring_lengthStart = NumCast(this.dataDoc.spring_lengthRest) + val;
+                                                this.dataDoc.mass1_positionYstart = this.springLengthRest + val;
+                                                this.dataDoc.spring_lengthStart = this.springLengthRest + val;
                                                 this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                                             }}
                                             radianEquivalent={false}
-                                            mode={'Freeform'}
+                                            mode="Freeform"
                                             labelWidth={'7em'}
                                         />
                                     </div>
                                 )}
-                                {this.dataDoc.simulation_type == 'Inclined Plane' && this.dataDoc.simulation_paused && (
+                                {this.simulationType == 'Inclined Plane' && this.dataDoc.simulation_paused && (
                                     <div>
                                         <InputField
                                             label={<Box>&theta;</Box>}
@@ -1586,7 +1597,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             step={1}
                                             unit={'°'}
                                             upperBound={49}
-                                            value={NumCast(this.dataDoc.wedge_angle, 26)}
+                                            value={this.wedgeAngle}
                                             effect={(val: number) => {
                                                 this.changeWedgeBasedOnNewAngle(val);
                                                 this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
@@ -1639,10 +1650,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                         />
                                     </div>
                                 )}
-                                {this.dataDoc.simulation_type == 'Inclined Plane' && !this.dataDoc.simulation_paused && (
+                                {this.simulationType == 'Inclined Plane' && !this.dataDoc.simulation_paused && (
                                     <Typography>
                                         <>
-                                            &theta;: {Math.round(NumCast(this.dataDoc.wedge_angle) * 100) / 100}° ≈ {Math.round(((NumCast(this.dataDoc.wedge_angle) * Math.PI) / 180) * 100) / 100} rad
+                                            &theta;: {Math.round(this.wedgeAngle * 100) / 100}° ≈ {Math.round(((this.wedgeAngle * Math.PI) / 180) * 100) / 100} rad
                                             <br />
                                             &mu; <sub>s</sub>: {this.dataDoc.coefficientOfStaticFriction}
                                             <br />
@@ -1650,12 +1661,12 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                         </>
                                     </Typography>
                                 )}
-                                {this.dataDoc.simulation_type == 'Pendulum' && !this.dataDoc.simulation_paused && (
+                                {this.simulationType == '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
+                                        &theta;: {Math.round(this.pendulumAngle * 100) / 100}° ≈ {Math.round(((this.pendulumAngle * Math.PI) / 180) * 100) / 100} rad
                                     </Typography>
                                 )}
-                                {this.dataDoc.simulation_type == 'Pendulum' && this.dataDoc.simulation_paused && (
+                                {this.simulationType == 'Pendulum' && this.dataDoc.simulation_paused && (
                                     <div>
                                         <InputField
                                             label={<Box>Angle</Box>}
@@ -1668,8 +1679,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             value={NumCast(this.dataDoc.pendulum_angle, 30)}
                                             effect={value => {
                                                 this.dataDoc.pendulum_angleStart = value;
-                                                if (this.dataDoc.simulation_type == 'Pendulum') {
-                                                    const mag = NumCast(this.dataDoc.mass1) * Math.abs(this.gravity) * Math.cos((value * Math.PI) / 180);
+                                                this.dataDoc.pendulum_lengthStart = this.dataDoc.pendulum_length;
+                                                if (this.simulationType == 'Pendulum') {
+                                                    const mag = this.mass1 * Math.abs(this.gravity) * Math.cos((value * Math.PI) / 180);
 
                                                     const forceOfTension: IForce = {
                                                         description: 'Tension',
@@ -1697,7 +1709,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                         component: true,
                                                     };
 
-                                                    const length = NumCast(this.dataDoc.pendulum_length);
+                                                    const length = this.pendulumLength;
                                                     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);
@@ -1708,7 +1720,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     this.dataDoc.mass1_forcesStart = JSON.stringify([
                                                         {
                                                             description: 'Gravity',
-                                                            magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
+                                                            magnitude: Math.abs(this.gravity) * this.mass1,
                                                             directionInDegrees: 270,
                                                             component: false,
                                                         },
@@ -1717,21 +1729,19 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     this.dataDoc.mass1_forcesUpdated = JSON.stringify([
                                                         {
                                                             description: 'Gravity',
-                                                            magnitude: Math.abs(this.gravity) * NumCast(this.dataDoc.mass1),
+                                                            magnitude: Math.abs(this.gravity) * this.mass1,
                                                             directionInDegrees: 270,
                                                             component: false,
                                                         },
                                                         forceOfTension,
                                                     ]);
                                                     this.dataDoc.mass1_componentForces = JSON.stringify([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'}
+                                            mode="Freeform"
+                                            labelWidth="5em"
                                         />
                                         <InputField
                                             label={<Box>Rod length</Box>}
@@ -1739,30 +1749,30 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             dataDoc={this.dataDoc}
                                             prop="pendulum_length"
                                             step={1}
-                                            unit={'m'}
+                                            unit="m"
                                             upperBound={400}
-                                            value={Math.round(NumCast(this.dataDoc.pendulum_length))}
+                                            value={Math.round(this.pendulumLength)}
                                             effect={value => {
-                                                if (this.dataDoc.simulation_type == 'Pendulum') {
-                                                    this.dataDoc.pendulum_angle_adjust = NumCast(this.dataDoc.pendulum_angle);
-                                                    this.dataDoc.pendulum_length_adjust = value;
+                                                if (this.simulationType == 'Pendulum') {
+                                                    this.dataDoc.pendulum_angleStart = this.pendulumAngle;
+                                                    this.dataDoc.pendulum_lengthStart = value;
                                                     this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                                                 }
                                             }}
                                             radianEquivalent={false}
-                                            mode={'Freeform'}
-                                            labelWidth={'5em'}
+                                            mode="Freeform"
+                                            labelWidth="5em"
                                         />
                                     </div>
                                 )}
                             </div>
                         )}
                         <div className="mechanicsSimulationEquation">
-                            {this.dataDoc.simulation_mode == 'Freeform' && (
+                            {this.simulationMode == 'Freeform' && (
                                 <table>
                                     <tbody>
                                         <tr>
-                                            <td>{this.dataDoc.simulation_type == 'Pulley' ? 'Red Weight' : ''}</td>
+                                            <td>{this.simulationType == 'Pulley' ? 'Red Weight' : ''}</td>
                                             <td>X</td>
                                             <td>Y</td>
                                         </tr>
@@ -1777,27 +1787,27 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             >
                                                 <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') && (
+                                            {(!this.dataDoc.simulation_paused || this.simulationType == 'Inclined Plane' || this.simulationType == 'Circular Motion' || this.simulationType == 'Pulley') && (
                                                 <td style={{ cursor: 'default' }}>
                                                     <>{this.dataDoc.mass1_positionX} m</>
                                                 </td>
                                             )}{' '}
-                                            {this.dataDoc.simulation_paused && this.dataDoc.simulation_type != 'Inclined Plane' && this.dataDoc.simulation_type != 'Circular Motion' && this.dataDoc.simulation_type != 'Pulley' && (
+                                            {this.dataDoc.simulation_paused && this.simulationType != 'Inclined Plane' && this.simulationType != 'Circular Motion' && this.simulationType != 'Pulley' && (
                                                 <td
                                                     style={{
                                                         cursor: 'default',
                                                     }}>
                                                     <InputField
-                                                        lowerBound={this.dataDoc.simulation_type == 'Projectile' ? 1 : (this.xMax + this.xMin) / 4 - this.radius - 15}
+                                                        lowerBound={this.simulationType == 'Projectile' ? 1 : (this.xMax + this.xMin) / 4 - this.radius - 15}
                                                         dataDoc={this.dataDoc}
                                                         prop="mass1_positionX"
                                                         step={1}
                                                         unit={'m'}
-                                                        upperBound={this.dataDoc.simulation_type == 'Projectile' ? this.xMax - 110 : (3 * (this.xMax + this.xMin)) / 4 - this.radius / 2 - 15}
+                                                        upperBound={this.simulationType == 'Projectile' ? this.xMax - 110 : (3 * (this.xMax + this.xMin)) / 4 - this.radius / 2 - 15}
                                                         value={NumCast(this.dataDoc.mass1_positionX)}
                                                         effect={value => {
                                                             this.dataDoc.mass1_xChange = value;
-                                                            if (this.dataDoc.simulation_type == 'Suspension') {
+                                                            if (this.simulationType == '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;
@@ -1805,7 +1815,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                                 let deltaY = this.getYPosFromDisplay(NumCast(this.dataDoc.mass1_positionY)) + this.radius;
                                                                 let dir1T = Math.PI - Math.atan(deltaY / deltaX1);
                                                                 let dir2T = Math.atan(deltaY / deltaX2);
-                                                                let tensionMag2 = (NumCast(this.dataDoc.mass1) * Math.abs(this.gravity)) / ((-Math.cos(dir2T) / Math.cos(dir1T)) * Math.sin(dir1T) + Math.sin(dir2T));
+                                                                let tensionMag2 = (this.mass1 * Math.abs(this.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;
@@ -1823,7 +1833,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                                 };
                                                                 const grav: IForce = {
                                                                     description: 'Gravity',
-                                                                    magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity),
+                                                                    magnitude: this.mass1 * Math.abs(this.gravity),
                                                                     directionInDegrees: 270,
                                                                     component: false,
                                                                 };
@@ -1831,14 +1841,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                             }
                                                         }}
                                                         small={true}
-                                                        mode={'Freeform'}
+                                                        mode="Freeform"
                                                     />
                                                 </td>
                                             )}{' '}
-                                            {(!this.dataDoc.simulation_paused || this.dataDoc.simulation_type == 'Inclined Plane' || this.dataDoc.simulation_type == 'Circular Motion' || this.dataDoc.simulation_type == 'Pulley') && (
+                                            {(!this.dataDoc.simulation_paused || this.simulationType == 'Inclined Plane' || this.simulationType == 'Circular Motion' || this.simulationType == 'Pulley') && (
                                                 <td style={{ cursor: 'default' }}>{`${NumCast(this.dataDoc.mass1_positionY)} m`}</td>
                                             )}{' '}
-                                            {this.dataDoc.simulation_paused && this.dataDoc.simulation_type != 'Inclined Plane' && this.dataDoc.simulation_type != 'Circular Motion' && this.dataDoc.simulation_type != 'Pulley' && (
+                                            {this.dataDoc.simulation_paused && this.simulationType != 'Inclined Plane' && this.simulationType != 'Circular Motion' && this.simulationType != 'Pulley' && (
                                                 <td
                                                     style={{
                                                         cursor: 'default',
@@ -1848,12 +1858,12 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                         dataDoc={this.dataDoc}
                                                         prop="mass1_positionY"
                                                         step={1}
-                                                        unit={'m'}
+                                                        unit="m"
                                                         upperBound={this.yMax - 110}
                                                         value={NumCast(this.dataDoc.mass1_positionY)}
                                                         effect={value => {
                                                             this.dataDoc.mass1_yChange = value;
-                                                            if (this.dataDoc.simulation_type == 'Suspension') {
+                                                            if (this.simulationType == '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.mass1_positionX) + this.radius - x1rod;
@@ -1861,7 +1871,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                                 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.mass1) * Math.abs(this.gravity)) / ((-Math.cos(dir2T) / Math.cos(dir1T)) * Math.sin(dir1T) + Math.sin(dir2T));
+                                                                let tensionMag2 = (this.mass1 * Math.abs(this.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;
@@ -1879,7 +1889,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                                 };
                                                                 const grav: IForce = {
                                                                     description: 'Gravity',
-                                                                    magnitude: NumCast(this.dataDoc.mass1) * Math.abs(this.gravity),
+                                                                    magnitude: this.mass1 * Math.abs(this.gravity),
                                                                     directionInDegrees: 270,
                                                                     component: false,
                                                                 };
@@ -1887,7 +1897,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                             }
                                                         }}
                                                         small={true}
-                                                        mode={'Freeform'}
+                                                        mode="Freeform"
                                                     />
                                                 </td>
                                             )}{' '}
@@ -1903,10 +1913,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             >
                                                 <Box>Velocity</Box>
                                             </td>
-                                            {(!this.dataDoc.simulation_paused || (this.dataDoc.simulation_type != 'One Weight' && this.dataDoc.simulation_type != 'Circular Motion')) && (
+                                            {(!this.dataDoc.simulation_paused || (this.simulationType != 'One Weight' && this.simulationType != 'Circular Motion')) && (
                                                 <td style={{ cursor: 'default' }}>{`${NumCast(this.dataDoc.mass1_velocityX)} m/s`}</td>
                                             )}{' '}
-                                            {this.dataDoc.simulation_paused && (this.dataDoc.simulation_type == 'One Weight' || this.dataDoc.simulation_type == 'Circular Motion') && (
+                                            {this.dataDoc.simulation_paused && (this.simulationType == 'One Weight' || this.simulationType == 'Circular Motion') && (
                                                 <td
                                                     style={{
                                                         cursor: 'default',
@@ -1924,16 +1934,16 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                             this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                                                         }}
                                                         small={true}
-                                                        mode={'Freeform'}
+                                                        mode="Freeform"
                                                     />
                                                 </td>
                                             )}{' '}
-                                            {(!this.dataDoc.simulation_paused || this.dataDoc.simulation_type != 'One Weight') && (
+                                            {(!this.dataDoc.simulation_paused || this.simulationType != 'One Weight') && (
                                                 <td style={{ cursor: 'default' }}>
                                                     <>{this.dataDoc.mass1_velocityY} m/s</>
                                                 </td>
                                             )}{' '}
-                                            {this.dataDoc.simulation_paused && this.dataDoc.simulation_type == 'One Weight' && (
+                                            {this.dataDoc.simulation_paused && this.simulationType == 'One Weight' && (
                                                 <td
                                                     style={{
                                                         cursor: 'default',
@@ -1943,14 +1953,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                         dataDoc={this.dataDoc}
                                                         prop="mass1_velocityY"
                                                         step={1}
-                                                        unit={'m/s'}
+                                                        unit="m/s"
                                                         upperBound={50}
                                                         value={NumCast(this.dataDoc.mass1_velocityY)}
                                                         effect={value => {
                                                             this.dataDoc.mass1_velocityYstart = -value;
                                                         }}
                                                         small={true}
-                                                        mode={'Freeform'}
+                                                        mode="Freeform"
                                                     />
                                                 </td>
                                             )}{' '}
@@ -1981,13 +1991,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             <td>
                                                 <Box>Momentum</Box>
                                             </td>
-                                            <td>{Math.round(NumCast(this.dataDoc.mass1_velocityX) * NumCast(this.dataDoc.mass1) * 10) / 10} kg*m/s</td>
-                                            <td>{Math.round(NumCast(this.dataDoc.mass1_velocityY) * NumCast(this.dataDoc.mass1) * 10) / 10} kg*m/s</td>
+                                            <td>{Math.round(NumCast(this.dataDoc.mass1_velocityX) * this.mass1 * 10) / 10} kg*m/s</td>
+                                            <td>{Math.round(NumCast(this.dataDoc.mass1_velocityY) * this.mass1 * 10) / 10} kg*m/s</td>
                                         </tr>
                                     </tbody>
                                 </table>
                             )}
-                            {this.dataDoc.simulation_mode == 'Freeform' && this.dataDoc.simulation_type == 'Pulley' && (
+                            {this.simulationMode == 'Freeform' && this.simulationType == 'Pulley' && (
                                 <table>
                                     <tbody>
                                         <tr>
@@ -2028,14 +2038,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             <td>
                                                 <Box>Momentum</Box>
                                             </td>
-                                            <td>{Math.round(NumCast(this.dataDoc.mass2_velocityX) * NumCast(this.dataDoc.mass1) * 10) / 10} kg*m/s</td>
-                                            <td>{Math.round(NumCast(this.dataDoc.mass2_velocityY) * NumCast(this.dataDoc.mass1) * 10) / 10} kg*m/s</td>
+                                            <td>{Math.round(NumCast(this.dataDoc.mass2_velocityX) * this.mass1 * 10) / 10} kg*m/s</td>
+                                            <td>{Math.round(NumCast(this.dataDoc.mass2_velocityY) * this.mass1 * 10) / 10} kg*m/s</td>
                                         </tr>
                                     </tbody>
                                 </table>
                             )}
                         </div>
-                        {this.dataDoc.simulation_type != 'Pendulum' && this.dataDoc.simulation_type != 'Spring' && (
+                        {this.simulationType != 'Pendulum' && this.simulationType != 'Spring' && (
                             <div>
                                 <p>Kinematic Equations</p>
                                 <ul>
@@ -2052,7 +2062,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </ul>
                             </div>
                         )}
-                        {this.dataDoc.simulation_type == 'Spring' && (
+                        {this.simulationType == 'Spring' && (
                             <div>
                                 <p>Harmonic Motion Equations: Spring</p>
                                 <ul>
@@ -2081,7 +2091,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </ul>
                             </div>
                         )}
-                        {this.dataDoc.simulation_type == 'Pendulum' && (
+                        {this.simulationType == 'Pendulum' && (
                             <div>
                                 <p>Harmonic Motion Equations: Pendulum</p>
                                 <ul>
@@ -2116,7 +2126,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                             top: this.yMax - 120 + 40 + 'px',
                             left: this.xMin + 90 - 80 + 'px',
                         }}>
-                        {this.dataDoc.simulation_type == 'Circular Motion' ? 'Z' : 'Y'}
+                        {this.simulationType == 'Circular Motion' ? 'Z' : 'Y'}
                     </p>
                     <p
                         style={{
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 025c757c9..ac28ee4a0 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -1,6 +1,5 @@
 import { computed, trace } from 'mobx';
 import { observer } from 'mobx-react';
-import { Doc, HeightSym, WidthSym } from '../../../../fields/Doc';
 import './PhysicsSimulationBox.scss';
 import React = require('react');
 
@@ -17,10 +16,9 @@ interface IForce {
     component: boolean;
 }
 export interface IWeightProps {
-    dataDoc: Doc;
-    layoutDoc: Doc;
-    adjustPendulumAngle: number;
-    adjustPendulumLength: number;
+    pause: () => void;
+    panelWidth: () => number;
+    panelHeight: () => number;
     circularMotionRadius: number;
     coefficientOfKineticFriction: number;
     color: string;
@@ -50,6 +48,7 @@ export interface IWeightProps {
     springStartLength: number;
     startForces: () => IForce[];
     startPendulumAngle: number;
+    startPendulumLength: number;
     startPosX: number;
     startPosY: number;
     startVelX: number;
@@ -59,6 +58,11 @@ export interface IWeightProps {
     updateMassPosY: number;
     forcesUpdated: () => IForce[];
     setForcesUpdated: (x: IForce[]) => {};
+    setPosition: (x: number | undefined, y: number | undefined) => void;
+    setVelocity: (x: number | undefined, y: number | undefined) => void;
+    setAcceleration: (x: number, y: number) => void;
+    setPendulumAngle: (ang: number | undefined, length: number | undefined) => void;
+    setSpringLength: (length: number) => void;
     wallPositions: IWallProps[];
     wedgeHeight: number;
     wedgeWidth: number;
@@ -147,43 +151,15 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     // Helper function to go between display and real values
     getDisplayYPos = (yPos: number) => this.props.yMax - yPos - 2 * this.props.radius + 5;
 
-    // Set display values based on real values
-    setPosition = (xPos: number | undefined, yPos: number | undefined) => {
-        if (this.props.color == 'red') {
-            yPos !== undefined && (this.props.dataDoc.mass1_positionY = Math.round(this.getDisplayYPos(yPos) * 100) / 100);
-            xPos !== undefined && (this.props.dataDoc.mass1_positionX = Math.round(xPos * 100) / 100);
-        } else {
-            yPos !== undefined && (this.props.dataDoc.mass2_positionY = Math.round(this.getDisplayYPos(yPos) * 100) / 100);
-            xPos !== undefined && (this.props.dataDoc.mass2_positionX = Math.round(xPos * 100) / 100);
-        }
-    };
-    setVelocity = (xVel: number | undefined, yVel: number | undefined) => {
-        if (this.props.color == 'red') {
-            yVel !== undefined && (this.props.dataDoc.mass1_velocityY = (-1 * Math.round(yVel * 100)) / 100);
-            xVel !== undefined && (this.props.dataDoc.mass1_velocityX = Math.round(xVel * 100) / 100);
-        } else {
-            yVel !== undefined && (this.props.dataDoc.mass2_velocityY = (-1 * Math.round(yVel * 100)) / 100);
-            xVel !== undefined && (this.props.dataDoc.mass2_velocityX = Math.round(xVel * 100) / 100);
-        }
-    };
-    setAcceleration = (xAccel: number, yAccel: number) => {
-        if (this.props.color == 'red') {
-            this.props.dataDoc.mass1_accelerationY = yAccel;
-            this.props.dataDoc.mass1_accelerationX = xAccel;
-        } else {
-            this.props.dataDoc.mass2_accelerationY = yAccel;
-            this.props.dataDoc.mass2_accelerationX = xAccel;
-        }
-
-        this.setState({ xAccel });
-        this.setState({ yAccel });
-    };
-
     // Update display values when simulation updates
     setDisplayValues = (xPos: number = this.state.xPosition, yPos: number = this.state.yPosition, xVel: number = this.state.xVelocity, yVel: number = this.state.yVelocity) => {
-        this.setPosition(xPos, yPos);
-        this.setVelocity(xVel, yVel);
-        this.setAcceleration(Math.round(this.getNewAccelerationX(this.props.forcesUpdated()) * 100) / 100, (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated()) * 100)) / 100);
+        this.props.setPosition(xPos, this.getDisplayYPos(yPos));
+        this.props.setVelocity(xVel, yVel);
+        const xAccel = Math.round(this.getNewAccelerationX(this.props.forcesUpdated()) * 100) / 100;
+        const yAccel = (-1 * Math.round(this.getNewAccelerationY(this.props.forcesUpdated()) * 100)) / 100;
+        this.props.setAcceleration(xAccel, yAccel);
+        this.setState({ xAccel });
+        this.setState({ yAccel });
     };
 
     componentDidUpdate(prevProps: Readonly<IWeightProps>, prevState: Readonly<IState>, snapshot?: any): void {
@@ -194,18 +170,17 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         }
 
         // Change pendulum angle from input field
-        if (prevProps.adjustPendulumAngle != this.props.adjustPendulumAngle || prevProps.adjustPendulumLength !== this.props.adjustPendulumLength) {
-            let length = this.props.adjustPendulumLength;
-            const x = length * Math.cos(((90 - this.props.adjustPendulumAngle) * Math.PI) / 180);
-            const y = length * Math.sin(((90 - this.props.adjustPendulumAngle) * Math.PI) / 180);
+        if (prevProps.startPendulumAngle != this.props.startPendulumAngle || prevProps.startPendulumLength !== this.props.startPendulumLength) {
+            let length = this.props.startPendulumLength;
+            const x = length * Math.cos(((90 - this.props.startPendulumAngle) * Math.PI) / 180);
+            const y = length * Math.sin(((90 - this.props.startPendulumAngle) * Math.PI) / 180);
             const xPos = this.props.xMax / 2 - x - this.props.radius;
             const yPos = y - this.props.radius - 5;
             this.setState({ xPosition: xPos });
             this.setState({ yPosition: yPos });
             this.setState({ updatedStartPosX: xPos });
             this.setState({ updatedStartPosY: yPos });
-            this.props.dataDoc.pendulum_angle = this.props.adjustPendulumAngle;
-            this.props.dataDoc.pendulum_length = this.props.adjustPendulumLength;
+            this.props.setPendulumAngle(this.props.startPendulumAngle, this.props.startPendulumLength);
         }
 
         // When display values updated by user, update real value
@@ -215,7 +190,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             x = Math.min(x, this.props.xMax - 2 * this.props.radius);
             this.setState({ updatedStartPosX: x });
             this.setState({ xPosition: x });
-            this.setPosition(x, undefined);
+            this.props.setPosition(x, undefined);
         }
         if (prevProps.updateMassPosY != this.props.updateMassPosY) {
             let y = this.props.updateMassPosY;
@@ -224,18 +199,18 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             let coordinatePosition = this.getDisplayYPos(y);
             this.setState({ updatedStartPosY: coordinatePosition });
             this.setState({ yPosition: coordinatePosition });
-            this.setPosition(undefined, y);
+            this.props.setPosition(undefined, this.getDisplayYPos(y));
 
             if (this.props.displayXVelocity != this.state.xVelocity) {
                 let x = this.props.displayXVelocity;
                 this.setState({ xVelocity: x });
-                this.setVelocity(x, undefined);
+                this.props.setVelocity(x, undefined);
             }
 
             if (this.props.displayYVelocity != -this.state.yVelocity) {
                 let y = this.props.displayYVelocity;
                 this.setState({ yVelocity: -y });
-                this.setVelocity(undefined, y);
+                this.props.setVelocity(undefined, y);
             }
         }
 
@@ -360,7 +335,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             if (this.props.paused && !isNaN(this.props.startPosX)) {
                 this.setState({ xPosition: this.props.startPosX });
                 this.setState({ updatedStartPosX: this.props.startPosX });
-                this.setPosition(this.props.startPosX, undefined);
+                this.props.setPosition(this.props.startPosX, undefined);
             }
         }
 
@@ -369,7 +344,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             if (this.props.paused && !isNaN(this.props.startPosY)) {
                 this.setState({ yPosition: this.props.startPosY });
                 this.setState({ updatedStartPosY: this.props.startPosY ?? 0 });
-                this.setPosition(undefined, this.props.startPosY ?? 0);
+                this.props.setPosition(undefined, this.getDisplayYPos(this.props.startPosY));
             }
         }
 
@@ -410,23 +385,11 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         this.setState({ yPosition: this.state.updatedStartPosY });
         this.setState({ xVelocity: this.props.startVelX });
         this.setState({ yVelocity: this.props.startVelY });
-        this.props.dataDoc.pendulum_angle = this.props.startPendulumAngle;
+        this.props.setPendulumAngle(this.props.startPendulumAngle, undefined);
         this.props.setForcesUpdated(this.props.startForces());
-        if (this.props.color == 'red') {
-            this.props.dataDoc.mass1_positionX = this.state.updatedStartPosX;
-            this.props.dataDoc.mass1_positionY = this.state.updatedStartPosY;
-            this.props.dataDoc.mass1_velocityX = this.props.startVelX;
-            this.props.dataDoc.mass1_velocityY = this.props.startVelY;
-            this.props.dataDoc.mass1_accelerationX = 0;
-            this.props.dataDoc.mass1_accelerationY = 0;
-        } else {
-            this.props.dataDoc.mass2_positionX = this.state.updatedStartPosX;
-            this.props.dataDoc.mass2_positionY = this.state.updatedStartPosY;
-            this.props.dataDoc.mass2_velocityX = this.props.startVelX;
-            this.props.dataDoc.mass2_velocityY = this.props.startVelY;
-            this.props.dataDoc.mass2_accelerationX = 0;
-            this.props.dataDoc.mass2_accelerationY = 0;
-        }
+        this.props.setPosition(this.state.updatedStartPosX, this.state.updatedStartPosY);
+        this.props.setVelocity(this.props.startVelX, this.props.startVelY);
+        this.props.setAcceleration(0, 0);
         this.setState({ angleLabel: Math.round(this.props.pendulumAngle * 100) / 100 });
     };
 
@@ -514,7 +477,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         }
 
         const pendulumLength = Math.sqrt(x * x + y * y);
-        this.props.dataDoc.pendulum_angle = oppositeAngle;
+        this.props.setPendulumAngle(oppositeAngle, undefined);
 
         const mag = this.props.mass * Math.abs(this.props.gravity) * Math.cos((oppositeAngle * Math.PI) / 180) + (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength;
 
@@ -544,7 +507,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         if (this.state.xVelocity != 0) {
             this.state.walls.forEach(wall => {
                 if (wall.angleInDegrees == 90) {
-                    const wallX = (wall.xPos / 100) * this.props.layoutDoc[WidthSym]();
+                    const wallX = (wall.xPos / 100) * this.props.panelWidth();
                     if (wall.xPos < 0.35) {
                         if (minX <= wallX) {
                             this.setState({ xPosition: wallX + 0.01 });
@@ -580,7 +543,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         if (this.state.yVelocity > 0) {
             this.state.walls.forEach(wall => {
                 if (wall.angleInDegrees == 0 && wall.yPos > 0.4) {
-                    const groundY = (wall.yPos / 100) * this.props.layoutDoc[HeightSym]();
+                    const groundY = (wall.yPos / 100) * this.props.panelHeight();
                     if (maxY > groundY) {
                         this.setState({ yPosition: groundY - 2 * this.props.radius - 0.01 });
                         if (this.props.elasticCollisions) {
@@ -626,7 +589,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         if (this.state.yVelocity < 0) {
             this.state.walls.forEach(wall => {
                 if (wall.angleInDegrees == 0 && wall.yPos < 0.4) {
-                    const groundY = (wall.yPos / 100) * this.props.layoutDoc[HeightSym]();
+                    const groundY = (wall.yPos / 100) * this.props.panelHeight();
                     if (minY < groundY) {
                         this.setState({ yPosition: groundY + 0.01 });
                         if (this.props.elasticCollisions) {
@@ -800,7 +763,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                     className="weightContainer"
                     onPointerDown={e => {
                         if (this.draggable) {
-                            this.props.dataDoc.paused = true;
+                            this.props.pause();
                             this.setState({ dragging: true });
                             this.setState({ clickPositionX: e.clientX });
                             this.setState({ clickPositionY: e.clientY });
@@ -830,10 +793,10 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             }
 
                             this.setState({ yPosition: newY });
-                            this.props.dataDoc.mass1_positionY = Math.round((this.props.yMax - 2 * this.props.radius - newY + 5) * 100) / 100;
+                            this.props.setPosition(undefined, Math.round((this.props.yMax - 2 * this.props.radius - newY + 5) * 100) / 100);
                             if (this.props.simulationType != 'Pulley') {
                                 this.setState({ xPosition: newX });
-                                this.props.dataDoc.mass1_positionX = newX;
+                                this.props.setPosition(newX, undefined);
                             }
                             if (this.props.simulationType != 'Suspension') {
                                 if (this.props.simulationType != 'Pulley') {
@@ -866,7 +829,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                 newX = 10;
                             }
                             if (this.props.simulationType == 'Spring') {
-                                this.props.dataDoc.spring_lengthStart = newY;
+                                this.props.setSpringLength(newY);
                             }
                             if (this.props.simulationType == 'Suspension') {
                                 let x1rod = (this.props.xMax + this.props.xMin) / 2 - this.props.radius - this.props.yMin - 200;
@@ -915,7 +878,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             left: 0,
                             top: 0,
                         }}>
-                        <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                        <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
                             {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(val => {
                                 const count = 10;
                                 let xPos1;
@@ -946,7 +909,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             left: 0,
                             top: 0,
                         }}>
-                        <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                        <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
                             <line x1={this.state.xPosition + this.props.radius} y1={this.state.yPosition + this.props.radius} x2={this.state.xPosition + this.props.radius} y2={this.props.yMin} stroke={'#deb887'} strokeWidth="10" />
                         </svg>
                     </div>
@@ -960,7 +923,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             left: 0,
                             top: 0,
                         }}>
-                        <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                        <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
                             <circle cx={(this.props.xMax + this.props.xMin) / 2} cy={this.props.radius} r={this.props.radius * 1.5} fill={'#808080'} />
                         </svg>
                     </div>
@@ -974,7 +937,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             left: 0,
                             top: 0,
                         }}>
-                        <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                        <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
                             <line
                                 x1={this.state.xPosition + this.props.radius}
                                 y1={this.state.yPosition + this.props.radius}
@@ -1004,7 +967,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                 left: 0,
                                 top: 0,
                             }}>
-                            <svg width={this.props.layoutDoc._width + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                            <svg width={this.props.panelWidth() + 'px'} height={this.props.panelHeight() + 'px'}>
                                 <line
                                     x1={this.state.xPosition + this.props.radius}
                                     y1={this.state.yPosition + this.props.radius}
@@ -1039,7 +1002,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             left: 0,
                             top: 0,
                         }}>
-                        <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                        <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
                             <line
                                 x1={this.state.xPosition + this.props.radius}
                                 y1={this.state.yPosition + this.props.radius}
@@ -1060,7 +1023,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             left: 0,
                             top: 0,
                         }}>
-                        <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                        <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
                             <line x1={this.state.xPosition + this.props.radius} y1={this.state.yPosition + this.props.radius} x2={this.props.xMax / 2} y2={-5} stroke={'#deb887'} strokeWidth="10" />
                         </svg>
                         {!this.state.dragging && (
@@ -1115,7 +1078,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                 left: 0,
                                 top: 0,
                             }}>
-                            <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                            <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
                                 <defs>
                                     <marker id="accArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
                                         <path d="M0,0 L0,6 L9,3 z" fill="green" />
@@ -1156,7 +1119,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                 left: 0,
                                 top: 0,
                             }}>
-                            <svg width={this.props.xMax + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                            <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
                                 <defs>
                                     <marker id="velArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
                                         <path d="M0,0 L0,6 L9,3 z" fill="blue" />
@@ -1224,7 +1187,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                         left: this.props.xMin,
                                         top: this.props.yMin,
                                     }}>
-                                    <svg width={this.props.xMax - this.props.xMin + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                                    <svg width={this.props.xMax - this.props.xMin + 'px'} height={this.props.panelHeight() + 'px'}>
                                         <defs>
                                             <marker id="forceArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
                                                 <path d="M0,0 L0,6 L9,3 z" fill={color} />
@@ -1289,7 +1252,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                         left: this.props.xMin,
                                         top: this.props.yMin,
                                     }}>
-                                    <svg width={this.props.xMax - this.props.xMin + 'px'} height={this.props.layoutDoc._height + 'px'}>
+                                    <svg width={this.props.xMax - this.props.xMin + 'px'} height={this.props.panelHeight() + 'px'}>
                                         <defs>
                                             <marker id="forceArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
                                                 <path d="M0,0 L0,6 L9,3 z" fill={color} />
-- 
cgit v1.2.3-70-g09d2


From ec0c8abac9b3a3064dd4f102df0fcc010cfca7cf Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 23 May 2023 15:16:15 -0400
Subject: fixed remaining errors in phys

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 132 +++++++++++----------
 1 file changed, 69 insertions(+), 63 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index fa47a218b..eb41e0de8 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -66,7 +66,7 @@ interface TutorialTemplate {
             directionInDegrees: number;
             component: boolean;
         }[];
-        show_Magnitude: boolean;
+        showMagnitude: boolean;
     }[];
 }
 
@@ -168,6 +168,16 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     radius = 50;
     wallPositions: IWallProps[] = [];
 
+    @computed get selectedQuestion() {
+        return this.dataDoc.selectedQuestion ? (JSON.parse(StrCast(this.dataDoc.selectedQuestion)) as QuestionTemplate) : questions.inclinePlane[0];
+    }
+    @computed get tutorial() {
+        return this.dataDoc.tutorial ? (JSON.parse(StrCast(this.dataDoc.tutorial)) as TutorialTemplate) : tutorials.inclinePlane;
+    }
+    @computed get selectedSolutions() {
+        return NumListCast(this.dataDoc.selectedSolutions);
+    }
+
     componentDidMount() {
         // Used throughout sims
         this.layoutDoc._width = 1000;
@@ -182,12 +192,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         // this.dataDoc.forceSketches = this.dataDoc.forceSketches ?? [];
         this.dataDoc.questionPartOne = '';
         this.dataDoc.questionPartTwo = '';
-        this.dataDoc.selectedQuestion = this.dataDoc.selectedQuestion ?? questions.inclinePlane[0];
         // this.dataDoc.sketching = this.dataDoc.sketching ?? false;
 
-        // Used for tutorial mode
-        this.dataDoc.tutorial = this.dataDoc.tutorial ?? tutorials.inclinePlane;
-
         // Setup simulation
         this.setupSimulation();
 
@@ -314,7 +320,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.dataDoc.simulation_showForces = true;
                 this.dataDoc.mass1_positionYstart = this.yMax - 100;
                 this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
-                this.dataDoc.tutorial = tutorials.freeWeight;
+                this.dataDoc.tutorial = JSON.stringify(tutorials.freeWeight);
                 this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.freeWeight.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.freeWeight.steps[0].showMagnitude;
             } else if (this.simulationType == 'Spring') {
@@ -322,37 +328,37 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.setupSpring();
                 this.dataDoc.mass1_positionYstart = this.yMin + 200 + 19.62;
                 this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
-                this.dataDoc.tutorial = tutorials.spring;
+                this.dataDoc.tutorial = JSON.stringify(tutorials.spring);
                 this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.spring.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.spring.steps[0].showMagnitude;
             } else if (this.simulationType == 'Pendulum') {
                 this.setupPendulum();
-                this.dataDoc.tutorial = tutorials.pendulum;
+                this.dataDoc.tutorial = JSON.stringify(tutorials.pendulum);
                 this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.pendulum.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.pendulum.steps[0].showMagnitude;
             } else if (this.simulationType == 'Inclined Plane') {
                 this.dataDoc.simulation_showForces = true;
                 this.dataDoc.wedge_angle = 26;
                 this.changeWedgeBasedOnNewAngle(26);
-                this.dataDoc.tutorial = tutorials.inclinePlane;
+                this.dataDoc.tutorial = JSON.stringify(tutorials.inclinePlane);
                 this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.inclinePlane.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.inclinePlane.steps[0].showMagnitude;
             } else if (this.simulationType == 'Circular Motion') {
                 this.dataDoc.simulation_showForces = true;
                 this.setupCircular(40);
-                this.dataDoc.tutorial = tutorials.circular;
+                this.dataDoc.tutorial = JSON.stringify(tutorials.circular);
                 this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.circular.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.circular.steps[0].showMagnitude;
             } else if (this.simulationType == 'Pulley') {
                 this.dataDoc.simulation_showForces = true;
                 this.setupPulley();
-                this.dataDoc.tutorial = tutorials.pulley;
+                this.dataDoc.tutorial = JSON.stringify(tutorials.pulley);
                 this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.pulley.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.pulley.steps[0].showMagnitude;
             } else if (this.simulationType == 'Suspension') {
                 this.dataDoc.simulation_showForces = true;
                 this.setupSuspension();
-                this.dataDoc.tutorial = tutorials.suspension;
+                this.dataDoc.tutorial = JSON.stringify(tutorials.suspension);
                 this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.suspension.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.suspension.steps[0].showMagnitude;
             }
@@ -469,7 +475,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     // In review mode, update forces when coefficient of static friction changed
     updateReviewForcesBasedOnCoefficient = (coefficient: number) => {
         let theta = this.wedgeAngle;
-        let index = this.dataDoc.selectedQuestion.variablesForQuestionSetup.indexOf('theta - max 45');
+        let index = this.selectedQuestion.variablesForQuestionSetup.indexOf('theta - max 45');
         if (index >= 0) {
             theta = NumListCast(this.dataDoc.questionVariables)[index];
         }
@@ -550,7 +556,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 solutions.push((Math.atan(muS) * 180) / Math.PI);
             }
         }
-        this.dataDoc.selectedSolutions = solutions;
+        this.dataDoc.selectedSolutions = new List<number>(solutions);
         return solutions;
     };
 
@@ -558,38 +564,38 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     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) {
+        if (this.selectedQuestion) {
+            for (let i = 0; i < this.selectedQuestion.answerParts.length; i++) {
+                if (this.selectedQuestion.answerParts[i] == 'force of gravity') {
+                    if (Math.abs(NumCast(this.dataDoc.review_GravityMagnitude) - this.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) {
+                } else if (this.selectedQuestion.answerParts[i] == 'angle of gravity') {
+                    if (Math.abs(NumCast(this.dataDoc.review_GravityAngle) - this.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) {
+                } else if (this.selectedQuestion.answerParts[i] == 'normal force') {
+                    if (Math.abs(NumCast(this.dataDoc.review_NormalMagnitude) - this.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) {
+                } else if (this.selectedQuestion.answerParts[i] == 'angle of normal force') {
+                    if (Math.abs(NumCast(this.dataDoc.review_NormalAngle) - this.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) {
+                } else if (this.selectedQuestion.answerParts[i] == 'force of static friction') {
+                    if (Math.abs(NumCast(this.dataDoc.review_StaticMagnitude) - this.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) {
+                } else if (this.selectedQuestion.answerParts[i] == 'angle of static friction') {
+                    if (Math.abs(NumCast(this.dataDoc.review_StaticAngle) - this.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) {
+                } else if (this.selectedQuestion.answerParts[i] == 'coefficient of static friction') {
+                    if (Math.abs(NumCast(this.dataDoc.coefficientOfStaticFriction) - this.selectedSolutions[i]) > epsilon) {
                         error = true;
                     }
-                } else if (this.dataDoc.selectedQuestion.answerParts[i] == 'wedge angle') {
-                    if (Math.abs(this.wedgeAngle - this.dataDoc.selectedSolutions[i]) > epsilon) {
+                } else if (this.selectedQuestion.answerParts[i] == 'wedge angle') {
+                    if (Math.abs(this.wedgeAngle - this.selectedSolutions[i]) > epsilon) {
                         error = true;
                     }
                 }
@@ -608,7 +614,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 }, 3000);
             }
         }
-        if (this.dataDoc.selectedQuestion.goal == 'noMovement') {
+        if (this.selectedQuestion.goal == 'noMovement') {
             if (!error) {
                 this.dataDoc.noMovement = true;
             } else {
@@ -674,7 +680,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             }
         }
         this.dataDoc.questionVariables = new List<number>(vars);
-        this.dataDoc.selectedQuestion = question;
+        this.dataDoc.selectedQuestion = JSON.stringify(question);
         this.dataDoc.questionPartOne = q;
         this.dataDoc.questionPartTwo = question.question;
         this.dataDoc.answers = new List<number>(this.getAnswersToQuestion(question, vars));
@@ -1111,7 +1117,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 <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) => (
+                                        {this.selectedQuestion.hints?.map((hint: any, index: number) => (
                                             <div key={index}>
                                                 <DialogContentText>
                                                     <details>
@@ -1136,7 +1142,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                         <p>{StrCast(this.dataDoc.questionPartTwo)}</p>
                                     </div>
                                     <div className="answers">
-                                        {this.dataDoc.selectedQuestion.answerParts.includes('force of gravity') && (
+                                        {this.selectedQuestion.answerParts.includes('force of gravity') && (
                                             <InputField
                                                 label={<p>Gravity magnitude</p>}
                                                 lowerBound={0}
@@ -1147,11 +1153,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 upperBound={50}
                                                 value={NumCast(this.dataDoc.review_GravityMagnitude)}
                                                 showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
-                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('force of gravity')]}
+                                                correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('force of gravity')]}
                                                 labelWidth={'7em'}
                                             />
                                         )}
-                                        {this.dataDoc.selectedQuestion.answerParts.includes('angle of gravity') && (
+                                        {this.selectedQuestion.answerParts.includes('angle of gravity') && (
                                             <InputField
                                                 label={<p>Gravity angle</p>}
                                                 lowerBound={0}
@@ -1163,11 +1169,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 value={NumCast(this.dataDoc.review_GravityAngle)}
                                                 radianEquivalent={true}
                                                 showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
-                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('angle of gravity')]}
+                                                correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('angle of gravity')]}
                                                 labelWidth={'7em'}
                                             />
                                         )}
-                                        {this.dataDoc.selectedQuestion.answerParts.includes('normal force') && (
+                                        {this.selectedQuestion.answerParts.includes('normal force') && (
                                             <InputField
                                                 label={<p>Normal force magnitude</p>}
                                                 lowerBound={0}
@@ -1178,11 +1184,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 upperBound={50}
                                                 value={NumCast(this.dataDoc.review_NormalMagnitude)}
                                                 showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
-                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('normal force')]}
+                                                correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('normal force')]}
                                                 labelWidth={'7em'}
                                             />
                                         )}
-                                        {this.dataDoc.selectedQuestion.answerParts.includes('angle of normal force') && (
+                                        {this.selectedQuestion.answerParts.includes('angle of normal force') && (
                                             <InputField
                                                 label={<p>Normal force angle</p>}
                                                 lowerBound={0}
@@ -1194,11 +1200,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 value={NumCast(this.dataDoc.review_NormalAngle)}
                                                 radianEquivalent={true}
                                                 showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
-                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('angle of normal force')]}
+                                                correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('angle of normal force')]}
                                                 labelWidth={'7em'}
                                             />
                                         )}
-                                        {this.dataDoc.selectedQuestion.answerParts.includes('force of static friction') && (
+                                        {this.selectedQuestion.answerParts.includes('force of static friction') && (
                                             <InputField
                                                 label={<p>Static friction magnitude</p>}
                                                 lowerBound={0}
@@ -1209,11 +1215,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 upperBound={50}
                                                 value={NumCast(this.dataDoc.review_StaticMagnitude)}
                                                 showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
-                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('force of static friction')]}
+                                                correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('force of static friction')]}
                                                 labelWidth={'7em'}
                                             />
                                         )}
-                                        {this.dataDoc.selectedQuestion.answerParts.includes('angle of static friction') && (
+                                        {this.selectedQuestion.answerParts.includes('angle of static friction') && (
                                             <InputField
                                                 label={<p>Static friction angle</p>}
                                                 lowerBound={0}
@@ -1225,11 +1231,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 value={NumCast(this.dataDoc.review_StaticAngle)}
                                                 radianEquivalent={true}
                                                 showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
-                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('angle of static friction')]}
+                                                correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('angle of static friction')]}
                                                 labelWidth={'7em'}
                                             />
                                         )}
-                                        {this.dataDoc.selectedQuestion.answerParts.includes('coefficient of static friction') && (
+                                        {this.selectedQuestion.answerParts.includes('coefficient of static friction') && (
                                             <InputField
                                                 label={
                                                     <Box>
@@ -1245,10 +1251,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 value={NumCast(this.dataDoc.coefficientOfStaticFriction)}
                                                 effect={this.updateReviewForcesBasedOnCoefficient}
                                                 showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
-                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('coefficient of static friction')]}
+                                                correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('coefficient of static friction')]}
                                             />
                                         )}
-                                        {this.dataDoc.selectedQuestion.answerParts.includes('wedge angle') && (
+                                        {this.selectedQuestion.answerParts.includes('wedge angle') && (
                                             <InputField
                                                 label={<Box>&theta;</Box>}
                                                 lowerBound={0}
@@ -1264,7 +1270,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                 }}
                                                 radianEquivalent={true}
                                                 showIcon={BoolCast(this.dataDoc.simulation_showIcon)}
-                                                correctValue={NumListCast(this.dataDoc.answers)[this.dataDoc.selectedQuestion.answerParts.indexOf('wedge angle')]}
+                                                correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('wedge angle')]}
                                             />
                                         )}
                                     </div>
@@ -1275,7 +1281,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                             <div className="wordProblemBox">
                                 <div className="question">
                                     <h2>Problem</h2>
-                                    <p>{this.dataDoc.tutorial.question}</p>
+                                    <p>{this.tutorial.question}</p>
                                 </div>
                                 <div
                                     style={{
@@ -1287,32 +1293,32 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                         onClick={() => {
                                             let step = NumCast(this.dataDoc.tutorial_stepNumber) - 1;
                                             step = Math.max(step, 0);
-                                            step = Math.min(step, this.dataDoc.tutorial.steps.length - 1);
+                                            step = Math.min(step, this.tutorial.steps.length - 1);
                                             this.dataDoc.tutorial_stepNumber = step;
-                                            this.dataDoc.mass1_forcesStart = this.dataDoc.tutorial.steps[step].forces;
-                                            this.dataDoc.mass1_forcesUpdated = this.dataDoc.tutorial.steps[step].forces;
-                                            this.dataDoc.simulation_showForceMagnitudes = this.dataDoc.tutorial.steps[step].show_Magnitude;
+                                            this.dataDoc.mass1_forcesStart = JSON.stringify(this.tutorial.steps[step].forces);
+                                            this.dataDoc.mass1_forcesUpdated = JSON.stringify(this.tutorial.steps[step].forces);
+                                            this.dataDoc.simulation_showForceMagnitudes = this.tutorial.steps[step].showMagnitude;
                                         }}
                                         disabled={this.dataDoc.tutorial_stepNumber == 0}>
                                         <ArrowLeftIcon />
                                     </IconButton>
                                     <div>
                                         <h3>
-                                            Step {NumCast(this.dataDoc.tutorial_stepNumber) + 1}: {this.dataDoc.tutorial.steps[this.dataDoc.tutorial_stepNumber].description}
+                                            Step {NumCast(this.dataDoc.tutorial_stepNumber) + 1}: {this.tutorial.steps[NumCast(this.dataDoc.tutorial_stepNumber)].description}
                                         </h3>
-                                        <p>{this.dataDoc.tutorial.steps[NumCast(this.dataDoc.tutorial_stepNumber)].content}</p>
+                                        <p>{this.tutorial.steps[NumCast(this.dataDoc.tutorial_stepNumber)].content}</p>
                                     </div>
                                     <IconButton
                                         onClick={() => {
                                             let step = NumCast(this.dataDoc.tutorial_stepNumber) + 1;
                                             step = Math.max(step, 0);
-                                            step = Math.min(step, this.dataDoc.tutorial.steps.length - 1);
+                                            step = Math.min(step, this.tutorial.steps.length - 1);
                                             this.dataDoc.tutorial_stepNumber = step;
-                                            this.dataDoc.mass1_forcesStart = this.dataDoc.tutorial.steps[step].forces;
-                                            this.dataDoc.mass1_forcesUpdated = this.dataDoc.tutorial.steps[step].forces;
-                                            this.dataDoc.simulation_showForceMagnitudes = this.dataDoc.tutorial.steps[step].show_Magnitude;
+                                            this.dataDoc.mass1_forcesStart = JSON.stringify(this.tutorial.steps[step].forces);
+                                            this.dataDoc.mass1_forcesUpdated = JSON.stringify(this.tutorial.steps[step].forces);
+                                            this.dataDoc.simulation_showForceMagnitudes = this.tutorial.steps[step].showMagnitude;
                                         }}
-                                        disabled={this.dataDoc.tutorial_stepNumber === this.dataDoc.tutorial.steps.length - 1}>
+                                        disabled={this.dataDoc.tutorial_stepNumber === this.tutorial.steps.length - 1}>
                                         <ArrowRightIcon />
                                     </IconButton>
                                 </div>
-- 
cgit v1.2.3-70-g09d2


From 26af8ab71bec926e4514c7df2d523f1635f55f9b Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 23 May 2023 15:59:44 -0400
Subject: fixed resizing physbox container.

---
 src/client/documents/Documents.ts                  |   4 +-
 .../nodes/PhysicsBox/PhysicsSimulationBox.scss     |   2 +
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 138 ++++++++++-----------
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   |   2 +-
 4 files changed, 68 insertions(+), 78 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 1a2409508..13c27d182 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -689,8 +689,8 @@ export namespace Docs {
                 DocumentType.SIMULATION,
                 {
                     data: '',
-                    layout: { view: PhysicsSimulationBox, dataField: defaultDataKey },
-                    options: { _height: 100, position: '', acceleration: '', pendulum: '', spring: '', wedge: '', simulation: '', review: '' },
+                    layout: { view: PhysicsSimulationBox, dataField: defaultDataKey, _width: 1000, _height: 800 },
+                    options: { _height: 100, layout_forceReflow: true, nativeHeightUnfrozen: true, nativeDimModifiable: true, position: '', acceleration: '', pendulum: '', spring: '', wedge: '', simulation: '', review: '' },
                 },
             ],
         ]);
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
index c29e36a97..b498296bf 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
@@ -14,6 +14,8 @@
             position: fixed;
             left: 60%;
             padding: 1em;
+            height: 100%;
+            overflow: auto;
 
             .mechanicsSimulationControls {
                 display: flex;
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index eb41e0de8..bb41cd72e 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -76,10 +76,6 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         return FieldView.LayoutString(PhysicsSimulationBox, fieldKey);
     }
 
-    constructor(props: any) {
-        super(props);
-    }
-
     @computed get circularMotionRadius() {
         return NumCast(this.dataDoc.circularMotionRadius, 150);
     }
@@ -137,7 +133,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         return NumCast(this.dataDoc.mass1_positionXstart, Math.round((this.xMax * 0.5 - 200) * 10) / 10);
     }
     @computed get mass1PosYStart() {
-        return NumCast(this.dataDoc.mass1_positionYstart, this.getDisplayYPos((400 - 0.08 * this.layoutDoc[HeightSym]()) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26)));
+        return NumCast(this.dataDoc.mass1_positionYstart, this.getDisplayYPos((400 - 0.08 * this.props.PanelHeight()) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26)));
     }
     @computed get mass1VelXStart() {
         return NumCast(this.dataDoc.mass1_velocityXstart);
@@ -150,7 +146,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         return NumCast(this.dataDoc.mass2_positionXstart);
     }
     @computed get mass2PosYStart() {
-        return NumCast(this.dataDoc.mass2_positionYstart, this.getDisplayYPos((400 - 0.08 * this.layoutDoc[HeightSym]()) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26)));
+        return NumCast(this.dataDoc.mass2_positionYstart, this.getDisplayYPos((400 - 0.08 * this.props.PanelHeight()) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26)));
     }
     @computed get mass2VelXStart() {
         return NumCast(this.dataDoc.mass2_velocityXstart);
@@ -159,15 +155,6 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         return NumCast(this.dataDoc.mass2_velocityYstart);
     }
 
-    // Constants
-    xMin = 0;
-    yMin = 0;
-    xMax = 100;
-    yMax = 100;
-    color = `rgba(0,0,0,0.5)`;
-    radius = 50;
-    wallPositions: IWallProps[] = [];
-
     @computed get selectedQuestion() {
         return this.dataDoc.selectedQuestion ? (JSON.parse(StrCast(this.dataDoc.selectedQuestion)) as QuestionTemplate) : questions.inclinePlane[0];
     }
@@ -177,41 +164,42 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     @computed get selectedSolutions() {
         return NumListCast(this.dataDoc.selectedSolutions);
     }
+    @computed get questionPartOne() {
+        return StrCast(this.dataDoc.questionPartOne);
+    }
+    @computed get questionPartTwo() {
+        return StrCast(this.dataDoc.questionPartTwo);
+    }
+
+    // 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.simulation_showComponentForces = this.dataDoc.simulation_showComponentForces ?? false;
-        this.dataDoc.simulation_speed = NumCast(this.dataDoc.simulation_speed, 2);
-        // 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.questionPartOne = '';
-        this.dataDoc.questionPartTwo = '';
-        // this.dataDoc.sketching = this.dataDoc.sketching ?? false;
+        this.xMax = this.props.PanelWidth() * 0.6;
+        this.yMax = this.props.PanelHeight() * 0.9;
 
         // Setup simulation
         this.setupSimulation();
 
         // 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;
+        this.wallPositions = [
+            { length: (this.xMax / this.props.PanelWidth()) * 100, xPos: 0, yPos: 0, angleInDegrees: 0 },
+            { length: (this.xMax / this.props.PanelWidth()) * 100, xPos: 0, yPos: (this.yMax / this.props.PanelHeight()) * 100, angleInDegrees: 0 },
+            { length: (this.yMax / this.props.PanelHeight()) * 100, xPos: 0, yPos: 0, angleInDegrees: 90 },
+            { length: (this.yMax / this.props.PanelHeight()) * 100, xPos: (this.xMax / this.props.PanelWidth()) * 100, yPos: 0, angleInDegrees: 90 },
+        ];
     }
 
     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;
+        if (this.xMax !== this.props.PanelWidth() * 0.6 || this.yMax != this.props.PanelHeight() * 0.9) {
+            this.xMax = this.props.PanelWidth() * 0.6;
+            this.yMax = this.props.PanelHeight() * 0.9;
             this.setupSimulation();
         }
     }
@@ -230,10 +218,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             this.dataDoc.simulation_showForceMagnitudes = true;
             if (simulationType == 'One Weight') {
                 this.dataDoc.simulation_showComponentForces = false;
-                this.dataDoc.mass1_positionYstart = this.yMin + 0.08 * this.layoutDoc[HeightSym]();
-                this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
-                this.dataDoc.mass1_positionY = this.getDisplayYPos(this.yMin + 0.08 * this.layoutDoc[HeightSym]());
-                this.dataDoc.mass1_positionX = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
+                this.dataDoc.mass1_positionYstart = this.yMin + 0.08 * this.props.PanelHeight();
+                this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
+                this.dataDoc.mass1_positionY = this.getDisplayYPos(this.yMin + 0.08 * this.props.PanelHeight());
+                this.dataDoc.mass1_positionX = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
                 this.dataDoc.mass1_forcesUpdated = JSON.stringify([
                     {
                         description: 'Gravity',
@@ -319,7 +307,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             if (this.simulationType == 'One Weight') {
                 this.dataDoc.simulation_showForces = true;
                 this.dataDoc.mass1_positionYstart = this.yMax - 100;
-                this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
+                this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
                 this.dataDoc.tutorial = JSON.stringify(tutorials.freeWeight);
                 this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.freeWeight.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.freeWeight.steps[0].showMagnitude;
@@ -327,7 +315,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.dataDoc.simulation_showForces = true;
                 this.setupSpring();
                 this.dataDoc.mass1_positionYstart = this.yMin + 200 + 19.62;
-                this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
+                this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
                 this.dataDoc.tutorial = JSON.stringify(tutorials.spring);
                 this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.spring.steps[0].forces);
                 this.dataDoc.simulation_showForceMagnitudes = tutorials.spring.steps[0].showMagnitude;
@@ -368,10 +356,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
 
     // Helper function to go between display and real values
     getDisplayYPos = (yPos: number) => {
-        return this.yMax - yPos - 2 * (0.08 * this.layoutDoc[HeightSym]()) + 5;
+        return this.yMax - yPos - 2 * (0.08 * this.props.PanelHeight()) + 5;
     };
     getYPosFromDisplay = (yDisplay: number) => {
-        return this.yMax - yDisplay - 2 * (0.08 * this.layoutDoc[HeightSym]()) + 5;
+        return this.yMax - yDisplay - 2 * (0.08 * this.props.PanelHeight()) + 5;
     };
 
     // Update forces when coefficient of static friction changes in freeform mode
@@ -442,27 +430,27 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.wedge_height = 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;
+        let yPos = this.yMax - 0.08 * this.props.PanelHeight() * 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;
+            yPos += 0.08 * this.props.PanelHeight() * 0.1;
         } else if (angle >= 10 && angle < 15) {
-            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.23;
+            yPos += 0.08 * this.props.PanelHeight() * 0.23;
         } else if (angle >= 15 && angle < 20) {
-            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.26;
+            yPos += 0.08 * this.props.PanelHeight() * 0.26;
         } else if (angle >= 20 && angle < 25) {
-            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.33;
+            yPos += 0.08 * this.props.PanelHeight() * 0.33;
         } else if (angle >= 25 && angle < 30) {
-            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.35;
+            yPos += 0.08 * this.props.PanelHeight() * 0.35;
         } else if (angle >= 30 && angle < 35) {
-            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.4;
+            yPos += 0.08 * this.props.PanelHeight() * 0.4;
         } else if (angle >= 35 && angle < 40) {
-            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.45;
+            yPos += 0.08 * this.props.PanelHeight() * 0.45;
         } else if (angle >= 40 && angle < 45) {
-            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.47;
+            yPos += 0.08 * this.props.PanelHeight() * 0.47;
         } else if (angle >= 45) {
-            yPos += 0.08 * this.layoutDoc[HeightSym]() * 0.52;
+            yPos += 0.08 * this.props.PanelHeight() * 0.52;
         }
 
         this.dataDoc.mass1_positionXstart = this.xMax * 0.25;
@@ -692,8 +680,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.simulation_showComponentForces = false;
         this.dataDoc.mass1_velocityYstart = 0;
         this.dataDoc.mass1_velocityXstart = value;
-        let xPos = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
-        let yPos = (this.yMax + this.yMin) / 2 + this.circularMotionRadius - 0.08 * this.layoutDoc[HeightSym]();
+        let xPos = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
+        let yPos = (this.yMax + this.yMin) / 2 + this.circularMotionRadius - 0.08 * this.props.PanelHeight();
         this.dataDoc.mass1_positionYstart = yPos;
         this.dataDoc.mass1_positionXstart = xPos;
         const tensionForce: IForce = {
@@ -713,8 +701,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         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;
+        const xPos = this.xMax / 2 - x - 0.08 * this.props.PanelHeight();
+        const yPos = y - 0.08 * this.props.PanelHeight() - 5;
         this.dataDoc.mass1_positionXstart = xPos;
         this.dataDoc.mass1_positionYstart = yPos;
         const mag = this.mass1 * Math.abs(this.gravity) * Math.sin((60 * Math.PI) / 180);
@@ -778,7 +766,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         };
         this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce]);
         this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce]);
-        this.dataDoc.mass1_positionXstart = this.xMax / 2 - 0.08 * this.layoutDoc[HeightSym]();
+        this.dataDoc.mass1_positionXstart = this.xMax / 2 - 0.08 * this.props.PanelHeight();
         this.dataDoc.mass1_positionYstart = 200;
         this.dataDoc.spring_constant = 0.5;
         this.dataDoc.spring_lengthRest = 200;
@@ -788,7 +776,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
 
     // Default setup for suspension simulation
     setupSuspension = () => {
-        let xPos = (this.xMax + this.xMin) / 2 - 0.08 * this.layoutDoc[HeightSym]();
+        let xPos = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
         let yPos = this.yMin + 200;
         this.dataDoc.mass1_positionYstart = yPos;
         this.dataDoc.mass1_positionXstart = xPos;
@@ -822,9 +810,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     setupPulley = () => {
         this.dataDoc.simulation_showComponentForces = false;
         this.dataDoc.mass1_positionYstart = (this.yMax + this.yMin) / 2;
-        this.dataDoc.mass1_positionXstart = (this.xMin + this.xMax) / 2 - 2 * (0.08 * this.layoutDoc[HeightSym]()) - 5;
+        this.dataDoc.mass1_positionXstart = (this.xMin + this.xMax) / 2 - 2 * (0.08 * this.props.PanelHeight()) - 5;
         this.dataDoc.mass1_positionY = this.getDisplayYPos((this.yMax + this.yMin) / 2);
-        this.dataDoc.mass1_positionX = (this.xMin + this.xMax) / 2 - 2 * (0.08 * this.layoutDoc[HeightSym]()) - 5;
+        this.dataDoc.mass1_positionX = (this.xMin + this.xMax) / 2 - 2 * (0.08 * this.props.PanelHeight()) - 5;
         let a = (-1 * ((this.mass1 - this.mass2) * Math.abs(this.gravity))) / (this.mass1 + this.mass2);
         const gravityForce1: IForce = {
             description: 'Gravity',
@@ -938,8 +926,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         const commonWeightProps = {
             pause: this.pause,
             paused: BoolCast(this.dataDoc.simulation_paused),
-            panelWidth: this.layoutDoc[WidthSym],
-            panelHeight: this.layoutDoc[HeightSym],
+            panelWidth: this.props.PanelWidth,
+            panelHeight: this.props.PanelHeight,
             xMax: this.xMax,
             xMin: this.xMin,
             yMax: this.yMax,
@@ -964,9 +952,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             pendulumLength: this.pendulumLength,
             startPendulumAngle: this.pendulumAngleStart,
             startPendulumLength: this.pendulumLengthStart,
-            radius: 0.08 * this.layoutDoc[HeightSym](),
+            radius: 0.08 * this.props.PanelHeight(),
             reset: BoolCast(this.dataDoc.simulation_reset),
-            simulationSpeed: NumCast(this.dataDoc.simulation_speed),
+            simulationSpeed: NumCast(this.dataDoc.simulation_speed, 2),
             showAcceleration: BoolCast(this.dataDoc.simulation_showAcceleration),
             showForceMagnitudes: BoolCast(this.dataDoc.simulation_showForceMagnitudes),
             showForces: BoolCast(this.dataDoc.simulation_showForces),
@@ -983,9 +971,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     <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',
+                                            left: 0.1 * this.props.PanelWidth() + 'px',
+                                            top: 0.95 * this.props.PanelHeight() + 'px',
+                                            width: 0.5 * this.props.PanelWidth() + 'px',
                                         }}>
                                         <LinearProgress />
                                     </div>
@@ -1138,8 +1126,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </Dialog>
                                 <div className="wordProblemBox">
                                     <div className="question">
-                                        <p>{StrCast(this.dataDoc.questionPartOne)}</p>
-                                        <p>{StrCast(this.dataDoc.questionPartTwo)}</p>
+                                        <p>{this.questionPartOne}</p>
+                                        <p>{this.questionPartTwo}</p>
                                     </div>
                                     <div className="answers">
                                         {this.selectedQuestion.answerParts.includes('force of gravity') && (
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index ac28ee4a0..c036f1041 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -1062,7 +1062,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                         <p
                             style={{
                                 position: 'absolute',
-                                left: Math.round(this.props.xMax * 0.5 - 200 + this.props.wedgeWidth - 80) + 'px',
+                                left: Math.round(this.props.xMax * 0.25 + this.props.wedgeWidth / 3) + 'px',
                                 top: Math.round(this.props.yMax - 40) + 'px',
                             }}>
                             {Math.round(((Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI) * 100) / 100}°
-- 
cgit v1.2.3-70-g09d2


From 1413ba695ee3efcf8686f8a6c618ff0cdda634db Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 23 May 2023 16:06:17 -0400
Subject: from last

---
 src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index bb41cd72e..e2b882389 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -174,16 +174,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     // Constants
     xMin = 0;
     yMin = 0;
-    xMax = 100;
-    yMax = 100;
+    xMax = this.props.PanelWidth() * 0.6;
+    yMax = this.props.PanelHeight() * 0.9;
     color = `rgba(0,0,0,0.5)`;
     radius = 50;
     wallPositions: IWallProps[] = [];
 
     componentDidMount() {
-        this.xMax = this.props.PanelWidth() * 0.6;
-        this.yMax = this.props.PanelHeight() * 0.9;
-
         // Setup simulation
         this.setupSimulation();
 
-- 
cgit v1.2.3-70-g09d2


From 18b4c2ff62eb6fc3d6c1b5d0c6aeeaa785208aa6 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 24 May 2023 12:38:21 -0400
Subject: physics cleanup for window resizing, etc

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 354 ++++++++-------------
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   |  30 +-
 2 files changed, 146 insertions(+), 238 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index e2b882389..c4e8e7721 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -6,8 +6,11 @@ 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 { computed } from 'mobx';
 import { observer } from 'mobx-react';
-import { HeightSym, NumListCast, WidthSym } from '../../../../fields/Doc';
+import { NumListCast } from '../../../../fields/Doc';
+import { List } from '../../../../fields/List';
+import { BoolCast, NumCast, StrCast } from '../../../../fields/Types';
 import { ViewBoxAnnotatableComponent } from '../../DocComponent';
 import { FieldView, FieldViewProps } from './../FieldView';
 import './PhysicsSimulationBox.scss';
@@ -17,9 +20,6 @@ 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';
-import { computed, trace } from 'mobx';
 
 interface IWallProps {
     length: number;
@@ -82,6 +82,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     @computed get gravity() {
         return NumCast(this.dataDoc.simulation_gravity, -9.81);
     }
+    gravityForce = (mass: number): IForce => {
+        return {
+            description: 'Gravity',
+            magnitude: mass * Math.abs(this.gravity),
+            directionInDegrees: 270,
+            component: false,
+        };
+    };
     @computed get simulationType() {
         return StrCast(this.dataDoc.simulation_type, 'Inclined Plane');
     }
@@ -129,6 +137,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         return NumCast(this.dataDoc.mass2, 1);
     }
 
+    @computed get mass1Radius() {
+        return NumCast(this.dataDoc.mass1_radius, 60);
+    }
     @computed get mass1PosXStart() {
         return NumCast(this.dataDoc.mass1_positionXstart, Math.round((this.xMax * 0.5 - 200) * 10) / 10);
     }
@@ -213,51 +224,29 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         }
         if (mode == 'Freeform') {
             this.dataDoc.simulation_showForceMagnitudes = true;
-            if (simulationType == 'One Weight') {
-                this.dataDoc.simulation_showComponentForces = false;
-                this.dataDoc.mass1_positionYstart = this.yMin + 0.08 * this.props.PanelHeight();
-                this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
-                this.dataDoc.mass1_positionY = this.getDisplayYPos(this.yMin + 0.08 * this.props.PanelHeight());
-                this.dataDoc.mass1_positionX = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
-                this.dataDoc.mass1_forcesUpdated = JSON.stringify([
-                    {
-                        description: 'Gravity',
-                        magnitude: Math.abs(this.gravity) * this.mass1,
-                        directionInDegrees: 270,
-                        component: false,
-                    },
-                ]);
-                this.dataDoc.mass1_forcesStart = JSON.stringify([
-                    {
-                        description: 'Gravity',
-                        magnitude: Math.abs(this.gravity) * this.mass1,
-                        directionInDegrees: 270,
-                        component: false,
-                    },
-                ]);
-                this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
-                ``;
-            } else if (simulationType == 'Inclined Plane') {
-                this.changeWedgeBasedOnNewAngle(26);
-                this.dataDoc.mass1_forcesStart = JSON.stringify([
-                    {
-                        description: 'Gravity',
-                        magnitude: Math.abs(this.gravity) * this.mass1,
-                        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();
+            // prettier-ignore
+            switch (simulationType) {
+                case 'One Weight': 
+                    this.dataDoc.simulation_showComponentForces = false;
+                    this.dataDoc.mass1_positionYstart = this.yMin + 0.08 * this.props.PanelHeight();
+                    this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
+                    this.dataDoc.mass1_positionY = this.getDisplayYPos(this.yMin + 0.08 * this.props.PanelHeight());
+                    this.dataDoc.mass1_positionX = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
+                    this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1)]);
+                    this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1)]);
+                    this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
+                    ``;
+                    break;
+                case 'Inclined Plane': 
+                    this.changeWedgeBasedOnNewAngle(26);
+                    this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1)]);
+                    this.updateForcesWithFriction(NumCast(this.dataDoc.coefficientOfStaticFriction));
+                    break;
+                case 'Pendulum': this.setupPendulum(); break;
+                case 'Spring':   this.setupSpring(); break;
+                case 'Circular Motion': this.setupCircular(0); break;
+                case 'Pulley':this.setupPulley(); break;
+                case 'Suspension': this.setupSuspension();break;
             }
         } else if (mode == 'Review') {
             this.dataDoc.simulation_showComponentForces = false;
@@ -266,26 +255,18 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             this.dataDoc.simulation_showVelocity = false;
             this.dataDoc.simulation_showForces = 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.mass1_forcesUpdated = '';
-                this.dataDoc.mass1_forcesStart = '';
-            } 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
+            // prettier-ignore
+            switch (simulationType) {
+                case 'One Weight' : break;// TODO - one weight review problems
+                case 'Spring':  this.setupSpring(); break; // TODO - spring review problems
+                case 'Inclined Plane': 
+                    this.dataDoc.mass1_forcesUpdated = '';
+                    this.dataDoc.mass1_forcesStart = '';
+                    break;
+                case 'Pendulum':  this.setupPendulum(); break;  // TODO - pendulum review problems
+                case 'Circular Motion':  this.setupCircular(0); break;  // TODO - circular motion review problems
+                case 'Pulley':  this.setupPulley(); break; // TODO - pulley tutorial review problems
+                case 'Suspension': this.setupSuspension(); break;  // TODO - suspension tutorial review problems
             }
         } else if (mode == 'Tutorial') {
             this.dataDoc.simulation_showComponentForces = false;
@@ -301,51 +282,59 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 this.dataDoc.simulation_showVelocity = true;
             }
 
-            if (this.simulationType == 'One Weight') {
-                this.dataDoc.simulation_showForces = true;
-                this.dataDoc.mass1_positionYstart = this.yMax - 100;
-                this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
-                this.dataDoc.tutorial = JSON.stringify(tutorials.freeWeight);
-                this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.freeWeight.steps[0].forces);
-                this.dataDoc.simulation_showForceMagnitudes = tutorials.freeWeight.steps[0].showMagnitude;
-            } else if (this.simulationType == 'Spring') {
-                this.dataDoc.simulation_showForces = true;
-                this.setupSpring();
-                this.dataDoc.mass1_positionYstart = this.yMin + 200 + 19.62;
-                this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
-                this.dataDoc.tutorial = JSON.stringify(tutorials.spring);
-                this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.spring.steps[0].forces);
-                this.dataDoc.simulation_showForceMagnitudes = tutorials.spring.steps[0].showMagnitude;
-            } else if (this.simulationType == 'Pendulum') {
-                this.setupPendulum();
-                this.dataDoc.tutorial = JSON.stringify(tutorials.pendulum);
-                this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.pendulum.steps[0].forces);
-                this.dataDoc.simulation_showForceMagnitudes = tutorials.pendulum.steps[0].showMagnitude;
-            } else if (this.simulationType == 'Inclined Plane') {
-                this.dataDoc.simulation_showForces = true;
-                this.dataDoc.wedge_angle = 26;
-                this.changeWedgeBasedOnNewAngle(26);
-                this.dataDoc.tutorial = JSON.stringify(tutorials.inclinePlane);
-                this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.inclinePlane.steps[0].forces);
-                this.dataDoc.simulation_showForceMagnitudes = tutorials.inclinePlane.steps[0].showMagnitude;
-            } else if (this.simulationType == 'Circular Motion') {
-                this.dataDoc.simulation_showForces = true;
-                this.setupCircular(40);
-                this.dataDoc.tutorial = JSON.stringify(tutorials.circular);
-                this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.circular.steps[0].forces);
-                this.dataDoc.simulation_showForceMagnitudes = tutorials.circular.steps[0].showMagnitude;
-            } else if (this.simulationType == 'Pulley') {
-                this.dataDoc.simulation_showForces = true;
-                this.setupPulley();
-                this.dataDoc.tutorial = JSON.stringify(tutorials.pulley);
-                this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.pulley.steps[0].forces);
-                this.dataDoc.simulation_showForceMagnitudes = tutorials.pulley.steps[0].showMagnitude;
-            } else if (this.simulationType == 'Suspension') {
-                this.dataDoc.simulation_showForces = true;
-                this.setupSuspension();
-                this.dataDoc.tutorial = JSON.stringify(tutorials.suspension);
-                this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.suspension.steps[0].forces);
-                this.dataDoc.simulation_showForceMagnitudes = tutorials.suspension.steps[0].showMagnitude;
+            switch (this.simulationType) {
+                case 'One Weight':
+                    this.dataDoc.simulation_showForces = true;
+                    this.dataDoc.mass1_positionYstart = this.yMax - 100;
+                    this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
+                    this.dataDoc.tutorial = JSON.stringify(tutorials.freeWeight);
+                    this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.freeWeight.steps[0].forces);
+                    this.dataDoc.simulation_showForceMagnitudes = tutorials.freeWeight.steps[0].showMagnitude;
+                    break;
+                case 'Spring':
+                    this.dataDoc.simulation_showForces = true;
+                    this.setupSpring();
+                    this.dataDoc.mass1_positionYstart = this.yMin + 200 + 19.62;
+                    this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
+                    this.dataDoc.tutorial = JSON.stringify(tutorials.spring);
+                    this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.spring.steps[0].forces);
+                    this.dataDoc.simulation_showForceMagnitudes = tutorials.spring.steps[0].showMagnitude;
+                    break;
+                case 'Pendulum':
+                    this.setupPendulum();
+                    this.dataDoc.tutorial = JSON.stringify(tutorials.pendulum);
+                    this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.pendulum.steps[0].forces);
+                    this.dataDoc.simulation_showForceMagnitudes = tutorials.pendulum.steps[0].showMagnitude;
+                    break;
+                case 'Inclined Plane':
+                    this.dataDoc.simulation_showForces = true;
+                    this.dataDoc.wedge_angle = 26;
+                    this.changeWedgeBasedOnNewAngle(26);
+                    this.dataDoc.tutorial = JSON.stringify(tutorials.inclinePlane);
+                    this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.inclinePlane.steps[0].forces);
+                    this.dataDoc.simulation_showForceMagnitudes = tutorials.inclinePlane.steps[0].showMagnitude;
+                    break;
+                case 'Circular Motion':
+                    this.dataDoc.simulation_showForces = true;
+                    this.setupCircular(40);
+                    this.dataDoc.tutorial = JSON.stringify(tutorials.circular);
+                    this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.circular.steps[0].forces);
+                    this.dataDoc.simulation_showForceMagnitudes = tutorials.circular.steps[0].showMagnitude;
+                    break;
+                case 'Pulley':
+                    this.dataDoc.simulation_showForces = true;
+                    this.setupPulley();
+                    this.dataDoc.tutorial = JSON.stringify(tutorials.pulley);
+                    this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.pulley.steps[0].forces);
+                    this.dataDoc.simulation_showForceMagnitudes = tutorials.pulley.steps[0].showMagnitude;
+                    break;
+                case 'Suspension':
+                    this.dataDoc.simulation_showForces = true;
+                    this.setupSuspension();
+                    this.dataDoc.tutorial = JSON.stringify(tutorials.suspension);
+                    this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.suspension.steps[0].forces);
+                    this.dataDoc.simulation_showForceMagnitudes = tutorials.suspension.steps[0].showMagnitude;
+                    break;
             }
             this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
         }
@@ -404,12 +393,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             directionInDegrees: 360 - (Math.atan(height / width) * 180) / Math.PI,
             component: true,
         };
-        const gravityForce: IForce = {
-            description: 'Gravity',
-            magnitude: this.mass1 * Math.abs(this.gravity),
-            directionInDegrees: 270,
-            component: false,
-        };
+        const gravityForce = this.gravityForce(this.mass1);
         if (coefficient != 0) {
             this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce, normalForce, frictionForce]);
             this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce, normalForce, frictionForce]);
@@ -423,37 +407,18 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
 
     // Change wedge height and width and weight position to match new wedge angle
     changeWedgeBasedOnNewAngle = (angle: number) => {
+        const radAng = (angle * Math.PI) / 180;
         this.dataDoc.wedge_width = this.xMax * 0.5;
-        this.dataDoc.wedge_height = Math.tan((angle * Math.PI) / 180) * this.xMax * 0.5;
+        this.dataDoc.wedge_height = Math.tan(radAng) * this.dataDoc.wedge_width;
 
         // update weight position based on updated wedge width/height
-        let yPos = this.yMax - 0.08 * this.props.PanelHeight() * 2 - Math.tan((angle * Math.PI) / 180) * this.xMax * 0.5;
+        let yPos = this.yMax - this.mass1Radius * 2 - this.dataDoc.wedge_height - this.mass1Radius * Math.cos(radAng) + this.mass1Radius;
+        let xPos = this.xMax * 0.25 + this.mass1Radius * Math.sin(radAng) - this.mass1Radius;
 
-        // adjust y position
-        if (angle >= 5 && angle < 10) {
-            yPos += 0.08 * this.props.PanelHeight() * 0.1;
-        } else if (angle >= 10 && angle < 15) {
-            yPos += 0.08 * this.props.PanelHeight() * 0.23;
-        } else if (angle >= 15 && angle < 20) {
-            yPos += 0.08 * this.props.PanelHeight() * 0.26;
-        } else if (angle >= 20 && angle < 25) {
-            yPos += 0.08 * this.props.PanelHeight() * 0.33;
-        } else if (angle >= 25 && angle < 30) {
-            yPos += 0.08 * this.props.PanelHeight() * 0.35;
-        } else if (angle >= 30 && angle < 35) {
-            yPos += 0.08 * this.props.PanelHeight() * 0.4;
-        } else if (angle >= 35 && angle < 40) {
-            yPos += 0.08 * this.props.PanelHeight() * 0.45;
-        } else if (angle >= 40 && angle < 45) {
-            yPos += 0.08 * this.props.PanelHeight() * 0.47;
-        } else if (angle >= 45) {
-            yPos += 0.08 * this.props.PanelHeight() * 0.52;
-        }
-
-        this.dataDoc.mass1_positionXstart = this.xMax * 0.25;
+        this.dataDoc.mass1_positionXstart = xPos;
         this.dataDoc.mass1_positionYstart = yPos;
         if (this.simulationMode == 'Freeform') {
-            this.updateForcesWithFriction(NumCast(this.dataDoc.coefficientOfStaticFriction), this.xMax * 0.5, Math.tan((angle * Math.PI) / 180) * this.xMax * 0.5);
+            this.updateForcesWithFriction(NumCast(this.dataDoc.coefficientOfStaticFriction), this.dataDoc.wedge_width, Math.tan(radAng) * this.dataDoc.wedge_width);
         }
     };
 
@@ -730,24 +695,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         };
 
         this.dataDoc.mass1_componentForces = JSON.stringify([tensionComponent, gravityParallel, gravityPerpendicular]);
-        this.dataDoc.mass1_forcesUpdated = JSON.stringify([
-            {
-                description: 'Gravity',
-                magnitude: this.mass1 * Math.abs(this.gravity),
-                directionInDegrees: 270,
-                component: false,
-            },
-            forceOfTension,
-        ]);
-        this.dataDoc.mass1_forcesStart = JSON.stringify([
-            {
-                description: 'Gravity',
-                magnitude: this.mass1 * Math.abs(this.gravity),
-                directionInDegrees: 270,
-                component: false,
-            },
-            forceOfTension,
-        ]);
+        this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1)]);
+        this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1), forceOfTension]);
         this.dataDoc.pendulum_angle = this.dataDoc.pendulum_angleStart = 30;
         this.dataDoc.pendulum_length = this.dataDoc.pendulum_lengthStart = 300;
     };
@@ -755,14 +704,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     // Default setup for spring simulation
     setupSpring = () => {
         this.dataDoc.simulation_showComponentForces = false;
-        const gravityForce: IForce = {
-            description: 'Gravity',
-            magnitude: Math.abs(this.gravity) * this.mass1,
-            directionInDegrees: 270,
-            component: false,
-        };
-        this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce]);
-        this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce]);
+        this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1)]);
+        this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1)]);
         this.dataDoc.mass1_positionXstart = this.xMax / 2 - 0.08 * this.props.PanelHeight();
         this.dataDoc.mass1_positionYstart = 200;
         this.dataDoc.spring_constant = 0.5;
@@ -792,14 +735,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             directionInDegrees: 135,
             component: false,
         };
-        const grav: IForce = {
-            description: 'Gravity',
-            magnitude: this.mass1 * Math.abs(this.gravity),
-            directionInDegrees: 270,
-            component: false,
-        };
-        this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, grav]);
-        this.dataDoc.mass1_forcesStart = JSON.stringify([tensionForce1, tensionForce2, grav]);
+        const gravity = this.gravityForce(this.mass1);
+        this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, gravity]);
+        this.dataDoc.mass1_forcesStart = JSON.stringify([tensionForce1, tensionForce2, gravity]);
         this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
     };
 
@@ -811,12 +749,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.mass1_positionY = this.getDisplayYPos((this.yMax + this.yMin) / 2);
         this.dataDoc.mass1_positionX = (this.xMin + this.xMax) / 2 - 2 * (0.08 * this.props.PanelHeight()) - 5;
         let a = (-1 * ((this.mass1 - this.mass2) * Math.abs(this.gravity))) / (this.mass1 + this.mass2);
-        const gravityForce1: IForce = {
-            description: 'Gravity',
-            magnitude: this.mass1 * Math.abs(this.gravity),
-            directionInDegrees: 270,
-            component: false,
-        };
+        const gravityForce1 = this.gravityForce(this.mass1);
         const tensionForce1: IForce = {
             description: 'Tension',
             magnitude: this.mass1 * a + this.mass1 * Math.abs(this.gravity),
@@ -824,12 +757,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             component: false,
         };
         a *= -1;
-        const gravityForce2: IForce = {
-            description: 'Gravity',
-            magnitude: this.mass2 * Math.abs(this.gravity),
-            directionInDegrees: 270,
-            component: false,
-        };
+        const gravityForce2 = this.gravityForce(this.mass2);
         const tensionForce2: IForce = {
             description: 'Tension',
             magnitude: this.mass2 * a + this.mass2 * Math.abs(this.gravity),
@@ -949,7 +877,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             pendulumLength: this.pendulumLength,
             startPendulumAngle: this.pendulumAngleStart,
             startPendulumLength: this.pendulumLengthStart,
-            radius: 0.08 * this.props.PanelHeight(),
+            radius: this.mass1Radius,
             reset: BoolCast(this.dataDoc.simulation_reset),
             simulationSpeed: NumCast(this.dataDoc.simulation_speed, 2),
             showAcceleration: BoolCast(this.dataDoc.simulation_showAcceleration),
@@ -976,7 +904,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     </div>
                                 )}
                             </div>
-                            <div className="mechanicsSimulationElements">
+                            <div className="mechanicsSimulationElements" style={{ transform: `scale(${this.props.PanelWidth() / 1000})` }}>
                                 <Weight
                                     {...commonWeightProps}
                                     color="red"
@@ -1022,7 +950,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     />
                                 )}
                             </div>
-                            <div>
+                            <div style={{ position: 'absolute', transform: `scale(${this.props.PanelWidth() / 1000}`, transformOrigin: 'top left', top: 0, left: 0, width: '100%', height: '100%' }}>
                                 {(this.simulationType == 'One Weight' || this.simulationType == 'Inclined Plane') &&
                                     this.wallPositions?.map((element, index) => <Wall key={index} length={element.length} xPos={element.xPos} yPos={element.yPos} angleInDegrees={element.angleInDegrees} />)}
                             </div>
@@ -1708,24 +1636,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     this.dataDoc.mass1_positionXstart = xPos;
                                                     this.dataDoc.mass1_positionYstart = yPos;
 
-                                                    this.dataDoc.mass1_forcesStart = JSON.stringify([
-                                                        {
-                                                            description: 'Gravity',
-                                                            magnitude: Math.abs(this.gravity) * this.mass1,
-                                                            directionInDegrees: 270,
-                                                            component: false,
-                                                        },
-                                                        forceOfTension,
-                                                    ]);
-                                                    this.dataDoc.mass1_forcesUpdated = JSON.stringify([
-                                                        {
-                                                            description: 'Gravity',
-                                                            magnitude: Math.abs(this.gravity) * this.mass1,
-                                                            directionInDegrees: 270,
-                                                            component: false,
-                                                        },
-                                                        forceOfTension,
-                                                    ]);
+                                                    this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1), forceOfTension]);
+                                                    this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1), forceOfTension]);
                                                     this.dataDoc.mass1_componentForces = JSON.stringify([tensionComponent, gravityParallel, gravityPerpendicular]);
                                                     this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                                                 }
@@ -1822,13 +1734,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                                     directionInDegrees: dir2T,
                                                                     component: false,
                                                                 };
-                                                                const grav: IForce = {
-                                                                    description: 'Gravity',
-                                                                    magnitude: this.mass1 * Math.abs(this.gravity),
-                                                                    directionInDegrees: 270,
-                                                                    component: false,
-                                                                };
-                                                                this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, grav]);
+                                                                const gravity = this.gravityForce(this.mass1);
+                                                                this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, gravity]);
                                                             }
                                                         }}
                                                         small={true}
@@ -1878,13 +1785,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                                     directionInDegrees: dir2T,
                                                                     component: false,
                                                                 };
-                                                                const grav: IForce = {
-                                                                    description: 'Gravity',
-                                                                    magnitude: this.mass1 * Math.abs(this.gravity),
-                                                                    directionInDegrees: 270,
-                                                                    component: false,
-                                                                };
-                                                                this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, grav]);
+                                                                const gravity = this.gravityForce(this.mass1);
+                                                                this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, gravity]);
                                                             }
                                                         }}
                                                         small={true}
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 97f1d3f6c..35aeb59bf 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -126,6 +126,12 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     @computed get draggable() {
         return !['Inclined Plane', 'Pendulum'].includes(this.props.simulationType) && this.props.simulationMode === 'Freeform';
     }
+    @computed get panelHeight() {
+        return Math.max(800, this.props.panelHeight()) + 'px';
+    }
+    @computed get panelWidth() {
+        return Math.max(1000, this.props.panelWidth()) + 'px';
+    }
     epsilon = 0.0001;
     labelBackgroundColor = `rgba(255,255,255,0.5)`;
 
@@ -782,7 +788,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             left: 0,
                             top: 0,
                         }}>
-                        <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
+                        <svg width={this.panelWidth} height={this.panelHeight}>
                             {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(val => {
                                 const count = 10;
                                 const xPos1 = this.state.xPosition + this.props.radius + (val % 2 === 0 ? -20 : 20);
@@ -804,7 +810,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             left: 0,
                             top: 0,
                         }}>
-                        <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
+                        <svg width={this.panelWidth} height={this.panelHeight}>
                             <line x1={this.state.xPosition + this.props.radius} y1={this.state.yPosition + this.props.radius} x2={this.state.xPosition + this.props.radius} y2={this.props.yMin} stroke={'#deb887'} strokeWidth="10" />
                         </svg>
                     </div>
@@ -818,7 +824,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             left: 0,
                             top: 0,
                         }}>
-                        <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
+                        <svg width={this.panelWidth} height={this.panelHeight}>
                             <circle cx={(this.props.xMax + this.props.xMin) / 2} cy={this.props.radius} r={this.props.radius * 1.5} fill={'#808080'} />
                         </svg>
                     </div>
@@ -832,7 +838,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             left: 0,
                             top: 0,
                         }}>
-                        <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
+                        <svg width={this.panelWidth} height={this.panelHeight}>
                             <line
                                 x1={this.state.xPosition + this.props.radius}
                                 y1={this.state.yPosition + this.props.radius}
@@ -862,7 +868,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                 left: 0,
                                 top: 0,
                             }}>
-                            <svg width={this.props.panelWidth() + 'px'} height={this.props.panelHeight() + 'px'}>
+                            <svg width={this.props.panelWidth() + 'px'} height={this.panelHeight}>
                                 <line
                                     x1={this.state.xPosition + this.props.radius}
                                     y1={this.state.yPosition + this.props.radius}
@@ -897,7 +903,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             left: 0,
                             top: 0,
                         }}>
-                        <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
+                        <svg width={this.panelWidth} height={this.panelHeight}>
                             <line
                                 x1={this.state.xPosition + this.props.radius}
                                 y1={this.state.yPosition + this.props.radius}
@@ -918,7 +924,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             left: 0,
                             top: 0,
                         }}>
-                        <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
+                        <svg width={this.panelWidth} height={this.panelHeight}>
                             <line x1={this.state.xPosition + this.props.radius} y1={this.state.yPosition + this.props.radius} x2={this.props.xMax / 2} y2={-5} stroke={'#deb887'} strokeWidth="10" />
                         </svg>
                         {!this.state.dragging && (
@@ -949,7 +955,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 {this.props.simulationType == 'Inclined Plane' && (
                     <div>
                         <div style={{ position: 'absolute', left: '0', top: '0' }}>
-                            <svg width={this.props.xMax + 'px'} height={this.props.yMax + 'px'}>
+                            <svg width={this.panelWidth} height={this.props.yMax + 'px'}>
                                 <polygon points={this.state.coordinates} style={{ fill: 'burlywood' }} />
                             </svg>
                         </div>
@@ -973,7 +979,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                 left: 0,
                                 top: 0,
                             }}>
-                            <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
+                            <svg width={this.panelWidth} height={this.panelHeight}>
                                 <defs>
                                     <marker id="accArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
                                         <path d="M0,0 L0,6 L9,3 z" fill="green" />
@@ -1014,7 +1020,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                 left: 0,
                                 top: 0,
                             }}>
-                            <svg width={this.props.xMax + 'px'} height={this.props.panelHeight() + 'px'}>
+                            <svg width={this.panelWidth} height={this.panelHeight}>
                                 <defs>
                                     <marker id="velArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
                                         <path d="M0,0 L0,6 L9,3 z" fill="blue" />
@@ -1082,7 +1088,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                         left: this.props.xMin,
                                         top: this.props.yMin,
                                     }}>
-                                    <svg width={this.props.xMax - this.props.xMin + 'px'} height={this.props.panelHeight() + 'px'}>
+                                    <svg width={this.props.xMax - this.props.xMin + 'px'} height={this.panelHeight}>
                                         <defs>
                                             <marker id="forceArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
                                                 <path d="M0,0 L0,6 L9,3 z" fill={color} />
@@ -1147,7 +1153,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                         left: this.props.xMin,
                                         top: this.props.yMin,
                                     }}>
-                                    <svg width={this.props.xMax - this.props.xMin + 'px'} height={this.props.panelHeight() + 'px'}>
+                                    <svg width={this.props.xMax - this.props.xMin + 'px'} height={this.panelHeight}>
                                         <defs>
                                             <marker id="forceArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
                                                 <path d="M0,0 L0,6 L9,3 z" fill={color} />
-- 
cgit v1.2.3-70-g09d2


From f0dad2a437ac339e2d6126bdadfd7a110d9ff999 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 24 May 2023 13:38:01 -0400
Subject: more phys fixes for resizing windows.

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 78 ++++++++++++----------
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   |  9 ++-
 2 files changed, 52 insertions(+), 35 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index c4e8e7721..a0b47f13f 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -6,7 +6,7 @@ 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 { computed } from 'mobx';
+import { computed, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import { NumListCast } from '../../../../fields/Doc';
 import { List } from '../../../../fields/List';
@@ -186,28 +186,28 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     xMin = 0;
     yMin = 0;
     xMax = this.props.PanelWidth() * 0.6;
-    yMax = this.props.PanelHeight() * 0.9;
+    yMax = this.props.PanelHeight();
     color = `rgba(0,0,0,0.5)`;
     radius = 50;
     wallPositions: IWallProps[] = [];
 
     componentDidMount() {
-        // Setup simulation
-        this.setupSimulation();
+        // Setup and update simulation
+        reaction(() => [this.props.PanelWidth(), this.props.PanelHeight()], this.setupSimulation, { fireImmediately: true });
 
         // Create walls
         this.wallPositions = [
-            { length: (this.xMax / this.props.PanelWidth()) * 100, xPos: 0, yPos: 0, angleInDegrees: 0 },
-            { length: (this.xMax / this.props.PanelWidth()) * 100, xPos: 0, yPos: (this.yMax / this.props.PanelHeight()) * 100, angleInDegrees: 0 },
-            { length: (this.yMax / this.props.PanelHeight()) * 100, xPos: 0, yPos: 0, angleInDegrees: 90 },
-            { length: (this.yMax / this.props.PanelHeight()) * 100, xPos: (this.xMax / this.props.PanelWidth()) * 100, yPos: 0, angleInDegrees: 90 },
+            { length: 100, xPos: 0, yPos: 0, angleInDegrees: 0 },
+            { length: 100, xPos: 0, yPos: 100, angleInDegrees: 0 },
+            { length: 100, xPos: 0, yPos: 0, angleInDegrees: 90 },
+            { length: 100, xPos: (this.xMax / this.props.PanelWidth()) * 100, yPos: 0, angleInDegrees: 90 },
         ];
     }
 
     componentDidUpdate() {
-        if (this.xMax !== this.props.PanelWidth() * 0.6 || this.yMax != this.props.PanelHeight() * 0.9) {
+        if (this.xMax !== this.props.PanelWidth() * 0.6 || this.yMax != this.props.PanelHeight()) {
             this.xMax = this.props.PanelWidth() * 0.6;
-            this.yMax = this.props.PanelHeight() * 0.9;
+            this.yMax = this.props.PanelHeight();
             this.setupSimulation();
         }
     }
@@ -237,17 +237,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                     this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                     ``;
                     break;
-                case 'Inclined Plane': 
-                    this.changeWedgeBasedOnNewAngle(26);
-                    this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1)]);
-                    this.updateForcesWithFriction(NumCast(this.dataDoc.coefficientOfStaticFriction));
-                    break;
-                case 'Pendulum': this.setupPendulum(); break;
-                case 'Spring':   this.setupSpring(); break;
-                case 'Circular Motion': this.setupCircular(0); break;
-                case 'Pulley':this.setupPulley(); break;
-                case 'Suspension': this.setupSuspension();break;
+                case 'Inclined Plane':  this.setupInclinedPlane(); break;
+                case 'Pendulum':        this.setupPendulum(); break;
+                case 'Spring':          this.setupSpring(); break;
+                case 'Circular Motion': this.setupCircular(20); break;
+                case 'Pulley':          this.setupPulley(); break;
+                case 'Suspension':      this.setupSuspension();break;
             }
+            this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
         } else if (mode == 'Review') {
             this.dataDoc.simulation_showComponentForces = false;
             this.dataDoc.simulation_showForceMagnitudes = true;
@@ -307,9 +304,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                     this.dataDoc.simulation_showForceMagnitudes = tutorials.pendulum.steps[0].showMagnitude;
                     break;
                 case 'Inclined Plane':
-                    this.dataDoc.simulation_showForces = true;
                     this.dataDoc.wedge_angle = 26;
-                    this.changeWedgeBasedOnNewAngle(26);
+                    this.setupInclinedPlane();
+                    this.dataDoc.simulation_showForces = true;
                     this.dataDoc.tutorial = JSON.stringify(tutorials.inclinePlane);
                     this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.inclinePlane.steps[0].forces);
                     this.dataDoc.simulation_showForceMagnitudes = tutorials.inclinePlane.steps[0].showMagnitude;
@@ -412,7 +409,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.wedge_height = Math.tan(radAng) * this.dataDoc.wedge_width;
 
         // update weight position based on updated wedge width/height
-        let yPos = this.yMax - this.mass1Radius * 2 - this.dataDoc.wedge_height - this.mass1Radius * Math.cos(radAng) + this.mass1Radius;
+        let yPos = this.yMax - this.dataDoc.wedge_height - this.mass1Radius * Math.cos(radAng) - this.mass1Radius;
         let xPos = this.xMax * 0.25 + this.mass1Radius * Math.sin(radAng) - this.mass1Radius;
 
         this.dataDoc.mass1_positionXstart = xPos;
@@ -657,9 +654,15 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
     };
 
+    setupInclinedPlane = () => {
+        this.changeWedgeBasedOnNewAngle(this.wedgeAngle);
+        this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1)]);
+        this.updateForcesWithFriction(NumCast(this.dataDoc.coefficientOfStaticFriction));
+    };
+
     // Default setup for pendulum simulation
     setupPendulum = () => {
-        const length = 300;
+        const length = (300 * this.props.PanelWidth()) / 1000;
         const angle = 30;
         const x = length * Math.cos(((90 - angle) * Math.PI) / 180);
         const y = length * Math.sin(((90 - angle) * Math.PI) / 180);
@@ -745,10 +748,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     setupPulley = () => {
         this.dataDoc.simulation_showComponentForces = false;
         this.dataDoc.mass1_positionYstart = (this.yMax + this.yMin) / 2;
-        this.dataDoc.mass1_positionXstart = (this.xMin + this.xMax) / 2 - 2 * (0.08 * this.props.PanelHeight()) - 5;
+        this.dataDoc.mass1_positionXstart = (this.xMin + this.xMax) / 2 - 2 * this.mass1Radius - 5;
         this.dataDoc.mass1_positionY = this.getDisplayYPos((this.yMax + this.yMin) / 2);
-        this.dataDoc.mass1_positionX = (this.xMin + this.xMax) / 2 - 2 * (0.08 * this.props.PanelHeight()) - 5;
-        let a = (-1 * ((this.mass1 - this.mass2) * Math.abs(this.gravity))) / (this.mass1 + this.mass2);
+        this.dataDoc.mass1_positionX = (this.xMin + this.xMax) / 2 - 2 * this.mass1Radius - 5;
+        const a = (-1 * ((this.mass1 - this.mass2) * Math.abs(this.gravity))) / (this.mass1 + this.mass2);
         const gravityForce1 = this.gravityForce(this.mass1);
         const tensionForce1: IForce = {
             description: 'Tension',
@@ -756,17 +759,16 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             directionInDegrees: 90,
             component: false,
         };
-        a *= -1;
+        this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce1, tensionForce1]);
+        this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce1, tensionForce1]);
+
         const gravityForce2 = this.gravityForce(this.mass2);
         const tensionForce2: IForce = {
             description: 'Tension',
-            magnitude: this.mass2 * a + this.mass2 * Math.abs(this.gravity),
+            magnitude: -this.mass2 * a + this.mass2 * Math.abs(this.gravity),
             directionInDegrees: 90,
             component: false,
         };
-
-        this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce1, tensionForce1]);
-        this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce1, tensionForce1]);
         this.dataDoc.mass2_positionYstart = (this.yMax + this.yMin) / 2;
         this.dataDoc.mass2_positionXstart = (this.xMin + this.xMax) / 2 + 5;
         this.dataDoc.mass2_positionY = this.getDisplayYPos((this.yMax + this.yMin) / 2);
@@ -904,7 +906,15 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     </div>
                                 )}
                             </div>
-                            <div className="mechanicsSimulationElements" style={{ transform: `scale(${this.props.PanelWidth() / 1000})` }}>
+                            <div
+                                className="mechanicsSimulationElements"
+                                style={{
+                                    //
+                                    width: '60%',
+                                    height: '100%',
+                                    position: 'absolute',
+                                    background: 'yellow',
+                                }}>
                                 <Weight
                                     {...commonWeightProps}
                                     color="red"
@@ -950,7 +960,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     />
                                 )}
                             </div>
-                            <div style={{ position: 'absolute', transform: `scale(${this.props.PanelWidth() / 1000}`, transformOrigin: 'top left', top: 0, left: 0, width: '100%', height: '100%' }}>
+                            <div style={{ position: 'absolute', transformOrigin: 'top left', top: 0, left: 0, width: '100%', height: '100%' }}>
                                 {(this.simulationType == 'One Weight' || this.simulationType == 'Inclined Plane') &&
                                     this.wallPositions?.map((element, index) => <Wall key={index} length={element.length} xPos={element.xPos} yPos={element.yPos} angleInDegrees={element.angleInDegrees} />)}
                             </div>
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 35aeb59bf..d062cc8c5 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -811,7 +811,14 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             top: 0,
                         }}>
                         <svg width={this.panelWidth} height={this.panelHeight}>
-                            <line x1={this.state.xPosition + this.props.radius} y1={this.state.yPosition + this.props.radius} x2={this.state.xPosition + this.props.radius} y2={this.props.yMin} stroke={'#deb887'} strokeWidth="10" />
+                            <line //
+                                x1={this.state.xPosition + this.props.radius}
+                                y1={this.state.yPosition + this.props.radius}
+                                x2={this.state.xPosition + this.props.radius}
+                                y2={this.props.yMin}
+                                stroke={'#deb887'}
+                                strokeWidth="10"
+                            />
                         </svg>
                     </div>
                 )}
-- 
cgit v1.2.3-70-g09d2


From 4c96bbd25d84964811838d005ff4e40487e1ec41 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 24 May 2023 15:04:13 -0400
Subject: more phys code streamlining

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.scss     |   6 +
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 168 +++++---------
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   | 251 +++++----------------
 3 files changed, 117 insertions(+), 308 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
index b498296bf..2e6ad413f 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
@@ -22,6 +22,12 @@
                 justify-content: space-between;
             }
         }
+        .rod {
+            pointer-events: none;
+            position: absolute;
+            left: 0;
+            top: 0;
+        }
     }
 
     .coordinateSystem {
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index a0b47f13f..d3e1c6fd2 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -6,7 +6,7 @@ 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 { computed, reaction } from 'mobx';
+import { computed, IReactionDisposer, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import { NumListCast } from '../../../../fields/Doc';
 import { List } from '../../../../fields/List';
@@ -31,7 +31,6 @@ interface IForce {
     description: string;
     magnitude: number;
     directionInDegrees: number;
-    component: boolean;
 }
 interface VectorTemplate {
     top: number;
@@ -76,20 +75,23 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         return FieldView.LayoutString(PhysicsSimulationBox, fieldKey);
     }
 
+    _widthDisposer: IReactionDisposer | undefined;
+
+    // semi-Constants
+    xMin = 0;
+    yMin = 0;
+    xMax = this.props.PanelWidth() * 0.6;
+    yMax = this.props.PanelHeight();
+    color = `rgba(0,0,0,0.5)`;
+    radius = 50;
+    wallPositions: IWallProps[] = [];
+
     @computed get circularMotionRadius() {
         return NumCast(this.dataDoc.circularMotionRadius, 150);
     }
     @computed get gravity() {
         return NumCast(this.dataDoc.simulation_gravity, -9.81);
     }
-    gravityForce = (mass: number): IForce => {
-        return {
-            description: 'Gravity',
-            magnitude: mass * Math.abs(this.gravity),
-            directionInDegrees: 270,
-            component: false,
-        };
-    };
     @computed get simulationType() {
         return StrCast(this.dataDoc.simulation_type, 'Inclined Plane');
     }
@@ -138,13 +140,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     }
 
     @computed get mass1Radius() {
-        return NumCast(this.dataDoc.mass1_radius, 60);
+        return NumCast(this.dataDoc.mass1_radius, 30);
     }
     @computed get mass1PosXStart() {
-        return NumCast(this.dataDoc.mass1_positionXstart, Math.round((this.xMax * 0.5 - 200) * 10) / 10);
+        return NumCast(this.dataDoc.mass1_positionXstart);
     }
     @computed get mass1PosYStart() {
-        return NumCast(this.dataDoc.mass1_positionYstart, this.getDisplayYPos((400 - 0.08 * this.props.PanelHeight()) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26)));
+        return NumCast(this.dataDoc.mass1_positionYstart);
     }
     @computed get mass1VelXStart() {
         return NumCast(this.dataDoc.mass1_velocityXstart);
@@ -157,7 +159,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         return NumCast(this.dataDoc.mass2_positionXstart);
     }
     @computed get mass2PosYStart() {
-        return NumCast(this.dataDoc.mass2_positionYstart, this.getDisplayYPos((400 - 0.08 * this.props.PanelHeight()) * Math.tan((26 * Math.PI) / 180) + Math.sqrt(26)));
+        return NumCast(this.dataDoc.mass2_positionYstart);
     }
     @computed get mass2VelXStart() {
         return NumCast(this.dataDoc.mass2_velocityXstart);
@@ -182,18 +184,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         return StrCast(this.dataDoc.questionPartTwo);
     }
 
-    // Constants
-    xMin = 0;
-    yMin = 0;
-    xMax = this.props.PanelWidth() * 0.6;
-    yMax = this.props.PanelHeight();
-    color = `rgba(0,0,0,0.5)`;
-    radius = 50;
-    wallPositions: IWallProps[] = [];
+    componentWillUnmount() {
+        this._widthDisposer?.();
+    }
 
     componentDidMount() {
         // Setup and update simulation
-        reaction(() => [this.props.PanelWidth(), this.props.PanelHeight()], this.setupSimulation, { fireImmediately: true });
+        this._widthDisposer = reaction(() => [this.props.PanelWidth(), this.props.PanelHeight()], this.setupSimulation, { fireImmediately: true });
 
         // Create walls
         this.wallPositions = [
@@ -212,6 +209,12 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         }
     }
 
+    gravityForce = (mass: number): IForce => ({
+        description: 'Gravity',
+        magnitude: mass * Math.abs(this.gravity),
+        directionInDegrees: 270,
+    });
+
     setupSimulation = () => {
         const simulationType = this.simulationType;
         const mode = this.simulationMode;
@@ -228,10 +231,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             switch (simulationType) {
                 case 'One Weight': 
                     this.dataDoc.simulation_showComponentForces = false;
-                    this.dataDoc.mass1_positionYstart = this.yMin + 0.08 * this.props.PanelHeight();
-                    this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
-                    this.dataDoc.mass1_positionY = this.getDisplayYPos(this.yMin + 0.08 * this.props.PanelHeight());
-                    this.dataDoc.mass1_positionX = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
+                    this.dataDoc.mass1_positionYstart = this.yMin + this.mass1Radius;
+                    this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - this.mass1Radius;
+                    this.dataDoc.mass1_positionY = this.getDisplayYPos(this.yMin + this.mass1Radius);
+                    this.dataDoc.mass1_positionX = (this.xMax + this.xMin) / 2 - this.mass1Radius;
                     this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1)]);
                     this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1)]);
                     this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
@@ -256,10 +259,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             switch (simulationType) {
                 case 'One Weight' : break;// TODO - one weight review problems
                 case 'Spring':  this.setupSpring(); break; // TODO - spring review problems
-                case 'Inclined Plane': 
-                    this.dataDoc.mass1_forcesUpdated = '';
-                    this.dataDoc.mass1_forcesStart = '';
-                    break;
+                case 'Inclined Plane': this.dataDoc.mass1_forcesUpdated =  this.dataDoc.mass1_forcesStart = ''; break;
                 case 'Pendulum':  this.setupPendulum(); break;  // TODO - pendulum review problems
                 case 'Circular Motion':  this.setupCircular(0); break;  // TODO - circular motion review problems
                 case 'Pulley':  this.setupPulley(); break; // TODO - pulley tutorial review problems
@@ -283,7 +283,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 case 'One Weight':
                     this.dataDoc.simulation_showForces = true;
                     this.dataDoc.mass1_positionYstart = this.yMax - 100;
-                    this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
+                    this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - this.mass1Radius;
                     this.dataDoc.tutorial = JSON.stringify(tutorials.freeWeight);
                     this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.freeWeight.steps[0].forces);
                     this.dataDoc.simulation_showForceMagnitudes = tutorials.freeWeight.steps[0].showMagnitude;
@@ -292,7 +292,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                     this.dataDoc.simulation_showForces = true;
                     this.setupSpring();
                     this.dataDoc.mass1_positionYstart = this.yMin + 200 + 19.62;
-                    this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
+                    this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - this.mass1Radius;
                     this.dataDoc.tutorial = JSON.stringify(tutorials.spring);
                     this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.spring.steps[0].forces);
                     this.dataDoc.simulation_showForceMagnitudes = tutorials.spring.steps[0].showMagnitude;
@@ -338,12 +338,8 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     };
 
     // Helper function to go between display and real values
-    getDisplayYPos = (yPos: number) => {
-        return this.yMax - yPos - 2 * (0.08 * this.props.PanelHeight()) + 5;
-    };
-    getYPosFromDisplay = (yDisplay: number) => {
-        return this.yMax - yDisplay - 2 * (0.08 * this.props.PanelHeight()) + 5;
-    };
+    getDisplayYPos = (yPos: number) => this.yMax - yPos - 2 * this.mass1Radius + 5;
+    getYPosFromDisplay = (yDisplay: number) => this.yMax - yDisplay - 2 * this.mass1Radius + 5;
 
     // Update forces when coefficient of static friction changes in freeform mode
     updateForcesWithFriction = (coefficient: number, width = this.wedgeWidth, height = this.wedgeHeight) => {
@@ -351,13 +347,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             description: 'Normal Force',
             magnitude: Math.abs(this.gravity) * Math.cos(Math.atan(height / width)) * this.mass1,
             directionInDegrees: 180 - 90 - (Math.atan(height / width) * 180) / Math.PI,
-            component: false,
         };
         let frictionForce: IForce = {
             description: 'Static Friction Force',
             magnitude: coefficient * Math.abs(this.gravity) * Math.cos(Math.atan(height / width)) * this.mass1,
             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(this.gravity) * this.mass1;
@@ -366,35 +360,27 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         if (yForce > 0) {
             frictionForce.magnitude = (-normalForce.magnitude * Math.sin((normalForce.directionInDegrees * Math.PI) / 180) + Math.abs(this.gravity) * this.mass1) / Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
         }
-        const frictionForceComponent: IForce = {
-            description: 'Static Friction Force',
-            magnitude: coefficient * Math.abs(this.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(this.gravity) * Math.cos(Math.atan(height / width)),
+            magnitude: this.mass1 * Math.abs(this.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: this.mass1 * Math.abs(this.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: this.mass1 * Math.abs(this.gravity) * Math.cos(Math.PI / 2 - Math.atan(height / width)),
             directionInDegrees: 360 - (Math.atan(height / width) * 180) / Math.PI,
-            component: true,
         };
         const gravityForce = this.gravityForce(this.mass1);
         if (coefficient != 0) {
             this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce, normalForce, frictionForce]);
             this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce, normalForce, frictionForce]);
-            this.dataDoc.mass1_componentForces = JSON.stringify([frictionForceComponent, normalForceComponent, gravityParallel, gravityPerpendicular]);
+            this.dataDoc.mass1_componentForces = JSON.stringify([frictionForce, normalForceComponent, gravityParallel, gravityPerpendicular]);
         } else {
             this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce, normalForce]);
             this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce, normalForce]);
@@ -549,24 +535,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             }
         }
         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);
-            }
+            this.dataDoc.simulation_paused = false;
+            setTimeout(() => (this.dataDoc.simulation_paused = true), 3000);
         }
         if (this.selectedQuestion.goal == 'noMovement') {
-            if (!error) {
-                this.dataDoc.noMovement = true;
-            } else {
-                this.dataDoc.roMovement = false;
-            }
+            this.dataDoc.noMovement = !error;
         }
     };
 
@@ -590,11 +563,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         let question: QuestionTemplate = questions.inclinePlane[0];
 
         if (this.simulationType === 'Inclined Plane') {
-            if (this.dataDoc.questionNumber === questions.inclinePlane.length - 1) {
-                this.dataDoc.questionNumber = 0;
-            } else {
-                this.dataDoc.questionNumber = NumCast(this.dataDoc.questionNumber) + 1;
-            }
+            this.dataDoc.questionNumber = (NumCast(this.dataDoc.questionNumber) + 1) % questions.inclinePlane.length;
             question = questions.inclinePlane[NumCast(this.dataDoc.questionNumber)];
 
             let coefficient = 0;
@@ -639,15 +608,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.simulation_showComponentForces = false;
         this.dataDoc.mass1_velocityYstart = 0;
         this.dataDoc.mass1_velocityXstart = value;
-        let xPos = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
-        let yPos = (this.yMax + this.yMin) / 2 + this.circularMotionRadius - 0.08 * this.props.PanelHeight();
+        let xPos = (this.xMax + this.xMin) / 2 - this.mass1Radius;
+        let yPos = (this.yMax + this.yMin) / 2 + this.circularMotionRadius - this.mass1Radius;
         this.dataDoc.mass1_positionYstart = yPos;
         this.dataDoc.mass1_positionXstart = xPos;
         const tensionForce: IForce = {
             description: 'Centripetal Force',
             magnitude: (this.dataDoc.mass1_velocityXstart ** 2 * this.mass1) / this.circularMotionRadius,
             directionInDegrees: 90,
-            component: false,
         };
         this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce]);
         this.dataDoc.mass1_forcesStart = JSON.stringify([tensionForce]);
@@ -666,38 +634,27 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         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.props.PanelHeight();
-        const yPos = y - 0.08 * this.props.PanelHeight() - 5;
+        const xPos = this.xMax / 2 - x - this.mass1Radius;
+        const yPos = y - this.mass1Radius - 5;
         this.dataDoc.mass1_positionXstart = xPos;
         this.dataDoc.mass1_positionYstart = yPos;
-        const mag = this.mass1 * Math.abs(this.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,
+            magnitude: this.mass1 * Math.abs(this.gravity) * Math.sin((60 * Math.PI) / 180),
             directionInDegrees: 90 - angle,
-            component: true,
         };
         const gravityParallel: IForce = {
             description: 'Gravity Parallel Component',
             magnitude: this.mass1 * Math.abs(this.gravity) * Math.sin(((90 - angle) * Math.PI) / 180),
             directionInDegrees: -angle - 90,
-            component: true,
         };
         const gravityPerpendicular: IForce = {
             description: 'Gravity Perpendicular Component',
             magnitude: this.mass1 * Math.abs(this.gravity) * Math.cos(((90 - angle) * Math.PI) / 180),
             directionInDegrees: -angle,
-            component: true,
         };
 
-        this.dataDoc.mass1_componentForces = JSON.stringify([tensionComponent, gravityParallel, gravityPerpendicular]);
+        this.dataDoc.mass1_componentForces = JSON.stringify([forceOfTension, gravityParallel, gravityPerpendicular]);
         this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1)]);
         this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1), forceOfTension]);
         this.dataDoc.pendulum_angle = this.dataDoc.pendulum_angleStart = 30;
@@ -709,7 +666,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.simulation_showComponentForces = false;
         this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1)]);
         this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1)]);
-        this.dataDoc.mass1_positionXstart = this.xMax / 2 - 0.08 * this.props.PanelHeight();
+        this.dataDoc.mass1_positionXstart = this.xMax / 2 - this.mass1Radius;
         this.dataDoc.mass1_positionYstart = 200;
         this.dataDoc.spring_constant = 0.5;
         this.dataDoc.spring_lengthRest = 200;
@@ -719,7 +676,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
 
     // Default setup for suspension simulation
     setupSuspension = () => {
-        let xPos = (this.xMax + this.xMin) / 2 - 0.08 * this.props.PanelHeight();
+        let xPos = (this.xMax + this.xMin) / 2 - this.mass1Radius;
         let yPos = this.yMin + 200;
         this.dataDoc.mass1_positionYstart = yPos;
         this.dataDoc.mass1_positionXstart = xPos;
@@ -730,13 +687,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             description: 'Tension',
             magnitude: tensionMag,
             directionInDegrees: 45,
-            component: false,
         };
         const tensionForce2: IForce = {
             description: 'Tension',
             magnitude: tensionMag,
             directionInDegrees: 135,
-            component: false,
         };
         const gravity = this.gravityForce(this.mass1);
         this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, gravity]);
@@ -757,7 +712,6 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             description: 'Tension',
             magnitude: this.mass1 * a + this.mass1 * Math.abs(this.gravity),
             directionInDegrees: 90,
-            component: false,
         };
         this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce1, tensionForce1]);
         this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce1, tensionForce1]);
@@ -767,7 +721,6 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             description: 'Tension',
             magnitude: -this.mass2 * a + this.mass2 * Math.abs(this.gravity),
             directionInDegrees: 90,
-            component: false,
         };
         this.dataDoc.mass2_positionYstart = (this.yMax + this.yMin) / 2;
         this.dataDoc.mass2_positionXstart = (this.xMin + this.xMax) / 2 + 5;
@@ -789,19 +742,16 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             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.mass1_forcesStart = JSON.stringify([forceOfGravityReview, normalForceReview, staticFrictionForceReview]);
         this.dataDoc.mass1_forcesUpdated = JSON.stringify([forceOfGravityReview, normalForceReview, staticFrictionForceReview]);
@@ -1378,7 +1328,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                         />
                                         {(this.simulationType == 'Inclined Plane' || this.simulationType == 'Pendulum') && (
                                             <FormControlLabel
-                                                control={<Checkbox checked={BoolCast(this.dataDoc.simulation_showForces)} onChange={() => (this.dataDoc.simulation_showComponentForces = !this.dataDoc.simulation_showComponentForces)} />}
+                                                control={<Checkbox checked={BoolCast(this.dataDoc.simulation_showComponentForces)} onChange={() => (this.dataDoc.simulation_showComponentForces = !this.dataDoc.simulation_showComponentForces)} />}
                                                 label="Show component force vectors"
                                                 labelPlacement="start"
                                             />
@@ -1616,26 +1566,16 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                         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(this.gravity) * Math.cos((value * Math.PI) / 180),
                                                         directionInDegrees: 270 - value,
-                                                        component: true,
                                                     };
                                                     const gravityPerpendicular: IForce = {
                                                         description: 'Gravity Perpendicular Component',
                                                         magnitude: Math.abs(this.gravity) * Math.sin((value * Math.PI) / 180),
                                                         directionInDegrees: -value,
-                                                        component: true,
                                                     };
 
                                                     const length = this.pendulumLength;
@@ -1648,7 +1588,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
 
                                                     this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1), forceOfTension]);
                                                     this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1), forceOfTension]);
-                                                    this.dataDoc.mass1_componentForces = JSON.stringify([tensionComponent, gravityParallel, gravityPerpendicular]);
+                                                    this.dataDoc.mass1_componentForces = JSON.stringify([forceOfTension, gravityParallel, gravityPerpendicular]);
                                                     this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
                                                 }
                                             }}
@@ -1736,13 +1676,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                                     description: 'Tension',
                                                                     magnitude: tensionMag1,
                                                                     directionInDegrees: dir1T,
-                                                                    component: false,
                                                                 };
                                                                 const tensionForce2: IForce = {
                                                                     description: 'Tension',
                                                                     magnitude: tensionMag2,
                                                                     directionInDegrees: dir2T,
-                                                                    component: false,
                                                                 };
                                                                 const gravity = this.gravityForce(this.mass1);
                                                                 this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, gravity]);
@@ -1787,13 +1725,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                                     description: 'Tension',
                                                                     magnitude: tensionMag1,
                                                                     directionInDegrees: dir1T,
-                                                                    component: false,
                                                                 };
                                                                 const tensionForce2: IForce = {
                                                                     description: 'Tension',
                                                                     magnitude: tensionMag2,
                                                                     directionInDegrees: dir2T,
-                                                                    component: false,
                                                                 };
                                                                 const gravity = this.gravityForce(this.mass1);
                                                                 this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, gravity]);
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index d062cc8c5..98b0e3f04 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -14,7 +14,6 @@ interface IForce {
     description: string;
     magnitude: number;
     directionInDegrees: number;
-    component: boolean;
 }
 export interface IWeightProps {
     pause: () => void;
@@ -250,13 +249,11 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                     description: 'Normal Force',
                     magnitude: this.props.mass * Math.abs(this.props.gravity) * Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
                     directionInDegrees: 180 - 90 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
-                    component: false,
                 };
                 const frictionForce: IForce = {
                     description: 'Kinetic Friction Force',
                     magnitude: this.props.mass * this.props.coefficientOfKineticFriction * Math.abs(this.props.gravity) * Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
                     directionInDegrees: 180 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
-                    component: false,
                 };
                 // reduce magnitude of friction force if necessary such that block cannot slide up plane
                 // prettier-ignore
@@ -271,31 +268,26 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                     description: 'Kinetic Friction Force',
                     magnitude: this.props.mass * this.props.coefficientOfKineticFriction * Math.abs(this.props.gravity) * Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
                     directionInDegrees: 180 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
-                    component: true,
                 };
                 const normalForceComponent: IForce = {
                     description: 'Normal Force',
                     magnitude: this.props.mass * Math.abs(this.props.gravity) * Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
                     directionInDegrees: 180 - 90 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
-                    component: true,
                 };
                 const gravityParallel: IForce = {
                     description: 'Gravity Parallel Component',
                     magnitude: this.props.mass * Math.abs(this.props.gravity) * Math.sin(Math.PI / 2 - Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
                     directionInDegrees: 180 - 90 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI + 180,
-                    component: true,
                 };
                 const gravityPerpendicular: IForce = {
                     description: 'Gravity Perpendicular Component',
                     magnitude: this.props.mass * Math.abs(this.props.gravity) * Math.cos(Math.PI / 2 - Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
                     directionInDegrees: 360 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
-                    component: true,
                 };
                 const gravityForce: IForce = {
                     description: 'Gravity',
                     magnitude: this.props.mass * Math.abs(this.props.gravity),
                     directionInDegrees: 270,
-                    component: false,
                 };
                 const kineticFriction = this.props.coefficientOfKineticFriction != 0;
                 this.props.setForcesUpdated([gravityForce, normalForce, ...(kineticFriction ? [frictionForce] : [])]);
@@ -394,7 +386,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 description: 'Centripetal Force',
                 magnitude: (this.props.startVelX ** 2 * this.props.mass) / this.props.circularMotionRadius,
                 directionInDegrees: (Math.atan2(deltaY, deltaX) * 180) / Math.PI,
-                component: false,
             },
         ];
     };
@@ -408,13 +399,11 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 description: 'Gravity',
                 magnitude: Math.abs(this.props.gravity) * this.props.mass,
                 directionInDegrees: 270,
-                component: false,
             },
             {
                 description: 'Spring Force',
                 magnitude: this.props.springConstant * (yPos - this.props.springRestLength) * (yPosPlus ? 1 : yPosMinus ? -1 : 0),
                 directionInDegrees: yPosPlus ? 90 : 270,
-                component: false,
             },
         ];
     };
@@ -442,13 +431,11 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 description: 'Gravity',
                 magnitude: Math.abs(this.props.gravity) * this.props.mass,
                 directionInDegrees: 270,
-                component: false,
             },
             {
                 description: 'Tension',
                 magnitude: mag,
                 directionInDegrees: angle,
-                component: false,
             },
         ];
     };
@@ -488,7 +475,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                         description: 'Gravity',
                         magnitude: Math.abs(this.props.gravity) * this.props.mass,
                         directionInDegrees: 270,
-                        component: false,
                     };
                     if (maxY > groundY) {
                         this.setState({ yPosition: groundY - 2 * this.props.radius - 0.01 });
@@ -500,11 +486,10 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                 description: 'Normal force',
                                 magnitude: gravity.magnitude,
                                 directionInDegrees: -gravity.directionInDegrees,
-                                component: false,
                             };
                             this.props.setForcesUpdated([gravity, normalForce]);
                             if (this.props.simulationType === 'Inclined Plane') {
-                                this.props.setComponentForces([gravity, { ...normalForce, component: true }]);
+                                this.props.setComponentForces([gravity, normalForce]);
                             }
                         }
                         collision = true;
@@ -641,19 +626,16 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 description: 'Tension',
                 magnitude: mag,
                 directionInDegrees: angle,
-                component: true,
             };
             const gravityParallel: IForce = {
                 description: 'Gravity Parallel Component',
                 magnitude: Math.abs(this.props.gravity) * Math.cos(((90 - angle) * Math.PI) / 180),
                 directionInDegrees: 270 - (90 - angle),
-                component: true,
             };
             const gravityPerpendicular: IForce = {
                 description: 'Gravity Perpendicular Component',
                 magnitude: Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180),
                 directionInDegrees: -(90 - angle),
-                component: true,
             };
             if (Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180) < 0) {
                 gravityPerpendicular.magnitude = Math.abs(Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180));
@@ -663,6 +645,57 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         }
     };
 
+    renderForce = (force: IForce, index: number, asComponent: boolean) => {
+        if (force.magnitude < this.epsilon) return;
+
+        const angle = (force.directionInDegrees * Math.PI) / 180;
+        const arrowStartY = this.state.yPosition + this.props.radius - this.props.radius * Math.sin(angle);
+        const arrowStartX = this.state.xPosition + this.props.radius + this.props.radius * Math.cos(angle);
+        const arrowEndY = arrowStartY - Math.abs(force.magnitude) * Math.sin(angle) - this.props.radius * Math.sin(angle);
+        const arrowEndX = arrowStartX + Math.abs(force.magnitude) * Math.cos(angle) + this.props.radius * Math.cos(angle);
+
+        const color = '#0d0d0d';
+
+        let labelTop = arrowEndY + (force.directionInDegrees >= 0 && force.directionInDegrees < 180 ? 40 : -40);
+        let labelLeft = arrowEndX + (force.directionInDegrees > 90 && force.directionInDegrees < 270 ? -120 : 30);
+
+        labelTop = Math.max(Math.min(labelTop, this.props.yMax + 50), this.props.yMin);
+        labelLeft = Math.max(Math.min(labelLeft, this.props.xMax - 60), this.props.xMin);
+
+        return (
+            <div key={index} style={{ zIndex: 6, position: 'absolute' }}>
+                <div
+                    style={{
+                        pointerEvents: 'none',
+                        position: 'absolute',
+                        left: this.props.xMin,
+                        top: this.props.yMin,
+                    }}>
+                    <svg width={this.props.xMax - this.props.xMin + 'px'} height={this.panelHeight}>
+                        <defs>
+                            <marker id="forceArrow" markerWidth="4" markerHeight="4" refX="0" refY="2" orient="auto" markerUnits="strokeWidth">
+                                <path d="M0,0 L0,4 L4,2 z" fill={color} />
+                            </marker>
+                        </defs>
+                        <line strokeDasharray={asComponent ? '10,10' : undefined} x1={arrowStartX} y1={arrowStartY} x2={arrowEndX} y2={arrowEndY} stroke={color} strokeWidth="5" markerEnd="url(#forceArrow)" />
+                    </svg>
+                </div>
+                <div
+                    style={{
+                        pointerEvents: 'none',
+                        position: 'absolute',
+                        left: labelLeft + 'px',
+                        top: labelTop + 'px',
+                        lineHeight: 1,
+                        backgroundColor: this.labelBackgroundColor,
+                    }}>
+                    <p>{force.description || 'Force'}</p>
+                    {this.props.showForceMagnitudes && <p>{Math.round(100 * force.magnitude) / 100} N</p>}
+                </div>
+            </div>
+        );
+    };
+
     // Render weight, spring, rod(s), vectors
     render() {
         return (
@@ -757,19 +790,16 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                     description: 'Tension',
                                     magnitude: tensionMag1,
                                     directionInDegrees: (dir1T * 180) / Math.PI,
-                                    component: false,
                                 };
                                 const tensionForce2: IForce = {
                                     description: 'Tension',
                                     magnitude: tensionMag2,
                                     directionInDegrees: (dir2T * 180) / Math.PI,
-                                    component: false,
                                 };
                                 const grav: IForce = {
                                     description: 'Gravity',
                                     magnitude: this.props.mass * Math.abs(this.props.gravity),
                                     directionInDegrees: 270,
-                                    component: false,
                                 };
                                 this.props.setForcesUpdated([tensionForce1, tensionForce2, grav]);
                             }
@@ -802,14 +832,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 )}
 
                 {this.props.simulationType == 'Pulley' && (
-                    <div
-                        className="rod"
-                        style={{
-                            pointerEvents: 'none',
-                            position: 'absolute',
-                            left: 0,
-                            top: 0,
-                        }}>
+                    <div className="rod">
                         <svg width={this.panelWidth} height={this.panelHeight}>
                             <line //
                                 x1={this.state.xPosition + this.props.radius}
@@ -837,14 +860,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                     </div>
                 )}
                 {this.props.simulationType == 'Suspension' && (
-                    <div
-                        className="rod"
-                        style={{
-                            pointerEvents: 'none',
-                            position: 'absolute',
-                            left: 0,
-                            top: 0,
-                        }}>
+                    <div className="rod">
                         <svg width={this.panelWidth} height={this.panelHeight}>
                             <line
                                 x1={this.state.xPosition + this.props.radius}
@@ -867,14 +883,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                             ) / 100}
                             °
                         </p>
-                        <div
-                            className="rod"
-                            style={{
-                                pointerEvents: 'none',
-                                position: 'absolute',
-                                left: 0,
-                                top: 0,
-                            }}>
+                        <div className="rod">
                             <svg width={this.props.panelWidth() + 'px'} height={this.panelHeight}>
                                 <line
                                     x1={this.state.xPosition + this.props.radius}
@@ -902,14 +911,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                     </div>
                 )}
                 {this.props.simulationType == 'Circular Motion' && (
-                    <div
-                        className="rod"
-                        style={{
-                            pointerEvents: 'none',
-                            position: 'absolute',
-                            left: 0,
-                            top: 0,
-                        }}>
+                    <div className="rod">
                         <svg width={this.panelWidth} height={this.panelHeight}>
                             <line
                                 x1={this.state.xPosition + this.props.radius}
@@ -923,14 +925,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                     </div>
                 )}
                 {this.props.simulationType == 'Pendulum' && (
-                    <div
-                        className="rod"
-                        style={{
-                            pointerEvents: 'none',
-                            position: 'absolute',
-                            left: 0,
-                            top: 0,
-                        }}>
+                    <div className="rod">
                         <svg width={this.panelWidth} height={this.panelHeight}>
                             <line x1={this.state.xPosition + this.props.radius} y1={this.state.yPosition + this.props.radius} x2={this.props.xMax / 2} y2={-5} stroke={'#deb887'} strokeWidth="10" />
                         </svg>
@@ -1056,136 +1051,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                         </div>
                     </div>
                 )}
-                {!this.state.dragging &&
-                    this.props.showComponentForces &&
-                    this.props.componentForces().map((force, index) => {
-                        if (force.magnitude < this.epsilon) {
-                            return;
-                        }
-                        const arrowStartY = this.state.yPosition + this.props.radius;
-                        const arrowStartX = this.state.xPosition + this.props.radius;
-                        const arrowEndY = arrowStartY - Math.abs(force.magnitude) * 20 * Math.sin((force.directionInDegrees * Math.PI) / 180);
-                        const arrowEndX = arrowStartX + Math.abs(force.magnitude) * 20 * Math.cos((force.directionInDegrees * Math.PI) / 180);
-
-                        const color = '#0d0d0d';
-
-                        let labelTop = arrowEndY;
-                        let labelLeft = arrowEndX;
-                        if (force.directionInDegrees > 90 && force.directionInDegrees < 270) {
-                            labelLeft -= 120;
-                        } else {
-                            labelLeft += 30;
-                        }
-                        if (force.directionInDegrees >= 0 && force.directionInDegrees < 180) {
-                            labelTop += 40;
-                        } else {
-                            labelTop -= 40;
-                        }
-                        labelTop = Math.min(labelTop, this.props.yMax + 50);
-                        labelTop = Math.max(labelTop, this.props.yMin);
-                        labelLeft = Math.min(labelLeft, this.props.xMax - 60);
-                        labelLeft = Math.max(labelLeft, this.props.xMin);
-
-                        return (
-                            <div key={index}>
-                                <div
-                                    style={{
-                                        pointerEvents: 'none',
-                                        position: 'absolute',
-                                        left: this.props.xMin,
-                                        top: this.props.yMin,
-                                    }}>
-                                    <svg width={this.props.xMax - this.props.xMin + 'px'} height={this.panelHeight}>
-                                        <defs>
-                                            <marker id="forceArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
-                                                <path d="M0,0 L0,6 L9,3 z" fill={color} />
-                                            </marker>
-                                        </defs>
-                                        {force.component == true && <line x1={arrowStartX} y1={arrowStartY} x2={arrowEndX} y2={arrowEndY} stroke={color} strokeWidth="5" strokeDasharray="10,10" markerEnd="url(#forceArrow)" />}
-                                        {force.component == false && <line x1={arrowStartX} y1={arrowStartY} x2={arrowEndX} y2={arrowEndY} stroke={color} strokeWidth="5" markerEnd="url(#forceArrow)" />}
-                                    </svg>
-                                </div>
-                                <div
-                                    style={{
-                                        pointerEvents: 'none',
-                                        position: 'absolute',
-                                        left: labelLeft + 'px',
-                                        top: labelTop + 'px',
-                                        lineHeight: 1,
-                                        backgroundColor: this.labelBackgroundColor,
-                                    }}>
-                                    {force.description && <p>{force.description}</p>}
-                                    {!force.description && <p>Force</p>}
-                                    {this.props.showForceMagnitudes && <p>{Math.round(100 * force.magnitude) / 100} N</p>}
-                                </div>
-                            </div>
-                        );
-                    })}
-                {!this.state.dragging &&
-                    this.props.showForces &&
-                    this.props.forcesUpdated().map((force, index) => {
-                        if (force.magnitude < this.epsilon) {
-                            return;
-                        }
-                        const arrowStartY = this.state.yPosition + this.props.radius;
-                        const arrowStartX = this.state.xPosition + this.props.radius;
-                        const arrowEndY = arrowStartY - Math.abs(force.magnitude) * 20 * Math.sin((force.directionInDegrees * Math.PI) / 180);
-                        const arrowEndX = arrowStartX + Math.abs(force.magnitude) * 20 * Math.cos((force.directionInDegrees * Math.PI) / 180);
-
-                        const color = '#0d0d0d';
-
-                        let labelTop = arrowEndY;
-                        let labelLeft = arrowEndX;
-                        if (force.directionInDegrees > 90 && force.directionInDegrees < 270) {
-                            labelLeft -= 120;
-                        } else {
-                            labelLeft += 30;
-                        }
-                        if (force.directionInDegrees >= 0 && force.directionInDegrees < 180) {
-                            labelTop += 40;
-                        } else {
-                            labelTop -= 40;
-                        }
-                        labelTop = Math.min(labelTop, this.props.yMax + 50);
-                        labelTop = Math.max(labelTop, this.props.yMin);
-                        labelLeft = Math.min(labelLeft, this.props.xMax - 60);
-                        labelLeft = Math.max(labelLeft, this.props.xMin);
-
-                        return (
-                            <div key={index}>
-                                <div
-                                    style={{
-                                        pointerEvents: 'none',
-                                        position: 'absolute',
-                                        left: this.props.xMin,
-                                        top: this.props.yMin,
-                                    }}>
-                                    <svg width={this.props.xMax - this.props.xMin + 'px'} height={this.panelHeight}>
-                                        <defs>
-                                            <marker id="forceArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
-                                                <path d="M0,0 L0,6 L9,3 z" fill={color} />
-                                            </marker>
-                                        </defs>
-                                        {force.component == true && <line x1={arrowStartX} y1={arrowStartY} x2={arrowEndX} y2={arrowEndY} stroke={color} strokeWidth="5" strokeDasharray="10,10" markerEnd="url(#forceArrow)" />}
-                                        {force.component == false && <line x1={arrowStartX} y1={arrowStartY} x2={arrowEndX} y2={arrowEndY} stroke={color} strokeWidth="5" markerEnd="url(#forceArrow)" />}
-                                    </svg>
-                                </div>
-                                <div
-                                    style={{
-                                        pointerEvents: 'none',
-                                        position: 'absolute',
-                                        left: labelLeft + 'px',
-                                        top: labelTop + 'px',
-                                        lineHeight: 1,
-                                        backgroundColor: this.labelBackgroundColor,
-                                    }}>
-                                    {force.description && <p>{force.description}</p>}
-                                    {!force.description && <p>Force</p>}
-                                    {this.props.showForceMagnitudes && <p>{Math.round(100 * force.magnitude) / 100} N</p>}
-                                </div>
-                            </div>
-                        );
-                    })}
+                {!this.state.dragging && this.props.showComponentForces && this.props.componentForces().map((force, index) => this.renderForce(force, index, true))}
+                {!this.state.dragging && this.props.showForces && this.props.forcesUpdated().map((force, index) => this.renderForce(force, index, false))}
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From 9e1c341955fb016f4a62339e4f11ac42d9572e95 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 24 May 2023 16:39:38 -0400
Subject: render cleanup for phys vector arrows.

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.scss     |   6 +-
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      |   6 +-
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   | 288 ++++++++-------------
 3 files changed, 120 insertions(+), 180 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
index 2e6ad413f..5f142df19 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
@@ -22,7 +22,11 @@
                 justify-content: space-between;
             }
         }
-        .rod {
+        .rod,
+        .spring,
+        .wheel,
+        .showvecs,
+        .wedge {
             pointer-events: none;
             position: absolute;
             left: 0;
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index d3e1c6fd2..f4acba2a6 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -87,7 +87,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     wallPositions: IWallProps[] = [];
 
     @computed get circularMotionRadius() {
-        return NumCast(this.dataDoc.circularMotionRadius, 150);
+        return (NumCast(this.dataDoc.circularMotionRadius, 150) * this.props.PanelWidth()) / 1000;
     }
     @computed get gravity() {
         return NumCast(this.dataDoc.simulation_gravity, -9.81);
@@ -757,7 +757,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.mass1_forcesUpdated = JSON.stringify([forceOfGravityReview, normalForceReview, staticFrictionForceReview]);
     };
 
-    pause = () => (this.dataDoc.paused = true);
+    pause = () => (this.dataDoc.simulation_paused = true);
     componentForces1 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass1_componentForces));
     setComponentForces1 = (forces: IForce[]) => (this.dataDoc.mass1_componentForces = JSON.stringify(forces));
     componentForces2 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass2_componentForces));
@@ -810,7 +810,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             yMax: this.yMax,
             yMin: this.yMin,
             wallPositions: this.wallPositions,
-            gravity: this.gravity,
+            gravity: Math.abs(this.gravity),
             timestepSize: 0.05,
             showComponentForces: BoolCast(this.dataDoc.simulation_showComponentForces),
             coefficientOfKineticFriction: NumCast(this.dataDoc.coefficientOfKineticFriction),
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index 98b0e3f04..f533df109 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -116,9 +116,20 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         };
     }
 
-    componentDidMount() {
-        // Timer for animating the simulation
-        setInterval(() => this.setState({ timer: this.state.timer + 1 }), 50);
+    _timer: NodeJS.Timeout | undefined;
+
+    componentWillUnmount() {
+        this._timer && clearTimeout(this._timer);
+    }
+    componentWillUpdate(nextProps: Readonly<IWeightProps>, nextState: Readonly<IState>, nextContext: any): void {
+        if (nextProps.simulationType !== this.props.simulationType) setTimeout(() => this.setState({ timer: this.state.timer + 1 }));
+        if (nextProps.paused) {
+            this._timer && clearTimeout(this._timer);
+            this._timer = undefined;
+        } else if (this.props.paused) {
+            this._timer && clearTimeout(this._timer);
+            this._timer = setInterval(() => this.setState({ timer: this.state.timer + 1 }), 50);
+        }
     }
 
     // Constants
@@ -154,7 +165,11 @@ export default class Weight extends React.Component<IWeightProps, IState> {
 
     // Helper function to go between display and real values
     getDisplayYPos = (yPos: number) => this.props.yMax - yPos - 2 * this.props.radius + 5;
-
+    gravityForce = (): IForce => ({
+        description: 'Gravity',
+        magnitude: this.props.mass * this.props.gravity,
+        directionInDegrees: 270,
+    });
     // Update display values when simulation updates
     setDisplayValues = (xPos: number = this.state.xPosition, yPos: number = this.state.yPosition, xVel: number = this.state.xVelocity, yVel: number = this.state.yVelocity) => {
         this.props.setPosition(xPos, this.getDisplayYPos(yPos));
@@ -210,7 +225,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             if (this.props.simulationType == 'One Weight') {
                 let maxYPos = this.state.updatedStartPosY;
                 if (this.props.startVelY != 0) {
-                    maxYPos -= (this.props.startVelY * this.props.startVelY) / (2 * Math.abs(this.props.gravity));
+                    maxYPos -= (this.props.startVelY * this.props.startVelY) / (2 * this.props.gravity);
                 }
                 if (maxYPos < 0) maxYPos = 0;
 
@@ -247,51 +262,41 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 this.setState({ kineticFriction: true });
                 const normalForce: IForce = {
                     description: 'Normal Force',
-                    magnitude: this.props.mass * Math.abs(this.props.gravity) * Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
+                    magnitude: this.props.mass * this.props.gravity * Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
                     directionInDegrees: 180 - 90 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
                 };
                 const frictionForce: IForce = {
                     description: 'Kinetic Friction Force',
-                    magnitude: this.props.mass * this.props.coefficientOfKineticFriction * Math.abs(this.props.gravity) * Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
+                    magnitude: this.props.mass * this.props.coefficientOfKineticFriction * this.props.gravity * Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
                     directionInDegrees: 180 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
                 };
                 // reduce magnitude of friction force if necessary such that block cannot slide up plane
                 // prettier-ignore
-                const yForce = -Math.abs(this.props.gravity) +
+                const yForce = - this.props.gravity +
                         normalForce.magnitude * Math.sin((normalForce.directionInDegrees * Math.PI) / 180) +
                         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(this.props.gravity)) / Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
+                    frictionForce.magnitude = (-normalForce.magnitude * Math.sin((normalForce.directionInDegrees * Math.PI) / 180) + this.props.gravity) / Math.sin((frictionForce.directionInDegrees * Math.PI) / 180);
                 }
 
-                const frictionForceComponent: IForce = {
-                    description: 'Kinetic Friction Force',
-                    magnitude: this.props.mass * this.props.coefficientOfKineticFriction * Math.abs(this.props.gravity) * Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
-                    directionInDegrees: 180 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
-                };
                 const normalForceComponent: IForce = {
                     description: 'Normal Force',
-                    magnitude: this.props.mass * Math.abs(this.props.gravity) * Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
+                    magnitude: this.props.mass * this.props.gravity * Math.cos(Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
                     directionInDegrees: 180 - 90 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
                 };
                 const gravityParallel: IForce = {
                     description: 'Gravity Parallel Component',
-                    magnitude: this.props.mass * Math.abs(this.props.gravity) * Math.sin(Math.PI / 2 - Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
+                    magnitude: this.props.mass * this.props.gravity * Math.sin(Math.PI / 2 - Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
                     directionInDegrees: 180 - 90 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI + 180,
                 };
                 const gravityPerpendicular: IForce = {
                     description: 'Gravity Perpendicular Component',
-                    magnitude: this.props.mass * Math.abs(this.props.gravity) * Math.cos(Math.PI / 2 - Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
+                    magnitude: this.props.mass * this.props.gravity * Math.cos(Math.PI / 2 - Math.atan(this.props.wedgeHeight / this.props.wedgeWidth)),
                     directionInDegrees: 360 - (Math.atan(this.props.wedgeHeight / this.props.wedgeWidth) * 180) / Math.PI,
                 };
-                const gravityForce: IForce = {
-                    description: 'Gravity',
-                    magnitude: this.props.mass * Math.abs(this.props.gravity),
-                    directionInDegrees: 270,
-                };
-                const kineticFriction = this.props.coefficientOfKineticFriction != 0;
-                this.props.setForcesUpdated([gravityForce, normalForce, ...(kineticFriction ? [frictionForce] : [])]);
-                this.props.setComponentForces([normalForceComponent, gravityParallel, gravityPerpendicular, ...(kineticFriction ? [frictionForceComponent] : [])]);
+                const kineticFriction = this.props.coefficientOfKineticFriction != 0 ? [frictionForce] : [];
+                this.props.setForcesUpdated([this.gravityForce(), normalForce, ...kineticFriction]);
+                this.props.setComponentForces([normalForceComponent, gravityParallel, gravityPerpendicular, ...kineticFriction]);
             }
         }
 
@@ -317,13 +322,12 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         }
 
         // Update wedge coordinates
-        if (this.state.coordinates === '' || prevProps.wedgeWidth != this.props.wedgeWidth || prevProps.wedgeHeight != this.props.wedgeHeight) {
+        if (!this.state.coordinates || prevProps.wedgeWidth != this.props.wedgeWidth || prevProps.wedgeHeight != this.props.wedgeHeight) {
             const left = this.props.xMax * 0.25;
             const coordinatePair1 = Math.round(left) + ',' + this.props.yMax + ' ';
             const coordinatePair2 = Math.round(left + this.props.wedgeWidth) + ',' + this.props.yMax + ' ';
             const coordinatePair3 = Math.round(left) + ',' + (this.props.yMax - this.props.wedgeHeight);
-            const coord = coordinatePair1 + coordinatePair2 + coordinatePair3;
-            this.setState({ coordinates: coord });
+            this.setState({ coordinates: coordinatePair1 + coordinatePair2 + coordinatePair3 });
         }
 
         if (this.state.xPosition != prevState.xPosition || this.state.yPosition != prevState.yPosition) {
@@ -395,11 +399,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         const yPosPlus = yPos - this.props.springRestLength > 0;
         const yPosMinus = yPos - this.props.springRestLength < 0;
         return [
-            {
-                description: 'Gravity',
-                magnitude: Math.abs(this.props.gravity) * this.props.mass,
-                directionInDegrees: 270,
-            },
+            this.gravityForce(),
             {
                 description: 'Spring Force',
                 magnitude: this.props.springConstant * (yPos - this.props.springRestLength) * (yPosPlus ? 1 : yPosMinus ? -1 : 0),
@@ -412,10 +412,8 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     getNewPendulumForces = (xPos: number, yPos: number, xVel: number, yVel: number): IForce[] => {
         const x = this.props.xMax / 2 - xPos - this.props.radius;
         const y = yPos + this.props.radius + 5;
-        let angle = (Math.atan(y / x) * 180) / Math.PI;
-        if (angle < 0) {
-            angle += 180;
-        }
+        const angle = (ang => (ang < 0 ? ang + 180 : ang))((Math.atan(y / x) * 180) / Math.PI);
+
         let oppositeAngle = 90 - angle;
         if (oppositeAngle < 0) {
             oppositeAngle = 90 - (180 - angle);
@@ -424,14 +422,10 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         const pendulumLength = Math.sqrt(x * x + y * y);
         this.props.setPendulumAngle(oppositeAngle, undefined);
 
-        const mag = this.props.mass * Math.abs(this.props.gravity) * Math.cos((oppositeAngle * Math.PI) / 180) + (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength;
+        const mag = this.props.mass * this.props.gravity * Math.cos((oppositeAngle * Math.PI) / 180) + (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength;
 
         return [
-            {
-                description: 'Gravity',
-                magnitude: Math.abs(this.props.gravity) * this.props.mass,
-                directionInDegrees: 270,
-            },
+            this.gravityForce(),
             {
                 description: 'Tension',
                 magnitude: mag,
@@ -471,11 +465,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             this.state.walls.forEach(wall => {
                 if (wall.angleInDegrees == 0 && wall.yPos > 0.4) {
                     const groundY = (wall.yPos / 100) * this.props.panelHeight();
-                    const gravity: IForce = {
-                        description: 'Gravity',
-                        magnitude: Math.abs(this.props.gravity) * this.props.mass,
-                        directionInDegrees: 270,
-                    };
+                    const gravity = this.gravityForce();
                     if (maxY > groundY) {
                         this.setState({ yPosition: groundY - 2 * this.props.radius - 0.01 });
                         if (this.props.elasticCollisions) {
@@ -536,11 +526,11 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     getForces = (xPos: number, yPos: number, xVel: number, yVel: number) => {
         // prettier-ignore
         switch (this.props.simulationType) {
-                case 'Pendulum':        return this.getNewPendulumForces(xPos, yPos, xVel, yVel);
-                case 'Spring'  :        return this.getNewSpringForces(yPos);
-                case 'Circular Motion': return this.getNewCircularMotionForces(xPos, yPos);
-                default:                return this.props.forcesUpdated();
-            }
+            case 'Pendulum':        return this.getNewPendulumForces(xPos, yPos, xVel, yVel);
+            case 'Spring'  :        return this.getNewSpringForces(yPos);
+            case 'Circular Motion': return this.getNewCircularMotionForces(xPos, yPos);
+            default:                return this.props.forcesUpdated();
+        }
     };
 
     // Update position, velocity using RK4 method
@@ -569,13 +559,11 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         // make sure harmonic motion maintained and errors don't propagate
         switch (this.props.simulationType) {
             case 'Spring':
+                const equilibriumPos = this.props.springRestLength + (this.props.mass * this.props.gravity) / this.props.springConstant;
+                const amplitude = Math.abs(equilibriumPos - this.props.springStartLength);
                 if (startYVel < 0 && yVel > 0 && yPos < this.props.springRestLength) {
-                    const equilibriumPos = this.props.springRestLength + (this.props.mass * Math.abs(this.props.gravity)) / this.props.springConstant;
-                    const amplitude = Math.abs(equilibriumPos - this.props.springStartLength);
                     yPos = equilibriumPos - amplitude;
                 } else if (startYVel > 0 && yVel < 0 && yPos > this.props.springRestLength) {
-                    const equilibriumPos = this.props.springRestLength + (this.props.mass * Math.abs(this.props.gravity)) / this.props.springConstant;
-                    const amplitude = Math.abs(equilibriumPos - this.props.springStartLength);
                     yPos = equilibriumPos + amplitude;
                 }
                 break;
@@ -620,32 +608,30 @@ export default class Weight extends React.Component<IWeightProps, IState> {
 
             const pendulumLength = Math.sqrt(x * x + y * y);
 
-            const mag = this.props.mass * Math.abs(this.props.gravity) * Math.cos((oppositeAngle * Math.PI) / 180) + (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength;
-
             const tensionComponent: IForce = {
                 description: 'Tension',
-                magnitude: mag,
+                magnitude: this.props.mass * this.props.gravity * Math.cos((oppositeAngle * Math.PI) / 180) + (this.props.mass * (xVel * xVel + yVel * yVel)) / pendulumLength,
                 directionInDegrees: angle,
             };
             const gravityParallel: IForce = {
                 description: 'Gravity Parallel Component',
-                magnitude: Math.abs(this.props.gravity) * Math.cos(((90 - angle) * Math.PI) / 180),
+                magnitude: this.props.gravity * Math.cos(((90 - angle) * Math.PI) / 180),
                 directionInDegrees: 270 - (90 - angle),
             };
             const gravityPerpendicular: IForce = {
                 description: 'Gravity Perpendicular Component',
-                magnitude: Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180),
+                magnitude: this.props.gravity * Math.sin(((90 - angle) * Math.PI) / 180),
                 directionInDegrees: -(90 - angle),
             };
-            if (Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180) < 0) {
-                gravityPerpendicular.magnitude = Math.abs(Math.abs(this.props.gravity) * Math.sin(((90 - angle) * Math.PI) / 180));
+            if (this.props.gravity * Math.sin(((90 - angle) * Math.PI) / 180) < 0) {
+                gravityPerpendicular.magnitude = Math.abs(this.props.gravity * Math.sin(((90 - angle) * Math.PI) / 180));
                 gravityPerpendicular.directionInDegrees = 180 - (90 - angle);
             }
             this.props.setComponentForces([tensionComponent, gravityParallel, gravityPerpendicular]);
         }
     };
 
-    renderForce = (force: IForce, index: number, asComponent: boolean) => {
+    renderForce = (force: IForce, index: number, asComponent: boolean, color = '#0d0d0d') => {
         if (force.magnitude < this.epsilon) return;
 
         const angle = (force.directionInDegrees * Math.PI) / 180;
@@ -654,8 +640,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         const arrowEndY = arrowStartY - Math.abs(force.magnitude) * Math.sin(angle) - this.props.radius * Math.sin(angle);
         const arrowEndX = arrowStartX + Math.abs(force.magnitude) * Math.cos(angle) + this.props.radius * Math.cos(angle);
 
-        const color = '#0d0d0d';
-
         let labelTop = arrowEndY + (force.directionInDegrees >= 0 && force.directionInDegrees < 180 ? 40 : -40);
         let labelLeft = arrowEndX + (force.directionInDegrees > 90 && force.directionInDegrees < 270 ? -120 : 30);
 
@@ -696,6 +680,40 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         );
     };
 
+    renderVector = (id: string, magX: number, magY: number, color: string, label: string) => {
+        const mag = Math.sqrt(magX * magX + magY * magY);
+        return (
+            <div className="showvecs" style={{ zIndex: 6 }}>
+                <svg width={this.panelWidth} height={this.panelHeight}>
+                    <defs>
+                        <marker id={id} markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
+                            <path d="M0,0 L0,6 L9,3 z" fill={color} />
+                        </marker>
+                    </defs>
+                    <line
+                        x1={this.state.xPosition + this.props.radius + (magX / mag) * this.props.radius}
+                        y1={this.state.yPosition + this.props.radius + (magY / mag) * this.props.radius}
+                        x2={this.state.xPosition + this.props.radius + (magX / mag) * this.props.radius + magX}
+                        y2={this.state.yPosition + this.props.radius + (magY / mag) * this.props.radius + magY}
+                        stroke={color}
+                        strokeWidth="5"
+                        markerEnd={`url(#${id})`}
+                    />
+                </svg>
+                <div
+                    style={{
+                        pointerEvents: 'none',
+                        position: 'absolute',
+                        left: this.state.xPosition + this.props.radius + 2 * (magX / mag) * this.props.radius + magX + 'px',
+                        top: this.state.yPosition + this.props.radius + 2 * (magY / mag) * this.props.radius + magY + 'px',
+                        lineHeight: 1,
+                    }}>
+                    {/* <p>{label}</p> */}
+                </div>
+            </div>
+        );
+    };
+
     // Render weight, spring, rod(s), vectors
     render() {
         return (
@@ -784,7 +802,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                 const deltaY = this.state.yPosition + this.props.radius;
                                 const dir1T = Math.PI - Math.atan(deltaY / deltaX1);
                                 const dir2T = Math.atan(deltaY / deltaX2);
-                                const tensionMag2 = (this.props.mass * Math.abs(this.props.gravity)) / ((-Math.cos(dir2T) / Math.cos(dir1T)) * Math.sin(dir1T) + Math.sin(dir2T));
+                                const tensionMag2 = (this.props.mass * this.props.gravity) / ((-Math.cos(dir2T) / Math.cos(dir1T)) * Math.sin(dir1T) + Math.sin(dir2T));
                                 const tensionMag1 = (-tensionMag2 * Math.cos(dir2T)) / Math.cos(dir1T);
                                 const tensionForce1: IForce = {
                                     description: 'Tension',
@@ -796,12 +814,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                     magnitude: tensionMag2,
                                     directionInDegrees: (dir2T * 180) / Math.PI,
                                 };
-                                const grav: IForce = {
-                                    description: 'Gravity',
-                                    magnitude: this.props.mass * Math.abs(this.props.gravity),
-                                    directionInDegrees: 270,
-                                };
-                                this.props.setForcesUpdated([tensionForce1, tensionForce2, grav]);
+                                this.props.setForcesUpdated([tensionForce1, tensionForce2, this.gravityForce()]);
                             }
                         }
                     }}>
@@ -810,22 +823,15 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                     </div>
                 </div>
                 {this.props.simulationType == 'Spring' && (
-                    <div
-                        className="spring"
-                        style={{
-                            pointerEvents: 'none',
-                            position: 'absolute',
-                            left: 0,
-                            top: 0,
-                        }}>
+                    <div className="spring">
                         <svg width={this.panelWidth} height={this.panelHeight}>
-                            {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(val => {
+                            {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(val => {
                                 const count = 10;
                                 const xPos1 = this.state.xPosition + this.props.radius + (val % 2 === 0 ? -20 : 20);
+                                const xPos2 = this.state.xPosition + this.props.radius + (val === 10 ? 0 : val % 2 === 0 ? 20 : -20);
                                 const yPos1 = (val * this.state.yPosition) / count;
-                                const xPos2 = this.state.xPosition + this.props.radius + (val % 2 === 0 ? 20 : -20);
-                                const yPos2 = ((val + 1) * this.state.yPosition) / count;
-                                return <line key={val} x1={xPos1} y1={yPos1} x2={xPos2} y2={yPos2} stroke={'#808080'} strokeWidth="10" />;
+                                const yPos2 = val === 10 ? this.state.yPosition + this.props.radius : ((val + 1) * this.state.yPosition) / count;
+                                return <line key={val} x1={xPos1} strokeLinecap="round" y1={yPos1} x2={xPos2} y2={yPos2} stroke={'#808080'} strokeWidth="10" />;
                             })}
                         </svg>
                     </div>
@@ -846,14 +852,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                     </div>
                 )}
                 {this.props.simulationType == 'Pulley' && (
-                    <div
-                        className="wheel"
-                        style={{
-                            pointerEvents: 'none',
-                            position: 'absolute',
-                            left: 0,
-                            top: 0,
-                        }}>
+                    <div className="wheel">
                         <svg width={this.panelWidth} height={this.panelHeight}>
                             <circle cx={(this.props.xMax + this.props.xMin) / 2} cy={this.props.radius} r={this.props.radius * 1.5} fill={'#808080'} />
                         </svg>
@@ -895,7 +894,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                                 />
                             </svg>
                         </div>
-
                         <p
                             style={{
                                 position: 'absolute',
@@ -956,12 +954,11 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                 )}
                 {this.props.simulationType == 'Inclined Plane' && (
                     <div>
-                        <div style={{ position: 'absolute', left: '0', top: '0' }}>
+                        <div className="wedge">
                             <svg width={this.panelWidth} height={this.props.yMax + 'px'}>
                                 <polygon points={this.state.coordinates} style={{ fill: 'burlywood' }} />
                             </svg>
                         </div>
-
                         <p
                             style={{
                                 position: 'absolute',
@@ -972,85 +969,24 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                         </p>
                     </div>
                 )}
-                {!this.state.dragging && this.props.showAcceleration && (
-                    <div>
-                        <div
-                            style={{
-                                pointerEvents: 'none',
-                                position: 'absolute',
-                                left: 0,
-                                top: 0,
-                            }}>
-                            <svg width={this.panelWidth} height={this.panelHeight}>
-                                <defs>
-                                    <marker id="accArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
-                                        <path d="M0,0 L0,6 L9,3 z" fill="green" />
-                                    </marker>
-                                </defs>
-                                <line
-                                    x1={this.state.xPosition + this.props.radius}
-                                    y1={this.state.yPosition + this.props.radius}
-                                    x2={this.state.xPosition + this.props.radius + this.getNewAccelerationX(this.props.forcesUpdated()) * 15}
-                                    y2={this.state.yPosition + this.props.radius + this.getNewAccelerationY(this.props.forcesUpdated()) * 15}
-                                    stroke={'green'}
-                                    strokeWidth="5"
-                                    markerEnd="url(#accArrow)"
-                                />
-                            </svg>
-                            <div
-                                style={{
-                                    pointerEvents: 'none',
-                                    position: 'absolute',
-                                    left: this.state.xPosition + this.props.radius + this.state.xAccel * 15 + 25 + 'px',
-                                    top: this.state.yPosition + this.props.radius + this.state.yAccel * 15 + 70 + 'px',
-                                    lineHeight: 1,
-                                }}>
-                                <p>
-                                    {Math.round(100 * Math.sqrt(this.state.xAccel * this.state.xAccel + this.state.yAccel * this.state.yAccel)) / 100} m/s
-                                    <sup>2</sup>
-                                </p>
-                            </div>
-                        </div>
-                    </div>
-                )}
-                {!this.state.dragging && this.props.showVelocity && (
-                    <div>
-                        <div
-                            style={{
-                                pointerEvents: 'none',
-                                position: 'absolute',
-                                left: 0,
-                                top: 0,
-                            }}>
-                            <svg width={this.panelWidth} height={this.panelHeight}>
-                                <defs>
-                                    <marker id="velArrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
-                                        <path d="M0,0 L0,6 L9,3 z" fill="blue" />
-                                    </marker>
-                                </defs>
-                                <line
-                                    x1={this.state.xPosition + this.props.radius}
-                                    y1={this.state.yPosition + this.props.radius}
-                                    x2={this.state.xPosition + this.props.radius + this.state.xVelocity * 7}
-                                    y2={this.state.yPosition + this.props.radius + this.state.yVelocity * 7}
-                                    stroke={'blue'}
-                                    strokeWidth="5"
-                                    markerEnd="url(#velArrow)"
-                                />
-                            </svg>
-                            <div
-                                style={{
-                                    pointerEvents: 'none',
-                                    position: 'absolute',
-                                    left: this.state.xPosition + this.props.radius + this.state.xVelocity * 7 + 25 + 'px',
-                                    top: this.state.yPosition + this.props.radius + this.state.yVelocity * 7 + 'px',
-                                    lineHeight: 1,
-                                }}>
-                                <p>{Math.round(100 * Math.sqrt(this.props.displayXVelocity * this.props.displayXVelocity + this.props.displayYVelocity * this.props.displayYVelocity)) / 100} m/s</p>
-                            </div>
-                        </div>
-                    </div>
-                )}
+                {!this.state.dragging &&
+                    this.props.showAcceleration &&
+                    this.renderVector(
+                        'accArrow',
+                        this.getNewAccelerationX(this.props.forcesUpdated()),
+                        this.getNewAccelerationY(this.props.forcesUpdated()),
+                        'green',
+                        `${Math.round(100 * Math.sqrt(this.state.xAccel * this.state.xAccel + this.state.yAccel * this.state.yAccel)) / 100} m/s^2`
+                    )}
+                {!this.state.dragging &&
+                    this.props.showVelocity &&
+                    this.renderVector(
+                        'velArrow',
+                        this.state.xVelocity,
+                        this.state.yVelocity,
+                        'blue',
+                        `${Math.round(100 * Math.sqrt(this.props.displayXVelocity * this.props.displayXVelocity + this.props.displayYVelocity * this.props.displayYVelocity)) / 100} m/s`
+                    )}
                 {!this.state.dragging && this.props.showComponentForces && this.props.componentForces().map((force, index) => this.renderForce(force, index, true))}
                 {!this.state.dragging && this.props.showForces && this.props.forcesUpdated().map((force, index) => this.renderForce(force, index, false))}
             </div>
-- 
cgit v1.2.3-70-g09d2


From 55f3c138354101664df80b1ce48416de6adf2da0 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 25 May 2023 10:47:14 -0400
Subject: physics layout fixes for window resizing and for resetting walls
 properly

---
 .../nodes/PhysicsBox/PhysicsSimulationBox.scss     |  2 +-
 .../nodes/PhysicsBox/PhysicsSimulationBox.tsx      | 80 +++++++++++-----------
 .../nodes/PhysicsBox/PhysicsSimulationWeight.tsx   | 39 +++++------
 3 files changed, 59 insertions(+), 62 deletions(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
index 5f142df19..ac2c611c7 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.scss
@@ -15,7 +15,7 @@
             left: 60%;
             padding: 1em;
             height: 100%;
-            overflow: auto;
+            transform-origin: top left;
 
             .mechanicsSimulationControls {
                 display: flex;
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index f4acba2a6..be8dbbd40 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -6,7 +6,7 @@ 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 { computed, IReactionDisposer, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import { NumListCast } from '../../../../fields/Doc';
 import { List } from '../../../../fields/List';
@@ -76,6 +76,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     }
 
     _widthDisposer: IReactionDisposer | undefined;
+    @observable _simReset = 0;
 
     // semi-Constants
     xMin = 0;
@@ -215,6 +216,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         directionInDegrees: 270,
     });
 
+    @action
     setupSimulation = () => {
         const simulationType = this.simulationType;
         const mode = this.simulationMode;
@@ -237,8 +239,6 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                     this.dataDoc.mass1_positionX = (this.xMax + this.xMin) / 2 - this.mass1Radius;
                     this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1)]);
                     this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1)]);
-                    this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
-                    ``;
                     break;
                 case 'Inclined Plane':  this.setupInclinedPlane(); break;
                 case 'Pendulum':        this.setupPendulum(); break;
@@ -247,7 +247,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                 case 'Pulley':          this.setupPulley(); break;
                 case 'Suspension':      this.setupSuspension();break;
             }
-            this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
+            this._simReset++;
         } else if (mode == 'Review') {
             this.dataDoc.simulation_showComponentForces = false;
             this.dataDoc.simulation_showForceMagnitudes = true;
@@ -333,7 +333,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                     this.dataDoc.simulation_showForceMagnitudes = tutorials.suspension.steps[0].showMagnitude;
                     break;
             }
-            this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
+            this._simReset++;
         }
     };
 
@@ -604,6 +604,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     };
 
     // Default setup for uniform circular motion simulation
+    @action
     setupCircular = (value: number) => {
         this.dataDoc.simulation_showComponentForces = false;
         this.dataDoc.mass1_velocityYstart = 0;
@@ -619,7 +620,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         };
         this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce]);
         this.dataDoc.mass1_forcesStart = JSON.stringify([tensionForce]);
-        this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
+        this._simReset++;
     };
 
     setupInclinedPlane = () => {
@@ -662,6 +663,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     };
 
     // Default setup for spring simulation
+    @action
     setupSpring = () => {
         this.dataDoc.simulation_showComponentForces = false;
         this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1)]);
@@ -671,10 +673,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.spring_constant = 0.5;
         this.dataDoc.spring_lengthRest = 200;
         this.dataDoc.spring_lengthStart = 200;
-        this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
+        this._simReset++;
     };
 
     // Default setup for suspension simulation
+    @action
     setupSuspension = () => {
         let xPos = (this.xMax + this.xMin) / 2 - this.mass1Radius;
         let yPos = this.yMin + 200;
@@ -696,10 +699,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         const gravity = this.gravityForce(this.mass1);
         this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, gravity]);
         this.dataDoc.mass1_forcesStart = JSON.stringify([tensionForce1, tensionForce2, gravity]);
-        this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
+        this._simReset++;
     };
 
     // Default setup for pulley simulation
+    @action
     setupPulley = () => {
         this.dataDoc.simulation_showComponentForces = false;
         this.dataDoc.mass1_positionYstart = (this.yMax + this.yMin) / 2;
@@ -728,8 +732,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
         this.dataDoc.mass2_positionX = (this.xMin + this.xMax) / 2 + 5;
         this.dataDoc.mass2_forcesUpdated = JSON.stringify([gravityForce2, tensionForce2]);
         this.dataDoc.mass2_forcesStart = JSON.stringify([gravityForce2, tensionForce2]);
-
-        this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
+        this._simReset++;
     };
 
     public static parseJSON(json: string) {
@@ -799,12 +802,14 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
     setSpringLength = (length: number) => {
         this.dataDoc.spring_lengthStart = length;
     };
+    resetRequest = () => this._simReset;
     render() {
         const commonWeightProps = {
             pause: this.pause,
             paused: BoolCast(this.dataDoc.simulation_paused),
             panelWidth: this.props.PanelWidth,
             panelHeight: this.props.PanelHeight,
+            resetRequest: this.resetRequest,
             xMax: this.xMax,
             xMin: this.xMin,
             yMax: this.yMax,
@@ -830,7 +835,6 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
             startPendulumAngle: this.pendulumAngleStart,
             startPendulumLength: this.pendulumLengthStart,
             radius: this.mass1Radius,
-            reset: BoolCast(this.dataDoc.simulation_reset),
             simulationSpeed: NumCast(this.dataDoc.simulation_speed, 2),
             showAcceleration: BoolCast(this.dataDoc.simulation_showAcceleration),
             showForceMagnitudes: BoolCast(this.dataDoc.simulation_showForceMagnitudes),
@@ -916,7 +920,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                             </div>
                         </div>
                     </div>
-                    <div className="mechanicsSimulationEquationContainer">
+                    <div className="mechanicsSimulationEquationContainer" style={{ overflow: 'auto', height: `${(1000 / this.props.PanelWidth()) * 100}%`, transform: `scale(${this.props.PanelWidth() / 1000})` }}>
                         <div className="mechanicsSimulationControls">
                             <Stack direction="row" spacing={1}>
                                 {this.dataDoc.simulation_paused && this.simulationMode != 'Tutorial' && (
@@ -930,7 +934,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                     </IconButton>
                                 )}
                                 {this.dataDoc.simulation_paused && this.simulationMode != 'Tutorial' && (
-                                    <IconButton onClick={() => (this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset)}>
+                                    <IconButton onClick={action(() => this._simReset++)}>
                                         <ReplayIcon />
                                     </IconButton>
                                 )}
@@ -1291,11 +1295,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                 </p>
                                 <div style={{ display: 'flex', flexDirection: 'column' }}>
                                     <Button
-                                        onClick={() => {
-                                            this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
+                                        onClick={action(() => {
+                                            this._simReset++;
                                             this.checkAnswers();
                                             this.dataDoc.simulation_showIcon = true;
-                                        }}
+                                        })}
                                         variant="outlined">
                                         <p>Submit</p>
                                     </Button>
@@ -1427,7 +1431,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             unit={'N/m'}
                                             upperBound={500}
                                             value={this.springConstant}
-                                            effect={(val: number) => (this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset)}
+                                            effect={action(() => this._simReset++)}
                                             radianEquivalent={false}
                                             mode={'Freeform'}
                                             labelWidth={'7em'}
@@ -1441,7 +1445,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             unit=""
                                             upperBound={500}
                                             value={this.springLengthRest}
-                                            effect={(val: number) => (this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset)}
+                                            effect={action(() => this._simReset++)}
                                             radianEquivalent={false}
                                             mode="Freeform"
                                             labelWidth={'7em'}
@@ -1455,11 +1459,11 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             unit=""
                                             upperBound={this.springLengthRest}
                                             value={this.springLengthStart - this.springLengthRest}
-                                            effect={(val: number) => {
+                                            effect={action((val: number) => {
                                                 this.dataDoc.mass1_positionYstart = this.springLengthRest + val;
                                                 this.dataDoc.spring_lengthStart = this.springLengthRest + val;
-                                                this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
-                                            }}
+                                                this._simReset++;
+                                            })}
                                             radianEquivalent={false}
                                             mode="Freeform"
                                             labelWidth={'7em'}
@@ -1477,10 +1481,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             unit={'°'}
                                             upperBound={49}
                                             value={this.wedgeAngle}
-                                            effect={(val: number) => {
+                                            effect={action((val: number) => {
                                                 this.changeWedgeBasedOnNewAngle(val);
-                                                this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
-                                            }}
+                                                this._simReset++;
+                                            })}
                                             radianEquivalent={true}
                                             mode={'Freeform'}
                                             labelWidth={'2em'}
@@ -1498,13 +1502,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             unit={''}
                                             upperBound={1}
                                             value={NumCast(this.dataDoc.coefficientOfStaticFriction) ?? 0}
-                                            effect={(val: number) => {
+                                            effect={action((val: number) => {
                                                 this.updateForcesWithFriction(val);
                                                 if (val < NumCast(this.dataDoc.coefficientOfKineticFriction)) {
                                                     this.dataDoc.soefficientOfKineticFriction = val;
                                                 }
-                                                this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
-                                            }}
+                                                this._simReset++;
+                                            })}
                                             mode={'Freeform'}
                                             labelWidth={'2em'}
                                         />
@@ -1521,9 +1525,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             unit={''}
                                             upperBound={NumCast(this.dataDoc.coefficientOfStaticFriction)}
                                             value={NumCast(this.dataDoc.coefficientOfKineticFriction) ?? 0}
-                                            effect={(val: number) => {
-                                                this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
-                                            }}
+                                            effect={action(() => this._simReset++)}
                                             mode={'Freeform'}
                                             labelWidth={'2em'}
                                         />
@@ -1556,7 +1558,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             unit={'°'}
                                             upperBound={59}
                                             value={NumCast(this.dataDoc.pendulum_angle, 30)}
-                                            effect={value => {
+                                            effect={action(value => {
                                                 this.dataDoc.pendulum_angleStart = value;
                                                 this.dataDoc.pendulum_lengthStart = this.dataDoc.pendulum_length;
                                                 if (this.simulationType == 'Pendulum') {
@@ -1589,9 +1591,9 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                     this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1), forceOfTension]);
                                                     this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1), forceOfTension]);
                                                     this.dataDoc.mass1_componentForces = JSON.stringify([forceOfTension, gravityParallel, gravityPerpendicular]);
-                                                    this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
+                                                    this._simReset++;
                                                 }
-                                            }}
+                                            })}
                                             radianEquivalent={true}
                                             mode="Freeform"
                                             labelWidth="5em"
@@ -1605,13 +1607,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                             unit="m"
                                             upperBound={400}
                                             value={Math.round(this.pendulumLength)}
-                                            effect={value => {
+                                            effect={action(value => {
                                                 if (this.simulationType == 'Pendulum') {
                                                     this.dataDoc.pendulum_angleStart = this.pendulumAngle;
                                                     this.dataDoc.pendulum_lengthStart = value;
-                                                    this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
+                                                    this._simReset++;
                                                 }
-                                            }}
+                                            })}
                                             radianEquivalent={false}
                                             mode="Freeform"
                                             labelWidth="5em"
@@ -1768,10 +1770,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                                                         unit={'m/s'}
                                                         upperBound={50}
                                                         value={NumCast(this.dataDoc.mass1_velocityX)}
-                                                        effect={value => {
+                                                        effect={action(value => {
                                                             this.dataDoc.mass1_velocityXstart = value;
-                                                            this.dataDoc.simulation_reset = !this.dataDoc.simulation_reset;
-                                                        }}
+                                                            this._simReset++;
+                                                        })}
                                                         small={true}
                                                         mode="Freeform"
                                                     />
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
index f533df109..2165c8ba9 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationWeight.tsx
@@ -1,8 +1,7 @@
-import { computed } from 'mobx';
+import { computed, IReactionDisposer, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import './PhysicsSimulationBox.scss';
 import React = require('react');
-import _ = require('lodash');
 
 interface IWallProps {
     length: number;
@@ -19,6 +18,7 @@ export interface IWeightProps {
     pause: () => void;
     panelWidth: () => number;
     panelHeight: () => number;
+    resetRequest: () => number;
     circularMotionRadius: number;
     coefficientOfKineticFriction: number;
     color: string;
@@ -35,7 +35,6 @@ export interface IWeightProps {
     pendulumAngle: number;
     pendulumLength: number;
     radius: number;
-    reset: boolean;
     showAcceleration: boolean;
     showComponentForces: boolean;
     showForceMagnitudes: boolean;
@@ -83,7 +82,6 @@ interface IState {
     timer: number;
     updatedStartPosX: any;
     updatedStartPosY: any;
-    walls: IWallProps[];
     xPosition: number;
     xVelocity: number;
     yPosition: number;
@@ -106,7 +104,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             timer: 0,
             updatedStartPosX: this.props.startPosX,
             updatedStartPosY: this.props.startPosY,
-            walls: [],
             xPosition: this.props.startPosX,
             xVelocity: this.props.startVelX,
             yPosition: this.props.startPosY,
@@ -117,12 +114,13 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     }
 
     _timer: NodeJS.Timeout | undefined;
+    _resetDisposer: IReactionDisposer | undefined;
 
     componentWillUnmount() {
         this._timer && clearTimeout(this._timer);
+        this._resetDisposer?.();
     }
     componentWillUpdate(nextProps: Readonly<IWeightProps>, nextState: Readonly<IState>, nextContext: any): void {
-        if (nextProps.simulationType !== this.props.simulationType) setTimeout(() => this.setState({ timer: this.state.timer + 1 }));
         if (nextProps.paused) {
             this._timer && clearTimeout(this._timer);
             this._timer = undefined;
@@ -142,6 +140,10 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     @computed get panelWidth() {
         return Math.max(1000, this.props.panelWidth()) + 'px';
     }
+
+    @computed get walls() {
+        return ['One Weight', 'Inclined Plane'].includes(this.props.simulationType) ? this.props.wallPositions : [];
+    }
     epsilon = 0.0001;
     labelBackgroundColor = `rgba(255,255,255,0.5)`;
 
@@ -179,7 +181,9 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         this.props.setAcceleration(xAccel, yAccel);
         this.setState({ xAccel, yAccel });
     };
-
+    componentDidMount() {
+        this._resetDisposer = reaction(() => this.props.resetRequest(), this.resetEverything);
+    }
     componentDidUpdate(prevProps: Readonly<IWeightProps>, prevState: Readonly<IState>, snapshot?: any): void {
         if (prevProps.simulationType != this.props.simulationType) {
             this.setState({ xVelocity: this.props.startVelX, yVelocity: this.props.startVelY });
@@ -251,11 +255,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             this.setDisplayValues();
         }
 
-        // Reset everything on reset button click
-        if (prevProps.reset != this.props.reset) {
-            this.resetEverything();
-        }
-
         // Convert from static to kinetic friction if/when weight slips on inclined plane
         if (prevState.xVelocity != this.state.xVelocity) {
             if (this.props.simulationType == 'Inclined Plane' && Math.abs(this.state.xVelocity) > 0.1 && this.props.simulationMode != 'Review' && !this.state.kineticFriction) {
@@ -300,11 +299,6 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             }
         }
 
-        // Add/remove walls when simulation type changes
-        if (prevProps.simulationType != this.props.simulationType) {
-            this.setState({ walls: ['One Weight', 'Inclined Plane'].includes(this.props.simulationType) ? this.props.wallPositions : [] });
-        }
-
         // Update x position when start pos x changes
         if (prevProps.startPosX != this.props.startPosX) {
             if (this.props.paused && !isNaN(this.props.startPosX)) {
@@ -322,7 +316,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         }
 
         // Update wedge coordinates
-        if (!this.state.coordinates || prevProps.wedgeWidth != this.props.wedgeWidth || prevProps.wedgeHeight != this.props.wedgeHeight) {
+        if (!this.state.coordinates || this.props.yMax !== prevProps.yMax || prevProps.wedgeWidth != this.props.wedgeWidth || prevProps.wedgeHeight != this.props.wedgeHeight) {
             const left = this.props.xMax * 0.25;
             const coordinatePair1 = Math.round(left) + ',' + this.props.yMax + ' ';
             const coordinatePair2 = Math.round(left + this.props.wedgeWidth) + ',' + this.props.yMax + ' ';
@@ -365,6 +359,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         this.props.setPosition(this.state.updatedStartPosX, this.state.updatedStartPosY);
         this.props.setVelocity(this.props.startVelX, this.props.startVelY);
         this.props.setAcceleration(0, 0);
+        setTimeout(() => this.setState({ timer: this.state.timer + 1 }));
     };
 
     // Compute x acceleration from forces, F=ma
@@ -438,7 +433,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
     checkForCollisionsWithWall = () => {
         let collision = false;
         if (this.state.xVelocity !== 0) {
-            this.state.walls
+            this.walls
                 .filter(wall => wall.angleInDegrees === 90)
                 .forEach(wall => {
                     const wallX = (wall.xPos / 100) * this.props.panelWidth();
@@ -462,7 +457,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
         const minY = this.state.yPosition;
         const maxY = this.state.yPosition + 2 * this.props.radius;
         if (this.state.yVelocity > 0) {
-            this.state.walls.forEach(wall => {
+            this.walls.forEach(wall => {
                 if (wall.angleInDegrees == 0 && wall.yPos > 0.4) {
                     const groundY = (wall.yPos / 100) * this.props.panelHeight();
                     const gravity = this.gravityForce();
@@ -488,7 +483,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
             });
         }
         if (this.state.yVelocity < 0) {
-            this.state.walls.forEach(wall => {
+            this.walls.forEach(wall => {
                 if (wall.angleInDegrees == 0 && wall.yPos < 0.4) {
                     const groundY = (wall.yPos / 100) * this.props.panelHeight();
                     if (minY < groundY) {
@@ -708,7 +703,7 @@ export default class Weight extends React.Component<IWeightProps, IState> {
                         top: this.state.yPosition + this.props.radius + 2 * (magY / mag) * this.props.radius + magY + 'px',
                         lineHeight: 1,
                     }}>
-                    {/* <p>{label}</p> */}
+                    <p style={{ background: 'white' }}>{label}</p>
                 </div>
             </div>
         );
-- 
cgit v1.2.3-70-g09d2


From 3d30bdaf6dcf4972593f10b9b0f2fabd79c7062b Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 25 May 2023 11:02:41 -0400
Subject: fixed phys scrolling

---
 src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

(limited to 'src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx')

diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index be8dbbd40..cd1ff17dd 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -920,7 +920,10 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
                             </div>
                         </div>
                     </div>
-                    <div className="mechanicsSimulationEquationContainer" style={{ overflow: 'auto', height: `${(1000 / this.props.PanelWidth()) * 100}%`, transform: `scale(${this.props.PanelWidth() / 1000})` }}>
+                    <div
+                        className="mechanicsSimulationEquationContainer"
+                        onWheel={e => this.props.isContentActive() && e.stopPropagation()}
+                        style={{ overflow: 'auto', height: `${Math.max(1, 800 / this.props.PanelWidth()) * 100}%`, transform: `scale(${Math.min(1, this.props.PanelWidth() / 850)})` }}>
                         <div className="mechanicsSimulationControls">
                             <Stack direction="row" spacing={1}>
                                 {this.dataDoc.simulation_paused && this.simulationMode != 'Tutorial' && (
-- 
cgit v1.2.3-70-g09d2

