algomin
Version:
Algomin - Viszualizing Distributed Algorithms
170 lines (148 loc) • 4.78 kB
JavaScript
import {Shape} from "./objects/Shape";
import {Message} from "./objects/Message";
export class Model {
/**
* The static time attribute is the current runtime
* @type {number}
*/
static time = 0;
/**
* The algorithm_duration is the maximum duration of the parsed current algorithm
* @type {number}
*/
static algorithm_duration = 0;
static shape = Shape;
static message = Message;
/**
* Initially set _running to false, the _start_time to 0
* and trigger the time increment loop
*/
constructor() {
this._running = false;
this._start_time = 0;
this.incrementTime();
}
get running() {
return this._running;
}
/**
* Since the increment loop calculates the passed time by calculating the
* current time subtracted by the start_time of the animation, the start_time needs
* to be readjusted when stopping and restarting the animation, so it doesn't keep
* going when the animation is stopped.
* @param value
*/
set running(value) {
this._start_time = new Date().getTime() - Model.time;
this._running = value;
}
start() {
this.running = true;
}
stop() {
this.running = false;
}
reStart() {
this._start_time = new Date().getTime();
Model.time = 0;
}
setTime(value) {
this._start_time = new Date().getTime() - Model.time;
Model.time = value;
}
/**
* The increment loop, restarts the animation when it finished.
* Also it increments the runtime when the animation is running
* by setting the runtime to = current_time - start_time
*/
incrementTime() {
if (Model.time > Model.algorithm_duration) {
this.reStart();
}
setTimeout(() => {
if (this._running) {
Model.time = new Date().getTime() - this._start_time;
}
this.incrementTime();
}, 6)
}
/**
* Cleares all Nodes and Messages
*/
clearObjects() {
Message.clearMessages();
Shape.clearShapes();
}
/**
* Creates all class objects and adds wait times of the animation by
* traversing the instructions JSON Array
* @param instructions JSON Array
*/
createObjects(instructions) {
let current_duration = 0;
instructions.forEach(instruction => {
switch (instruction.type) {
case "WAIT":
break;
case "SHAPE":
this.createShape(instruction, current_duration);
break;
case "SEND":
this.createMessage(instruction, current_duration);
break;
case "KILL":
this.killShape(instruction, current_duration);
break;
default:
break;
}
if (instruction.args.duration) {
current_duration += parseInt(instruction.args.duration);
}
})
Model.algorithm_duration = current_duration;
}
/**
* Creates a Shape (Node) object
* @param instruction JSON
* @param creation_time Integer
*/
createShape(instruction, creation_time) {
const args = instruction.args;
new Shape(instruction.id, args.x, args.y, args.w, args.h, args.label, creation_time);
}
/**
* Creates a Message object by getting and passing the source
* and target Node
* @param instruction JSON
* @param creation_time Integer
*/
createMessage(instruction, creation_time) {
const args = instruction.args;
const source_shape = Shape.get(instruction.source);
const target_shape = Shape.get(args.target);
if (!source_shape || !target_shape){
throw new Error(`sendMessage - Reference Error`);
} else {
new Message(
source_shape,
target_shape,
args.speed ? args.speed : 1000,
args.message ? args.message : "",
creation_time);
}
}
/**
* Kills a Node by setting its death_time to the passed value
* @param instruction JSON
* @param death_time Integer
*/
killShape(instruction, death_time) {
let shape = Shape.get(instruction.source);
if(!shape){
throw new Error(`kill - Reference Error`);
} else {
shape.deathTime = death_time;
}
}
}