LevinAleksey commited on
Commit
6fdc6ff
·
verified ·
1 Parent(s): 77f8d78

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +64 -164
app.py CHANGED
@@ -1,173 +1,73 @@
1
  import streamlit as st
2
  import pandas as pd
3
  import plotly.express as px
4
- import plotly.graph_objects as go
5
  import json
6
- import datetime
7
 
8
- # --- КОНФИГУРАЦИЯ СТРАНИЦЫ ---
9
- st.set_page_config(
10
- page_title="Blockchain Contract Analytics",
11
- page_icon="📊",
12
- layout="wide",
13
- initial_sidebar_state="collapsed"
14
- )
15
-
16
- # Скрываем стандартное меню Streamlit для чистоты
17
- st.markdown("""
18
- <style>
19
- #MainMenu {visibility: hidden;}
20
- footer {visibility: hidden;}
21
- header {visibility: hidden;}
22
- </style>
23
- """, unsafe_allow_html=True)
24
 
25
  st.title("📊 Аналитика Смарт-Контракта")
26
 
27
- # --- ЗАГРУЗКА И ОБРАБОТКА ДАННЫХ ---
28
- @st.cache_data
29
- def load_and_process_data():
 
 
 
30
  try:
31
- with open('data.json', 'r') as f:
32
- raw_data = json.load(f)[0]
33
- except FileNotFoundError:
34
- return None, None, None, None
35
-
36
- # 1. Основные метрики
37
- metrics = {
38
- "total_tx": raw_data['total_tx_amount'],
39
- "tx_delta": raw_data['percentage_of_tx_prev_day'],
40
- "dau": raw_data['dau'],
41
- "dau_delta": raw_data['dau_comparison_prev_day'],
42
- "new_wallets": raw_data['new_wallets_amount'],
43
- "failed_tx": raw_data['failed_tx'],
44
- "contract": raw_data['contract_address'],
45
- "report_date": raw_data['datetime']
46
- }
47
-
48
- # 2. Данные когорт (линейный график)
49
- df_cohorts = pd.DataFrame(raw_data['users_by_cohorts'])
50
-
51
- # 3. Данные по дням (столбчатый график)
52
- # Парсим вложенный словарь txs_per_day_by_cohorts
53
- daily_records = []
54
- for date_str, cohorts in raw_data['txs_per_day_by_cohorts'].items():
55
- total_day_tx = sum(cohorts.values())
56
- daily_records.append({"Дата": date_str, "Транзакции": total_day_tx})
57
- df_daily = pd.DataFrame(daily_records)
58
- # Сортируем по дате, так как JSON может быть не упорядочен
59
- df_daily['Дата'] = pd.to_datetime(df_daily['Дата'])
60
- df_daily = df_daily.sort_values('Дата')
61
-
62
- # 4. Данные методов (круговая диаграмма)
63
- df_methods = pd.DataFrame(raw_data['method_amount'])
64
- # Упростим имя метода для легенды (берем до первой скобки)
65
- df_methods['method_label'] = df_methods['method_name'].apply(lambda x: x.split('(')[0])
66
-
67
- return metrics, df_cohorts, df_daily, df_methods
68
-
69
- metrics, df_cohorts, df_daily, df_methods = load_and_process_data()
70
-
71
- if metrics is None:
72
- st.error("❌ Файл data.json не найден. Пожалуйста, положите его в корневую папку приложения.")
73
- st.stop()
74
-
75
- # --- САЙДБАР (Информация) ---
76
- st.sidebar.markdown(f"**Контракт:**\n`{metrics['contract']}`")
77
- report_dt = datetime.datetime.strptime(metrics['report_date'], "%Y-%m-%d %H:%M:%S.%f%z")
78
- st.sidebar.write(f"**Дата отчета:** {report_dt.strftime('%d.%m.%Y %H:%M')}")
79
- st.sidebar.divider()
80
- st.sidebar.info("Дашборд работает автономно на базе статического JSON файла.")
81
-
82
- # --- ИНТЕРФЕЙС: РЯД 1 (KPI) ---
83
- col1, col2, col3, col4 = st.columns(4)
84
-
85
- with col1:
86
- st.metric(
87
- label="Всего транзакций",
88
- value=f"{metrics['total_tx']:,}",
89
- delta=f"{metrics['tx_delta']:.1f}% (24ч)"
90
- )
91
-
92
- with col2:
93
- st.metric(
94
- label="Активные пользователи (DAU)",
95
- value=f"{metrics['dau']:,}",
96
- delta=f"{metrics['dau_delta']:.1f}% (24ч)"
97
- )
98
-
99
- with col3:
100
- st.metric(
101
- label="Новые кошельки",
102
- value=f"{metrics['new_wallets']:,}"
103
- )
104
-
105
- with col4:
106
- success_rate = ((metrics['total_tx'] - metrics['failed_tx']) / metrics['total_tx']) * 100
107
- st.metric(
108
- label="Успешность (Success Rate)",
109
- value=f"{success_rate:.1f}%",
110
- delta=f"-{metrics['failed_tx']} ошибок",
111
- delta_color="inverse"
112
- )
113
-
114
- st.divider()
115
-
116
- # --- ИНТЕРФЕЙС: РЯД 2 (ГРАФИКИ) ---
117
- left_chart, right_chart = st.columns([2, 1])
118
-
119
- with left_chart:
120
- st.subheader("📈 Динамика активности по дням жизни (Cohorts)")
121
- # Красивый линейный график с областями
122
- fig_cohorts = px.area(
123
- df_cohorts,
124
- x='cohort_day',
125
- y='user_count',
126
- labels={'cohort_day': 'День жизни пользователя', 'user_count': 'Кол-во пользователей'},
127
- color_discrete_sequence=['#00CC96'] # Зеленый крипто-цвет
128
- )
129
- fig_cohorts.update_layout(
130
- hovermode="x unified",
131
- xaxis=dict(showgrid=False),
132
- yaxis=dict(showgrid=True, gridcolor='rgba(255,255,255,0.05)')
133
- )
134
- # Добавим пик
135
- peak_day = df_cohorts.loc[df_cohorts['user_count'].idxmax()]
136
- fig_cohorts.add_annotation(
137
- x=peak_day['cohort_day'], y=peak_day['user_count'],
138
- text="Аномальный пик", showarrow=True, arrowhead=1, ax=-50, ay=-30
139
- )
140
- st.plotly_chart(fig_cohorts, use_container_width=True, theme="streamlit")
141
-
142
- with right_chart:
143
- st.subheader("🧩 Используемые методы")
144
- # Донут-чарт (бублик)
145
- fig_methods = px.pie(
146
- df_methods,
147
- values='tx_count',
148
- names='method_label',
149
- hole=0.5,
150
- color_discrete_sequence=px.colors.qualitative.Pastel
151
- )
152
- fig_methods.update_traces(textposition='inside', textinfo='percent+label')
153
- fig_methods.update_layout(showlegend=False) # Скрываем легенду, так как имена длинные
154
- st.plotly_chart(fig_methods, use_container_width=True)
155
-
156
- st.divider()
157
-
158
- # --- ИНТЕРФЕЙС: РЯД 3 (ДЕТАЛИЗАЦИЯ) ---
159
- details_col, _ = st.columns([2, 1])
160
-
161
- with details_col:
162
- st.subheader("📅 Сравнение транзакций по календарным датам")
163
- # Бар-чарт
164
- fig_daily = px.bar(
165
- df_daily,
166
- x='Дата',
167
- y='Транзакции',
168
- text_auto='.2s',
169
- color_discrete_sequence=['#636EFA']
170
- )
171
- # Настройка оси X, чтобы показывала только дни
172
- fig_daily.update_xaxes(dtick="86400000.0", tickformat="%d %b")
173
- st.plotly_chart(fig_daily, use_container_width=True)
 
