rafaldembski commited on
Commit
2bc78fb
verified
1 Parent(s): 2e9428f

Update pages/Statistics.py

Browse files
Files changed (1) hide show
  1. pages/Statistics.py +117 -81
pages/Statistics.py CHANGED
@@ -14,14 +14,8 @@ import requests
14
  # Importowanie funkcji z utils/functions.py
15
  from utils.functions import get_phone_info, get_stats, get_history, get_fake_numbers
16
 
17
- # Opcjonalne: Importowanie dodatkowych komponent贸w
18
  from streamlit_extras.metric_cards import style_metric_cards
19
- from streamlit_elements import elements, mui, html
20
-
21
- # Definiowanie 艣cie偶ek do plik贸w JSON
22
- FAKE_NUMBERS_FILE = os.path.join('data', 'fake_numbers.json')
23
- HISTORY_FILE = os.path.join('data', 'history.json')
24
- STATS_FILE = os.path.join('data', 'stats.json')
25
 
26
  # Definiowanie t艂umacze艅 dla zak艂adki "Statystyki"
27
  page_translations = {
@@ -67,7 +61,7 @@ page_translations = {
67
  'no_data': "Keine Daten zur Anzeige verf眉gbar.",
68
  'download_button': "馃摜 Daten als CSV herunterladen",
69
  'select_date_range': "W盲hle einen Datumsbereich:",
70
- 'recent_days': 30 # Domy艣lny zakres dat
71
  },
72
  'English': {
73
  'page_title': "馃搳 Statistics",
@@ -89,19 +83,94 @@ page_translations = {
89
  'no_data': "No data available to display.",
90
  'download_button': "馃摜 Download data as CSV",
91
  'select_date_range': "Select date range:",
92
- 'recent_days': 30 # Default date range
93
  }
94
  }
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  def main(language):
97
  translations = page_translations.get(language, page_translations['English'])
98
 
 
 
 
 
 
 
99
  st.title(translations['header'])
100
  st.markdown(translations['description'])
101
 
102
  # Pobieranie danych z plik贸w JSON
103
- stats = get_stats()
104
- history = get_history()
 
 
 
 
105
 
106
  # Kluczowe metryki
107
  total_analyses = stats.get("total_analyses", 0)
@@ -122,29 +191,39 @@ def main(language):
122
 
123
  st.markdown("---")
124
 
125
- # Dodanie interaktywnego filtra daty w bocznym panelu
126
- st.sidebar.header(translations['select_date_range'])
127
- start_date = st.sidebar.date_input(
128
- "Start Date",
129
- value=datetime.now().date() - timedelta(days=translations['recent_days']),
130
- min_value=datetime.now().date() - timedelta(days=365),
131
- max_value=datetime.now().date()
132
- )
133
- end_date = st.sidebar.date_input(
134
- "End Date",
135
- value=datetime.now().date(),
136
- min_value=start_date,
137
- max_value=datetime.now().date()
138
- )
 
 
 
 
139
 
140
  # Filtracja historii na podstawie daty
141
  if history:
142
- df_history = pd.DataFrame(history)
143
- # Upewnij si臋, 偶e 'timestamp' jest w formacie datetime
144
- df_history['timestamp'] = pd.to_datetime(df_history['timestamp'])
145
- # Filtracja na podstawie daty
146
- mask = (df_history['timestamp'].dt.date >= start_date) & (df_history['timestamp'].dt.date <= end_date)
147
- df_filtered = df_history.loc[mask]
 
 
 
 
 
 
148
 
149
  # Wy艣wietlenie tabeli historii analiz
150
  st.markdown(f"### {translations['history_title']}")
@@ -188,9 +267,9 @@ def main(language):
188
  # Trend oszustw w czasie
189
  st.markdown("### " + translations['frauds_over_time'])
190
  fraud_over_time = df_filtered.groupby(df_filtered['timestamp'].dt.date)['phone_number'].count().reset_index()
191
- fraud_over_time.rename(columns={'phone_number': 'frauds_detected'}, inplace=True)
192
- fig_trend = px.line(fraud_over_time, x='timestamp', y='frauds_detected', title=translations['frauds_over_time'],
193
- labels={'timestamp': 'Date', 'frauds_detected': 'Frauds Detected'}, markers=True)
194
  fig_trend.update_traces(line=dict(color='firebrick'))
195
  st.plotly_chart(fig_trend, use_container_width=True)
196
 
@@ -219,7 +298,7 @@ def main(language):
219
  fraud_countries.columns = ['country', 'counts']
220
 
221
  # Dodanie kod贸w kraj贸w
222
- fraud_countries['iso_alpha'] = fraud_countries['country'].apply(lambda x: pycountry.countries.lookup(x).alpha_3 if x != "Unknown" else None)
223
  fraud_countries = fraud_countries.dropna(subset=['iso_alpha'])
224
 
225
  if not fraud_countries.empty:
@@ -238,52 +317,6 @@ def main(language):
238
 
239
  st.markdown("---")
240
 
241
- # Dodatkowe Wizualizacje
242
- st.markdown("### " + translations['heatmap_title'])
243
- # Heatmapa oszustw na podstawie lokalizacji
244
- if not fraud_countries.empty:
245
- # Przygotowanie danych geograficznych
246
- # U偶yjemy szeroko艣ci i d艂ugo艣ci geograficznej kraj贸w
247
- country_coords = {}
248
- for country in fraud_countries['country'].unique():
249
- if country == "Unknown":
250
- country_coords[country] = (0, 0) # Centrum 艣wiata
251
- else:
252
- try:
253
- country_obj = pycountry.countries.lookup(country)
254
- # U偶yjemy 艣rednich szeroko艣ci i d艂ugo艣ci geograficznej
255
- geocode_url = f"https://restcountries.com/v3.1/name/{country}"
256
- response = requests.get(geocode_url)
257
- if response.status_code == 200:
258
- data = response.json()
259
- lat = data[0]['latlng'][0]
260
- lon = data[0]['latlng'][1]
261
- country_coords[country] = (lat, lon)
262
- else:
263
- country_coords[country] = (0, 0)
264
- except:
265
- country_coords[country] = (0, 0)
266
-
267
- fraud_countries['lat'] = fraud_countries['country'].apply(lambda x: country_coords.get(x, (0,0))[0])
268
- fraud_countries['lon'] = fraud_countries['country'].apply(lambda x: country_coords.get(x, (0,0))[1])
269
-
270
- # Tworzenie Heatmapy
271
- fig_heatmap = px.density_mapbox(
272
- fraud_countries,
273
- lat='lat',
274
- lon='lon',
275
- z='counts',
276
- radius=10,
277
- center=dict(lat=20, lon=0),
278
- zoom=1,
279
- mapbox_style="stamen-terrain",
280
- title=translations['heatmap_title']
281
- )
282
- fig_heatmap.update_geos(showcountries=True, showcoastlines=True)
283
- st.plotly_chart(fig_heatmap, use_container_width=True)
284
- else:
285
- st.info(translations['no_data'])
286
-
287
  # Gauge Chart - Procentowy udzia艂 oszustw
288
  st.markdown("### " + translations['fraud_percentage'])
289
  fig_gauge = go.Figure(go.Indicator(
@@ -308,3 +341,6 @@ def main(language):
308
  }
309
  ))
