DP1110 commited on
Commit
0b15132
·
verified ·
1 Parent(s): f6afa55

Upload index.html

Browse files
Files changed (1) hide show
  1. index.html +896 -836
index.html CHANGED
@@ -1,836 +1,896 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>🏙️ Urban Spatial Accessibility Predictor</title>
7
- <!-- Bootstrap CSS -->
8
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
9
- <!-- Plotly.js -->
10
- <script src="https://cdn.plot.ly/plotly-2.20.0.min.js"></script>
11
- <!-- Font Awesome -->
12
- <script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script>
13
- <style>
14
- :root {
15
- --primary-color: #2E86AB;
16
- --secondary-color: #A23B72;
17
- --success-color: #4CAF50;
18
- --warning-color: #FF9800;
19
- --danger-color: #F44336;
20
- --info-color: #17a2b8;
21
- --card-bg: rgba(255, 255, 255, 0.95);
22
- }
23
-
24
- body {
25
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
26
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
27
- min-height: 100vh;
28
- padding: 20px;
29
- }
30
-
31
- .main-container {
32
- background: var(--card-bg);
33
- border-radius: 20px;
34
- box-shadow: 0 15px 35px rgba(0, 0, 0, 0.3);
35
- overflow: hidden;
36
- backdrop-filter: blur(10px);
37
- }
38
-
39
- .header-section {
40
- background: linear-gradient(135deg, var(--primary-color), #1a5f7a);
41
- color: white;
42
- padding: 2rem;
43
- border-radius: 0 0 30px 30px;
44
- margin-bottom: 2rem;
45
- }
46
-
47
- .metric-card {
48
- background: white;
49
- border-radius: 15px;
50
- padding: 1.5rem;
51
- box-shadow: 0 5px 15px rgba(0,0,0,0.1);
52
- border-left: 5px solid var(--primary-color);
53
- margin-bottom: 1rem;
54
- }
55
-
56
- .slider-container {
57
- background: #f8f9fa;
58
- border-radius: 10px;
59
- padding: 1.5rem;
60
- margin: 1rem 0;
61
- }
62
-
63
- .feature-value {
64
- font-size: 1.2rem;
65
- font-weight: 600;
66
- color: var(--primary-color);
67
- float: right;
68
- }
69
-
70
- .accessibility-score {
71
- font-size: 4rem;
72
- font-weight: 800;
73
- text-align: center;
74
- color: var(--primary-color);
75
- text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
76
- }
77
-
78
- .classification-badge {
79
- display: inline-block;
80
- padding: 0.5rem 1.5rem;
81
- border-radius: 25px;
82
- font-weight: 700;
83
- font-size: 1.2rem;
84
- margin: 0.5rem;
85
- }
86
-
87
- .excellent { background: linear-gradient(135deg, #4CAF50, #2E7D32); color: white; }
88
- .good { background: linear-gradient(135deg, #8BC34A, #558B2F); color: white; }
89
- .moderate { background: linear-gradient(135deg, #FF9800, #EF6C00); color: white; }
90
- .poor { background: linear-gradient(135deg, #F44336, #C62828); color: white; }
91
-
92
- .feature-slider {
93
- width: 100%;
94
- margin: 1rem 0;
95
- }
96
-
97
- .feature-icon {
98
- font-size: 1.5rem;
99
- margin-right: 10px;
100
- }
101
-
102
- .chart-container {
103
- background: white;
104
- border-radius: 15px;
105
- padding: 1.5rem;
106
- box-shadow: 0 5px 15px rgba(0,0,0,0.1);
107
- margin: 1rem 0;
108
- }
109
-
110
- .info-box {
111
- background: #E3F2FD;
112
- border-left: 4px solid #2196F3;
113
- padding: 1rem;
114
- border-radius: 8px;
115
- margin: 1rem 0;
116
- }
117
-
118
- .remedial-box {
119
- border-left: 5px solid;
120
- padding: 1rem;
121
- border-radius: 8px;
122
- margin: 0.5rem 0;
123
- background: #f8f9fa;
124
- }
125
-
126
- .remedial-excellent { border-left-color: #4CAF50; }
127
- .remedial-good { border-left-color: #8BC34A; }
128
- .remedial-moderate { border-left-color: #FF9800; }
129
- .remedial-poor { border-left-color: #F44336; }
130
-
131
- .city-highlight {
132
- background: linear-gradient(135deg, #4a6572, #5d8aa8);
133
- color: white;
134
- padding: 0.5rem 1rem;
135
- border-radius: 8px;
136
- font-weight: 600;
137
- margin-bottom: 1rem;
138
- display: inline-block;
139
- }
140
-
141
- .measure-item {
142
- padding: 0.5rem 0;
143
- border-bottom: 1px dashed #dee2e6;
144
- }
145
-
146
- .measure-item:last-child {
147
- border-bottom: none;
148
- }
149
-
150
- .raw-value-badge {
151
- background: #6c757d;
152
- color: white;
153
- padding: 0.2rem 0.5rem;
154
- border-radius: 4px;
155
- font-size: 0.85rem;
156
- margin-left: 0.5rem;
157
- }
158
-
159
- .average-score {
160
- font-size: 2.5rem;
161
- font-weight: 700;
162
- color: #A23B72;
163
- text-align: center;
164
- margin: 0.5rem 0;
165
- }
166
-
167
- .distance-band-badge {
168
- background: linear-gradient(135deg, #6f42c1, #6610f2);
169
- color: white;
170
- padding: 0.3rem 1rem;
171
- border-radius: 15px;
172
- font-weight: 600;
173
- }
174
-
175
- @media (max-width: 768px) {
176
- .accessibility-score {
177
- font-size: 3rem;
178
- }
179
- .average-score {
180
- font-size: 2rem;
181
- }
182
- }
183
- </style>
184
- </head>
185
- <body>
186
- <div class="container main-container">
187
- <!-- Header -->
188
- <div class="header-section">
189
- <div class="d-flex align-items-center justify-content-center gap-3 mb-3">
190
- <div style="font-size: 2.5rem; color: white;">🏙️</div>
191
- <div>
192
- <h1 class="display-5 mb-2">Urban Spatial Accessibility Predictor</h1>
193
- <p class="lead mb-0">AI-powered tool for predicting urban accessibility across Tier-II Indian cities with tailored remedial measures</p>
194
- </div>
195
- </div>
196
- </div>
197
-
198
- <div class="container-fluid">
199
- <div class="row">
200
- <!-- Left Column - Inputs -->
201
- <div class="col-lg-6 col-md-12 mb-4">
202
- <div class="card shadow">
203
- <div class="card-header bg-primary text-white">
204
- <h3 class="mb-0">📊 Input Urban Indicators</h3>
205
- <p class="mb-0 opacity-75">Select a city and adjust indicators for prediction</p>
206
- </div>
207
- <div class="card-body">
208
- <!-- City Selection -->
209
- <div class="slider-container">
210
- <div class="d-flex justify-content-between mb-2">
211
- <label class="form-label h5">
212
- <span class="feature-icon">🏙️</span>
213
- Select Tier-II City
214
- </label>
215
- </div>
216
- <p class="text-muted mb-3">Choose an Indian Tier-II city for context-specific analysis</p>
217
- <select class="form-select form-select-lg mb-3" id="citySelector" onchange="updateCityInfo()">
218
- <option value="0">-- Select a City --</option>
219
- </select>
220
- </div>
221
-
222
- <!-- Distance Band Selection -->
223
- <div class="slider-container">
224
- <div class="d-flex justify-content-between mb-2">
225
- <label class="form-label h5">
226
- <span class="feature-icon">📏</span>
227
- Distance Band
228
- </label>
229
- <span id="distanceBandValue" class="feature-value">400m</span>
230
- </div>
231
- <p class="text-muted mb-3">Select walking distance threshold for accessibility analysis</p>
232
- <select class="form-select form-select-lg mb-3" id="distanceBandSelector" onchange="updateDistanceBand(); updatePrediction();">
233
- <option value="200">200m (Short Walk)</option>
234
- <option value="400" selected>400m (Standard Walk)</option>
235
- <option value="600">600m (Moderate Walk)</option>
236
- <option value="800">800m (Long Walk)</option>
237
- <option value="1000">1000m (Extended Walk)</option>
238
- </select>
239
- <div class="mt-2">
240
- <span class="distance-band-badge" id="distanceBandBadge">400m Standard Walking Distance</span>
241
- </div>
242
- </div>
243
-
244
- <!-- Euclidean ASF Slider -->
245
- <div class="slider-container">
246
- <div class="d-flex justify-content-between mb-2">
247
- <label class="form-label h5">
248
- <span class="feature-icon">📐</span>
249
- Euclidean ASF
250
- <span class="raw-value-badge" id="euclideanRawValue">70%</span>
251
- </label>
252
- <span id="euclideanValue" class="feature-value">0.70</span>
253
- </div>
254
- <p class="text-muted mb-3">Percentage of Accessible Street Frontage (Euclidean Distance)</p>
255
- <input type="range" class="form-range feature-slider" id="euclideanSlider"
256
- min="0" max="100" value="70" step="1"
257
- oninput="updateValue('euclidean', this.value); updatePrediction();">
258
- <div class="d-flex justify-content-between">
259
- <small class="text-muted">0% (Low)</small>
260
- <small class="text-muted">100% (High)</small>
261
- </div>
262
- </div>
263
-
264
- <!-- Built-Up Area Slider -->
265
- <div class="slider-container">
266
- <div class="d-flex justify-content-between mb-2">
267
- <label class="form-label h5">
268
- <span class="feature-icon">🏗️</span>
269
- Built-Up Area
270
- <span class="raw-value-badge" id="builtupRawValue">60%</span>
271
- </label>
272
- <span id="builtupValue" class="feature-value">0.60</span>
273
- </div>
274
- <p class="text-muted mb-3">Percentage of Built-Up Area in the selected region</p>
275
- <input type="range" class="form-range feature-slider" id="builtupSlider"
276
- min="0" max="100" value="60" step="1"
277
- oninput="updateValue('builtup', this.value); updatePrediction();">
278
- <div class="d-flex justify-content-between">
279
- <small class="text-muted">0% (Low)</small>
280
- <small class="text-muted">100% (High)</small>
281
- </div>
282
- </div>
283
-
284
- <!-- Network ASF Slider -->
285
- <div class="slider-container">
286
- <div class="d-flex justify-content-between mb-2">
287
- <label class="form-label h5">
288
- <span class="feature-icon">🛣️</span>
289
- Network ASF
290
- <span class="raw-value-badge" id="networkRawValue">75%</span>
291
- </label>
292
- <span id="networkValue" class="feature-value">0.75</span>
293
- </div>
294
- <p class="text-muted mb-3">Percentage of Accessible Street Frontage (Network Distance)</p>
295
- <input type="range" class="form-range feature-slider" id="networkSlider"
296
- min="0" max="100" value="75" step="1"
297
- oninput="updateValue('network', this.value); updatePrediction();">
298
- <div class="d-flex justify-content-between">
299
- <small class="text-muted">0% (Low)</small>
300
- <small class="text-muted">100% (High)</small>
301
- </div>
302
- </div>
303
-
304
- <!-- Bus Stop ASF Slider -->
305
- <div class="slider-container">
306
- <div class="d-flex justify-content-between mb-2">
307
- <label class="form-label h5">
308
- <span class="feature-icon">🚌</span>
309
- Bus Stop ASF
310
- <span class="raw-value-badge" id="busstopRawValue">80%</span>
311
- </label>
312
- <span id="busstopValue" class="feature-value">0.80</span>
313
- </div>
314
- <p class="text-muted mb-3">Percentage of Street Frontage accessible from Bus Stops</p>
315
- <input type="range" class="form-range feature-slider" id="busstopSlider"
316
- min="0" max="100" value="80" step="1"
317
- oninput="updateValue('busstop', this.value); updatePrediction();">
318
- <div class="d-flex justify-content-between">
319
- <small class="text-muted">0% (Low)</small>
320
- <small class="text-muted">100% (High)</small>
321
- </div>
322
- </div>
323
-
324
- <!-- Average Score Display -->
325
- <div class="slider-container">
326
- <div class="d-flex justify-content-between mb-2">
327
- <label class="form-label h5">
328
- <span class="feature-icon">📈</span>
329
- Input Feature Average
330
- </label>
331
- </div>
332
- <p class="text-muted mb-3">Average of all normalized input features (Simple Baseline)</p>
333
- <div class="average-score" id="averageScore">0.7125</div>
334
- <div class="progress mb-2" style="height: 20px;">
335
- <div id="averageProgressBar" class="progress-bar bg-info" role="progressbar" style="width: 71.25%"></div>
336
- </div>
337
- <div class="d-flex justify-content-between">
338
- <small class="text-muted">0.0 (Low)</small>
339
- <small class="text-muted">0.5 (Medium)</small>
340
- <small class="text-muted">1.0 (High)</small>
341
- </div>
342
- </div>
343
-
344
- <!-- Action Buttons -->
345
- <div class="row mt-4">
346
- <div class="col-md-6">
347
- <button class="btn btn-outline-primary btn-lg w-100" onclick="resetSliders()">
348
- 🔄 Reset Values
349
- </button>
350
- </div>
351
- <div class="col-md-6">
352
- <button class="btn btn-success btn-lg w-100" onclick="exportResults()">
353
- 💾 Export Results
354
- </button>
355
- </div>
356
- </div>
357
- </div>
358
- </div>
359
- </div>
360
-
361
- <!-- Right Column - Results -->
362
- <div class="col-lg-6 col-md-12 mb-4">
363
- <div class="card shadow">
364
- <div class="card-header bg-success text-white">
365
- <h3 class="mb-0">📈 Prediction Results</h3>
366
- <p class="mb-0 opacity-75">Real-time prediction based on ML model</p>
367
- </div>
368
- <div class="card-body">
369
- <!-- Selected City Info -->
370
- <div id="cityInfoPanel" class="mb-4" style="display: none;">
371
- <div class="d-flex justify-content-between align-items-center mb-3">
372
- <h5 class="mb-0">📍 Selected City Analysis</h5>
373
- <div>
374
- <span id="cityBadge" class="badge bg-info fs-6 me-2"></span>
375
- <span id="distanceBadge" class="badge bg-purple fs-6">400m</span>
376
- </div>
377
- </div>
378
- <div class="city-highlight" id="cityDisplay">
379
- <i class="fas fa-city me-2"></i>
380
- <span id="currentCityName">No city selected</span>
381
- </div>
382
- </div>
383
-
384
- <!-- Prediction Score -->
385
- <div class="text-center mb-4">
386
- <h4 class="mb-3">MLP Model Prediction</h4>
387
- <div class="accessibility-score" id="predictionScore">0.685</div>
388
-
389
- <!-- Classification Badge -->
390
- <div id="classificationBadge" class="mt-3">
391
- <div class="classification-badge moderate" id="badge">Moderate</div>
392
- </div>
393
-
394
- <!-- ML Model Info -->
395
- <div class="row mt-3">
396
- <div class="col-md-6">
397
- <div class="metric-card">
398
- <h6>📊 Simple Average</h6>
399
- <div class="h4 text-center" id="simpleAverageDisplay">0.7125</div>
400
- <small class="text-muted">Baseline calculation</small>
401
- </div>
402
- </div>
403
- <div class="col-md-6">
404
- <div class="metric-card">
405
- <h6>🤖 MLP Prediction</h6>
406
- <div class="h4 text-center" id="mlpPredictionDisplay">0.685</div>
407
- <small class="text-muted">Neural network output</small>
408
- </div>
409
- </div>
410
- </div>
411
-
412
- <!-- Status Message -->
413
- <div class="alert alert-info mt-3" id="statusMessage">
414
- The predicted accessibility is Moderate. Improvement opportunities exist.
415
- </div>
416
- </div>
417
-
418
- <!-- Feature Visualization -->
419
- <div class="chart-container">
420
- <h5 class="mb-3">📊 Input Feature Visualization</h5>
421
- <div id="featureChart" style="height: 300px;"></div>
422
- <div class="text-center mt-2">
423
- <small class="text-muted">
424
- Raw values shown in <span class="raw-value-badge">gray badges</span>,
425
- Normalized values in <span class="feature-value">blue</span>
426
- </small>
427
- </div>
428
- </div>
429
-
430
- <!-- Remedial Measures -->
431
- <div class="chart-container" id="remedialPanel" style="display: none;">
432
- <h5 class="mb-3">🛠️ Context-Specific Remedial Measures</h5>
433
- <p class="text-muted mb-3">Tailored recommendations for <span id="cityNameForMeasures">selected city</span> based on accessibility classification</p>
434
- <div id="remedialMeasuresContent">
435
- <!-- Measures will be dynamically inserted here -->
436
- </div>
437
- </div>
438
-
439
- <!-- Accessibility Scale -->
440
- <div class="chart-container">
441
- <h5 class="mb-3">📏 Accessibility Classification Scale</h5>
442
- <div class="row text-center">
443
- <div class="col-3 mb-2">
444
- <div class="p-2 excellent rounded">
445
- <strong>Excellent</strong><br>≥ 0.8
446
- </div>
447
- </div>
448
- <div class="col-3 mb-2">
449
- <div class="p-2 good rounded">
450
- <strong>Good</strong><br>0.6 - 0.8
451
- </div>
452
- </div>
453
- <div class="col-3 mb-2">
454
- <div class="p-2 moderate rounded">
455
- <strong>Moderate</strong><br>0.4 - 0.6
456
- </div>
457
- </div>
458
- <div class="col-3 mb-2">
459
- <div class="p-2 poor rounded">
460
- <strong>Poor</strong><br>&lt; 0.4
461
- </div>
462
- </div>
463
- </div>
464
- </div>
465
- </div>
466
- </div>
467
- </div>
468
- </div>
469
-
470
- <!-- Additional Information -->
471
- <div class="row mt-4">
472
- <div class="col-12">
473
- <div class="card shadow">
474
- <div class="card-header bg-secondary text-white">
475
- <h4 class="mb-0">ℹ️ How to Interpret Results & Deployment Information</h4>
476
- </div>
477
- <div class="card-body">
478
- <div class="row">
479
- <div class="col-md-6">
480
- <h5>📋 Understanding the Metrics</h5>
481
- <ul>
482
- <li><strong>Distance Band:</strong> Walking distance threshold (200m-1000m) for accessibility calculation</li>
483
- <li><strong>Euclidean ASF:</strong> Measures straight-line accessibility to street frontage</li>
484
- <li><strong>Built-Up Area:</strong> Percentage of developed land in the region</li>
485
- <li><strong>Network ASF:</strong> Accessibility considering actual road networks</li>
486
- <li><strong>Bus Stop ASF:</strong> Proximity to public transport infrastructure</li>
487
- </ul>
488
- <p>Higher values in these metrics typically lead to better overall accessibility scores.</p>
489
- <div class="info-box">
490
- <h6>🔢 Normalization Process</h6>
491
- <p>Raw percentage values (0-100%) are normalized to (0-1) range for ML model input.</p>
492
- <p><strong>Example:</strong> 75% 0.75 normalized value</p>
493
- </div>
494
- </div>
495
- <div class="col-md-6">
496
- <h5>🤖 MLP Model Details</h5>
497
- <p>The Multi-Layer Perceptron (MLP) model uses 4 input features, 2 hidden layers (16 and 8 neurons), and produces one output prediction.</p>
498
- <h6>Model Architecture:</h6>
499
- <ul>
500
- <li><strong>Input Layer:</strong> 4 features (normalized 0-1)</li>
501
- <li><strong>Hidden Layer 1:</strong> 16 neurons with ReLU activation</li>
502
- <li><strong>Hidden Layer 2:</strong> 8 neurons with ReLU activation</li>
503
- <li><strong>Output Layer:</strong> 1 neuron with sigmoid activation</li>
504
- </ul>
505
- <h6 class="mt-3">🚀 Deployment Instructions</h6>
506
- <p>To deploy this app:</p>
507
- <ol class="small">
508
- <li>Create a new Space on Hugging Face: <code>hf.co/new/space</code></li>
509
- <li>Choose "Streamlit" or "Static" as the SDK</li>
510
- <li>Clone repository and upload files</li>
511
- <li>Commit and push to deploy</li>
512
- </ol>
513
- </div>
514
- </div>
515
- </div>
516
- </div>
517
- </div>
518
- </div>
519
-
520
- <!-- Footer -->
521
- <footer class="text-center mt-4 mb-3 text-muted">
522
- <p>© 2024 Urban Accessibility Predictor | Powered by MLP Neural Network | Tier-II India Focus</p>
523
- <p class="small">This tool supports evidence-based urban planning for sustainable development</p>
524
- </footer>
525
- </div>
526
- </div>
527
-
528
- <!-- JavaScript -->
529
- <script>
530
- // ===== DATABASE: Indian Tier-II Cities =====
531
- const indianTier2Cities = [
532
- // ... (keep the existing city data as is)
533
- ];
534
-
535
- // ===== DATABASE: Remedial Measures by Classification =====
536
- const remedialMeasures = {
537
- // ... (keep the existing remedial measures as is)
538
- };
539
-
540
- // ===== DATABASE: Distance Band Effects =====
541
- const distanceBandEffects = {
542
- "200": { name: "Short Walk", multiplier: 1.2, description: "High accessibility expectation" },
543
- "400": { name: "Standard Walk", multiplier: 1.0, description: "Standard walking distance" },
544
- "600": { name: "Moderate Walk", multiplier: 0.9, description: "Moderate walking distance" },
545
- "800": { name: "Long Walk", multiplier: 0.8, description: "Long walking distance" },
546
- "1000": { name: "Extended Walk", multiplier: 0.7, description: "Extended walking distance" }
547
- };
548
-
549
- // ===== APPLICATION STATE =====
550
- let features = {
551
- euclidean: 0.7,
552
- builtup: 0.6,
553
- network: 0.75,
554
- busstop: 0.8
555
- };
556
-
557
- let currentCity = null;
558
- let currentDistanceBand = "400";
559
-
560
- // ===== INITIALIZATION FUNCTIONS =====
561
- function initializeCitySelector() {
562
- const selector = document.getElementById('citySelector');
563
- indianTier2Cities.forEach((city, index) => {
564
- const option = document.createElement('option');
565
- option.value = city.id;
566
- option.textContent = `${city.name}, ${city.state} (${city.region})`;
567
- selector.appendChild(option);
568
- });
569
- }
570
-
571
- function updateCityInfo() {
572
- const selector = document.getElementById('citySelector');
573
- const cityId = parseInt(selector.value);
574
- const cityInfoPanel = document.getElementById('cityInfoPanel');
575
- const cityBadge = document.getElementById('cityBadge');
576
- const cityDisplay = document.getElementById('currentCityName');
577
- const distanceBadge = document.getElementById('distanceBadge');
578
-
579
- if (cityId > 0) {
580
- currentCity = indianTier2Cities.find(city => city.id === cityId);
581
- cityDisplay.textContent = `${currentCity.name}, ${currentCity.state}`;
582
- cityBadge.textContent = currentCity.region;
583
- distanceBadge.textContent = currentDistanceBand + 'm';
584
- cityInfoPanel.style.display = 'block';
585
-
586
- // Update remedial measures panel
587
- updateRemedialMeasures();
588
- } else {
589
- currentCity = null;
590
- cityInfoPanel.style.display = 'none';
591
- document.getElementById('remedialPanel').style.display = 'none';
592
- }
593
- }
594
-
595
- // ===== DISTANCE BAND FUNCTIONS =====
596
- function updateDistanceBand() {
597
- const selector = document.getElementById('distanceBandSelector');
598
- currentDistanceBand = selector.value;
599
-
600
- const bandInfo = distanceBandEffects[currentDistanceBand];
601
- document.getElementById('distanceBandValue').textContent = currentDistanceBand + 'm';
602
- document.getElementById('distanceBandBadge').textContent =
603
- `${currentDistanceBand}m ${bandInfo.name}`;
604
-
605
- // Update distance badge in city info panel
606
- const distanceBadge = document.getElementById('distanceBadge');
607
- if (distanceBadge) {
608
- distanceBadge.textContent = currentDistanceBand + 'm';
609
- }
610
- }
611
-
612
- // ===== AVERAGE CALCULATION FUNCTION =====
613
- function calculateAverageScore() {
614
- const values = Object.values(features);
615
- const sum = values.reduce((a, b) => a + b, 0);
616
- const average = sum / values.length;
617
-
618
- // Update display
619
- document.getElementById('averageScore').textContent = average.toFixed(4);
620
- document.getElementById('simpleAverageDisplay').textContent = average.toFixed(4);
621
-
622
- // Update progress bar
623
- const progressBar = document.getElementById('averageProgressBar');
624
- const percentage = average * 100;
625
- progressBar.style.width = `${percentage}%`;
626
- progressBar.setAttribute('aria-valuenow', percentage);
627
-
628
- return average;
629
- }
630
-
631
- // ===== PREDICTION FUNCTIONS =====
632
- function predictAccessibility(euclidean, builtup, network, busstop) {
633
- // Enhanced prediction with city-specific adjustments and distance band
634
- const baseWeights = {
635
- euclidean: 0.25,
636
- builtup: 0.15,
637
- network: 0.35,
638
- busstop: 0.25
639
- };
640
-
641
- // Region-specific adjustments
642
- const regionFactors = {
643
- "Northern": { network: 1.1, builtup: 0.9 },
644
- "Southern": { euclidean: 1.05, busstop: 1.1 },
645
- "Eastern": { builtup: 1.1, network: 0.95 },
646
- "Western": { euclidean: 0.95, busstop: 1.05 },
647
- "Central": { network: 1.05, builtup: 1.05 },
648
- "Northeastern": { euclidean: 1.1, network: 0.9 }
649
- };
650
-
651
- // Distance band adjustment
652
- const distanceMultiplier = distanceBandEffects[currentDistanceBand].multiplier;
653
-
654
- // Apply region factor if city is selected
655
- let adjustedWeights = { ...baseWeights };
656
- if (currentCity && regionFactors[currentCity.region]) {
657
- const factors = regionFactors[currentCity.region];
658
- Object.keys(factors).forEach(key => {
659
- adjustedWeights[key] *= factors[key];
660
- });
661
- }
662
-
663
- // Calculate weighted score with non-linearity and distance adjustment
664
- let score =
665
- adjustedWeights.euclidean * Math.pow(euclidean, 1.2) +
666
- adjustedWeights.builtup * Math.pow(builtup, 0.9) +
667
- adjustedWeights.network * Math.pow(network, 1.5) +
668
- adjustedWeights.busstop * Math.pow(busstop, 1.1);
669
-
670
- // Apply distance band multiplier
671
- score *= distanceMultiplier;
672
-
673
- // Normalize to 0-1 range
674
- score = Math.max(0, Math.min(1, score));
675
-
676
- // Add realistic noise (simulating MLP output)
677
- const noise = (Math.random() - 0.5) * 0.02;
678
- score += noise;
679
-
680
- // Simulate MLP prediction (slightly different from simple average)
681
- const simpleAverage = (euclidean + builtup + network + busstop) / 4;
682
- const mlpPrediction = (score * 0.8) + (simpleAverage * 0.2); // Blend of complex and simple
683
-
684
- return Math.max(0, Math.min(1, mlpPrediction));
685
- }
686
-
687
- // ===== UI UPDATE FUNCTIONS =====
688
- function updateValue(feature, value) {
689
- const rawValue = parseInt(value);
690
- const normalizedValue = (rawValue / 100).toFixed(2);
691
-
692
- // Update raw value display
693
- document.getElementById(feature + 'RawValue').textContent = rawValue + '%';
694
-
695
- // Update normalized value display
696
- features[feature] = parseFloat(normalizedValue);
697
- document.getElementById(feature + 'Value').textContent = normalizedValue;
698
-
699
- // Update average score
700
- calculateAverageScore();
701
- }
702
-
703
- function updatePrediction() {
704
- // Get prediction
705
- const prediction = predictAccessibility(
706
- features.euclidean,
707
- features.builtup,
708
- features.network,
709
- features.busstop
710
- );
711
-
712
- // Update prediction display
713
- document.getElementById('predictionScore').textContent = prediction.toFixed(3);
714
- document.getElementById('mlpPredictionDisplay').textContent = prediction.toFixed(3);
715
-
716
- // Determine classification
717
- let classification = '';
718
- let badgeClass = '';
719
- let message = '';
720
-
721
- if (prediction >= 0.8) {
722
- classification = 'Excellent';
723
- badgeClass = 'excellent';
724
- message = 'The predicted accessibility is Excellent! The city demonstrates superior urban mobility.';
725
- } else if (prediction >= 0.6) {
726
- classification = 'Good';
727
- badgeClass = 'good';
728
- message = 'The predicted accessibility is Good. Minor improvements can enhance urban mobility further.';
729
- } else if (prediction >= 0.4) {
730
- classification = 'Moderate';
731
- badgeClass = 'moderate';
732
- message = 'The predicted accessibility is Moderate. Strategic interventions are needed for improvement.';
733
- } else {
734
- classification = 'Poor';
735
- badgeClass = 'poor';
736
- message = 'The predicted accessibility is Poor. Comprehensive planning and investments are urgently required.';
737
- }
738
-
739
- // Add distance band info to message
740
- const bandInfo = distanceBandEffects[currentDistanceBand];
741
- message += ` (Based on ${currentDistanceBand}m ${bandInfo.name.toLowerCase()} distance)`;
742
-
743
- // Update UI elements
744
- document.getElementById('badge').className = `classification-badge ${badgeClass}`;
745
- document.getElementById('badge').textContent = classification;
746
- document.getElementById('statusMessage').innerHTML = message;
747
-
748
- // Update chart
749
- updateChart();
750
-
751
- // Update remedial measures if city is selected
752
- if (currentCity) {
753
- updateRemedialMeasures();
754
- }
755
- }
756
-
757
- function updateRemedialMeasures() {
758
- const classification = document.getElementById('badge').textContent;
759
- const measures = remedialMeasures[classification];
760
- const contentDiv = document.getElementById('remedialMeasuresContent');
761
- const panel = document.getElementById('remedialPanel');
762
- const cityNameSpan = document.getElementById('cityNameForMeasures');
763
-
764
- if (measures && currentCity) {
765
- cityNameSpan.textContent = `${currentCity.name} (${currentDistanceBand}m distance band)`;
766
-
767
- let measuresHtml = `
768
- <div class="remedial-box remedial-${classification.toLowerCase()}">
769
- <div class="d-flex align-items-center mb-3">
770
- <div class="fs-4 me-3">${measures.icon}</div>
771
- <div>
772
- <h6 class="mb-1">${measures.title} for ${currentDistanceBand}m Distance Band</h6>
773
- <p class="mb-0 text-muted small">${measures.description}</p>
774
- </div>
775
- </div>
776
-
777
- <div class="row">
778
- <div class="col-md-4">
779
- <h6><i class="fas fa-bolt me-2"></i>Short-term (0-1 year)</h6>
780
- <div class="measure-list">`;
781
-
782
- measures.short_term.forEach(item => {
783
- measuresHtml += `<div class="measure-item">${item}</div>`;
784
- });
785
-
786
- measuresHtml += `</div></div><div class="col-md-4">
787
- <h6><i class="fas fa-chart-line me-2"></i>Medium-term (1-3 years)</h6>
788
- <div class="measure-list">`;
789
-
790
- measures.medium_term.forEach(item => {
791
- measuresHtml += `<div class="measure-item">${item}</div>`;
792
- });
793
-
794
- measuresHtml += `</div></div><div class="col-md-4">
795
- <h6><i class="fas fa-flag-checkered me-2"></i>Long-term (3+ years)</h6>
796
- <div class="measure-list">`;
797
-
798
- measures.long_term.forEach(item => {
799
- measuresHtml += `<div class="measure-item">${item}</div>`;
800
- });
801
-
802
- measuresHtml += `</div></div></div></div>`;
803
-
804
- contentDiv.innerHTML = measuresHtml;
805
- panel.style.display = 'block';
806
- }
807
- }
808
-
809
- function updateChart() {
810
- const featureNames = ['Euclidean ASF', 'Built-Up Area', 'Network ASF', 'Bus Stop ASF'];
811
- const featureValues = [
812
- features.euclidean,
813
- features.builtup,
814
- features.network,
815
- features.busstop
816
- ];
817
-
818
- // Raw percentage values
819
- const rawValues = [
820
- features.euclidean * 100,
821
- features.builtup * 100,
822
- features.network * 100,
823
- features.busstop * 100
824
- ];
825
-
826
- const colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728'];
827
-
828
- const data = [{
829
- x: featureNames,
830
- y: featureValues,
831
- type: 'bar',
832
- marker: {
833
- color: colors,
834
- opacity: 0.8
835
- },
836
- text: featureValues.map(v
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>🏙️ Urban Spatial Accessibility Predictor</title>
7
+ <!-- Bootstrap CSS -->
8
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
9
+ <!-- Plotly.js -->
10
+ <script src="https://cdn.plot.ly/plotly-2.20.0.min.js"></script>
11
+ <!-- Font Awesome -->
12
+ <script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script>
13
+ <style>
14
+ :root {
15
+ --primary-color: #2E86AB;
16
+ --secondary-color: #A23B72;
17
+ --success-color: #4CAF50;
18
+ --warning-color: #FF9800;
19
+ --danger-color: #F44336;
20
+ --info-color: #17a2b8;
21
+ --card-bg: rgba(255, 255, 255, 0.95);
22
+ }
23
+
24
+ body {
25
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
26
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
27
+ min-height: 100vh;
28
+ padding: 20px;
29
+ }
30
+
31
+ .main-container {
32
+ background: var(--card-bg);
33
+ border-radius: 20px;
34
+ box-shadow: 0 15px 35px rgba(0, 0, 0, 0.3);
35
+ overflow: hidden;
36
+ backdrop-filter: blur(10px);
37
+ }
38
+
39
+ .header-section {
40
+ background: linear-gradient(135deg, var(--primary-color), #1a5f7a);
41
+ color: white;
42
+ padding: 2rem;
43
+ border-radius: 0 0 30px 30px;
44
+ margin-bottom: 2rem;
45
+ }
46
+
47
+ .metric-card {
48
+ background: white;
49
+ border-radius: 15px;
50
+ padding: 1.5rem;
51
+ box-shadow: 0 5px 15px rgba(0,0,0,0.1);
52
+ border-left: 5px solid var(--primary-color);
53
+ margin-bottom: 1rem;
54
+ }
55
+
56
+ .slider-container {
57
+ background: #f8f9fa;
58
+ border-radius: 10px;
59
+ padding: 1.5rem;
60
+ margin: 1rem 0;
61
+ }
62
+
63
+ .feature-value {
64
+ font-size: 1.2rem;
65
+ font-weight: 600;
66
+ color: var(--primary-color);
67
+ float: right;
68
+ }
69
+
70
+ .accessibility-score {
71
+ font-size: 4rem;
72
+ font-weight: 800;
73
+ text-align: center;
74
+ color: var(--primary-color);
75
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
76
+ }
77
+
78
+ .classification-badge {
79
+ display: inline-block;
80
+ padding: 0.5rem 1.5rem;
81
+ border-radius: 25px;
82
+ font-weight: 700;
83
+ font-size: 1.2rem;
84
+ margin: 0.5rem;
85
+ }
86
+
87
+ .excellent { background: linear-gradient(135deg, #4CAF50, #2E7D32); color: white; }
88
+ .good { background: linear-gradient(135deg, #8BC34A, #558B2F); color: white; }
89
+ .moderate { background: linear-gradient(135deg, #FF9800, #EF6C00); color: white; }
90
+ .poor { background: linear-gradient(135deg, #F44336, #C62828); color: white; }
91
+
92
+ .feature-slider {
93
+ width: 100%;
94
+ margin: 1rem 0;
95
+ }
96
+
97
+ .feature-icon {
98
+ font-size: 1.5rem;
99
+ margin-right: 10px;
100
+ }
101
+
102
+ .chart-container {
103
+ background: white;
104
+ border-radius: 15px;
105
+ padding: 1.5rem;
106
+ box-shadow: 0 5px 15px rgba(0,0,0,0.1);
107
+ margin: 1rem 0;
108
+ }
109
+
110
+ .info-box {
111
+ background: #E3F2FD;
112
+ border-left: 4px solid #2196F3;
113
+ padding: 1rem;
114
+ border-radius: 8px;
115
+ margin: 1rem 0;
116
+ }
117
+
118
+ .remedial-box {
119
+ border-left: 5px solid;
120
+ padding: 1rem;
121
+ border-radius: 8px;
122
+ margin: 0.5rem 0;
123
+ background: #f8f9fa;
124
+ }
125
+
126
+ .remedial-excellent { border-left-color: #4CAF50; }
127
+ .remedial-good { border-left-color: #8BC34A; }
128
+ .remedial-moderate { border-left-color: #FF9800; }
129
+ .remedial-poor { border-left-color: #F44336; }
130
+
131
+ .city-highlight {
132
+ background: linear-gradient(135deg, #4a6572, #5d8aa8);
133
+ color: white;
134
+ padding: 0.5rem 1rem;
135
+ border-radius: 8px;
136
+ font-weight: 600;
137
+ margin-bottom: 1rem;
138
+ display: inline-block;
139
+ }
140
+
141
+ .measure-item {
142
+ padding: 0.5rem 0;
143
+ border-bottom: 1px dashed #dee2e6;
144
+ }
145
+
146
+ .measure-item:last-child {
147
+ border-bottom: none;
148
+ }
149
+
150
+ @media (max-width: 768px) {
151
+ .accessibility-score {
152
+ font-size: 3rem;
153
+ }
154
+ }
155
+ </style>
156
+ </head>
157
+ <body>
158
+ <div class="container main-container">
159
+ <!-- Header -->
160
+ <div class="header-section">
161
+ <div class="d-flex align-items-center justify-content-center gap-3 mb-3">
162
+ <div style="font-size: 2.5rem; color: white;">🏙️</div>
163
+ <div>
164
+ <h1 class="display-5 mb-2">Urban Spatial Accessibility Predictor</h1>
165
+ <p class="lead mb-0">AI-powered tool for predicting urban accessibility across Tier-II Indian cities with tailored remedial measures</p>
166
+ </div>
167
+ </div>
168
+ </div>
169
+
170
+ <div class="container-fluid">
171
+ <div class="row">
172
+ <!-- Left Column - Inputs -->
173
+ <div class="col-lg-6 col-md-12 mb-4">
174
+ <div class="card shadow">
175
+ <div class="card-header bg-primary text-white">
176
+ <h3 class="mb-0">📊 Input Urban Indicators</h3>
177
+ <p class="mb-0 opacity-75">Select a city and adjust indicators for prediction</p>
178
+ </div>
179
+ <div class="card-body">
180
+ <!-- City Selection -->
181
+ <div class="slider-container">
182
+ <div class="d-flex justify-content-between mb-2">
183
+ <label class="form-label h5">
184
+ <span class="feature-icon">🏙️</span>
185
+ Select Tier-II City
186
+ </label>
187
+ </div>
188
+ <p class="text-muted mb-3">Choose an Indian Tier-II city for context-specific analysis</p>
189
+ <select class="form-select form-select-lg mb-3" id="citySelector" onchange="updateCityInfo()">
190
+ <option value="0">-- Select a City --</option>
191
+ </select>
192
+ </div>
193
+
194
+ <!-- Euclidean ASF Slider -->
195
+ <div class="slider-container">
196
+ <div class="d-flex justify-content-between mb-2">
197
+ <label class="form-label h5">
198
+ <span class="feature-icon">📐</span>
199
+ Euclidean ASF
200
+ </label>
201
+ <span id="euclideanValue" class="feature-value">0.70</span>
202
+ </div>
203
+ <p class="text-muted mb-3">Percentage of Accessible Street Frontage (Euclidean Distance)</p>
204
+ <input type="range" class="form-range feature-slider" id="euclideanSlider"
205
+ min="0" max="100" value="70" step="1"
206
+ oninput="updateValue('euclidean', this.value); updatePrediction();">
207
+ <div class="d-flex justify-content-between">
208
+ <small class="text-muted">0.0 (Low)</small>
209
+ <small class="text-muted">1.0 (High)</small>
210
+ </div>
211
+ </div>
212
+
213
+ <!-- Built-Up Area Slider -->
214
+ <div class="slider-container">
215
+ <div class="d-flex justify-content-between mb-2">
216
+ <label class="form-label h5">
217
+ <span class="feature-icon">🏗️</span>
218
+ Built-Up Area
219
+ </label>
220
+ <span id="builtupValue" class="feature-value">0.60</span>
221
+ </div>
222
+ <p class="text-muted mb-3">Percentage of Built-Up Area in the selected region</p>
223
+ <input type="range" class="form-range feature-slider" id="builtupSlider"
224
+ min="0" max="100" value="60" step="1"
225
+ oninput="updateValue('builtup', this.value); updatePrediction();">
226
+ <div class="d-flex justify-content-between">
227
+ <small class="text-muted">0.0 (Low)</small>
228
+ <small class="text-muted">1.0 (High)</small>
229
+ </div>
230
+ </div>
231
+
232
+ <!-- Network ASF Slider -->
233
+ <div class="slider-container">
234
+ <div class="d-flex justify-content-between mb-2">
235
+ <label class="form-label h5">
236
+ <span class="feature-icon">🛣️</span>
237
+ Network ASF
238
+ </label>
239
+ <span id="networkValue" class="feature-value">0.75</span>
240
+ </div>
241
+ <p class="text-muted mb-3">Percentage of Accessible Street Frontage (Network Distance)</p>
242
+ <input type="range" class="form-range feature-slider" id="networkSlider"
243
+ min="0" max="100" value="75" step="1"
244
+ oninput="updateValue('network', this.value); updatePrediction();">
245
+ <div class="d-flex justify-content-between">
246
+ <small class="text-muted">0.0 (Low)</small>
247
+ <small class="text-muted">1.0 (High)</small>
248
+ </div>
249
+ </div>
250
+
251
+ <!-- Bus Stop ASF Slider -->
252
+ <div class="slider-container">
253
+ <div class="d-flex justify-content-between mb-2">
254
+ <label class="form-label h5">
255
+ <span class="feature-icon">🚌</span>
256
+ Bus Stop ASF
257
+ </label>
258
+ <span id="busstopValue" class="feature-value">0.80</span>
259
+ </div>
260
+ <p class="text-muted mb-3">Percentage of Street Frontage accessible from Bus Stops</p>
261
+ <input type="range" class="form-range feature-slider" id="busstopSlider"
262
+ min="0" max="100" value="80" step="1"
263
+ oninput="updateValue('busstop', this.value); updatePrediction();">
264
+ <div class="d-flex justify-content-between">
265
+ <small class="text-muted">0.0 (Low)</small>
266
+ <small class="text-muted">1.0 (High)</small>
267
+ </div>
268
+ </div>
269
+
270
+ <!-- Action Buttons -->
271
+ <div class="row mt-4">
272
+ <div class="col-md-6">
273
+ <button class="btn btn-outline-primary btn-lg w-100" onclick="resetSliders()">
274
+ 🔄 Reset Values
275
+ </button>
276
+ </div>
277
+ <div class="col-md-6">
278
+ <button class="btn btn-success btn-lg w-100" onclick="exportResults()">
279
+ 💾 Export Results
280
+ </button>
281
+ </div>
282
+ </div>
283
+ </div>
284
+ </div>
285
+ </div>
286
+
287
+ <!-- Right Column - Results -->
288
+ <div class="col-lg-6 col-md-12 mb-4">
289
+ <div class="card shadow">
290
+ <div class="card-header bg-success text-white">
291
+ <h3 class="mb-0">📈 Prediction Results</h3>
292
+ <p class="mb-0 opacity-75">Real-time prediction based on ML model</p>
293
+ </div>
294
+ <div class="card-body">
295
+ <!-- Selected City Info -->
296
+ <div id="cityInfoPanel" class="mb-4" style="display: none;">
297
+ <div class="d-flex justify-content-between align-items-center mb-3">
298
+ <h5 class="mb-0">📍 Selected City Analysis</h5>
299
+ <span id="cityBadge" class="badge bg-info fs-6"></span>
300
+ </div>
301
+ <div class="city-highlight" id="cityDisplay">
302
+ <i class="fas fa-city me-2"></i>
303
+ <span id="currentCityName">No city selected</span>
304
+ </div>
305
+ </div>
306
+
307
+ <!-- Prediction Score -->
308
+ <div class="text-center mb-4">
309
+ <h4 class="mb-3">Predicted Accessibility Score</h4>
310
+ <div class="accessibility-score" id="predictionScore">0.685</div>
311
+
312
+ <!-- Classification Badge -->
313
+ <div id="classificationBadge" class="mt-3">
314
+ <div class="classification-badge moderate" id="badge">Moderate</div>
315
+ </div>
316
+
317
+ <!-- Status Message -->
318
+ <div class="alert alert-info mt-3" id="statusMessage">
319
+ The predicted accessibility is Moderate. Improvement opportunities exist.
320
+ </div>
321
+ </div>
322
+
323
+ <!-- Feature Visualization -->
324
+ <div class="chart-container">
325
+ <h5 class="mb-3">📊 Input Feature Visualization</h5>
326
+ <div id="featureChart" style="height: 300px;"></div>
327
+ </div>
328
+
329
+ <!-- Remedial Measures -->
330
+ <div class="chart-container" id="remedialPanel" style="display: none;">
331
+ <h5 class="mb-3">🛠️ Context-Specific Remedial Measures</h5>
332
+ <p class="text-muted mb-3">Tailored recommendations for <span id="cityNameForMeasures">selected city</span> based on accessibility classification</p>
333
+ <div id="remedialMeasuresContent">
334
+ <!-- Measures will be dynamically inserted here -->
335
+ </div>
336
+ </div>
337
+
338
+ <!-- Accessibility Scale -->
339
+ <div class="chart-container">
340
+ <h5 class="mb-3">📏 Accessibility Classification Scale</h5>
341
+ <div class="row text-center">
342
+ <div class="col-3 mb-2">
343
+ <div class="p-2 excellent rounded">
344
+ <strong>Excellent</strong><br>≥ 0.8
345
+ </div>
346
+ </div>
347
+ <div class="col-3 mb-2">
348
+ <div class="p-2 good rounded">
349
+ <strong>Good</strong><br>0.6 - 0.8
350
+ </div>
351
+ </div>
352
+ <div class="col-3 mb-2">
353
+ <div class="p-2 moderate rounded">
354
+ <strong>Moderate</strong><br>0.4 - 0.6
355
+ </div>
356
+ </div>
357
+ <div class="col-3 mb-2">
358
+ <div class="p-2 poor rounded">
359
+ <strong>Poor</strong><br>&lt; 0.4
360
+ </div>
361
+ </div>
362
+ </div>
363
+ </div>
364
+ </div>
365
+ </div>
366
+ </div>
367
+ </div>
368
+
369
+ <!-- Additional Information -->
370
+ <div class="row mt-4">
371
+ <div class="col-12">
372
+ <div class="card shadow">
373
+ <div class="card-header bg-secondary text-white">
374
+ <h4 class="mb-0">ℹ️ How to Interpret Results & Deployment Information</h4>
375
+ </div>
376
+ <div class="card-body">
377
+ <div class="row">
378
+ <div class="col-md-6">
379
+ <h5>📋 Understanding the Metrics</h5>
380
+ <ul>
381
+ <li><strong>Euclidean ASF:</strong> Measures straight-line accessibility to street frontage</li>
382
+ <li><strong>Built-Up Area:</strong> Percentage of developed land in the region</li>
383
+ <li><strong>Network ASF:</strong> Accessibility considering actual road networks</li>
384
+ <li><strong>Bus Stop ASF:</strong> Proximity to public transport infrastructure</li>
385
+ </ul>
386
+ <p>Higher values in these metrics typically lead to better overall accessibility scores.</p>
387
+ </div>
388
+ <div class="col-md-6">
389
+ <h5>🏙️ About Tier-II Cities</h5>
390
+ <p>Tier-II Indian cities are urban centers with populations between 50,000 and 100,000, experiencing rapid urbanization and facing unique accessibility challenges. This tool provides data-driven insights for evidence-based urban planning.</p>
391
+ <h6 class="mt-3">🚀 Deployment Instructions</h6>
392
+ <p>To deploy this app:</p>
393
+ <ol class="small">
394
+ <li>Create a new Space on Hugging Face: <code>hf.co/new/space</code></li>
395
+ <li>Choose "Streamlit" or "Static" as the SDK</li>
396
+ <li>Clone repository and upload files</li>
397
+ <li>Commit and push to deploy</li>
398
+ </ol>
399
+ </div>
400
+ </div>
401
+ </div>
402
+ </div>
403
+ </div>
404
+ </div>
405
+
406
+ <!-- Footer -->
407
+ <footer class="text-center mt-4 mb-3 text-muted">
408
+ <p>© 2024 Urban Accessibility Predictor | Powered by ML Models | Tier-II India Focus</p>
409
+ <p class="small">This tool supports evidence-based urban planning for sustainable development</p>
410
+ </footer>
411
+ </div>
412
+ </div>
413
+
414
+ <!-- JavaScript -->
415
+ <script>
416
+ // ===== DATABASE: Indian Tier-II Cities =====
417
+ const indianTier2Cities = [
418
+ // Maharashtra
419
+ { id: 1, name: "Nashik", state: "Maharashtra", region: "Western" },
420
+ { id: 2, name: "Nagpur", state: "Maharashtra", region: "Central" },
421
+ { id: 3, name: "Aurangabad", state: "Maharashtra", region: "Western" },
422
+ { id: 4, name: "Solapur", state: "Maharashtra", region: "Southern" },
423
+ { id: 5, name: "Pune", state: "Maharashtra", region: "Western" },
424
+
425
+ // Madhya Pradesh
426
+ { id: 6, name: "Indore", state: "Madhya Pradesh", region: "Central" },
427
+ { id: 7, name: "Bhopal", state: "Madhya Pradesh", region: "Central" },
428
+ { id: 8, name: "Jabalpur", state: "Madhya Pradesh", region: "Central" },
429
+ { id: 9, name: "Gwalior", state: "Madhya Pradesh", region: "Northern" },
430
+
431
+ // Uttar Pradesh
432
+ { id: 10, name: "Lucknow", state: "Uttar Pradesh", region: "Northern" },
433
+ { id: 11, name: "Kanpur", state: "Uttar Pradesh", region: "Northern" },
434
+ { id: 12, name: "Varanasi", state: "Uttar Pradesh", region: "Eastern" },
435
+ { id: 13, name: "Agra", state: "Uttar Pradesh", region: "Northern" },
436
+ { id: 14, name: "Allahabad", state: "Uttar Pradesh", region: "Northern" },
437
+
438
+ // Gujarat
439
+ { id: 15, name: "Surat", state: "Gujarat", region: "Western" },
440
+ { id: 16, name: "Vadodara", state: "Gujarat", region: "Western" },
441
+ { id: 17, name: "Rajkot", state: "Gujarat", region: "Western" },
442
+
443
+ // Tamil Nadu
444
+ { id: 18, name: "Coimbatore", state: "Tamil Nadu", region: "Southern" },
445
+ { id: 19, name: "Madurai", state: "Tamil Nadu", region: "Southern" },
446
+ { id: 20, name: "Tiruchirappalli", state: "Tamil Nadu", region: "Southern" },
447
+
448
+ // Karnataka
449
+ { id: 21, name: "Mysore", state: "Karnataka", region: "Southern" },
450
+ { id: 22, name: "Mangalore", state: "Karnataka", region: "Southern" },
451
+ { id: 23, name: "Hubli-Dharwad", state: "Karnataka", region: "Southern" },
452
+
453
+ // Andhra Pradesh & Telangana
454
+ { id: 24, name: "Vijayawada", state: "Andhra Pradesh", region: "Southern" },
455
+ { id: 25, name: "Visakhapatnam", state: "Andhra Pradesh", region: "Southern" },
456
+ { id: 26, name: "Warangal", state: "Telangana", region: "Southern" },
457
+
458
+ // Rajasthan
459
+ { id: 27, name: "Jaipur", state: "Rajasthan", region: "Northern" },
460
+ { id: 28, name: "Jodhpur", state: "Rajasthan", region: "Northern" },
461
+ { id: 29, name: "Kota", state: "Rajasthan", region: "Northern" },
462
+ { id: 30, name: "Bikaner", state: "Rajasthan", region: "Northern" },
463
+
464
+ // Punjab
465
+ { id: 31, name: "Amritsar", state: "Punjab", region: "Northern" },
466
+ { id: 32, name: "Ludhiana", state: "Punjab", region: "Northern" },
467
+ { id: 33, name: "Jalandhar", state: "Punjab", region: "Northern" },
468
+
469
+ // Kerala
470
+ { id: 34, name: "Kochi", state: "Kerala", region: "Southern" },
471
+ { id: 35, name: "Kozhikode", state: "Kerala", region: "Southern" },
472
+ { id: 36, name: "Thrissur", state: "Kerala", region: "Southern" },
473
+
474
+ // West Bengal
475
+ { id: 37, name: "Howrah", state: "West Bengal", region: "Eastern" },
476
+ { id: 38, name: "Durgapur", state: "West Bengal", region: "Eastern" },
477
+ { id: 39, name: "Siliguri", state: "West Bengal", region: "Eastern" },
478
+
479
+ // Bihar & Jharkhand
480
+ { id: 40, name: "Patna", state: "Bihar", region: "Eastern" },
481
+ { id: 41, name: "Ranchi", state: "Jharkhand", region: "Eastern" },
482
+ { id: 42, name: "Jamshedpur", state: "Jharkhand", region: "Eastern" },
483
+
484
+ // Odisha
485
+ { id: 43, name: "Bhubaneswar", state: "Odisha", region: "Eastern" },
486
+ { id: 44, name: "Cuttack", state: "Odisha", region: "Eastern" },
487
+ { id: 45, name: "Rourkela", state: "Odisha", region: "Eastern" },
488
+
489
+ // Assam & Northeast
490
+ { id: 46, name: "Guwahati", state: "Assam", region: "Northeastern" },
491
+ { id: 47, name: "Imphal", state: "Manipur", region: "Northeastern" },
492
+ { id: 48, name: "Shillong", state: "Meghalaya", region: "Northeastern" },
493
+
494
+ // Union Territories
495
+ { id: 49, name: "Chandigarh", state: "Chandigarh", region: "Northern" },
496
+ { id: 50, name: "Puducherry", state: "Puducherry", region: "Southern" }
497
+ ];
498
+
499
+ // ===== DATABASE: Remedial Measures by Classification =====
500
+ const remedialMeasures = {
501
+ "Excellent": {
502
+ "color": "success",
503
+ "icon": "✅",
504
+ "title": "Maintenance & Sustainability Plan",
505
+ "description": "The city shows excellent accessibility. Focus should be on maintaining this standard and implementing sustainable practices.",
506
+ "short_term": [
507
+ "Conduct regular audits of pedestrian infrastructure every 6 months",
508
+ "Implement predictive maintenance for public transport systems",
509
+ "Launch public awareness campaigns about sustainable mobility options"
510
+ ],
511
+ "medium_term": [
512
+ "Develop digital twin for real-time urban mobility monitoring",
513
+ "Create green corridors connecting parks and public spaces",
514
+ "Implement smart parking management systems"
515
+ ],
516
+ "long_term": [
517
+ "Establish urban mobility innovation lab for future planning",
518
+ "Develop comprehensive 20-year sustainable mobility master plan",
519
+ "Create city-wide IoT sensor network for data collection"
520
+ ]
521
+ },
522
+ "Good": {
523
+ "color": "info",
524
+ "icon": "👍",
525
+ "title": "Enhancement & Integration Actions",
526
+ "description": "Good accessibility with room for improvement. Focus on integration and minor enhancements.",
527
+ "short_term": [
528
+ "Improve last-mile connectivity with bike/scooter sharing",
529
+ "Optimize traffic signal timings at 10 busiest intersections",
530
+ "Install real-time passenger information systems at bus stops"
531
+ ],
532
+ "medium_term": [
533
+ "Develop integrated multi-modal transport app",
534
+ "Create dedicated pedestrian zones in commercial areas",
535
+ "Implement bus priority lanes on major corridors"
536
+ ],
537
+ "long_term": [
538
+ "Plan for metro/BRT system integration",
539
+ "Develop comprehensive wayfinding system",
540
+ "Create unified transport authority for coordinated planning"
541
+ ]
542
+ },
543
+ "Moderate": {
544
+ "color": "warning",
545
+ "icon": "⚠️",
546
+ "title": "Priority Infrastructure & Policy Interventions",
547
+ "description": "Moderate accessibility requiring significant interventions. Priority infrastructure projects needed.",
548
+ "short_term": [
549
+ "Complete missing network links within 6 months",
550
+ "Relocate poorly placed bus stops to maximize coverage",
551
+ "Introduce congestion pricing in city center"
552
+ ],
553
+ "medium_term": [
554
+ "Develop 3-5 year transit-oriented development plan",
555
+ "Construct pedestrian overpasses at dangerous crossings",
556
+ "Implement smart traffic management system"
557
+ ],
558
+ "long_term": [
559
+ "Plan and design BRT or light rail system",
560
+ "Develop comprehensive non-motorized transport network",
561
+ "Create urban regeneration plan for low-accessibility areas"
562
+ ]
563
+ },
564
+ "Poor": {
565
+ "color": "danger",
566
+ "icon": "🚨",
567
+ "title": "Immediate & Comprehensive Revitalization",
568
+ "description": "Poor accessibility requiring emergency interventions. Comprehensive revitalization plan needed.",
569
+ "short_term": [
570
+ "Declare emergency mobility plan for worst-performing zones",
571
+ "Fast-track construction of critical missing road links",
572
+ "Implement emergency bus services in underserved areas"
573
+ ],
574
+ "medium_term": [
575
+ "Allocate 15% of city budget to accessibility projects",
576
+ "Develop comprehensive pedestrian infrastructure plan",
577
+ "Create special purpose vehicle for transport projects"
578
+ ],
579
+ "long_term": [
580
+ "Master plan for complete street redesign",
581
+ "Develop regional transport integration plan",
582
+ "Establish urban mobility research center"
583
+ ]
584
+ }
585
+ };
586
+
587
+ // ===== APPLICATION STATE =====
588
+ let features = {
589
+ euclidean: 0.7,
590
+ builtup: 0.6,
591
+ network: 0.75,
592
+ busstop: 0.8
593
+ };
594
+
595
+ let currentCity = null;
596
+
597
+ // ===== INITIALIZATION FUNCTIONS =====
598
+ function initializeCitySelector() {
599
+ const selector = document.getElementById('citySelector');
600
+ indianTier2Cities.forEach((city, index) => {
601
+ const option = document.createElement('option');
602
+ option.value = city.id;
603
+ option.textContent = `${city.name}, ${city.state} (${city.region})`;
604
+ selector.appendChild(option);
605
+ });
606
+ }
607
+
608
+ function updateCityInfo() {
609
+ const selector = document.getElementById('citySelector');
610
+ const cityId = parseInt(selector.value);
611
+ const cityInfoPanel = document.getElementById('cityInfoPanel');
612
+ const cityBadge = document.getElementById('cityBadge');
613
+ const cityDisplay = document.getElementById('currentCityName');
614
+
615
+ if (cityId > 0) {
616
+ currentCity = indianTier2Cities.find(city => city.id === cityId);
617
+ cityDisplay.textContent = `${currentCity.name}, ${currentCity.state}`;
618
+ cityBadge.textContent = currentCity.region;
619
+ cityInfoPanel.style.display = 'block';
620
+
621
+ // Update remedial measures panel
622
+ updateRemedialMeasures();
623
+ } else {
624
+ currentCity = null;
625
+ cityInfoPanel.style.display = 'none';
626
+ document.getElementById('remedialPanel').style.display = 'none';
627
+ }
628
+ }
629
+
630
+ // ===== PREDICTION FUNCTIONS =====
631
+ function predictAccessibility(euclidean, builtup, network, busstop) {
632
+ // Enhanced prediction with city-specific adjustments
633
+ const baseWeights = {
634
+ euclidean: 0.25,
635
+ builtup: 0.15,
636
+ network: 0.35,
637
+ busstop: 0.25
638
+ };
639
+
640
+ // Region-specific adjustments
641
+ const regionFactors = {
642
+ "Northern": { network: 1.1, builtup: 0.9 },
643
+ "Southern": { euclidean: 1.05, busstop: 1.1 },
644
+ "Eastern": { builtup: 1.1, network: 0.95 },
645
+ "Western": { euclidean: 0.95, busstop: 1.05 },
646
+ "Central": { network: 1.05, builtup: 1.05 },
647
+ "Northeastern": { euclidean: 1.1, network: 0.9 }
648
+ };
649
+
650
+ // Apply region factor if city is selected
651
+ let adjustedWeights = { ...baseWeights };
652
+ if (currentCity && regionFactors[currentCity.region]) {
653
+ const factors = regionFactors[currentCity.region];
654
+ Object.keys(factors).forEach(key => {
655
+ adjustedWeights[key] *= factors[key];
656
+ });
657
+ }
658
+
659
+ // Calculate weighted score with non-linearity
660
+ let score =
661
+ adjustedWeights.euclidean * Math.pow(euclidean, 1.2) +
662
+ adjustedWeights.builtup * Math.pow(builtup, 0.9) +
663
+ adjustedWeights.network * Math.pow(network, 1.5) +
664
+ adjustedWeights.busstop * Math.pow(busstop, 1.1);
665
+
666
+ // Normalize to 0-1 range
667
+ score = Math.max(0, Math.min(1, score));
668
+
669
+ // Add realistic noise
670
+ score += (Math.random() - 0.5) * 0.02;
671
+
672
+ return Math.max(0, Math.min(1, score));
673
+ }
674
+
675
+ // ===== UI UPDATE FUNCTIONS =====
676
+ function updateValue(feature, value) {
677
+ const normalizedValue = (value / 100).toFixed(2);
678
+ features[feature] = parseFloat(normalizedValue);
679
+ document.getElementById(feature + 'Value').textContent = normalizedValue;
680
+ }
681
+
682
+ function updatePrediction() {
683
+ // Get prediction
684
+ const prediction = predictAccessibility(
685
+ features.euclidean,
686
+ features.builtup,
687
+ features.network,
688
+ features.busstop
689
+ );
690
+
691
+ // Update prediction display
692
+ document.getElementById('predictionScore').textContent = prediction.toFixed(3);
693
+
694
+ // Determine classification
695
+ let classification = '';
696
+ let badgeClass = '';
697
+ let message = '';
698
+
699
+ if (prediction >= 0.8) {
700
+ classification = 'Excellent';
701
+ badgeClass = 'excellent';
702
+ message = 'The predicted accessibility is Excellent! The city demonstrates superior urban mobility.';
703
+ } else if (prediction >= 0.6) {
704
+ classification = 'Good';
705
+ badgeClass = 'good';
706
+ message = 'The predicted accessibility is Good. Minor improvements can enhance urban mobility further.';
707
+ } else if (prediction >= 0.4) {
708
+ classification = 'Moderate';
709
+ badgeClass = 'moderate';
710
+ message = 'The predicted accessibility is Moderate. Strategic interventions are needed for improvement.';
711
+ } else {
712
+ classification = 'Poor';
713
+ badgeClass = 'poor';
714
+ message = 'The predicted accessibility is Poor. Comprehensive planning and investments are urgently required.';
715
+ }
716
+
717
+ // Update UI elements
718
+ document.getElementById('badge').className = `classification-badge ${badgeClass}`;
719
+ document.getElementById('badge').textContent = classification;
720
+ document.getElementById('statusMessage').innerHTML = message;
721
+
722
+ // Update chart
723
+ updateChart();
724
+
725
+ // Update remedial measures if city is selected
726
+ if (currentCity) {
727
+ updateRemedialMeasures();
728
+ }
729
+ }
730
+
731
+ function updateRemedialMeasures() {
732
+ const classification = document.getElementById('badge').textContent;
733
+ const measures = remedialMeasures[classification];
734
+ const contentDiv = document.getElementById('remedialMeasuresContent');
735
+ const panel = document.getElementById('remedialPanel');
736
+ const cityNameSpan = document.getElementById('cityNameForMeasures');
737
+
738
+ if (measures && currentCity) {
739
+ cityNameSpan.textContent = currentCity.name;
740
+
741
+ let measuresHtml = `
742
+ <div class="remedial-box remedial-${classification.toLowerCase()}">
743
+ <div class="d-flex align-items-center mb-3">
744
+ <div class="fs-4 me-3">${measures.icon}</div>
745
+ <div>
746
+ <h6 class="mb-1">${measures.title}</h6>
747
+ <p class="mb-0 text-muted small">${measures.description}</p>
748
+ </div>
749
+ </div>
750
+
751
+ <div class="row">
752
+ <div class="col-md-4">
753
+ <h6><i class="fas fa-bolt me-2"></i>Short-term (0-1 year)</h6>
754
+ <div class="measure-list">`;
755
+
756
+ measures.short_term.forEach(item => {
757
+ measuresHtml += `<div class="measure-item">${item}</div>`;
758
+ });
759
+
760
+ measuresHtml += `</div></div><div class="col-md-4">
761
+ <h6><i class="fas fa-chart-line me-2"></i>Medium-term (1-3 years)</h6>
762
+ <div class="measure-list">`;
763
+
764
+ measures.medium_term.forEach(item => {
765
+ measuresHtml += `<div class="measure-item">${item}</div>`;
766
+ });
767
+
768
+ measuresHtml += `</div></div><div class="col-md-4">
769
+ <h6><i class="fas fa-flag-checkered me-2"></i>Long-term (3+ years)</h6>
770
+ <div class="measure-list">`;
771
+
772
+ measures.long_term.forEach(item => {
773
+ measuresHtml += `<div class="measure-item">${item}</div>`;
774
+ });
775
+
776
+ measuresHtml += `</div></div></div></div>`;
777
+
778
+ contentDiv.innerHTML = measuresHtml;
779
+ panel.style.display = 'block';
780
+ }
781
+ }
782
+
783
+ function updateChart() {
784
+ const featureNames = ['Euclidean ASF', 'Built-Up Area', 'Network ASF', 'Bus Stop ASF'];
785
+ const featureValues = [
786
+ features.euclidean,
787
+ features.builtup,
788
+ features.network,
789
+ features.busstop
790
+ ];
791
+
792
+ const colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728'];
793
+
794
+ const data = [{
795
+ x: featureNames,
796
+ y: featureValues,
797
+ type: 'bar',
798
+ marker: {
799
+ color: colors,
800
+ opacity: 0.8
801
+ },
802
+ text: featureValues.map(v => v.toFixed(2)),
803
+ textposition: 'auto'
804
+ }];
805
+
806
+ const layout = {
807
+ title: 'Current Input Feature Values',
808
+ yaxis: {
809
+ range: [0, 1],
810
+ title: 'Normalized Value'
811
+ },
812
+ xaxis: {
813
+ title: 'Features'
814
+ },
815
+ margin: {t: 40, b: 80, l: 60, r: 40},
816
+ height: 300,
817
+ showlegend: false
818
+ };
819
+
820
+ Plotly.newPlot('featureChart', data, layout);
821
+ }
822
+
823
+ // ===== UTILITY FUNCTIONS =====
824
+ function resetSliders() {
825
+ document.getElementById('euclideanSlider').value = 70;
826
+ document.getElementById('builtupSlider').value = 60;
827
+ document.getElementById('networkSlider').value = 75;
828
+ document.getElementById('busstopSlider').value = 80;
829
+
830
+ features = {
831
+ euclidean: 0.7,
832
+ builtup: 0.6,
833
+ network: 0.75,
834
+ busstop: 0.8
835
+ };
836
+
837
+ updateValue('euclidean', 70);
838
+ updateValue('builtup', 60);
839
+ updateValue('network', 75);
840
+ updateValue('busstop', 80);
841
+
842
+ updatePrediction();
843
+ }
844
+
845
+ function exportResults() {
846
+ const predictionScore = document.getElementById('predictionScore').textContent;
847
+ const classification = document.getElementById('badge').textContent;
848
+ const cityName = currentCity ? `${currentCity.name}, ${currentCity.state}` : 'Not selected';
849
+
850
+ const results = {
851
+ timestamp: new Date().toISOString(),
852
+ city: cityName,
853
+ features: {
854
+ euclidean_asf: features.euclidean,
855
+ built_up_area: features.builtup,
856
+ network_asf: features.network,
857
+ bus_stop_asf: features.busstop
858
+ },
859
+ prediction: parseFloat(predictionScore),
860
+ classification: classification,
861
+ remedial_measures: remedialMeasures[classification] ? remedialMeasures[classification].title : 'N/A'
862
+ };
863
+
864
+ const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(results, null, 2));
865
+ const downloadAnchor = document.createElement('a');
866
+ downloadAnchor.setAttribute("href", dataStr);
867
+ downloadAnchor.setAttribute("download", `accessibility_${cityName.replace(/[^a-z0-9]/gi, '_')}_${Date.now()}.json`);
868
+ document.body.appendChild(downloadAnchor);
869
+ downloadAnchor.click();
870
+ document.body.removeChild(downloadAnchor);
871
+
872
+ // Show success message
873
+ const originalText = document.querySelector('.btn-success').innerHTML;
874
+ document.querySelector('.btn-success').innerHTML = '✅ Exported!';
875
+ setTimeout(() => {
876
+ document.querySelector('.btn-success').innerHTML = originalText;
877
+ }, 2000);
878
+ }
879
+
880
+ // ===== INITIALIZATION =====
881
+ window.onload = function() {
882
+ // Initialize city selector
883
+ initializeCitySelector();
884
+
885
+ // Set initial values
886
+ updateValue('euclidean', 70);
887
+ updateValue('builtup', 60);
888
+ updateValue('network', 75);
889
+ updateValue('busstop', 80);
890
+
891
+ // Initial prediction and chart
892
+ updatePrediction();
893
+ };
894
+ </script>
895
+ </body>
896
+ </html>