mapa-blend-es / app.py
ouhenio's picture
Update app.py
2b09c8a verified
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'<iframe src="/d3-map?{param}" style="width:100%; height:650px; border:none;"></iframe>'
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)