310
  st.plotly_chart(fig_gauge, use_container_width=True)
 
 
 
 
14
  # Importowanie funkcji z utils/functions.py
15
  from utils.functions import get_phone_info, get_stats, get_history, get_fake_numbers
16
 
17
+ # Importowanie dodatkowych komponent贸w
18
  from streamlit_extras.metric_cards import style_metric_cards
 
 
 
 
 
 
19
 
20
  # Definiowanie t艂umacze艅 dla zak艂adki "Statystyki"
21
  page_translations = {
 
61
  'no_data': "Keine Daten zur Anzeige verf眉gbar.",
62
  'download_button': "馃摜 Daten als CSV herunterladen",
63
  'select_date_range': "W盲hle einen Datumsbereich:",
64
+ 'recent_days': 30
65
  },
66
  'English': {
67
  'page_title': "馃搳 Statistics",
 
83
  'no_data': "No data available to display.",
84
  'download_button': "馃摜 Download data as CSV",
85
  'select_date_range': "Select date range:",
86
+ 'recent_days': 30
87
  }
88
  }
89
 
90
+ # Mapowanie polskich nazw kraj贸w na kody ISO alfa-3
91
+ country_name_mapping = {
92
+ 'niemcy': 'DEU', # Niemcy
93
+ 'polska': 'POL', # Polska
94
+ 'francja': 'FRA', # Francja
95
+ 'w艂ochy': 'ITA', # W艂ochy
96
+ 'hiszpania': 'ESP', # Hiszpania
97
+ 'stany zjednoczone': 'USA', # USA
98
+ 'wielka brytania': 'GBR', # Wielka Brytania
99
+ 'unknown': None,
100
+ 'nieznany': None
101
+ # Dodaj inne kraje w razie potrzeby
102
+ }
103
+
104
+ def get_iso_alpha3(country_name):
105
+ country_code = country_name_mapping.get(country_name.lower())
106
+ if country_code:
107
+ return country_code
108
+ else:
109
+ # Je艣li nie znaleziono w mapowaniu, spr贸buj u偶y膰 pycountry
110
+ try:
111
+ country = pycountry.countries.lookup(country_name)
112
+ return country.alpha_3
113
+ except LookupError:
114
+ return None
115
+
116
+ def set_theme_variables():
117
+ if st.get_option("theme.base") == "dark":
118
+ background_color = "#31333F" # Kolor t艂a dla trybu ciemnego
119
+ text_color = "#FFFFFF"
120
+ border_color = "#4A4A4A"
121
+ else:
122
+ background_color = "#FFFFFF" # Kolor t艂a dla trybu jasnego
123
+ text_color = "#000000"
124
+ border_color = "#E0E0E0"
125
+
126
+ custom_css = f"""
127
+ <style>
128
+ :root {{
129
+ --background-color: {background_color};
130
+ --text-color: {text_color};
131
+ --border-color: {border_color};
132
+ }}
133
+ </style>
134
+ """
135
+ st.markdown(custom_css, unsafe_allow_html=True)
136
+
137
+ def inject_custom_css():
138
+ custom_css = """
139
+ <style>
140
+ /* Stylizacja kart metryk dla obu motyw贸w */
141
+ [data-testid="metric-container"] {{
142
+ background-color: var(--background-color);
143
+ padding: 1rem;
144
+ border-radius: 0.5rem;
145
+ border: 1px solid var(--border-color);
146
+ box-shadow: 0px 2px 4px rgba(0,0,0,0.1);
147
+ }}
148
+ [data-testid="stMetricLabel"], [data-testid="stMetricValue"] {{
149
+ color: var(--text-color);
150
+ }}
151
+ </style>
152
+ """
153
+ st.markdown(custom_css, unsafe_allow_html=True)
154
+
155
  def main(language):
