diff --git a/README.md b/README.md
index 3ec2450..3e6f4bb 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,19 @@
**RouteIQ** is an enterprise-grade, full-stack transit management, real-time satellite vehicle tracking, and intelligent seat reservation system. Designed as a SaaS-ready multi-tenant platform, it features low-latency WebSocket coordinate streaming, AI-driven traffic arrival estimation, mobile driver location broadcasting, Stripe card checkout, and PWA offline ticket vault storage.
+### ๐ฑ๐ฐ Sri Lanka โ Colombo Focus
+
+This build is customized for **Sri Lanka's Western Province** with Colombo as the central transit hub:
+
+- **Pre-seeded Colombo routes**: Colombo Fort โ Kandy, Galle, Negombo, Matara, Nuwara Eliya, Jaffna, Gampaha & local Kadawatha corridor
+- **Real Colombo bus stops** with accurate GPS coordinates (Fort, Pettah, Kadawatha, Katunayake Airport, Wellawatte, Panadura, Kalutara, Galle, Matara, etc.)
+- **Multi-corridor map overlays**: A1 Highway, E01 Southern Expressway, A3 Negombo Road & Southern coastal route โ each in a distinct color
+- **Sri Lankan Rupee (LKR) pricing** across booking and seat selection
+- **Sri Lankan phone numbers** (+94) and local operator contact details
+- **Trilingual i18n**: English, เทเทเถเทเถฝ (Sinhala), เฎคเฎฎเฎฟเฎดเฏ (Tamil)
+- **Sri Lankan bus registration format** (e.g. `WP-CA-1001`, `SP-GA-1501`)
+- **Realistic SLTB & private operator route names** with distance/duration tuned for local traffic conditions
+
---
## ๐ Key Platform Features
@@ -121,7 +134,14 @@ STRIPE_SECRET_KEY=sk_test_mock_stripe_key
VITE_API_BASE_URL=http://localhost:5000
```
-### 3. Run Development Servers
+### 3. Seed Colombo Routes & Buses
+```bash
+cd backend
+npm run seed:colombo
+```
+This inserts **8 real Colombo transit routes** (Fort โ Kandy, Galle, Negombo, Matara, Nuwara Eliya, Jaffna, Gampaha, Kadawatha local) with accurate GPS waypoints, and **12 sample buses** with Sri Lankan registration numbers.
+
+### 4. Run Development Servers
```bash
# Terminal 1: Backend API & WebSocket Server
cd backend
diff --git a/backend/package.json b/backend/package.json
index 93551a3..55f7472 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -6,7 +6,8 @@
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js",
- "test": "node --test"
+ "test": "node --test",
+ "seed:colombo": "node seeds/colomboRoutes.js"
},
"dependencies": {
"bcryptjs": "^2.4.3",
diff --git a/backend/seeds/colomboRoutes.js b/backend/seeds/colomboRoutes.js
new file mode 100644
index 0000000..56923d4
--- /dev/null
+++ b/backend/seeds/colomboRoutes.js
@@ -0,0 +1,194 @@
+/**
+ * Seed script: Colombo Metropolitan Bus Routes
+ * Run: node seeds/colomboRoutes.js
+ * Requires: MONGO_URI in .env
+ */
+require("dotenv").config();
+const mongoose = require("mongoose");
+const Route = require("../models/Route");
+const Bus = require("../models/Bus");
+const connectDb = require("../config/db");
+
+const COLOMBO_ROUTES = [
+ {
+ routeName: "Colombo Fort โ Kandy",
+ origin: "Colombo Fort",
+ destination: "Kandy",
+ distanceKm: 116,
+ estimatedDurationMinutes: 150,
+ farePrice: 520,
+ active: true,
+ stops: [
+ { name: "Colombo Fort Bus Station", latitude: 6.9271, longitude: 79.8612, sequenceOrder: 1 },
+ { name: "Pettah Bus Stand", latitude: 6.9487, longitude: 79.8593, sequenceOrder: 2 },
+ { name: "Kadawatha Interchange", latitude: 7.0840, longitude: 79.9926, sequenceOrder: 3 },
+ { name: "Nittambuwa Station", latitude: 7.2000, longitude: 79.9800, sequenceOrder: 4 },
+ { name: "Mawanella Central", latitude: 7.2483, longitude: 80.3458, sequenceOrder: 5 },
+ { name: "Kandy Goods Shed", latitude: 7.2906, longitude: 80.6337, sequenceOrder: 6 },
+ ],
+ },
+ {
+ routeName: "Colombo Fort โ Galle",
+ origin: "Colombo Fort",
+ destination: "Galle",
+ distanceKm: 119,
+ estimatedDurationMinutes: 135,
+ farePrice: 480,
+ active: true,
+ stops: [
+ { name: "Colombo Fort Bus Station", latitude: 6.9271, longitude: 79.8612, sequenceOrder: 1 },
+ { name: "Wellawatte Junction", latitude: 6.8890, longitude: 79.8531, sequenceOrder: 2 },
+ { name: "Panadura Bus Stand", latitude: 6.7905, longitude: 79.9057, sequenceOrder: 3 },
+ { name: "Kalutara South", latitude: 6.6833, longitude: 79.9000, sequenceOrder: 4 },
+ { name: "Beruwala", latitude: 6.5833, longitude: 80.1500, sequenceOrder: 5 },
+ { name: "Galle Main Stand", latitude: 6.0535, longitude: 80.2208, sequenceOrder: 6 },
+ ],
+ },
+ {
+ routeName: "Colombo Fort โ Negombo",
+ origin: "Colombo Fort",
+ destination: "Negombo",
+ distanceKm: 37,
+ estimatedDurationMinutes: 55,
+ farePrice: 180,
+ active: true,
+ stops: [
+ { name: "Colombo Fort Bus Station", latitude: 6.9271, longitude: 79.8612, sequenceOrder: 1 },
+ { name: "Ja-Ela Junction", latitude: 7.0033, longitude: 79.8833, sequenceOrder: 2 },
+ { name: "Seeduwa", latitude: 7.0833, longitude: 79.8833, sequenceOrder: 3 },
+ { name: "Katunayake Airport", latitude: 7.1500, longitude: 79.8500, sequenceOrder: 4 },
+ { name: "Negombo Bus Stand", latitude: 7.2100, longitude: 79.8300, sequenceOrder: 5 },
+ ],
+ },
+ {
+ routeName: "Colombo Fort โ Matara",
+ origin: "Colombo Fort",
+ destination: "Matara",
+ distanceKm: 160,
+ estimatedDurationMinutes: 180,
+ farePrice: 650,
+ active: true,
+ stops: [
+ { name: "Colombo Fort Bus Station", latitude: 6.9271, longitude: 79.8612, sequenceOrder: 1 },
+ { name: "Kalutara South", latitude: 6.6833, longitude: 79.9000, sequenceOrder: 2 },
+ { name: "Ambalangoda", latitude: 6.4500, longitude: 80.0500, sequenceOrder: 3 },
+ { name: "Hikkaduwa", latitude: 6.2500, longitude: 80.1000, sequenceOrder: 4 },
+ { name: "Galle Main Stand", latitude: 6.0535, longitude: 80.2208, sequenceOrder: 5 },
+ { name: "Matara Bus Complex", latitude: 5.9485, longitude: 80.5353, sequenceOrder: 6 },
+ ],
+ },
+ {
+ routeName: "Colombo Fort โ Nuwara Eliya",
+ origin: "Colombo Fort",
+ destination: "Nuwara Eliya",
+ distanceKm: 180,
+ estimatedDurationMinutes: 240,
+ farePrice: 780,
+ active: true,
+ stops: [
+ { name: "Colombo Fort Bus Station", latitude: 6.9271, longitude: 79.8612, sequenceOrder: 1 },
+ { name: "Kadawatha Interchange", latitude: 7.0840, longitude: 79.9926, sequenceOrder: 2 },
+ { name: "Kandy Goods Shed", latitude: 7.2906, longitude: 80.6337, sequenceOrder: 3 },
+ { name: "Peradeniya Junction", latitude: 7.2733, longitude: 80.5833, sequenceOrder: 4 },
+ { name: "Hatton", latitude: 6.8889, longitude: 80.5833, sequenceOrder: 5 },
+ { name: "Nuwara Eliya Bus Stand", latitude: 6.9493, longitude: 80.7888, sequenceOrder: 6 },
+ ],
+ },
+ {
+ routeName: "Colombo Fort โ Jaffna",
+ origin: "Colombo Fort",
+ destination: "Jaffna",
+ distanceKm: 397,
+ estimatedDurationMinutes: 480,
+ farePrice: 1250,
+ active: true,
+ stops: [
+ { name: "Colombo Fort Bus Station", latitude: 6.9271, longitude: 79.8612, sequenceOrder: 1 },
+ { name: "Kadawatha Interchange", latitude: 7.0840, longitude: 79.9926, sequenceOrder: 2 },
+ { name: "Kurunegala", latitude: 7.4863, longitude: 80.3647, sequenceOrder: 3 },
+ { name: "Anuradhapura", latitude: 8.3114, longitude: 80.4037, sequenceOrder: 4 },
+ { name: "Vavuniya", latitude: 8.7380, longitude: 80.4770, sequenceOrder: 5 },
+ { name: "Jaffna Bus Stand", latitude: 9.6615, longitude: 80.0255, sequenceOrder: 6 },
+ ],
+ },
+ {
+ routeName: "Colombo Pettah โ Kadawatha (Local)",
+ origin: "Colombo Pettah",
+ destination: "Kadawatha",
+ distanceKm: 16,
+ estimatedDurationMinutes: 35,
+ farePrice: 80,
+ active: true,
+ stops: [
+ { name: "Colombo Pettah Stand", latitude: 6.9487, longitude: 79.8593, sequenceOrder: 1 },
+ { name: "Maradana", latitude: 6.9328, longitude: 79.8742, sequenceOrder: 2 },
+ { name: "Kelaniya Temple", latitude: 6.9567, longitude: 79.9267, sequenceOrder: 3 },
+ { name: "Kiribathgoda", latitude: 6.9700, longitude: 79.9300, sequenceOrder: 4 },
+ { name: "Kadawatha Interchange", latitude: 7.0840, longitude: 79.9926, sequenceOrder: 5 },
+ ],
+ },
+ {
+ routeName: "Colombo Fort โ Gampaha",
+ origin: "Colombo Fort",
+ destination: "Gampaha",
+ distanceKm: 33,
+ estimatedDurationMinutes: 55,
+ farePrice: 150,
+ active: true,
+ stops: [
+ { name: "Colombo Fort Bus Station", latitude: 6.9271, longitude: 79.8612, sequenceOrder: 1 },
+ { name: "Kelaniya Temple", latitude: 6.9567, longitude: 79.9267, sequenceOrder: 2 },
+ { name: "Kiribathgoda", latitude: 6.9700, longitude: 79.9300, sequenceOrder: 3 },
+ { name: "Kadawatha Interchange", latitude: 7.0840, longitude: 79.9926, sequenceOrder: 4 },
+ { name: "Gampaha Bus Stand", latitude: 7.0872, longitude: 80.0144, sequenceOrder: 5 },
+ ],
+ },
+];
+
+// Sample bus fleet seeded on each route
+const COLOMBO_BUSES = [
+ { busNumber: "WP-CA-1001", route: "Colombo Fort โ Kandy", driverName: "Kumara Perera", driverContact: "+94771234001", capacity: 45, busType: "AC", status: "Active", latitude: 6.9271, longitude: 79.8612, speedKmph: 55 },
+ { busNumber: "WP-CA-1002", route: "Colombo Fort โ Kandy", driverName: "Sunil Jayawardena", driverContact: "+94771234002", capacity: 45, busType: "Non-AC", status: "Active", latitude: 7.0840, longitude: 79.9926, speedKmph: 45 },
+ { busNumber: "WP-CA-2001", route: "Colombo Fort โ Galle", driverName: "Ruwan Fernando", driverContact: "+94771234003", capacity: 50, busType: "AC", status: "Active", latitude: 6.6833, longitude: 79.9000, speedKmph: 60 },
+ { busNumber: "SP-GA-1501", route: "Colombo Fort โ Galle", driverName: "Anura Bandara", driverContact: "+94771234004", capacity: 50, busType: "Express", status: "On Route", latitude: 6.0535, longitude: 80.2208, speedKmph: 65 },
+ { busNumber: "WP-CA-3001", route: "Colombo Fort โ Negombo", driverName: "Dinesh Silva", driverContact: "+94771234005", capacity: 40, busType: "Non-AC", status: "Active", latitude: 7.0033, longitude: 79.8833, speedKmph: 40 },
+ { busNumber: "WP-CA-3002", route: "Colombo Fort โ Negombo", driverName: "Mahinda Rajapakshe", driverContact: "+94771234006", capacity: 40, busType: "AC", status: "Active", latitude: 7.1500, longitude: 79.8500, speedKmph: 50 },
+ { busNumber: "SP-MT-4001", route: "Colombo Fort โ Matara", driverName: "Prasanna Kumara", driverContact: "+94771234007", capacity: 50, busType: "Express", status: "On Route", latitude: 6.2500, longitude: 80.1000, speedKmph: 70 },
+ { busNumber: "CP-NE-5001", route: "Colombo Fort โ Nuwara Eliya", driverName: "Saman Wijesinghe", driverContact: "+94771234008", capacity: 45, busType: "AC", status: "Active", latitude: 7.2906, longitude: 80.6337, speedKmph: 40 },
+ { busNumber: "NP-JF-6001", route: "Colombo Fort โ Jaffna", driverName: "Vijaya Rajan", driverContact: "+94771234009", capacity: 50, busType: "Sleeper", status: "Active", latitude: 8.3114, longitude: 80.4037, speedKmph: 65 },
+ { busNumber: "WP-LC-7001", route: "Colombo Pettah โ Kadawatha (Local)", driverName: "Nimal de Silva", driverContact: "+94771234010", capacity: 55, busType: "Non-AC", status: "Active", latitude: 6.9487, longitude: 79.8593, speedKmph: 30 },
+ { busNumber: "WP-LC-7002", route: "Colombo Pettah โ Kadawatha (Local)", driverName: "Asanka Gunasekara", driverContact: "+94771234011", capacity: 55, busType: "Non-AC", status: "Active", latitude: 6.9567, longitude: 79.9267, speedKmph: 35 },
+ { busNumber: "WP-GP-8001", route: "Colombo Fort โ Gampaha", driverName: "Lakshman Peris", driverContact: "+94771234012", capacity: 45, busType: "Non-AC", status: "Active", latitude: 7.0872, longitude: 80.0144, speedKmph: 45 },
+];
+
+async function seed() {
+ await connectDb();
+
+ // Clear existing demo data
+ await Route.deleteMany({});
+ await Bus.deleteMany({});
+ console.log("๐งน Cleared existing routes and buses");
+
+ // Insert routes
+ const routes = await Route.insertMany(COLOMBO_ROUTES);
+ console.log(`โ
Inserted ${routes.length} Colombo routes`);
+
+ // Link buses to routes
+ const busesWithRouteId = COLOMBO_BUSES.map((bus) => {
+ const route = routes.find((r) => r.routeName === bus.route);
+ return { ...bus, routeId: route ? route._id : null };
+ });
+
+ const buses = await Bus.insertMany(busesWithRouteId);
+ console.log(`โ
Inserted ${buses.length} buses on Colombo routes`);
+
+ console.log("\n๐ Seeded Colombo routes:");
+ routes.forEach((r) => console.log(` โข ${r.routeName} (${r.distanceKm} km, LKR ${r.farePrice})`));
+
+ process.exit(0);
+}
+
+seed().catch((err) => {
+ console.error("โ Seed failed:", err);
+ process.exit(1);
+});
diff --git a/backend/server.js b/backend/server.js
index f373048..983a11b 100644
--- a/backend/server.js
+++ b/backend/server.js
@@ -79,7 +79,7 @@ app.get("/api/health", (req, res) => {
});
app.get("/", (req, res) => {
- res.send("โ
RouteIQ Engine Engine 2.0 Running & Operational");
+ res.send("โ
RouteIQ Colombo โ Sri Lanka Smart Transit Engine 2.0 Running & Operational");
});
// โก Socket.IO Integration
@@ -117,7 +117,7 @@ app.use(errorHandler);
const PORT = process.env.PORT || 5000;
server.listen(PORT, () => {
- console.log(`๐ Busgo Engine 2.0 server listening on port ${PORT}`);
+ console.log(`๐ RouteIQ Colombo Engine 2.0 server listening on port ${PORT}`);
});
module.exports = { app, server };
diff --git a/backend/tests/api.test.js b/backend/tests/api.test.js
index 0f96b02..d5e1ffe 100644
--- a/backend/tests/api.test.js
+++ b/backend/tests/api.test.js
@@ -26,7 +26,7 @@ assert.strictEqual(decoded.email, 'test@routeiq.io', 'JWT Email mismatch');
assert.strictEqual(decoded.role, 'customer', 'JWT Role mismatch');
console.log(' โ
JWT Token Generation & Verification: PASSED');
-// 3. Haversine Distance Formula Test (Delhi to Noida ~20km)
+// 3. Haversine Distance Formula Test (Colombo Fort โ Kadawatha ~20km)
function calculateHaversineDistance(lat1, lon1, lat2, lon2) {
const R = 6371;
const dLat = ((lat2 - lat1) * Math.PI) / 180;
@@ -41,7 +41,7 @@ function calculateHaversineDistance(lat1, lon1, lat2, lon2) {
return R * c;
}
-const distance = calculateHaversineDistance(28.6139, 77.2090, 28.5355, 77.3910);
+const distance = calculateHaversineDistance(6.9271, 79.8612, 7.0840, 79.9926);
assert.ok(distance > 15 && distance < 25, `Haversine distance out of expected range: ${distance} km`);
console.log(` โ
Spherical Haversine GPS Distance Algorithm (${distance.toFixed(2)} km): PASSED`);
diff --git a/frontend/src/components/AddBusForm.jsx b/frontend/src/components/AddBusForm.jsx
index 41a48da..8a8c5c6 100644
--- a/frontend/src/components/AddBusForm.jsx
+++ b/frontend/src/components/AddBusForm.jsx
@@ -11,8 +11,8 @@ export default function AddBusForm({ addBusToList }) {
busNumber: "",
driverName: "",
route: "",
- latitude: "28.6139",
- longitude: "77.2090",
+ latitude: "6.9271",
+ longitude: "79.8612",
busType: "AC",
});
const [error, setError] = useState("");
@@ -35,8 +35,8 @@ export default function AddBusForm({ addBusToList }) {
busNumber: "",
driverName: "",
route: "",
- latitude: "28.6139",
- longitude: "77.2090",
+ latitude: "6.9271",
+ longitude: "79.8612",
busType: "AC",
});
setError("");
@@ -50,11 +50,11 @@ export default function AddBusForm({ addBusToList }) {
return (
- Register New Bus Vehicle
+ Register New Bus Vehicle
{error && (
-
+
{error}
)}
@@ -65,10 +65,10 @@ export default function AddBusForm({ addBusToList }) {
setForm({ ...form, busNumber: e.target.value })}
- className="w-full px-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-rose-500"
+ className="w-full px-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
@@ -80,7 +80,7 @@ export default function AddBusForm({ addBusToList }) {
placeholder="Driver Name"
value={form.driverName}
onChange={(e) => setForm({ ...form, driverName: e.target.value })}
- className="w-full px-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-rose-500"
+ className="w-full px-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
@@ -89,10 +89,10 @@ export default function AddBusForm({ addBusToList }) {
setForm({ ...form, route: e.target.value })}
- className="w-full px-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-rose-500"
+ className="w-full px-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
@@ -103,7 +103,7 @@ export default function AddBusForm({ addBusToList }) {
step="any"
value={form.latitude}
onChange={(e) => setForm({ ...form, latitude: e.target.value })}
- className="w-full px-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-rose-500"
+ className="w-full px-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
@@ -114,7 +114,7 @@ export default function AddBusForm({ addBusToList }) {
step="any"
value={form.longitude}
onChange={(e) => setForm({ ...form, longitude: e.target.value })}
- className="w-full px-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-rose-500"
+ className="w-full px-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
@@ -122,7 +122,7 @@ export default function AddBusForm({ addBusToList }) {
diff --git a/frontend/src/components/AiChatbotModal.jsx b/frontend/src/components/AiChatbotModal.jsx
index 8d4f8ec..d1b549d 100644
--- a/frontend/src/components/AiChatbotModal.jsx
+++ b/frontend/src/components/AiChatbotModal.jsx
@@ -49,7 +49,7 @@ export default function AiChatbotModal() {
{!isOpen && (