Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -94,22 +94,21 @@ countries = {
|
|
94 |
"emoji": "๐ป๐ช"
|
95 |
}
|
96 |
}
|
|
|
97 |
@lru_cache(maxsize=32)
|
98 |
def get_user_contributions_cached(cache_buster: int):
|
99 |
return get_user_contributions()
|
100 |
|
101 |
def get_user_contributions():
|
102 |
-
"""
|
103 |
-
user_contributions = defaultdict(lambda: {"username": "", "contributions": 0, "datasets": {}})
|
104 |
user_id_to_username = {}
|
105 |
-
|
106 |
-
# Process each dataset
|
107 |
for country in countries.keys():
|
108 |
iso = countries[country]["iso"]
|
109 |
emoji = countries[country]["emoji"]
|
110 |
-
|
111 |
dataset_name = f"{emoji} {country} - {iso} - Responder"
|
112 |
-
|
113 |
try:
|
114 |
print(f"Processing dataset: {dataset_name}")
|
115 |
dataset = client.datasets(dataset_name)
|
@@ -137,63 +136,52 @@ def get_user_contributions():
|
|
137 |
username = user_id_to_username.get(user_id, f"User-{user_id[:8]}")
|
138 |
user_contributions[user_id]["username"] = username
|
139 |
user_contributions[user_id]["contributions"] += count
|
140 |
-
user_contributions[user_id]["
|
141 |
|
142 |
except Exception as e:
|
143 |
print(f"Error processing dataset {dataset_name}: {e}")
|
144 |
|
145 |
-
# Convert to dataframe for easier handling
|
146 |
rows = []
|
147 |
for user_id, data in user_contributions.items():
|
148 |
row = {
|
149 |
"Username": data["username"],
|
150 |
-
"Total
|
|
|
151 |
}
|
152 |
-
# Add individual dataset contributions
|
153 |
-
for dataset_name in DATASETS:
|
154 |
-
row[dataset_name] = data["datasets"].get(dataset_name, 0)
|
155 |
rows.append(row)
|
156 |
|
157 |
df = pd.DataFrame(rows)
|
158 |
|
159 |
-
# Sort by total contributions (descending)
|
160 |
if not df.empty:
|
161 |
-
df = df.sort_values("Total
|
162 |
|
163 |
return df
|
164 |
|
165 |
-
# App setup
|
166 |
app = FastAPI()
|
167 |
|
168 |
last_update_time = 0
|
169 |
cached_data = None
|
170 |
|
171 |
def create_leaderboard_ui():
|
172 |
-
"""Create the leaderboard UI"""
|
173 |
global cached_data, last_update_time
|
174 |
current_time = time.time()
|
175 |
|
176 |
-
# Use cached data if available and not expired (5 minute cache)
|
177 |
if cached_data is not None and current_time - last_update_time < 300:
|
178 |
df = cached_data
|
179 |
else:
|
180 |
-
# Fetch fresh data
|
181 |
cache_buster = int(current_time)
|
182 |
df = get_user_contributions_cached(cache_buster)
|
183 |
cached_data = df
|
184 |
last_update_time = current_time
|
185 |
|
186 |
-
# Add rank column
|
187 |
if not df.empty:
|
188 |
df = df.reset_index(drop=True)
|
189 |
df.index = df.index + 1
|
190 |
df = df.rename_axis("Rank")
|
191 |
df = df.reset_index()
|
192 |
|
193 |
-
# Format for better display
|
194 |
df_html = df.to_html(classes="leaderboard-table", border=0, index=False)
|
195 |
|
196 |
-
# Add some styling
|
197 |
styled_html = f"""
|
198 |
<div style="margin: 20px 0;">
|
199 |
<h2>๐ Leaderboard of User Contributions</h2>
|
@@ -202,84 +190,100 @@ def create_leaderboard_ui():
|
|
202 |
.leaderboard-table {{
|
203 |
width: 100%;
|
204 |
border-collapse: collapse;
|
205 |
-
font-family:
|
|
|
|
|
|
|
206 |
}}
|
207 |
.leaderboard-table th {{
|
208 |
-
background-color: #
|
209 |
-
color:
|
210 |
font-weight: bold;
|
211 |
text-align: left;
|
212 |
-
padding:
|
213 |
-
border-bottom: 2px solid #
|
214 |
}}
|
215 |
.leaderboard-table td {{
|
216 |
-
padding:
|
217 |
-
border-bottom: 1px solid #
|
218 |
}}
|
219 |
.leaderboard-table tr:nth-child(even) {{
|
220 |
-
background-color: #
|
|
|
|
|
|
|
221 |
}}
|
222 |
.leaderboard-table tr:hover {{
|
223 |
-
background-color: #
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
}}
|
225 |
-
.leaderboard-table tr:nth-child(1) td:first-child,
|
226 |
.leaderboard-table tr:nth-child(1) td:nth-child(2) {{
|
227 |
font-weight: bold;
|
228 |
-
color:
|
229 |
}}
|
230 |
-
.leaderboard-table tr:nth-child(2) td:first-child,
|
231 |
.leaderboard-table tr:nth-child(2) td:nth-child(2) {{
|
232 |
font-weight: bold;
|
233 |
-
color:
|
234 |
}}
|
235 |
-
.leaderboard-table tr:nth-child(3) td:first-child,
|
236 |
.leaderboard-table tr:nth-child(3) td:nth-child(2) {{
|
237 |
font-weight: bold;
|
238 |
-
color: #
|
239 |
}}
|
240 |
</style>
|
241 |
{df_html}
|
242 |
-
<p><small>Note: This leaderboard shows user contributions across all
|
243 |
</div>
|
244 |
"""
|
245 |
return styled_html
|
246 |
|
247 |
def refresh_data():
|
248 |
-
"""Force refresh of the data"""
|
249 |
global cached_data, last_update_time
|
250 |
cached_data = None
|
251 |
last_update_time = 0
|
252 |
return create_leaderboard_ui()
|
253 |
|
254 |
-
|
255 |
-
with gr.
|
256 |
-
gr.Markdown("# Contribution Leaderboard")
|
257 |
-
gr.Markdown("Track user contributions across datasets in real-time")
|
258 |
-
|
259 |
-
# Create leaderboard display
|
260 |
-
leaderboard_html = gr.HTML(create_leaderboard_ui)
|
261 |
-
|
262 |
-
# Add refresh button
|
263 |
-
refresh_btn = gr.Button("๐ Refresh Data")
|
264 |
-
refresh_btn.click(fn=refresh_data, outputs=leaderboard_html)
|
265 |
-
|
266 |
-
# Additional information
|
267 |
-
with gr.Accordion("About this leaderboard", open=False):
|
268 |
gr.Markdown("""
|
269 |
-
|
270 |
-
|
271 |
-
### How it works
|
272 |
-
- **Contributions**: Each response provided by a user counts as one contribution
|
273 |
-
- **Refresh**: Data is automatically cached for 5 minutes. Click the refresh button to update manually
|
274 |
-
- **Datasets tracked**:
|
275 |
-
- ๐ช๐ธ Espaรฑa - ESP - Responder
|
276 |
-
- [Add more datasets as needed]
|
277 |
""")
|
|
|
|
|
|
|
|
|
|
|
278 |
|
279 |
-
# Mount the Gradio app
|
280 |
gr.mount_gradio_app(app, demo, path="/")
|
281 |
|
282 |
-
# Run the app
|
283 |
if __name__ == "__main__":
|
284 |
import uvicorn
|
285 |
uvicorn.run(app, host="0.0.0.0", port=7860)
|
|
|
94 |
"emoji": "๐ป๐ช"
|
95 |
}
|
96 |
}
|
97 |
+
|
98 |
@lru_cache(maxsize=32)
|
99 |
def get_user_contributions_cached(cache_buster: int):
|
100 |
return get_user_contributions()
|
101 |
|
102 |
def get_user_contributions():
|
103 |
+
user_contributions = defaultdict(lambda: {"username": "", "contributions": 0, "country_contributions": {}})
|
|
|
104 |
user_id_to_username = {}
|
105 |
+
|
|
|
106 |
for country in countries.keys():
|
107 |
iso = countries[country]["iso"]
|
108 |
emoji = countries[country]["emoji"]
|
109 |
+
|
110 |
dataset_name = f"{emoji} {country} - {iso} - Responder"
|
111 |
+
|
112 |
try:
|
113 |
print(f"Processing dataset: {dataset_name}")
|
114 |
dataset = client.datasets(dataset_name)
|
|
|
136 |
username = user_id_to_username.get(user_id, f"User-{user_id[:8]}")
|
137 |
user_contributions[user_id]["username"] = username
|
138 |
user_contributions[user_id]["contributions"] += count
|
139 |
+
user_contributions[user_id]["country_contributions"][country] = count
|
140 |
|
141 |
except Exception as e:
|
142 |
print(f"Error processing dataset {dataset_name}: {e}")
|
143 |
|
|
|
144 |
rows = []
|
145 |
for user_id, data in user_contributions.items():
|
146 |
row = {
|
147 |
"Username": data["username"],
|
148 |
+
"Total": data["contributions"],
|
149 |
+
"Blend-es": data["contributions"]
|
150 |
}
|
|
|
|
|
|
|
151 |
rows.append(row)
|
152 |
|
153 |
df = pd.DataFrame(rows)
|
154 |
|
|
|
155 |
if not df.empty:
|
156 |
+
df = df.sort_values("Total", ascending=False)
|
157 |
|
158 |
return df
|
159 |
|
|
|
160 |
app = FastAPI()
|
161 |
|
162 |
last_update_time = 0
|
163 |
cached_data = None
|
164 |
|
165 |
def create_leaderboard_ui():
|
|
|
166 |
global cached_data, last_update_time
|
167 |
current_time = time.time()
|
168 |
|
|
|
169 |
if cached_data is not None and current_time - last_update_time < 300:
|
170 |
df = cached_data
|
171 |
else:
|
|
|
172 |
cache_buster = int(current_time)
|
173 |
df = get_user_contributions_cached(cache_buster)
|
174 |
cached_data = df
|
175 |
last_update_time = current_time
|
176 |
|
|
|
177 |
if not df.empty:
|
178 |
df = df.reset_index(drop=True)
|
179 |
df.index = df.index + 1
|
180 |
df = df.rename_axis("Rank")
|
181 |
df = df.reset_index()
|
182 |
|
|
|
183 |
df_html = df.to_html(classes="leaderboard-table", border=0, index=False)
|
184 |
|
|
|
185 |
styled_html = f"""
|
186 |
<div style="margin: 20px 0;">
|
187 |
<h2>๐ Leaderboard of User Contributions</h2>
|
|
|
190 |
.leaderboard-table {{
|
191 |
width: 100%;
|
192 |
border-collapse: collapse;
|
193 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
194 |
+
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
195 |
+
border-radius: 8px;
|
196 |
+
overflow: hidden;
|
197 |
}}
|
198 |
.leaderboard-table th {{
|
199 |
+
background-color: #1a1a2e;
|
200 |
+
color: white;
|
201 |
font-weight: bold;
|
202 |
text-align: left;
|
203 |
+
padding: 14px;
|
204 |
+
border-bottom: 2px solid #16213e;
|
205 |
}}
|
206 |
.leaderboard-table td {{
|
207 |
+
padding: 12px 14px;
|
208 |
+
border-bottom: 1px solid #e0e0e0;
|
209 |
}}
|
210 |
.leaderboard-table tr:nth-child(even) {{
|
211 |
+
background-color: #f8f9fa;
|
212 |
+
}}
|
213 |
+
.leaderboard-table tr:nth-child(odd) {{
|
214 |
+
background-color: white;
|
215 |
}}
|
216 |
.leaderboard-table tr:hover {{
|
217 |
+
background-color: #e7f5ff;
|
218 |
+
}}
|
219 |
+
.leaderboard-table tr:nth-child(1) {{
|
220 |
+
background-color: #fff7e6;
|
221 |
+
}}
|
222 |
+
.leaderboard-table tr:nth-child(2) {{
|
223 |
+
background-color: #f8f9fa;
|
224 |
+
}}
|
225 |
+
.leaderboard-table tr:nth-child(3) {{
|
226 |
+
background-color: #fff5f5;
|
227 |
+
}}
|
228 |
+
.leaderboard-table tr:nth-child(1) td:first-child {{
|
229 |
+
background-color: #ffd700;
|
230 |
+
color: #333;
|
231 |
+
font-weight: bold;
|
232 |
+
text-align: center;
|
233 |
+
border-right: 1px solid #e0e0e0;
|
234 |
+
}}
|
235 |
+
.leaderboard-table tr:nth-child(2) td:first-child {{
|
236 |
+
background-color: #c0c0c0;
|
237 |
+
color: #333;
|
238 |
+
font-weight: bold;
|
239 |
+
text-align: center;
|
240 |
+
border-right: 1px solid #e0e0e0;
|
241 |
+
}}
|
242 |
+
.leaderboard-table tr:nth-child(3) td:first-child {{
|
243 |
+
background-color: #cd7f32;
|
244 |
+
color: #333;
|
245 |
+
font-weight: bold;
|
246 |
+
text-align: center;
|
247 |
+
border-right: 1px solid #e0e0e0;
|
248 |
}}
|
|
|
249 |
.leaderboard-table tr:nth-child(1) td:nth-child(2) {{
|
250 |
font-weight: bold;
|
251 |
+
color: #333;
|
252 |
}}
|
|
|
253 |
.leaderboard-table tr:nth-child(2) td:nth-child(2) {{
|
254 |
font-weight: bold;
|
255 |
+
color: #333;
|
256 |
}}
|
|
|
257 |
.leaderboard-table tr:nth-child(3) td:nth-child(2) {{
|
258 |
font-weight: bold;
|
259 |
+
color: #333;
|
260 |
}}
|
261 |
</style>
|
262 |
{df_html}
|
263 |
+
<p><small>Note: This leaderboard shows user contributions to the BLEND-ES project across all countries.</small></p>
|
264 |
</div>
|
265 |
"""
|
266 |
return styled_html
|
267 |
|
268 |
def refresh_data():
|
|
|
269 |
global cached_data, last_update_time
|
270 |
cached_data = None
|
271 |
last_update_time = 0
|
272 |
return create_leaderboard_ui()
|
273 |
|
274 |
+
with gr.Blocks(theme=gr.themes.Base()) as demo:
|
275 |
+
with gr.Column(scale=1):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
276 |
gr.Markdown("""
|
277 |
+
# ๐ Hackaton Leaderboard
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
""")
|
279 |
+
|
280 |
+
leaderboard_html = gr.HTML(create_leaderboard_ui)
|
281 |
+
|
282 |
+
refresh_btn = gr.Button("๐ Refresh Data", variant="primary")
|
283 |
+
refresh_btn.click(fn=refresh_data, outputs=leaderboard_html)
|
284 |
|
|
|
285 |
gr.mount_gradio_app(app, demo, path="/")
|
286 |
|
|
|
287 |
if __name__ == "__main__":
|
288 |
import uvicorn
|
289 |
uvicorn.run(app, host="0.0.0.0", port=7860)
|