156
  translations = page_translations.get(language, page_translations['English'])
157
 
158
+ # Ustawienie zmiennych motywu
159
+ set_theme_variables()
160
+
161
+ # Wstrzykni臋cie niestandardowego CSS
162
+ inject_custom_css()
163
+
164
  st.title(translations['header'])
165
  st.markdown(translations['description'])
166
 
167
  # Pobieranie danych z plik贸w JSON
168
+ try:
169
+ stats = get_stats()
170
+ history = get_history()
171
+ except Exception as e:
172
+ st.error(f"Wyst膮pi艂 b艂膮d podczas pobierania danych: {e}")
173
+ st.stop()
174
 
175
  # Kluczowe metryki
176
  total_analyses = stats.get("total_analyses", 0)
 
191
 
192
  st.markdown("---")
193
 
194
+ # Dodanie interaktywnego filtra daty w g艂贸wnym obszarze
195
+ st.header(translations['select_date_range'])
196
+ try:
197
+ start_date = st.date_input(
198
+ translations['select_date_range'] + " - " + "Start",
199
+ value=datetime.now().date() - timedelta(days=translations['recent_days']),
200
+ min_value=datetime.now().date() - timedelta(days=365),
201
+ max_value=datetime.now().date()
202
+ )
203
+ end_date = st.date_input(
204
+ translations['select_date_range'] + " - " + "End",
205
+ value=datetime.now().date(),
206
+ min_value=start_date,
207
+ max_value=datetime.now().date()
208
+ )
209
+ except Exception as e:
210
+ st.error(f"Wyst膮pi艂 b艂膮d przy wyborze daty: {e}")
211
+ st.stop()
212
 
213
  # Filtracja historii na podstawie daty
214
  if history:
215
+ try:
216
+ df_history = pd.DataFrame(history)
217
+ # Upewnij si臋, 偶e 'timestamp' jest w formacie datetime
218
+ df_history['timestamp'] = pd.to_datetime(df_history['timestamp'], errors='coerce')
219
+ # Usuni臋cie wpis贸w z b艂臋dnymi datami
220
+ df_history = df_history.dropna(subset=['timestamp'])
221
+ # Filtracja na podstawie daty
222
+ mask = (df_history['timestamp'].dt.date >= start_date) & (df_history['timestamp'].dt.date <= end_date)
223
+ df_filtered = df_history.loc[mask]
224
+ except Exception as e:
225
+ st.error(f"Wyst膮pi艂 b艂膮d podczas filtrowania danych: {e}")
226
+ st.stop()
227
 
228
  # Wy艣wietlenie tabeli historii analiz
229
  st.markdown(f"### {translations['history_title']}")
 
267
  # Trend oszustw w czasie
268
  st.markdown("### " + translations['frauds_over_time'])
269
  fraud_over_time = df_filtered.groupby(df_filtered['timestamp'].dt.date)['phone_number'].count().reset_index()
270
+ fraud_over_time.rename(columns={'timestamp': 'Date', 'phone_number': 'Frauds Detected'}, inplace=True)
271
+ fig_trend = px.line(fraud_over_time, x='Date', y='Frauds Detected', title=translations['frauds_over_time'],
272
+ labels={'Date': 'Date', 'Frauds Detected': 'Frauds Detected'}, markers=True)
273
  fig_trend.update_traces(line=dict(color='firebrick'))
274
  st.plotly_chart(fig_trend, use_container_width=True)
275
 
 
298
  fraud_countries.columns = ['country', 'counts']
299
 
300
  # Dodanie kod贸w kraj贸w
301
+ fraud_countries['iso_alpha'] = fraud_countries['country'].apply(lambda x: get_iso_alpha3(x) if x != "Unknown" else None)
302
  fraud_countries = fraud_countries.dropna(subset=['iso_alpha'])
303
 
304
  if not fraud_countries.empty:
 
317
 
318
  st.markdown("---")
319
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
320
  # Gauge Chart - Procentowy udzia艂 oszustw
321
  st.markdown("### " + translations['fraud_percentage'])
322
  fig_gauge = go.Figure(go.Indicator(
 
341
  }
342
  ))
343
  st.plotly_chart(fig_gauge, use_container_width=True)
344
+
345
+ else:
346
+ st.info(translations['no_data'])