From c16a8cb7a5166ee64438b64882d1731ad08bcd1d Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Mon, 25 May 2026 20:15:43 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20Polymarket=20=E6=B8=85?= =?UTF-8?q?=E7=90=86=E5=90=8E=E7=9A=84=E5=AF=BC=E5=85=A5=E9=94=99=E8=AF=AF?= =?UTF-8?q?=EF=BC=9Aanalysis=5Fservice=20=E7=A7=BB=E9=99=A4=20city=5Fpaylo?= =?UTF-8?q?ads=20market=5Fscan=20=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/analysis_service.py | 32 ++++++++--------- web/routers/city.py | 60 ------------------------------- web/scan_terminal_city_row.py | 62 ++------------------------------ web/services/city_api.py | 67 ++--------------------------------- 4 files changed, 20 insertions(+), 201 deletions(-) diff --git a/web/analysis_service.py b/web/analysis_service.py index aab387bc..8e5416cf 100644 --- a/web/analysis_service.py +++ b/web/analysis_service.py @@ -32,8 +32,7 @@ from src.data_collection.city_time import get_city_utc_offset_seconds from src.database.runtime_state import IntradayPathSnapshotRepository from web.services.city_payloads import ( build_city_detail_payload as _city_payload_detail, - build_city_market_scan_payload as _city_payload_market_scan, - build_city_summary_payload as _city_payload_summary, + build_city_summary_payload as _city_payload_summary ) from web.services.observation_freshness import ( build_observation_freshness as _build_observation_freshness, @@ -2054,20 +2053,6 @@ def _build_city_summary_payload(data: Dict[str, Any]) -> Dict[str, Any]: return _city_payload_summary(data) -def _build_city_market_scan_payload( - data: Dict[str, Any], - market_slug: Optional[str] = None, - target_date: Optional[str] = None, - lite: bool = False, - scan_filters: Optional[Dict[str, Any]] = None, -) -> Dict[str, Any]: - return _city_payload_market_scan( - data, - market_slug=market_slug, - target_date=target_date, - lite=lite, - scan_filters=scan_filters, - ) def _build_city_detail_payload( @@ -2086,3 +2071,18 @@ def _build_city_detail_payload( # ────────────────────────────────────────────────────────── # Routes # ────────────────────────────────────────────────────────── + +def _build_city_market_scan_payload( + data, + market_slug=None, + target_date=None, + lite=False, + scan_filters=None, +): + local_date = str(data.get("local_date") or "").strip() + return { + "market_scan": {"available": False}, + "selected_date": target_date or local_date, + "fetched_at": data.get("updated_at"), + } + diff --git a/web/routers/city.py b/web/routers/city.py index d876ff7d..fc1d687b 100644 --- a/web/routers/city.py +++ b/web/routers/city.py @@ -7,7 +7,6 @@ from fastapi import APIRouter, BackgroundTasks, Query, Request from web.services.city_api import ( get_city_detail_aggregate_payload, get_city_detail_payload, - get_city_market_scan_payload, get_city_summary_payload, list_cities_payload, ) @@ -152,65 +151,6 @@ async def city_detail_aggregate( ) -@router.get("/api/city/{name}/market-scan") -async def city_market_scan( - request: Request, - background_tasks: BackgroundTasks, - name: str, - force_refresh: bool = False, - market_slug: Optional[str] = None, - target_date: Optional[str] = None, - lite: bool = False, -): - return await get_city_market_scan_payload( - request, - background_tasks, - name, - force_refresh=force_refresh, - market_slug=market_slug, - target_date=target_date, - lite=lite, - ) - - -@router.get("/api/city/{name}/holders") -async def city_holders( - name: str, - limit: int = 10, -): - """Return top token holders for a city's primary Polymarket market.""" - from web.services.city_payloads import _get_polymarket_layer - from web.analysis_service import _analyze - - layer = _get_polymarket_layer() - if not layer.enabled: - return {"holders": [], "available": False} - - data = _analyze(name, force_refresh=False, include_llm_commentary=False, detail_mode="market") - local_date = str(data.get("local_date") or "").strip() - if not local_date: - return {"holders": [], "available": False} - - scan = layer.build_market_scan( - city=name, - target_date=local_date, - include_related_buckets=False, - ) - if not scan.get("available"): - return {"holders": [], "available": False} - - condition_id = scan.get("selected_condition_id") - if not condition_id: - return {"holders": [], "available": False} - - holders = layer.get_market_holders(condition_id, limit=limit) - return { - "holders": holders, - "available": True, - "condition_id": condition_id, - } - - @router.get("/api/city/{name}/realtime-stream") async def city_realtime_stream(name: str): """Return a rolling window of recent temperature readings + market diff --git a/web/scan_terminal_city_row.py b/web/scan_terminal_city_row.py index 37515d06..98992033 100644 --- a/web/scan_terminal_city_row.py +++ b/web/scan_terminal_city_row.py @@ -5,7 +5,7 @@ from datetime import datetime, timedelta from typing import Any, Dict, List, Optional from web.core import CITIES -from web.analysis_service import _analyze, _build_city_market_scan_payload +from web.analysis_service import _analyze from web.scan_city_ai_helpers import _safe_float from web.scan_terminal_ai_compact import _build_metar_decision_context from web.scan_terminal_filters import ( @@ -139,65 +139,7 @@ def _scan_city_terminal_rows( *, force_refresh: bool = False, ) -> Dict[str, Any]: - # Quick mode: skip Polymarket matching, return cached analysis rows only - if filters.get("skip_polymarket"): - return _scan_city_terminal_rows_quick(city, filters, force_refresh=force_refresh) - - # Try cached analysis first; force-refresh if probability distribution is missing - data = _analyze( - city, - force_refresh=force_refresh, - include_llm_commentary=False, - detail_mode="market", - ) - probs = data.get("probabilities") or {} - if not probs.get("distribution") and not force_refresh: - data = _analyze( - city, - force_refresh=True, - include_llm_commentary=False, - detail_mode="market", - ) - target_dates = _resolve_time_range_dates(data, filters["time_range"]) - rows: List[Dict[str, Any]] = [] - primary_scores: List[float] = [] - candidate_total = 0 - - for target_date in target_dates: - payload = _build_city_market_scan_payload( - data, - market_slug=None, - target_date=target_date, - lite=True, - scan_filters=filters, - ) - scan = payload.get("market_scan") or {} - candidate_total += int(scan.get("candidate_count") or 0) - raw_rows = scan.get("scan_rows") - if not isinstance(raw_rows, list) or not raw_rows: - raw_rows = [scan.get("primary_signal")] if isinstance(scan.get("primary_signal"), dict) else [] - if not raw_rows: - continue - for raw_row in raw_rows: - if not isinstance(raw_row, dict) or not raw_row: - continue - row = _build_terminal_row( - city=city, - data=data, - scan=scan, - row=raw_row, - ) - rows.append(row) - score = _safe_float(row.get("final_score")) - if score is not None and row.get("is_primary_signal"): - primary_scores.append(score) - - return { - "city": city, - "rows": rows, - "candidate_total": candidate_total, - "primary_scores": primary_scores, - } + return _scan_city_terminal_rows_quick(city, filters, force_refresh=force_refresh) def _scan_city_terminal_rows_quick( diff --git a/web/services/city_api.py b/web/services/city_api.py index efe79256..ba41fe75 100644 --- a/web/services/city_api.py +++ b/web/services/city_api.py @@ -4,7 +4,7 @@ from __future__ import annotations from typing import Any, Dict, Optional -from fastapi import BackgroundTasks, HTTPException, Request +from fastapi import HTTPException, Request from fastapi.concurrency import run_in_threadpool from loguru import logger @@ -165,67 +165,4 @@ async def get_city_detail_aggregate_payload( ) -async def get_city_market_scan_payload( - request: Request, - background_tasks: BackgroundTasks, - name: str, - *, - force_refresh: bool = False, - market_slug: Optional[str] = None, - target_date: Optional[str] = None, - lite: bool = False, -) -> Dict[str, Any]: - legacy_routes._assert_entitlement(request) - city = legacy_routes._normalize_city_or_404(name) - if force_refresh: - data = await run_in_threadpool(legacy_routes._refresh_city_market_cache, city, True) - cached_scan = legacy_routes._get_cached_market_scan_payload( - data, - market_slug=market_slug, - target_date=target_date, - lite=lite, - ) - if cached_scan is not None: - return cached_scan - else: - cached_entry = await run_in_threadpool(legacy_routes._CACHE_DB.get_city_cache, "market", city) - if cached_entry: - data = cached_entry.get("payload") or {} - cached_scan = legacy_routes._get_cached_market_scan_payload( - data, - market_slug=market_slug, - target_date=target_date, - lite=lite, - ) - if cached_scan is not None: - if not legacy_routes._market_analysis_cache_is_fresh(cached_entry): - legacy_routes._schedule_cache_refresh(background_tasks, kind="market", city=city) - return cached_scan - if legacy_routes._market_analysis_cache_is_fresh(cached_entry): - return await run_in_threadpool( - legacy_routes._refresh_market_scan_payload_from_cached_analysis, - city, - data, - market_slug=market_slug, - target_date=target_date, - lite=lite, - ) - else: - legacy_routes._schedule_cache_refresh(background_tasks, kind="market", city=city) - else: - data = await run_in_threadpool(legacy_routes._refresh_city_market_cache, city, False) - cached_scan = legacy_routes._get_cached_market_scan_payload( - data, - market_slug=market_slug, - target_date=target_date, - lite=lite, - ) - if cached_scan is not None: - return cached_scan - return await run_in_threadpool( - legacy_routes._build_city_market_scan_payload, - data, - market_slug, - target_date, - lite, - ) +