Files
service-finder/backend/app/workers/vehicle/robot_report.py
2026-03-22 11:02:05 +00:00

129 lines
7.2 KiB
Python

# /opt/docker/dev/service_finder/backend/app/workers/vehicle/robot_report.py
# docker exec sf_api python -m app.workers.vehicle.robot_report
import asyncio
import psutil
import pynvml
from datetime import datetime
from sqlalchemy import text
from sqlalchemy.ext.asyncio import create_async_engine
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.layout import Layout
from app.core.config import settings
console = Console()
async def get_data():
engine = create_async_engine(settings.DATABASE_URL)
async with engine.connect() as conn:
# Pipeline adatok (R1-R4)
pipe = await conn.execute(text("""
SELECT
(SELECT count(*) FROM vehicle.catalog_discovery WHERE status = 'pending') as r1,
(SELECT count(*) FROM vehicle.vehicle_model_definitions WHERE status = 'unverified') as r2,
(SELECT count(*) FROM vehicle.vehicle_model_definitions WHERE status = 'awaiting_ai_synthesis') as r3,
(SELECT count(*) FROM vehicle.vehicle_model_definitions WHERE status = 'gold_enriched') as r4
"""))
p_res = pipe.fetchone()
# AI Termelés
ai_hr = await conn.execute(text("SELECT count(*) FROM vehicle.vehicle_model_definitions WHERE status = 'gold_enriched' AND updated_at > NOW() - INTERVAL '1 hour'"))
ai_day = await conn.execute(text("SELECT count(*) FROM vehicle.vehicle_model_definitions WHERE status = 'gold_enriched' AND updated_at > NOW() - INTERVAL '24 hours'"))
# Market Matrix (1.3)
market_res = await conn.execute(text("SELECT vehicle_class, market, count(*) FROM vehicle.catalog_discovery GROUP BY 1, 2"))
m_data = market_res.fetchall()
# Robot Top listák (2.1 - 2.3)
r1_top = await conn.execute(text("SELECT make, count(*) FROM vehicle.catalog_discovery WHERE market = 'RDW' GROUP BY 1 ORDER BY 2 DESC LIMIT 5"))
r12_top = await conn.execute(text("SELECT make, count(*) FROM vehicle.catalog_discovery WHERE market = 'USA_IMPORT' GROUP BY 1 ORDER BY 2 DESC LIMIT 5"))
r14_top = await conn.execute(text("SELECT make, count(*) FROM vehicle.catalog_discovery WHERE vehicle_class = 'motorcycle' GROUP BY 1 ORDER BY 2 DESC LIMIT 5"))
# Általános Top (3.1 - 3.3)
pending_top = await conn.execute(text("SELECT make, count(*) FROM vehicle.catalog_discovery WHERE status = 'pending' GROUP BY 1 ORDER BY 2 DESC LIMIT 5"))
gold_top = await conn.execute(text("SELECT make, count(*) FROM vehicle.vehicle_model_definitions WHERE status = 'gold_enriched' GROUP BY 1 ORDER BY 2 DESC LIMIT 5"))
status_stats = await conn.execute(text("SELECT status, count(*) FROM vehicle.vehicle_model_definitions GROUP BY 1 ORDER BY 2 DESC LIMIT 5"))
# Kategória Top (4.1 - 4.3)
cat_tops = {}
for c in ['car', 'motorcycle', 'truck']:
res = await conn.execute(text(f"SELECT make, count(*) FROM vehicle.catalog_discovery WHERE vehicle_class = '{c}' GROUP BY 1 ORDER BY 2 DESC LIMIT 4"))
total = await conn.execute(text(f"SELECT count(*) FROM vehicle.catalog_discovery WHERE vehicle_class = '{c}'"))
cat_tops[c] = {"list": res.fetchall(), "total": total.scalar() or 0}
return {
"p": p_res, "ai": (ai_hr.scalar(), ai_day.scalar()), "markets": m_data,
"r1": r1_top.fetchall(), "r12": r12_top.fetchall(), "r14": r14_top.fetchall(),
"pending": pending_top.fetchall(), "gold": gold_top.fetchall(), "status": status_stats.fetchall(),
"cat": cat_tops
}
def get_hw():
try:
pynvml.nvmlInit()
h = pynvml.nvmlDeviceGetHandleByIndex(0)
info = pynvml.nvmlDeviceGetMemoryInfo(h)
return {"cpu": psutil.cpu_percent(), "ram": psutil.virtual_memory().percent, "gpu": pynvml.nvmlDeviceGetUtilizationRates(h).gpu,
"vram": f"{int(info.used/1024**2)}/{int(info.total/1024**2)}M", "temp": pynvml.nvmlDeviceGetTemperature(h, 0)}
except: return None
def mini_table(data, color="white"):
t = Table(show_header=False, box=None, expand=True, padding=(0,1))
t.add_column("L", ratio=3); t.add_column("R", justify="right", ratio=2)
for r in data: t.add_row(str(r[0])[:12], f"[{color}]{r[1]:,}[/]")
return t
async def main():
try:
d = await get_data(); hw = get_hw()
lay = Layout()
lay.split_column(Layout(name="head", size=3), Layout(name="body"))
lay["body"].split_column(Layout(name="row1"), Layout(name="row2"), Layout(name="row3"), Layout(name="row4"))
for r in ["row1", "row2", "row3", "row4"]:
lay[r].split_row(Layout(name=f"{r}1"), Layout(name=f"{r}2"), Layout(name=f"{r}3"))
# --- FEJLÉC ---
h_str = f"💻 CPU: {hw['cpu']}% | 🧠 RAM: {hw['ram']}% | 📟 VRAM: {hw['vram']} | 🔥 GPU: {hw['gpu']}% ({hw['temp']}°C)" if hw else "Hardware adatok nem elérhetőek"
lay["head"].update(Panel(h_str, title="[bold orange3]SZÁMÍTÓGÉP ADATOK[/]", style="orange3"))
# --- 1. SOR ---
r11_t = Table(show_header=False, box=None, expand=True)
r11_t.add_row("R1 (Hunter)", f"{d['p'][0]:,}"); r11_t.add_row("R2 (Res)", f"{d['p'][1]:,}")
r11_t.add_row("R3 (Wait)", f"{d['p'][2]:,}"); r11_t.add_row("R4 (Gold)", f"[green]{d['p'][3]:,}[/]")
r11_t.add_row("AI HR/DAY", f"[cyan]{d['ai'][0]}[/] / [yellow]{d['ai'][1]}[/]")
lay["row11"].update(Panel(r11_t, title="1.1 PIPE & AI"))
lay["row12"].update(Panel(mini_table(d['gold'], "green"), title="1.2 TOP MÁRKÁK"))
r13_t = Table(show_header=True, box=None, expand=True, header_style="bold blue")
r13_t.add_column("Típus", ratio=2); r13_t.add_column("EU", justify="right"); r13_t.add_column("USA", justify="right")
m_map = {c: {"EU": 0, "USA": 0} for c in ['car', 'motorcycle', 'truck', 'bus']}
for c, m, q in d['markets']:
key = 'USA' if m == 'USA_IMPORT' else 'EU'
if c in m_map: m_map[c][key] += q
for c, v in m_map.items(): r13_t.add_row(c[:4].upper(), f"{v['EU']:,}", f"{v['USA']:,}")
lay["row13"].update(Panel(r13_t, title="1.3 MARKET MATRIX"))
# --- 2. SOR (ROBOTOK) ---
lay["row21"].update(Panel(mini_table(d['r1']), title="2.1 ROBOT 1 (RDW)"))
lay["row22"].update(Panel(mini_table(d['r12']), title="2.2 ROBOT 1.2 (USA)"))
lay["row23"].update(Panel(mini_table(d['r14']), title="2.3 ROBOT 1.4 (BIKE)"))
# --- 3. SOR (ÖSSZESÍTŐ) ---
lay["row31"].update(Panel(mini_table(d['pending']), title="3.1 PENDING TOP"))
lay["row32"].update(Panel(mini_table(d['gold'], "green"), title="3.2 GOLD TOP", border_style="green"))
lay["row33"].update(Panel(mini_table(d['status'], "blue"), title="3.3 STATUS", border_style="blue"))
# --- 4. SOR (KATEGÓRIÁK) ---
for i, (k, l) in enumerate([('car', '4.1 AUTO'), ('motorcycle', '4.2 MOTOR'), ('truck', '4.3 TEHER')], 1):
t = mini_table(d['cat'][k]['list'], "yellow")
t.add_row("[bold]TOTAL[/]", f"[bold yellow]{d['cat'][k]['total']:,}[/]")
lay[f"row4{i}"].update(Panel(t, title=l, border_style="yellow"))
console.print(lay)
except Exception as e:
console.print(f"[bold red]HIBA TÖRTÉNT:[/] {e}")
if __name__ == "__main__":
asyncio.run(main())