mirror of
https://github.com/wisplite/BLE-mesh-sim.git
synced 2026-10-30 05:22:23 -05:00
HUGE update. New settings location, new styles, better dark mode, console, and ROUTING!!!
This commit is contained in:
+37
-14
@@ -43,30 +43,44 @@
|
||||
<input type="number" id="simSpeed" value="1" min="0.1" step="0.1" autocomplete="off">
|
||||
</div>
|
||||
</details>
|
||||
<details id="visualizationSettings">
|
||||
<summary>Visualization Settings</summary>
|
||||
<div id="visualizationSettingsContent">
|
||||
<div id="visualizationSettingsToggles">
|
||||
<input type="checkbox" id="showRanges">
|
||||
<label for="showRanges">Show Ranges</label>
|
||||
</div>
|
||||
<div id="visualizationSettingsToggles">
|
||||
<input type="checkbox" id="showTTL" checked>
|
||||
<label for="showTTL">Show TTL Colors</label>
|
||||
</div>
|
||||
<div id="visualizationSettingsToggles">
|
||||
<input type="checkbox" id="darkMode" checked>
|
||||
<label for="darkMode">Dark Mode</label>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
<div style="display: flex; flex-grow: 1; height: auto;"></div>
|
||||
<hr style="width: 100%;"/>
|
||||
<div id="darkModeContainer">
|
||||
<input type="checkbox" id="darkMode" class="simToggle">
|
||||
<label for="darkMode">Dark Mode</label>
|
||||
<input type="checkbox" id="quickPlace" class="simToggle">
|
||||
<label for="quickPlace">Quick Place</label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="centerColumn" style="display: flex; flex-direction: column; align-items: center; justify-content: center; width: 70%; height: 100%; margin: 0 auto;">
|
||||
<div id="simContainer"></div>
|
||||
|
||||
<div id="routingProgressContainer" style="display: none;">
|
||||
<progress id="routingProgress" value="0" max="100"></progress>
|
||||
</div>
|
||||
<div id="controlContainer">
|
||||
<div id="controlButtons">
|
||||
<button id="addNode" class="controlButton">Add Node</button>
|
||||
<button id="sendPacket" class="controlButton">Send Packet</button>
|
||||
<button id="quickPacket" class="controlButton">Quick Packet</button>
|
||||
<button id="sendPacket" class="controlButton">Send Flood Packet</button>
|
||||
<button id="quickPacket" class="controlButton">Quick Flood Packet</button>
|
||||
<button id="resetTTLColors" class="controlButton">Reset TTL Colors</button>
|
||||
<button id="createRandomGraph" class="controlButton">Create Random Network</button>
|
||||
</div>
|
||||
<div id="simToggles">
|
||||
<input type="checkbox" id="showRanges" class="simToggle">
|
||||
<label for="showRanges">Show Ranges</label>
|
||||
<input type="checkbox" id="showTTL" class="simToggle" checked>
|
||||
<label for="showTTL">Show TTL Colors</label>
|
||||
<input type="checkbox" id="quickPlace" class="simToggle">
|
||||
<label for="quickPlace">Quick Place</label>
|
||||
<button id="createRoutingTables" class="controlButton">Create Routing Tables</button>
|
||||
<button id="createRandomGraph" class="controlButton">Create Network</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -78,7 +92,10 @@
|
||||
<div id="randomGraphModalContent">
|
||||
<label for="randomGraphNodes">Number of Nodes</label>
|
||||
<input type="number" id="randomGraphNodes" value="10" autocomplete="off">
|
||||
<button id="createRandomGraphConfirm" class="controlButton">Create</button>
|
||||
<div id="randomGraphModalButtons" style="display: flex; flex-direction: row; gap: 10px; justify-content: end; align-items: center;">
|
||||
<button id="createRandomGraphCancel" class="controlButton" onclick="document.getElementById('randomGraphModal').style.display = 'none';">Cancel</button>
|
||||
<button id="createRandomGraphConfirm" class="controlButton">Create</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="warningModal">
|
||||
@@ -88,6 +105,12 @@
|
||||
<button id="warningModalConfirm" class="controlButton" onclick="document.getElementById('warningModal').style.display = 'none';">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="successModal">
|
||||
<div id="successModalContent">
|
||||
<p id="successModalMessage"></p>
|
||||
<button id="successModalConfirm" class="controlButton" onclick="document.getElementById('successModal').style.display = 'none';">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="script.js"></script>
|
||||
</body>
|
||||
|
||||
@@ -5,6 +5,8 @@ var TTL = 5;
|
||||
var MAX_OUTGOING_CONNECTIONS = 3;
|
||||
var MAX_INCOMING_CONNECTIONS = 3;
|
||||
var warningModalShown = false;
|
||||
var displayWarningWhenDone = false;
|
||||
var stillRouting = false;
|
||||
|
||||
function smoothColorTransition(color1, color2, min, max, current) {
|
||||
// Clamp current between min and max
|
||||
@@ -101,6 +103,10 @@ onEdgeEngine.createEdgesTable();
|
||||
onEdgeEngine.initMovement();
|
||||
onEdgeEngine.setArrivalCallback(({ from, to, dot }) => {
|
||||
var ttl = parseInt(dot.id.split('-')[2]);
|
||||
if (stillRouting) {
|
||||
routePacket(to, dot.id.split('-')[3], dot.id);
|
||||
return;
|
||||
}
|
||||
if (document.getElementById('showTTL').checked) {
|
||||
edges.update({id: `${from}->${to}`, color: {color: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1), highlight: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1)}});
|
||||
} else {
|
||||
@@ -184,6 +190,97 @@ function quickPacket(startNode, packetInfo, fromNode) {
|
||||
}
|
||||
}
|
||||
|
||||
// This is a modified version of quickPacket that contains some extra logic to save routing tables.
|
||||
// It also disables the TTL colors for unreachable nodes to save performance.
|
||||
function quickRoute(startNode, packetInfo, fromNode) {
|
||||
|
||||
const packetId = packetInfo.split('-')[0];
|
||||
const ttlStart = parseInt(packetInfo.split('-')[2]);
|
||||
const originNode = packetInfo.split('-')[3];
|
||||
|
||||
const queue = [{ nodeId: startNode, ttl: ttlStart, from: fromNode }];
|
||||
|
||||
while (queue.length > 0) {
|
||||
const { nodeId, ttl, from } = queue.shift();
|
||||
|
||||
if (ttl < 0) {
|
||||
displayWarningWhenDone = true;
|
||||
continue;
|
||||
}
|
||||
if (nodeTable[nodeId]?.packetCache?.includes(packetId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeTable[nodeId].packetCache.push(packetId);
|
||||
nodeTable[nodeId].routingTable[originNode] = from;
|
||||
|
||||
if (document.getElementById('showTTL').checked) {
|
||||
nodes.update({id: nodeId, color: {background: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl)}});
|
||||
edges.update({id: `${from}->${nodeId}`, color: {color: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl+1), highlight: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl)}});
|
||||
} else {
|
||||
nodes.update({id: nodeId, color: {background: '#97c2fc'}});
|
||||
edges.update({id: `${from}->${nodeId}`, color: {color: '#2b7ce9', highlight: '#2b7ce9'}});
|
||||
}
|
||||
|
||||
const neighborsSnapshot = (nodeTable[nodeId]?.outgoing?.slice()) || [];
|
||||
|
||||
for (let neighbor of neighborsSnapshot) {
|
||||
if (neighbor === originNode || neighbor === from) {
|
||||
continue;
|
||||
}
|
||||
queue.push({ nodeId: neighbor, ttl: ttl - 1, from: nodeId });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function routePacket(currentNode, goalNode, packetInfo, first=false) {
|
||||
stillRouting = true;
|
||||
const packetId = packetInfo.split('-')[0];
|
||||
var packetShift = generateRealisticLabel();
|
||||
let ttl = parseInt(packetInfo.split('-')[2]);
|
||||
nodes.update({id: currentNode, color: {background: '#97c2fc'}});
|
||||
nodes.update({id: goalNode, color: {background: '#ff00d9'}});
|
||||
if (ttl <= 0) {
|
||||
consoleLog(`Packet ${packetId} TTL expired. Dropping packet.`);
|
||||
stillRouting = false;
|
||||
return;
|
||||
}
|
||||
if (currentNode === goalNode) {
|
||||
consoleLog(`Packet ${packetId} reached ${goalNode}.`);
|
||||
stillRouting = false;
|
||||
return;
|
||||
}
|
||||
if (document.getElementById('showTTL').checked) {
|
||||
nodes.update({id: currentNode, color: {background: smoothColorTransition('#eb4034', '#40eb34', 0, TTL, ttl)}});
|
||||
} else {
|
||||
if (first) {
|
||||
nodes.update({id: currentNode, color: {background: '#ff00d9'}});
|
||||
} else {
|
||||
nodes.update({id: currentNode, color: {background: 'yellow'}});
|
||||
}
|
||||
}
|
||||
ttl--;
|
||||
const nextNode = nodeTable[currentNode].routingTable[goalNode];
|
||||
if (nextNode) {
|
||||
var movingNode = {
|
||||
id: `${packetId}-${packetShift}-${ttl}-${goalNode}`,
|
||||
label: packetId + `-${ttl}`,
|
||||
shape: 'dot',
|
||||
size: 10,
|
||||
color: {
|
||||
background: 'white',
|
||||
border: 'black'
|
||||
},
|
||||
font: {color: document.getElementById('darkMode').checked ? '#e0e0e0' : '#000'}
|
||||
};
|
||||
onEdgeEngine.createDotNode(movingNode, currentNode, nextNode);
|
||||
} else {
|
||||
consoleLog(`No route found from ${currentNode} to ${goalNode}. Dropping packet.`);
|
||||
console.log(nodeTable[currentNode].routingTable);
|
||||
stillRouting = false;
|
||||
}
|
||||
}
|
||||
|
||||
const markNeighborsAsFailed = (nodeId, from, packetId, visited = new Set()) => {
|
||||
if (visited.has(nodeId)) {
|
||||
return;
|
||||
@@ -492,7 +589,7 @@ function onNodeAdd() {
|
||||
document.getElementById('addNode').addEventListener('click', function() {
|
||||
const nodeId = generateRealisticLabel();
|
||||
nodes.add({id: nodeId, label: nodeId});
|
||||
nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': []};
|
||||
nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': [], 'routingTable': {}};
|
||||
onNodeAdd();
|
||||
});
|
||||
|
||||
@@ -503,7 +600,7 @@ network.on('click', function(properties) {
|
||||
if (document.getElementById('quickPlace').checked) {
|
||||
const nodeId = generateRealisticLabel();
|
||||
nodes.add({id: nodeId, label: nodeId, x: properties.pointer.canvas.x, y: properties.pointer.canvas.y});
|
||||
nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': []};
|
||||
nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': [], 'routingTable': {}};
|
||||
onNodeAdd();
|
||||
}
|
||||
});
|
||||
@@ -513,11 +610,12 @@ network.on('doubleClick', function(properties) {
|
||||
return;
|
||||
}
|
||||
if (properties.nodes.length > 0) {
|
||||
navigator.clipboard.writeText(properties.nodes[0]);
|
||||
return;
|
||||
}
|
||||
const nodeId = generateRealisticLabel();
|
||||
nodes.add({id: nodeId, label: nodeId, x: properties.pointer.canvas.x, y: properties.pointer.canvas.y});
|
||||
nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': []};
|
||||
nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': [], 'routingTable': {}};
|
||||
onNodeAdd();
|
||||
});
|
||||
|
||||
@@ -607,8 +705,8 @@ document.getElementById('createRandomGraphConfirm').addEventListener('click', fu
|
||||
let nodeCounter = 0;
|
||||
const interval = setInterval(() => {
|
||||
const nodeId = generateRealisticLabel();
|
||||
nodes.add({id: nodeId, label: nodeId, x: Math.random() * 100, y: Math.random() * 100});
|
||||
nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': []};
|
||||
nodes.add({id: nodeId, label: nodeId, x: Math.random() * 1000, y: Math.random() * 1000});
|
||||
nodeTable[nodeId] = {'incoming': [], 'outgoing': [], 'packetCache': [], 'routingTable': {}};
|
||||
onNodeAdd();
|
||||
nodeCounter++;
|
||||
if (nodeCounter >= nodeCount) {
|
||||
@@ -646,6 +744,36 @@ document.getElementById('quickPacket').addEventListener('click', async function(
|
||||
quickPacket(selectedNode, `${packetId}-${packetShift}-${ttl}-${selectedNode}`, selectedNode);
|
||||
});
|
||||
|
||||
document.getElementById('createRoutingTables').addEventListener('click', function() {
|
||||
let nodeCounter = 0;
|
||||
document.getElementById('routingProgressContainer').style.display = 'flex';
|
||||
document.getElementById('routingProgress').value = 0;
|
||||
document.getElementById('routingProgress').max = Object.keys(nodeTable).length;
|
||||
const interval = setInterval(() => {
|
||||
const packetId = generateRealisticLabel();
|
||||
var packetShift = generateRealisticLabel();
|
||||
let ttl = TTL;
|
||||
const nodeId = Object.keys(nodeTable)[nodeCounter];
|
||||
quickRoute(nodeId, `${packetId}-${packetShift}-${ttl}-${nodeId}`, nodeId);
|
||||
nodeCounter++;
|
||||
document.getElementById('routingProgress').value = nodeCounter;
|
||||
if (nodeCounter >= Object.keys(nodeTable).length) {
|
||||
clearInterval(interval);
|
||||
document.getElementById('routingProgressContainer').style.display = 'none';
|
||||
document.getElementById('routingProgress').value = 0;
|
||||
if (displayWarningWhenDone) {
|
||||
displayWarningWhenDone = false;
|
||||
document.getElementById('warningModal').style.display = 'block';
|
||||
document.getElementById('warningModalMessage').innerHTML = 'TTL hit zero while routing, some routes may be missing. If you experience issues, try increasing the TTL and routing again.';
|
||||
document.getElementById('warningModalCustomContent').innerHTML = '';
|
||||
} else {
|
||||
document.getElementById('successModal').style.display = 'block';
|
||||
document.getElementById('successModalMessage').innerHTML = 'Routing tables created successfully.';
|
||||
}
|
||||
}
|
||||
}, 10);
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
if (localStorage.getItem('darkMode') === 'true') {
|
||||
document.getElementById('darkMode').checked = true;
|
||||
@@ -654,4 +782,115 @@ window.onload = function() {
|
||||
document.getElementById('darkMode').checked = false;
|
||||
document.getElementById('styleSheet').href = 'style.css';
|
||||
}
|
||||
|
||||
let consoleContainer = document.createElement('div');
|
||||
consoleContainer.id = 'consoleContainer';
|
||||
document.getElementById('simContainer').appendChild(consoleContainer);
|
||||
|
||||
let openConsoleButton = document.createElement('button');
|
||||
openConsoleButton.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-terminal-icon lucide-terminal"><path d="M12 19h8"/><path d="m4 17 6-6-6-6"/></svg>';
|
||||
openConsoleButton.id = 'openConsole';
|
||||
openConsoleButton.addEventListener('click', function() {
|
||||
const consoleElement = document.getElementById('consoleContainer');
|
||||
const currentDisplay = window.getComputedStyle(consoleElement).display;
|
||||
consoleElement.style.display = currentDisplay === 'none' ? 'flex' : 'none';
|
||||
});
|
||||
|
||||
let consoleInputContainer = document.createElement('div');
|
||||
consoleInputContainer.id = 'consoleInputContainer';
|
||||
consoleContainer.appendChild(consoleInputContainer);
|
||||
|
||||
let consoleCarrot = document.createElement('pre');
|
||||
consoleCarrot.innerHTML = '>';
|
||||
consoleInputContainer.appendChild(consoleCarrot);
|
||||
|
||||
let consoleInput = document.createElement('input');
|
||||
consoleInput.id = 'consoleInput';
|
||||
consoleInput.placeholder = 'Enter command';
|
||||
consoleInputContainer.appendChild(consoleInput);
|
||||
let consoleInputHistory = [];
|
||||
let consoleInputHistoryIndex = 0;
|
||||
// Handle Enter key for command execution
|
||||
consoleInput.addEventListener('keypress', function(event) {
|
||||
if (event.key === 'Enter') {
|
||||
const command = consoleInput.value.trim();
|
||||
if (command) { // Only add non-empty commands to history
|
||||
consoleInputHistory.push(command);
|
||||
}
|
||||
consoleInputHistoryIndex = consoleInputHistory.length;
|
||||
|
||||
const rootCommand = command.split(' ')[0];
|
||||
const args = command.split(' ')[1];
|
||||
|
||||
switch (rootCommand) {
|
||||
case 'help':
|
||||
switch (args) {
|
||||
case 'routePacket':
|
||||
consoleLog('Sends a packet from one specific node to another. Usage: routePacket [startNode]->[endNode]');
|
||||
break;
|
||||
case 'exit':
|
||||
consoleLog('Exits the console');
|
||||
break;
|
||||
default:
|
||||
consoleLog('Available commands: help, routePacket, exit');
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'routePacket':
|
||||
if (!args) {
|
||||
consoleLog('Usage: routePacket [startNode]->[endNode]');
|
||||
break;
|
||||
}
|
||||
document.getElementById('resetTTLColors').click();
|
||||
const packetInfo = `${generateRealisticLabel()}-${generateRealisticLabel()}-${TTL}-${args.split('->')[1]}`;
|
||||
nodes.update({id: args.split('->')[0], color: {background: '#ff00d9'}});
|
||||
nodes.update({id: args.split('->')[1], color: {background: '#ff00d9'}});
|
||||
routePacket(args.split('->')[0], args.split('->')[1], packetInfo, true);
|
||||
break;
|
||||
case 'exit':
|
||||
document.getElementById('consoleContainer').style.display = 'none';
|
||||
break;
|
||||
default:
|
||||
consoleLog(`Unknown command "${rootCommand}"`);
|
||||
break;
|
||||
}
|
||||
consoleInput.value = '';
|
||||
}
|
||||
});
|
||||
|
||||
// Handle arrow keys for history navigation
|
||||
consoleInput.addEventListener('keydown', function(event) {
|
||||
if (event.key === 'ArrowUp') {
|
||||
event.preventDefault(); // Prevent cursor movement
|
||||
if (consoleInputHistory.length === 0) return;
|
||||
|
||||
if (consoleInputHistoryIndex > 0) {
|
||||
consoleInputHistoryIndex--;
|
||||
}
|
||||
consoleInput.value = consoleInputHistory[consoleInputHistoryIndex] || '';
|
||||
} else if (event.key === 'ArrowDown') {
|
||||
event.preventDefault(); // Prevent cursor movement
|
||||
if (consoleInputHistory.length === 0) return;
|
||||
|
||||
consoleInputHistoryIndex++;
|
||||
if (consoleInputHistoryIndex >= consoleInputHistory.length) {
|
||||
consoleInputHistoryIndex = consoleInputHistory.length;
|
||||
consoleInput.value = ''; // Clear input when going beyond history
|
||||
} else {
|
||||
consoleInput.value = consoleInputHistory[consoleInputHistoryIndex] || '';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let consoleOutput = document.createElement('pre');
|
||||
consoleOutput.id = 'consoleOutput';
|
||||
consoleContainer.appendChild(consoleOutput);
|
||||
|
||||
document.getElementById('simContainer').appendChild(openConsoleButton);
|
||||
}
|
||||
|
||||
function consoleLog(message) {
|
||||
const consoleOutput = document.getElementById('consoleOutput');
|
||||
consoleOutput.innerHTML = `${message}`;
|
||||
consoleOutput.scrollTop = consoleOutput.scrollHeight;
|
||||
}
|
||||
+102
-6
@@ -93,7 +93,7 @@ html, body {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
#simpleSettingsContent, #engineSettingsContent, #hardwareConstraintsContent {
|
||||
#simpleSettingsContent, #engineSettingsContent, #hardwareConstraintsContent, #visualizationSettingsContent {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
@@ -101,21 +101,21 @@ html, body {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
#simpleSettings, #hardwareConstraints, #engineSettings {
|
||||
#simpleSettings, #hardwareConstraints, #engineSettings, #visualizationSettings {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#randomGraphModal, #warningModal {
|
||||
#randomGraphModal, #warningModal, #successModal {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0%;
|
||||
left: 0%;
|
||||
transform: translate(0%, 0%);
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
padding: 20px;
|
||||
border: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
#warningModalContent {
|
||||
@@ -131,6 +131,19 @@ html, body {
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
#successModalContent {
|
||||
padding: 20px;
|
||||
background-color: #2d2d2d;
|
||||
border: 2px solid #00ff00;
|
||||
border-radius: 8px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: #e0e0e0;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
#randomGraphModalContent {
|
||||
padding: 20px;
|
||||
background-color: #2d2d2d;
|
||||
@@ -144,6 +157,16 @@ html, body {
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
#createRandomGraphCancel {
|
||||
margin-top: 10px;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
#createRandomGraphConfirm {
|
||||
margin-top: 10px;
|
||||
background-color: #4a9eff;
|
||||
@@ -205,4 +228,77 @@ button:active {
|
||||
/* Checkbox and radio button styling */
|
||||
input[type="checkbox"], input[type="radio"] {
|
||||
accent-color: #4a9eff;
|
||||
}
|
||||
|
||||
#routingProgressContainer {
|
||||
display: none;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#routingProgress {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
#openConsole {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#consoleContainer {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
z-index: 10;
|
||||
width: 100%;
|
||||
height: 10%;
|
||||
background-color: #000000;
|
||||
border-top: 1px solid #ffffff;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-left: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#consoleInput {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #000000;
|
||||
color: #e0e0e0;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#consoleInput:focus {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
#consoleInputContainer {
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
gap: 0px;
|
||||
}
|
||||
|
||||
|
||||
#consoleOutput {
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
background-color: #000000;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
@@ -52,7 +52,7 @@ html, body {
|
||||
position: absolute;
|
||||
border: 1px solid black;
|
||||
border-radius: 50%;
|
||||
z-index: 1000;
|
||||
z-index: 10;
|
||||
opacity: 0.2;
|
||||
background-color: red;
|
||||
pointer-events: none;
|
||||
@@ -73,7 +73,7 @@ html, body {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
#simpleSettingsContent, #engineSettingsContent, #hardwareConstraintsContent {
|
||||
#simpleSettingsContent, #engineSettingsContent, #hardwareConstraintsContent, #visualizationSettingsContent {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
@@ -81,21 +81,21 @@ html, body {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
#simpleSettings, #hardwareConstraints, #engineSettings {
|
||||
#simpleSettings, #hardwareConstraints, #engineSettings, #visualizationSettings {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#randomGraphModal, #warningModal {
|
||||
#randomGraphModal, #warningModal, #successModal {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0%;
|
||||
left: 0%;
|
||||
transform: translate(0%, 0%);
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
padding: 20px;
|
||||
border: 1px solid #000;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
#warningModalContent {
|
||||
@@ -108,6 +108,16 @@ html, body {
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
#successModalContent {
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #00ff00;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
#randomGraphModalContent {
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
@@ -118,6 +128,79 @@ html, body {
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
#createRandomGraphConfirm {
|
||||
#createRandomGraphConfirm, #createRandomGraphCancel {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#routingProgressContainer {
|
||||
display: none;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#routingProgress {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
#openConsole {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#consoleContainer {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
z-index: 10;
|
||||
width: 100%;
|
||||
height: 10%;
|
||||
background-color: #ffffff;
|
||||
border-top: 1px solid #000000;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-left: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#consoleInput {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #ffffff;
|
||||
color: #000000;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#consoleInput:focus {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
#consoleInputContainer {
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
gap: 0px;
|
||||
}
|
||||
|
||||
|
||||
#consoleOutput {
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
background-color: #ffffff;
|
||||
color: #000000;
|
||||
}
|
||||
Reference in New Issue
Block a user