1
  import streamlit as st
2
  import pandas as pd
3
  import plotly.express as px
 
4
  import json
5
+ import os
6
 
7
+ # Базовая настройка для работы в облаке
8
+ st.set_page_config(page_title="Blockchain Analytics", layout="wide")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
  st.title("📊 Аналитика Смарт-Контракта")
11
 
12
+ def load_data():
13
+ file_path = 'data.json'
14
+ if not os.path.exists(file_path):
15
+ st.error(f"❌ Файл {file_path} не найден!")
16
+ return None
17
+
18
  try:
19
+ with open(file_path, 'r') as f:
20
+ data = json.load(f)
21
+ # Твой JSON обернут в список [ {...} ], вытаскиваем первый элемент
22
+ if isinstance(data, list) and len(data) > 0:
23
+ return data[0]
24
+ return data
25
+ except Exception as e:
26
+ st.error(f"❌ Ошибка парсинга JSON: {e}")
27
+ return None
28
+
29
+ data = load_data()
30
+
31
+ if data:
32
+ # 1. KPI Секция
33
+ col1, col2, col3, col4 = st.columns(4)
34
+ col1.metric("Total TX", f"{data.get('total_tx_amount', 0):,}")
35
+ col2.metric("DAU", f"{data.get('dau', 0):,}")
36
+ col3.metric("New Wallets", f"{data.get('new_wallets_amount', 0):,}")
37
+ col4.metric("Failed TX", data.get('failed_tx', 0))
38
+
39
+ st.divider()
40
+
41
+ # 2. Графики
42
+ c1, c2 = st.columns(2)
43
+
44
+ with c1:
45
+ st.subheader("Активность по дням жизни (Когорты)")
46
+ df_cohorts = pd.DataFrame(data.get('users_by_cohorts', []))
47
+ if not df_cohorts.empty:
48
+ fig1 = px.line(df_cohorts, x='cohort_day', y='user_count', markers=True, template="plotly_dark")
49
+ st.plotly_chart(fig1, use_container_width=True)
50
+
51
+ with c2:
52
+ st.subheader("Методы контракта")
53
+ df_methods = pd.DataFrame(data.get('method_amount', []))
54
+ if not df_methods.empty:
55
+ # Обрезаем длинное название метода для красоты
56
+ df_methods['name'] = df_methods['method_name'].str.split('(').str[0]
57
+ fig2 = px.pie(df_methods, values='tx_count', names='name', hole=0.4)
58
+ st.plotly_chart(fig2, use_container_width=True)
59
+
60
+ # 3. Динамика по датам
61
+ st.subheader("Транзакции по календарным дням")
62
+ daily_data = []
63
+ tx_by_day = data.get('txs_per_day_by_cohorts', {})
64
+ for date, cohorts in tx_by_day.items():
65
+ daily_data.append({"date": date, "tx_count": sum(cohorts.values())})
66
+
67
+ if daily_data:
68
+ df_daily = pd.DataFrame(daily_data).sort_values('date')
69
+ fig3 = px.bar(df_daily, x='date', y='tx_count', color_discrete_sequence=['#00CC96'])
70
+ st.plotly_chart(fig3, use_container_width=True)
71
+
72
+ else:
73
+ st.info("Ожидание данных...")