Skip to content

Commit

Permalink
Source code documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
A-Herzog committed Feb 28, 2024
1 parent 98d1136 commit 6f64714
Show file tree
Hide file tree
Showing 17 changed files with 1,272 additions and 289 deletions.
139 changes: 112 additions & 27 deletions docs/js/Animator.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,17 @@ import {SimulatorWorker, WebSimulator} from './Simulator.js';
import {language, getCharacteristicsInfo} from "./Language.js";
import {simcore} from './SimCore.js';

/**
* Start animation.
*/
function startAnimation() {
/* Laufende Animation abbrechen */
/* Stop already running animation */
if (animationActive) {
stopAnimation();
return;
}

/* Falls die letzte Animation im Pause-Modus beendet wurde, diesen visuell zurücksetzen */
/* If the last animation was terminated in pause mode, do visual reset */
animationPause=false;
const playPauseButton=document.getElementById('animationPlayPauseButton');
playPauseButton.classList.remove('bi-play');
Expand All @@ -37,26 +40,26 @@ function startAnimation() {
const stepButton=document.getElementById('animationStepButtonOuter');
stepButton.classList.add("disabled");

/* Ggf. Funktion zum Hinzufügen von Kanten beenden */
/* Stop function for adding edges if needed */
if (addEdgeActive) addEdgeClick();

/* Modell prüfen & erstellen */
/* Check and generate model */
simulator=new WebSimulator(true);
const buildResult=simulator.build(elements,edges);
if (buildResult!=null) {
showMessage(language.builder.invalidModelTitle,language.builder.invalidModelText+"<br>"+buildResult);
return;
}

/* Positionsdaten für die Animation vorbereiten */
/* Prepare position data for animation */
const simStations=simulator.stations;
for (let i=0;i<simStations.length;i++) {
const div=document.getElementById(simStations[i].editElement.boxId);
stationDivs[simStations[i].id]=div;
}
stationConnections={};

/* Animation starten */
/* Start animation */
animationPause=false;
setAnimationMode(true);
animationSlider=document.getElementById('animationSpeed');
Expand All @@ -65,20 +68,29 @@ function startAnimation() {
animationStep();
}

/**
* Stops a running animation.
*/
function stopAnimation() {
setAnimationMode(false);
simulator.done();
simulator=null;

const canvas=document.getElementById("canvas_area");

/* Alte Symbole entfernen */
/* Remove old symbols */
for (let i=0;i<animationStaticClientsDivs.length;i++) {
canvas.removeChild(animationStaticClientsDivs[i]);
}
animationStaticClientsDivs=[];
}

/**
* Sets the GUI for animation or not animation mode
* @param {Boolean} active Animation active yes/no
* @see startAnimation()
* @see stopAnimation()
*/
function setAnimationMode(active) {
const button=document.getElementById('animation_button');
animationActive=active;
Expand All @@ -99,6 +111,9 @@ function setAnimationMode(active) {
document.querySelector('#sidebar h1').style.cursor=active?"default":"pointer";
}

/**
* Callback for the animation play/pause button.
*/
function animationPlayPause() {
const playpauseButton=document.getElementById('animationPlayPauseButton');
const stepButton=document.getElementById('animationStepButtonOuter');
Expand All @@ -122,11 +137,16 @@ function animationPlayPause() {
stepButton.classList.remove("disabled");
}
}



/**
* Is the animation active?
*/
let animationActive=false;

/**
* Is the animation in pause mode?
*/
let animationPause=false;

let animationStepTimeout=null;
let animationSlider;
let animationInfo;
Expand All @@ -135,49 +155,67 @@ let stationDivs={};
let stationConnections={};
let animationStaticClientsDivs=[];


/**
* Simulator object for running the animation.
*/
let simulator=null;

/**
* Animation delays in different speed modes
* @see animationStep()
*/
const animationDelay={1: 1000, 2: 500, 3: 200, 4: 50, 5: 0};


/**
* Executes a single animation step.
*/
function animationStep() {
animationStepTimeout=null;
const delay=animationDelay[animationSlider.value];
const now=Date.now();

/* Simulationsschritt ausführen */
/* Execute simulation step */
if (simulator==null) return;
const hasNext=simulator.executeNext();
if (!hasNext) {stopAnimation(); return;}

/* Bewegte Animationsbilder aktualisieren */
/* Update moving animation images */
const animationDuration=Math.max(5,Math.min(200,delay));
showMoveClients(animationDuration);

/* Statische Animationsbilder aktualisieren */
/* Update static animation images */
showStaticClients();

/* Anzeige aktualisieren */
/* Update status information */
animationInfo.innerHTML=simulator.info;

/* Visuelle Elemente aktualisieren */
/* Update the visual only elements */
updateVisualElements();

/* Nächsten Schritt planen */
/* Plan next animation step */
if (!animationPause) {
const nextStepDelay=simulator.nextEventIsSameTime?animationDuration:Math.max(animationDuration,delay);
animationStepTimeout=setTimeout(animationStep,nextStepDelay);
}
}

/**
* Executes one or more animation steps (as long as the time is not changing).
* This is the callback for the step button in animation pause mode.
*/
function animationSingleTimeStep() {
const startTime=simulator.time;
while (startTime==simulator.time) {
animationStep();
}
}

/**
* Generates a client icon as HTML node
* @param {Number} top Upper y coordinate
* @param {Number} left Left x coordinate
* @returns HTML icon node
*/
function createIcon(top, left) {
const icon=document.createElement("div");
icon.className="client bi bi-person-fill";
Expand All @@ -186,6 +224,9 @@ function createIcon(top, left) {
return icon;
}

/**
* Draw the static client icons on the canvas.
*/
function showStaticClients() {
const canvas=document.getElementById("canvas_area");

Expand All @@ -194,7 +235,7 @@ function showStaticClients() {
let oldIconsUsed=0;
animationStaticClientsDivs=[];

/* Neue Symbole erstellen bzw. alte recyclen */
/* Generate new symbols and/or recycle old symbols */
for (let id in simulator.animateStaticClients) {
const count=simulator.animateStaticClients[id];
const station=stationDivs[id];
Expand All @@ -204,13 +245,13 @@ function showStaticClients() {
for (let i=0;i<drawCount;i++) {
let icon;
if (oldIconsUsed<oldIcons.length) {
/* Altes Icon wiederverwenden */
/* Recycle old icon */
icon=oldIcons[oldIconsUsed];
oldIconsUsed++;
icon.style.top=top+"px";
icon.style.left=left+"px";
} else {
/* Neue Icon anlegen und einfügen */
/* Create and add new icon */
icon=createIcon(top,left);
canvas.appendChild(icon);
}
Expand All @@ -219,17 +260,23 @@ function showStaticClients() {
}
}

/* Nicht mehr verwendete alte Symbole entfernen */
/* Remove symbol which are not used anymore */
for (let i=oldIconsUsed;i<oldIconCount;i++) {
canvas.removeChild(oldIcons[i]);
}
}

/**
* Calculates the animation path from a origin to a destination station
* @param {Number} id1 Id of the origin station
* @param {Number} id2 Id of the destination station
* @returns Array containing the origin and the destination point of the animation movement path
*/
function calcConnection(id1, id2) {
const element1=stationDivs[id1];
const element2=stationDivs[id2];

/* Anknüpfpunkte für Kanten bestimmen */
/* Calculate connection points for the edge */
const startX1=element1.offsetLeft;
const startY1=element1.offsetTop;
const middleX1=element1.offsetLeft+element1.offsetWidth/2;
Expand All @@ -245,7 +292,7 @@ function calcConnection(id1, id2) {
const P1=[[endX1, middleY1], [middleX1, startY1], [startX1, middleY1], [middleX1, endY1]];
const P2=[[endX2, middleY2], [middleX2, startY2], [startX2, middleY2], [middleX2, endY2]];

/* Kürzeste Verbindung bestimmen */
/* Calculate shortest connection */
let best1=0;
let best2=0;
let bestDelta=999999999;
Expand All @@ -264,13 +311,17 @@ function calcConnection(id1, id2) {
return [arrow1, arrow2];
}

/**
* Adds the moving clients to the canvas.
* @param {Number} animationTime Time for movement (in ms)
*/
function showMoveClients(animationTime) {
const canvas=document.getElementById("canvas_area");

for (let i=0;i<simulator.animateMoveClients.length;i++) {
const move=simulator.animateMoveClients[i];

/* Weg vom Startpunkt zum Zielpunkt bestimmen */
/* Determine the route from the starting point to the destination */
if (typeof(stationConnections[move.from])=='undefined') stationConnections[move.from]={};
if (typeof(stationConnections[move.from][move.to])=='undefined') stationConnections[move.from][move.to]=calcConnection(move.from,move.to);
const path=stationConnections[move.from][move.to];
Expand Down Expand Up @@ -298,10 +349,18 @@ function showMoveClients(animationTime) {
}
}

/**
* Updates the visual only elements (diagrams) on the canvas.
*/
function updateVisualElements() {
for (let animationStation of simulator.animationStations) animationStation.template.animateFunc(simulator.time,animationStation.element,animationStation.data,simulator.stations);
}

/**
* Draws a client icon on its path from the origin to the destination station
* @param {Object} moveInfo Information on the client icon to be drawn
* @see showMoveClients
*/
function animationFrame(moveInfo) {
const now=Date.now();
const percent=(now-moveInfo.timeStart)/moveInfo.timeAnimation;
Expand All @@ -318,9 +377,23 @@ function animationFrame(moveInfo) {
}
}

/**
* Simulation progress dialog.
* @see animationFastForwardStep2
*/
let workerDialog=null;

/**
* Simulation web worker container object
* @see SimulatorWorker
* @see animationFastForwardStep2
*/
let worker=null;

/**
* Callback for the "Cancel simulation" button.
* @see animationFastForwardStep2
*/
function cancelWorker() {
if (worker!=null) {
worker.cancel();
Expand All @@ -329,11 +402,20 @@ function cancelWorker() {
}
}


/**
* Cancels the animation and starts a simulation.
* Calling this function will first show a confirmation message.
* @param {Number} arrivalMio Arrivals (in millions) to be simulated
*/
function animationFastForward(arrivalMio) {
showConfirmationMessage(language.tabAnimation.simulationTitle,language.tabAnimation.simulationText,()=>animationFastForwardStep2(arrivalMio));
}

/**
* Cancels the animation and starts a simulation (without confirmation message).
* @param {Number} arrivalMio Arrivals (in millions) to be simulated
* @see animationFastForward
*/
function animationFastForwardStep2(arrivalMio) {
stopAnimation();

Expand Down Expand Up @@ -379,6 +461,9 @@ function animationFastForwardStep2(arrivalMio) {
worker.start();
}

/**
* Shows the simulation results.
*/
function animationFastForwardShowFullData() {
const statistics=worker.full;
let content="";
Expand Down Expand Up @@ -461,4 +546,4 @@ function animationFastForwardShowFullData() {
const newWindow=window.open('');
newWindow.document.write(content);
newWindow.focus()
}
}
Loading

0 comments on commit 6f64714

Please sign in to comment.