Skip to content

Commit 63344ab

Browse files
committed
Yes
1 parent ad2ff5b commit 63344ab

4 files changed

Lines changed: 237 additions & 0 deletions

File tree

freight_project/index.html

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Freight Simulation</title>
5+
<meta charset="utf-8" />
6+
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
7+
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
8+
</head>
9+
<body>
10+
<h1>Freight Simulation Dashboard</h1>
11+
<div id="map" style="height:600px;"></div>
12+
13+
<script>
14+
const map = L.map('map').setView([39.5, -98.35], 4); // Center US
15+
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
16+
attribution: '© OpenStreetMap'
17+
}).addTo(map);
18+
19+
async function refresh() {
20+
const res = await fetch("/status");
21+
const data = await res.json();
22+
23+
data.trucks.forEach(truck => {
24+
L.circleMarker([truck.lat, truck.lon], {radius: 5, color: "blue"})
25+
.bindPopup(`${truck.truck_id} - ${truck.status}`)
26+
.addTo(map);
27+
});
28+
}
29+
30+
refresh();
31+
setInterval(refresh, 3000); // update every 3 sec
32+
</script>
33+
</body>
34+
</html>

freight_project/main.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from freight_sim import FreightSim
2+
3+
def main():
4+
print("Freight Route Trading Simulator")
5+
6+
# Ask user for input values
7+
num_trucks = int(input("Enter number of trucks: "))
8+
num_steps = int(input("Enter number of simulation steps: "))
9+
loads = int(input("Enter number of loads to create: "))
10+
min_pop = int(input("Enter minimum population for city selection: "))
11+
12+
# Start simulation
13+
sim = FreightSim("uscities.csv", num_trucks=num_trucks, min_pop=min_pop)
14+
15+
# Create loads
16+
for _ in range(loads):
17+
sim.create_random_load()
18+
19+
# Assign loads to trucks
20+
sim.assign_loads()
21+
22+
# Simulate step by step
23+
for step in range(steps):
24+
print(f"\n--- Simulation Step {step+1} ---")
25+
sim.update_trucks()
26+
27+
if __name__ == "__main__":
28+
main()

freight_project/script.js

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
let cities = [];
2+
3+
// Load CSV file dynamically
4+
Papa.parse("uscities.csv", {
5+
download: true,
6+
header: true,
7+
complete: (results) => {
8+
cities = results.data;
9+
console.log("Loaded cities:", cities.length);
10+
}
11+
});
12+
13+
// Pick a random city filtered by min population
14+
function randomCity(minPop) {
15+
const filtered = cities.filter(c => parseInt(c.population) > minPop);
16+
return filtered[Math.floor(Math.random() * filtered.length)];
17+
}
18+
19+
// Haversine distance calculator (miles)
20+
function haversine(lat1, lon1, lat2, lon2) {
21+
const R = 3956;
22+
const toRad = x => (x * Math.PI) / 180;
23+
24+
const dLat = toRad(lat2 - lat1);
25+
const dLon = toRad(lon2 - lon1);
26+
const a =
27+
Math.sin(dLat / 2)**2 +
28+
Math.cos(toRad(lat1)) *
29+
Math.cos(toRad(lat2)) *
30+
Math.sin(dLon / 2)**2;
31+
32+
return 2 * R * Math.asin(Math.sqrt(a));
33+
}
34+
35+
function startSimulation() {
36+
const numTrucks = parseInt(document.getElementById("trucks").value);
37+
const numLoads = parseInt(document.getElementById("loads").value);
38+
const minPop = parseInt(document.getElementById("min_pop").value);
39+
40+
let output = "";
41+
42+
//----------------------------------
43+
// 1. Create trucks
44+
//----------------------------------
45+
let trucks = [];
46+
for (let i = 0; i < numTrucks; i++) {
47+
let c = randomCity(minPop);
48+
trucks.push({
49+
id: "T" + (i+1),
50+
city: c.city,
51+
lat: parseFloat(c.lat),
52+
lon: parseFloat(c.lng),
53+
status: "Idle",
54+
capacity: Math.floor(Math.random() * 20) + 10
55+
});
56+
}
57+
58+
//----------------------------------
59+
// 2. Create loads
60+
//----------------------------------
61+
let loads = [];
62+
for (let i = 0; i < numLoads; i++) {
63+
let origin = randomCity(minPop);
64+
let dest = randomCity(minPop);
65+
66+
loads.push({
67+
id: "L" + (i+1),
68+
origin: origin.city,
69+
dest: dest.city,
70+
latO: parseFloat(origin.lat),
71+
lonO: parseFloat(origin.lng),
72+
latD: parseFloat(dest.lat),
73+
lonD: parseFloat(dest.lng),
74+
weight: Math.floor(Math.random() * 20) + 5
75+
});
76+
}
77+
78+
//----------------------------------
79+
// 3. Assign loads to trucks
80+
//----------------------------------
81+
loads.forEach(load => {
82+
let bestTruck = null;
83+
let bestScore = Infinity;
84+
85+
trucks.forEach(truck => {
86+
if (truck.status === "Idle") {
87+
if (truck.capacity < load.weight) return;
88+
89+
let dist = haversine(truck.lat, truck.lon, load.latO, load.lonO);
90+
91+
if (dist < bestScore) {
92+
bestScore = dist;
93+
bestTruck = truck;
94+
}
95+
}
96+
});
97+
98+
if (bestTruck) {
99+
bestTruck.status = "Assigned → " + load.id;
100+
load.assigned = bestTruck.id;
101+
} else {
102+
load.assigned = "NO AVAILABLE TRUCK";
103+
}
104+
});
105+
106+
//----------------------------------
107+
// Output
108+
//----------------------------------
109+
output += "🚛 TRUCKS:\n";
110+
trucks.forEach(t => {
111+
output += `${t.id}${t.city}${t.status} — cap ${t.capacity}\n`;
112+
});
113+
114+
output += "\n📦 LOADS:\n";
115+
loads.forEach(l => {
116+
output += `${l.id}${l.origin}${l.dest} — weight ${l.weight} — assigned: ${l.assigned}\n`;
117+
});
118+
119+
document.getElementById("output").innerText = output;
120+
}

freight_project/style.css

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
body {
2+
font-family: Arial, sans-serif;
3+
background: #f7f7f7;
4+
padding: 20px;
5+
}
6+
7+
h1 {
8+
color: #2e4053;
9+
text-align: center;
10+
margin-bottom: 30px;
11+
}
12+
13+
.input-box {
14+
background: white;
15+
padding: 20px;
16+
border-radius: 8px;
17+
width: 350px;
18+
margin: 0 auto 30px;
19+
box-shadow: 0 0 10px rgba(0,0,0,0.1);
20+
}
21+
22+
label {
23+
font-weight: bold;
24+
}
25+
26+
input {
27+
width: 100%;
28+
margin: 8px 0 16px;
29+
padding: 8px;
30+
}
31+
32+
button {
33+
width: 100%;
34+
padding: 10px;
35+
background: #1d84c6;
36+
color: white;
37+
font-size: 16px;
38+
border: none;
39+
border-radius: 5px;
40+
cursor: pointer;
41+
}
42+
43+
button:hover {
44+
background: #166a9c;
45+
}
46+
47+
#output {
48+
background: white;
49+
padding: 20px;
50+
border-radius: 8px;
51+
min-height: 120px;
52+
white-space: pre-wrap;
53+
font-family: monospace;
54+
box-shadow: 0 0 10px rgba(0,0,0,0.1);
55+
}

0 commit comments

Comments
 (0)