Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Packet speed #108

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
44 changes: 41 additions & 3 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { Layer } from "./types/devices/device";
import { IpAddress, IpAddressGenerator } from "./packets/ip";
import { layerFromName } from "./types/devices/layer";
import { SpeedMultiplier } from "./types/devices/speedMultiplier";

export class GlobalContext {
private viewport: Viewport = null;
Expand All @@ -30,15 +31,40 @@ export class GlobalContext {
return this.ipGenerator.getNextIp();
}

private setNetwork(datagraph: DataGraph, layer: Layer) {
private setNetwork(
datagraph: DataGraph,
layer: Layer,
speedMultiplier?: SpeedMultiplier,
) {
this.datagraph = datagraph;
this.viewport.clear();
this.viewgraph = new ViewGraph(this.datagraph, this.viewport, layer);
this.viewgraph.setSpeed(speedMultiplier?.value || 1);
this.setIpGenerator();
}

load(datagraph: DataGraph, layer: Layer = Layer.Link) {
private setSpeedMultiplier(speedMultiplier: SpeedMultiplier) {
if (speedMultiplier && speedMultiplier.value > 0) {
this.changeSpeedMultiplier(speedMultiplier.value);
// Update the wheel display after setting the speed
const speedWheel = document.getElementById(
"speed-wheel",
) as HTMLInputElement;
const valueDisplay = document.querySelector(".value-display");
if (speedWheel && valueDisplay) {
speedWheel.value = speedMultiplier.value.toString();
valueDisplay.textContent = `${speedMultiplier.value}x`;
}
}
}

load(
datagraph: DataGraph,
layer: Layer = Layer.Link,
speedMultiplier: SpeedMultiplier = SpeedMultiplier.parse(1),
) {
this.setNetwork(datagraph, layer);
this.setSpeedMultiplier(speedMultiplier);
this.setupAutoSave();
saveToLocalStorage(this);
urManager.reset();
Expand All @@ -56,14 +82,26 @@ export class GlobalContext {
return this.viewgraph.getLayer();
}

getCurrentSpeed() {
return this.viewgraph.getSpeed();
}

getDataGraph() {
return this.datagraph;
}

changeViewGraph(selectedLayer: string) {
const layer = layerFromName(selectedLayer);
const speedMultiplier = this.getCurrentSpeed();
urManager.reset();
this.setNetwork(this.datagraph, layer);
this.setNetwork(this.datagraph, layer, speedMultiplier);
}

changeSpeedMultiplier(speedMultiplier: number) {
if (this.viewgraph) {
this.viewgraph.setSpeed(speedMultiplier);
saveToLocalStorage(this);
}
}

private setupAutoSave() {
Expand Down
14 changes: 14 additions & 0 deletions src/index.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@
<button id="pause-button" class="pause-button" title="Pause"></button>
<i id="undo-button" class="undo-button" title="Undo"></i>
<i id="redo-button" class="redo-button" title="Redo"></i>
<div class="wheel-container">
<div class="wheel-label">Speed</div>
<div class="circular-slider">
<input
type="range"
id="speed-wheel"
min="0.1"
max="4"
step="0.1"
value="1"
>
</div>
<div class="value-display">1x</div>
</div>
<select id="layer-select" class="dropdown-menu">
<option value="application">App Layer</option>
<option value="transport">Transport Layer</option>
Expand Down
33 changes: 32 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import PauseSvg from "./assets/pause-icon.svg";
import UndoSvg from "./assets/left-curve-arrow.svg";
import RedoSvg from "./assets/right-curve-arrow.svg";
import { layerToName } from "./types/devices/layer";
import { SpeedMultiplier } from "./types/devices/speedMultiplier";

const assets = [RouterSvg, ComputerSvg, PlaySvg, PauseSvg, UndoSvg, RedoSvg];

Expand Down Expand Up @@ -201,7 +202,17 @@ async function loadAssets(otherPromises: Promise<void>[]) {

pauseButton.onclick = triggerPause;

// Layer abstraction logic
function updateSpeedWheel(value: number) {
const speedWheel = document.getElementById(
"speed-wheel",
) as HTMLInputElement;
const valueDisplay = document.querySelector(".value-display");

speedWheel.value = value.toString();
valueDisplay.textContent = `${value}x`;
}

// (!) For layer abstraction functionality
const selectNewLayer = (event: Event) => {
const selectedLayer = (event.target as HTMLSelectElement).value;
console.log(`Layer selected: ${selectedLayer}`);
Expand All @@ -223,5 +234,25 @@ async function loadAssets(otherPromises: Promise<void>[]) {
}
};

let speedMultiplier = ctx.getCurrentSpeed();
console.log("Current Speed Multiplier: ", speedMultiplier);

const speedWheel = document.getElementById("speed-wheel") as HTMLInputElement;
const valueDisplay = document.querySelector(".value-display");

// Update the wheel with the current speed value
updateSpeedWheel(speedMultiplier.value);

speedWheel.addEventListener("input", (event) => {
const value = parseFloat((event.target as HTMLInputElement).value);
speedMultiplier = SpeedMultiplier.parse(value);
valueDisplay.textContent = speedMultiplier.multiplier;

ctx.changeSpeedMultiplier(speedMultiplier.value);
});

// Initialize with default value
valueDisplay.textContent = `${(speedWheel as HTMLInputElement).value}x`;

console.log("initialized!");
})();
1 change: 1 addition & 0 deletions src/styles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import "./global.css";
import "./top-bar.css";
import "./left-bar.css";
import "./canvas.css";
import "./speed-wheel.css";
import "./right-bar.css";
import "./right-bar-buttons.css";
import "./table.css";
Expand Down
87 changes: 87 additions & 0 deletions src/styles/speed-wheel.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
.wheel-container {
position: absolute;
top: 10px;
right: 180px;
height: 20px;
display: flex;
flex-direction: row; /* Changed to row */
align-items: center; /* Center items vertically */
justify-content: space-between; /* Space between elements */
background-color: #333333;
padding: 5px 10px; /* Added more horizontal padding */
border-radius: 5px;
z-index: 1000;
width: auto; /* Let content determine width */
gap: 10px; /* Space between elements */
}

.wheel-label {
font-size: 15px;
color: white;
white-space: nowrap; /* Prevent text wrapping */
margin: 0; /* Remove margin */
}

.circular-slider {
position: relative;
width: 120px;
height: 30px;
margin: 0; /* Remove margin */
}

.circular-slider input[type="range"] {
position: absolute;
width: 120px;
height: 30px;
background: none;
-webkit-appearance: none;
transform: none;
cursor: pointer;
}

.circular-slider input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 15px;
height: 15px;
border-radius: 50%;
background: #007bff;
border: 2px solid #fff;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
cursor: pointer;
margin-top: -5px;
}

.circular-slider input[type="range"]::-webkit-slider-runnable-track {
width: 100%;
height: 5px;
background: #555;
border: none;
border-radius: 2.5px;
}

.circular-slider input[type="range"]::-moz-range-thumb {
width: 15px;
height: 15px;
border-radius: 50%;
background: #007bff;
border: 2px solid #fff;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
cursor: pointer;
}

.circular-slider input[type="range"]::-moz-range-track {
width: 100%;
height: 5px;
background: #444;
border: none;
border-radius: 2.5px;
}

.value-display {
font-size: 15px;
color: white;
margin: 0; /* Remove margin */
white-space: nowrap; /* Prevent text wrapping */
min-width: 35px; /* Ensure space for the value */
text-align: right;
}
35 changes: 35 additions & 0 deletions src/types/devices/speedMultiplier.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export class SpeedMultiplier {
private _value: number;

constructor(initialValue = 1) {
this._value = initialValue;
}

// Get the current speed value
get value(): number {
return this._value;
}

// Set a new speed value
set value(newValue: number) {
if (newValue > 0) {
this._value = newValue;
} else {
throw new Error("Speed value must be greater than 0");
}
}

// Get the speed multiplier as a formatted string
get multiplier(): string {
return `${this._value}x`;
}

// Static method to parse a number to a Speed instance
static parse(value: number): SpeedMultiplier {
if (value > 0) {
return new SpeedMultiplier(value);
} else {
throw new Error("Speed value must be greater than 0");
}
}
}
18 changes: 18 additions & 0 deletions src/types/graphs/viewgraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Edge, EdgeEdges } from "./../edge";
import { DataGraph, DeviceId, GraphNode, isRouter } from "./datagraph";
import { Viewport } from "../../graphics/viewport";
import { Layer, layerIncluded } from "../devices/layer";
import { SpeedMultiplier } from "../devices/speedMultiplier";
import { CreateDevice, createDevice } from "../devices/utils";
import { layerFromType } from "../devices/device";

Expand All @@ -20,12 +21,14 @@ export class ViewGraph {
private edges: Map<EdgeId, Edge> = new Map<EdgeId, Edge>();
datagraph: DataGraph;
private layer: Layer;
private speedMultiplier: SpeedMultiplier;
viewport: Viewport;

constructor(datagraph: DataGraph, viewport: Viewport, layer: Layer) {
this.datagraph = datagraph;
this.viewport = viewport;
this.layer = layer;
this.speedMultiplier = new SpeedMultiplier(1);
this.constructView();
}

Expand Down Expand Up @@ -170,6 +173,21 @@ export class ViewGraph {
return this.layer;
}

getSpeed(): SpeedMultiplier {
if (!this.speedMultiplier) {
this.speedMultiplier = new SpeedMultiplier(1);
}
return this.speedMultiplier;
}

setSpeed(speed: number) {
if (this.speedMultiplier) {
this.speedMultiplier.value = speed;
} else {
this.speedMultiplier = new SpeedMultiplier(speed);
}
}

// Get all connections of a device
getConnections(id: DeviceId): Edge[] {
const device = this.devices.get(id);
Expand Down
23 changes: 20 additions & 3 deletions src/types/packet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@ const contextPerPacketType: Record<string, GraphicsContext> = {
const highlightedPacketContext = circleGraphicsContext(Colors.Violet, 0, 0, 6);

export class Packet extends Graphics {
speed = 200;
speed = 100;
progress = 0;
viewgraph: ViewGraph;
currentEdge: Edge;
currentStart: number;
color: number;
type: string;

rawPacket: IPv4Packet;

static animationPaused = false;
Expand Down Expand Up @@ -187,6 +186,7 @@ export class Packet extends Graphics {
if (this.progress >= 1) {
this.progress = 0;
this.removeFromParent();

const newStart = this.currentEdge.otherEnd(this.currentStart);
this.currentStart = newStart;
const newEdgeId = this.routePacket(newStart);
Expand All @@ -203,18 +203,35 @@ export class Packet extends Graphics {
deleteSelf();
return;
}

const currentNodeEdges = this.viewgraph.getConnections(newStart);
this.currentEdge = currentNodeEdges.find((edge) => {
return edge.otherEnd(newStart) === newEdgeId;
});

if (this.currentEdge === undefined) {
deleteSelf();
return;
}
this.currentEdge.addChild(this);
}

// Calculate the edge length
const start = this.currentEdge.startPos;
const end = this.currentEdge.endPos;
const edgeLength = Math.sqrt(
Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2),
);

// Normalize the speed based on edge length
// The longer the edge, the slower the progress increment
const normalizedSpeed = this.speed / edgeLength;

// Update progress with normalized speed
if (!Packet.animationPaused) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could have this be a speed of 0 instead

this.progress += (ticker.deltaMS * this.speed) / 100000;
this.progress +=
(ticker.deltaMS * normalizedSpeed * this.viewgraph.getSpeed().value) /
1000;
}

this.updatePosition();
Expand Down
Loading
Loading