import gradio as gr import random import json import fastapi from fastapi import FastAPI, Request import os import argilla as rg from functools import lru_cache import time import asyncio from fastapi.responses import HTMLResponse from fastapi.staticfiles import StaticFiles from fastapi.middleware.gzip import GZipMiddleware client = rg.Argilla( api_url=os.getenv("ARGILLA_API_URL", ""), api_key=os.getenv("ARGILLA_API_KEY", "") ) countries = { "Argentina": { "iso": "ARG", "emoji": "🇦🇷" }, "Bolivia": { "iso": "BOL", "emoji": "🇧🇴" }, "Chile": { "iso": "CHL", "emoji": "🇨🇱" }, "Colombia": { "iso": "COL", "emoji": "🇨🇴" }, "Costa Rica": { "iso": "CRI", "emoji": "🇨🇷" }, "Cuba": { "iso": "CUB", "emoji": "🇨🇺" }, "Ecuador": { "iso": "ECU", "emoji": "🇪🇨" }, "El Salvador": { "iso": "SLV", "emoji": "🇸🇻" }, "España": { "iso": "ESP", "emoji": "🇪🇸" }, "Guatemala": { "iso": "GTM", "emoji": "🇬🇹" }, "Honduras": { "iso": "HND", "emoji": "🇭🇳" }, "México": { "iso": "MEX", "emoji": "🇲🇽" }, "Nicaragua": { "iso": "NIC", "emoji": "🇳🇮" }, "Panamá": { "iso": "PAN", "emoji": "🇵🇦" }, "Paraguay": { "iso": "PRY", "emoji": "🇵🇾" }, "Perú": { "iso": "PER", "emoji": "🇵🇪" }, "Puerto Rico": { "iso": "PRI", "emoji": "🇵🇷" }, "República Dominicana": { "iso": "DOM", "emoji": "🇩🇴" }, "Uruguay": { "iso": "URY", "emoji": "🇺🇾" }, "Venezuela": { "iso": "VEN", "emoji": "🇻🇪" } } @lru_cache(maxsize=32) def count_answers_per_space_cached(country: str, cache_buster: int): return count_answers_per_space(country) def count_answers_per_space(country: str): iso = countries[country]["iso"] emoji = countries[country]["emoji"] dataset_name = f"{emoji} {country} - {iso} - Responder" try: dataset = client.datasets(dataset_name) records = list(dataset.records(with_responses=True)) total_questions = len(records) completed_questions = 0 total_answers = 0 # answers_per_user = {} for record in records: record = record.to_dict() responses = record["responses"] if record["status"] == "completed": # +1 completed questions completed_questions += 1 if "answer_1" in responses: answers = responses["answer_1"] total_answers += len(answers) # for answer in answers: # user_id = answer["user_id"] # answers_per_user[user_id] = answers_per_user.get(user_id, 0) + 1 percentage_complete = (completed_questions / total_questions * 100) if total_questions > 0 else 0 return { "name": country, "total_questions": total_questions, "answered_questions": completed_questions, "total_answers": total_answers, "percent": round(percentage_complete, 2), "documents": total_questions } except Exception as e: print(f"No dataset found for {dataset_name}: {e}") return { "name": country, "total_questions": 0, "answered_questions": 0, "total_answers": 0, "percent": 0, "documents": 0 } app = FastAPI() # gzip compression middleware reduces transferred data size app.add_middleware(GZipMiddleware, minimum_size=1000) last_update_time = time.time() cached_html_content = None @app.get("/d3-map") async def serve_map(request: Request, refresh: bool = False): global last_update_time, cached_html_content current_time = time.time() # use cached content if available and not expired (5 minute cache) if cached_html_content and current_time - last_update_time < 300 and not refresh: return HTMLResponse(content=cached_html_content) cache_buster = int(current_time) # use current time to bust cache when refresh=True country_data = {} for country in countries.keys(): country_data[countries[country]["iso"]] = count_answers_per_space_cached(country, cache_buster) country_data_json = json.dumps(country_data) with open('template.txt', 'r') as f: html_template = f.read() html_content = html_template.replace("COUNTRY_DATA_PLACEHOLDER", country_data_json) cached_html_content = html_content last_update_time = current_time return HTMLResponse(content=html_content) def create_iframe(refresh=False): param = f"refresh={str(refresh).lower()}&t={random.randint(1, 10000)}" return f'' with gr.Blocks(theme=gr.themes.Soft(primary_hue="pink", secondary_hue="purple")) as demo: gr.Markdown("# Mapa anotación") iframe_output = gr.HTML(create_iframe()) def refresh(): return create_iframe(refresh=True) gr.Button("Actualizar Datos").click(fn=refresh, outputs=iframe_output) gr.mount_gradio_app(app, demo, path="/") if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=7860)