Show code
colors = ({
navy: "#2C3E50",
teal: "#16A085",
orange: "#E67E22",
blue: "#3498DB",
gray: "#7F8C8D",
purple: "#9B59B6",
red: "#E74C3C"
})
// User controls
viewof nodeCount = Inputs.range([10, 200], {
value: 50,
step: 10,
label: "Number of Nodes:"
})
viewof txPower = Inputs.range([-10, 20], {
value: 10,
step: 5,
label: "TX Power (dBm):",
width: 300
})
viewof dataRate = Inputs.range([1, 20], {
value: 5,
step: 1,
label: "Data Rate (packets/min):",
width: 300
})
// Simulation model (simplified for demonstration)
simulationResults = {
// PDR decreases with more nodes and higher data rates, increases with TX power
const basePDR = 98;
const nodeFactor = -0.15 * (nodeCount - 10);
const powerFactor = 0.3 * (txPower + 10);
const rateFactor = -0.5 * (dataRate - 1);
const pdr = Math.max(70, Math.min(99, basePDR + nodeFactor + powerFactor + rateFactor));
// Latency increases with more nodes and hops
const baseLatency = 50;
const latency = baseLatency + (nodeCount / 10) * 5 + (dataRate / 5) * 10;
// Energy increases with TX power and data rate
const baseEnergy = 100;
const energy = baseEnergy + Math.pow((txPower + 10) / 5, 1.5) * 20 + dataRate * 5;
// Throughput increases with data rate but limited by collisions
const collisionFactor = Math.max(0.3, 1 - (nodeCount * dataRate) / 2000);
const throughput = dataRate * nodeCount * collisionFactor * 0.1;
return { pdr, latency, energy, throughput };
}
// Display current metrics
html`<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin: 10px 0; border-left: 4px solid ${colors.navy};">
<h4 style="margin-top: 0; color: ${colors.navy};">Current Configuration Results</h4>
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px;">
<div>
<div style="color: ${colors.gray}; font-size: 0.9em;">Packet Delivery Ratio</div>
<div style="font-size: 1.8em; font-weight: bold; color: ${simulationResults.pdr >= 95 ? colors.teal : simulationResults.pdr >= 90 ? colors.orange : colors.red};">
${simulationResults.pdr.toFixed(1)}%
</div>
<div style="font-size: 0.8em; color: ${colors.gray};">Target: ≥95%</div>
</div>
<div>
<div style="color: ${colors.gray}; font-size: 0.9em;">Avg Latency</div>
<div style="font-size: 1.8em; font-weight: bold; color: ${simulationResults.latency <= 100 ? colors.teal : simulationResults.latency <= 200 ? colors.orange : colors.red};">
${simulationResults.latency.toFixed(0)} ms
</div>
<div style="font-size: 0.8em; color: ${colors.gray};">Target: ≤100ms</div>
</div>
<div>
<div style="color: ${colors.gray}; font-size: 0.9em;">Energy per Node</div>
<div style="font-size: 1.8em; font-weight: bold; color: ${simulationResults.energy <= 150 ? colors.teal : simulationResults.energy <= 250 ? colors.orange : colors.red};">
${simulationResults.energy.toFixed(0)} mJ
</div>
<div style="font-size: 0.8em; color: ${colors.gray};">Target: ≤150mJ</div>
</div>
<div>
<div style="color: ${colors.gray}; font-size: 0.9em;">Network Throughput</div>
<div style="font-size: 1.8em; font-weight: bold; color: ${colors.blue};">
${simulationResults.throughput.toFixed(1)} Kbps
</div>
<div style="font-size: 0.8em; color: ${colors.gray};">Higher is better</div>
</div>
</div>
</div>`Show code
{
const width = 640;
const height = 400;
const margin = {top: 20, right: 120, bottom: 40, left: 60};
// Generate parameter sweep data
const sweepData = [];
for (let nodes = 10; nodes <= 200; nodes += 10) {
const basePDR = 98;
const nodeFactor = -0.15 * (nodes - 10);
const powerFactor = 0.3 * (txPower + 10);
const rateFactor = -0.5 * (dataRate - 1);
const pdr = Math.max(70, Math.min(99, basePDR + nodeFactor + powerFactor + rateFactor));
const baseLatency = 50;
const latency = baseLatency + (nodes / 10) * 5 + (dataRate / 5) * 10;
const baseEnergy = 100;
const energy = baseEnergy + Math.pow((txPower + 10) / 5, 1.5) * 20 + dataRate * 5;
sweepData.push({ nodes, pdr, latency, energy });
}
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; background: white;");
// Scales
const xScale = d3.scaleLinear()
.domain([10, 200])
.range([margin.left, width - margin.right]);
const yScalePDR = d3.scaleLinear()
.domain([70, 100])
.range([height - margin.bottom, margin.top]);
const yScaleLatency = d3.scaleLinear()
.domain([0, d3.max(sweepData, d => d.latency)])
.range([height - margin.bottom, margin.top]);
// Axes
svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(xScale).ticks(10))
.call(g => g.select(".domain").attr("stroke", colors.gray))
.call(g => g.selectAll(".tick line").attr("stroke", colors.gray))
.call(g => g.selectAll(".tick text").attr("fill", colors.gray));
svg.append("g")
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(yScalePDR).ticks(6).tickFormat(d => d + "%"))
.call(g => g.select(".domain").attr("stroke", colors.teal))
.call(g => g.selectAll(".tick line").attr("stroke", colors.teal).attr("opacity", 0.3))
.call(g => g.selectAll(".tick text").attr("fill", colors.teal));
svg.append("g")
.attr("transform", `translate(${width - margin.right},0)`)
.call(d3.axisRight(yScaleLatency).ticks(6).tickFormat(d => d + "ms"))
.call(g => g.select(".domain").attr("stroke", colors.orange))
.call(g => g.selectAll(".tick line").attr("stroke", colors.orange).attr("opacity", 0.3))
.call(g => g.selectAll(".tick text").attr("fill", colors.orange));
// PDR line
const pdrLine = d3.line()
.x(d => xScale(d.nodes))
.y(d => yScalePDR(d.pdr))
.curve(d3.curveMonotoneX);
svg.append("path")
.datum(sweepData)
.attr("fill", "none")
.attr("stroke", colors.teal)
.attr("stroke-width", 3)
.attr("d", pdrLine);
// Latency line
const latencyLine = d3.line()
.x(d => xScale(d.nodes))
.y(d => yScaleLatency(d.latency))
.curve(d3.curveMonotoneX);
svg.append("path")
.datum(sweepData)
.attr("fill", "none")
.attr("stroke", colors.orange)
.attr("stroke-width", 3)
.attr("d", latencyLine);
// Current configuration marker
svg.append("circle")
.attr("cx", xScale(nodeCount))
.attr("cy", yScalePDR(simulationResults.pdr))
.attr("r", 6)
.attr("fill", colors.navy)
.attr("stroke", "white")
.attr("stroke-width", 2);
// Labels
svg.append("text")
.attr("x", width / 2)
.attr("y", height - 5)
.attr("text-anchor", "middle")
.attr("fill", colors.navy)
.attr("font-size", "12px")
.text("Number of Nodes");
svg.append("text")
.attr("x", -height / 2)
.attr("y", 15)
.attr("text-anchor", "middle")
.attr("transform", "rotate(-90)")
.attr("fill", colors.teal)
.attr("font-size", "12px")
.text("PDR (%)");
svg.append("text")
.attr("x", height / 2)
.attr("y", width - 10)
.attr("text-anchor", "middle")
.attr("transform", `rotate(90, ${width - 10}, ${height / 2})`)
.attr("fill", colors.orange)
.attr("font-size", "12px")
.text("Latency (ms)");
// Legend
const legend = svg.append("g")
.attr("transform", `translate(${width - margin.right + 10}, ${margin.top})`);
legend.append("line")
.attr("x1", 0).attr("x2", 20)
.attr("y1", 0).attr("y2", 0)
.attr("stroke", colors.teal)
.attr("stroke-width", 3);
legend.append("text")
.attr("x", 25).attr("y", 4)
.attr("fill", colors.teal)
.attr("font-size", "11px")
.text("PDR");
legend.append("line")
.attr("x1", 0).attr("x2", 20)
.attr("y1", 20).attr("y2", 20)
.attr("stroke", colors.orange)
.attr("stroke-width", 3);
legend.append("text")
.attr("x", 25).attr("y", 24)
.attr("fill", colors.orange)
.attr("font-size", "11px")
.text("Latency");
legend.append("circle")
.attr("cx", 10).attr("cy", 40)
.attr("r", 6)
.attr("fill", colors.navy);
legend.append("text")
.attr("x", 25).attr("y", 44)
.attr("fill", colors.navy)
.attr("font-size", "11px")
.text("Current");
return svg.node();
}Show code
html`<div style="margin-top: 10px; padding: 10px; background: #f0f7ff; border-radius: 4px; font-size: 0.9em; color: ${colors.navy};">
<strong>Interpretation:</strong> This visualization shows the trade-off between PDR and latency as node count increases.
Adjust the parameters above to see how TX power and data rate affect these metrics. Notice how increasing TX power improves PDR
but increases energy consumption, while higher data rates increase throughput but may reduce reliability due to collisions.
</div>`