anjabunga/API-FirstAidApp
0
1from fastapi import FastAPI
2from pydantic import BaseModel
3import joblib
4import re
5from Sastrawi.Stemmer.StemmerFactory import StemmerFactory
6from fastapi.middleware.cors import CORSMiddleware
7import sqlite3
8from datetime import datetime
9from fastapi.responses import HTMLResponse
10
11app = FastAPI()
12
13app.add_middleware(
14 CORSMiddleware,
15 allow_origins=["*"],
16 allow_methods=["*"],
17 allow_headers=["*"],
18)
19
20# load model
21model = joblib.load("model_nb.pkl")
22vectorizer = joblib.load("tfidf.pkl")
23
24factory = StemmerFactory()
25stemmer = factory.create_stemmer()
26
27class TextRequest(BaseModel):
28 text: str
29
30def preprocess(text):
31 text = text.lower()
32 text = re.sub(r"[^a-zA-Z\s]", "", text)
33 text = stemmer.stem(text)
34 return text
35
36@app.post("/predict")
37def predict(req: TextRequest):
38 text_clean = preprocess(req.text)
39 X = vectorizer.transform([text_clean])
40
41 pred = model.predict(X)[0]
42 proba = model.predict_proba(X)[0]
43
44 labels = model.classes_
45 prob_dict = dict(zip(labels, proba))
46
47 return {
48 "input": req.text,
49 "clean_text": text_clean,
50 "prediction": pred,
51 "probability": prob_dict
52 }
53
54# ================= SIMULASI DASHBOARD SOS =================
55
56def init_db():
57 # check_same_thread=False agar tidak error saat dipanggil oleh berbagai thread FastAPI
58 conn = sqlite3.connect("sos.db", check_same_thread=False)
59 cursor = conn.cursor()
60 cursor.execute("""
61 CREATE TABLE IF NOT EXISTS sos_logs (
62 id INTEGER PRIMARY KEY AUTOINCREMENT,
63 latitude REAL,
64 longitude REAL,
65 timestamp TEXT
66 )
67 """)
68 conn.commit()
69 return conn
70
71db_conn = init_db()
72
73class SosRequestModel(BaseModel):
74 latitude: float
75 longitude: float
76
77@app.post("/sos")
78def receive_sos(req: SosRequestModel):
79 timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
80 cursor = db_conn.cursor()
81 cursor.execute("INSERT INTO sos_logs (latitude, longitude, timestamp) VALUES (?, ?, ?)",
82 (req.latitude, req.longitude, timestamp))
83 db_conn.commit()
84 return {"message": "SOS received successfully", "timestamp": timestamp}
85
86@app.get("/dashboard", response_class=HTMLResponse)
87def get_dashboard():
88 cursor = db_conn.cursor()
89 cursor.execute("SELECT latitude, longitude, timestamp FROM sos_logs ORDER BY id DESC")
90 logs = cursor.fetchall()
91
92 # Membangun script Javascript untuk pin koordinat di peta
93 markers_js = ""
94 for row in logs:
95 lat, lng, ts = row
96 markers_js += f"L.marker([{lat}, {lng}]).addTo(map).bindPopup('<b>🚨 SOS Alert!</b><br>Waktu: {ts}').openPopup();\n"
97
98 # Halaman web HTML sederhana dengan map Leaflet.js
99 html_content = f"""
100 <!DOCTYPE html>
101 <html>
102 <head>
103 <title>Dasbor Admin PK3D (Simulasi)</title>
104 <meta charset="utf-8" />
105 <meta name="viewport" content="width=device-width, initial-scale=1.0">
106 <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
107 <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
108 <style>
109 body {{ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 20px; background-color: #f8f9fa; }}
110 .header-card {{ background-color: #d32f2f; color: white; padding: 20px; border-radius: 10px; margin-bottom: 20px; text-align: center; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }}
111 h1 {{ margin: 0; font-size: 24px; }}
112 p {{ margin: 5px 0 0 0; opacity: 0.9; font-size: 14px; }}
113 #map {{ height: 600px; width: 100%; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); z-index: 1; }}
114 .container {{ max-width: 1200px; margin: auto; }}
115 </style>
116 </head>
117 <body>
118 <div class="container">
119 <div class="header-card">
120 <h1>🚨 DASBOR PUSAT KENDALI DARURAT (PK3D)</h1>
121 <p>Pemantauan Sinyal Panggilan Darurat Medis Secara Real-Time</p>
122 </div>
123 <div id="map"></div>
124 </div>
125 <script>
126 // Titik awal peta difokuskan ke Jakarta (bisa berubah otomatis kalau ada data)
127 var map = L.map('map').setView([-6.200000, 106.816666], 11);
128 L.tileLayer('https://{{s}}.tile.openstreetmap.org/{{z}}/{{x}}/{{y}}.png', {{
129 maxZoom: 19,
130 attribution: '© OpenStreetMap | Sistem Simulasi P3K'
131 }}).addTo(map);
132
133 // Injeksi koordinat dari Database SQLite
134 {markers_js}
135
136 // Logika untuk menggeser kamera peta agar mencakup semua marker
137 var bounds = [];
138 map.eachLayer(function(layer) {{
139 if (layer instanceof L.Marker) {{
140 bounds.push(layer.getLatLng());
141 }}
142 }});
143 if (bounds.length > 0) {{
144 map.fitBounds(bounds, {{padding: [50, 50]}});
145 }}
146 </script>
147 </body>
148 </html>
149 """
150 return HTMLResponse(content=html_content)