dv/backend/services/chart-service/src/adapters/option_builders/map_builder.py

64 lines
1.8 KiB
Python

from __future__ import annotations
from collections import defaultdict
from typing import Any
from src.domain.entities.chart_instance import ChartInstance
from src.domain.entities.field_binding import FieldBinding
def _get_binding(bindings: list[FieldBinding], axis: str) -> FieldBinding | None:
for b in bindings:
if b.axis == axis:
return b
return None
def build_map_option(chart: ChartInstance, data: list[dict]) -> dict[str, Any]:
"""Geo map chart builder."""
region_bind = _get_binding(chart.bindings, "region")
val_bind = _get_binding(chart.bindings, "value")
if not region_bind or not val_bind:
return {"series": []}
groups: dict[str, list[float]] = defaultdict(list)
ordered: list[str] = []
for row in data:
region = str(row.get(region_bind.column_name, ""))
val = row.get(val_bind.column_name, 0)
if region not in ordered:
ordered.append(region)
if isinstance(val, (int, float)):
groups[region].append(val)
map_data = [
{"name": r, "value": sum(groups[r]) if groups[r] else 0}
for r in ordered
]
all_values = [d["value"] for d in map_data]
min_val = min(all_values) if all_values else 0
max_val = max(all_values) if all_values else 1
return {
"tooltip": {"trigger": "item"},
"visualMap": {
"min": min_val,
"max": max_val,
"left": "left",
"top": "bottom",
"text": ["High", "Low"],
"calculable": True,
},
"series": [
{
"type": "map",
"map": "china",
"roam": True,
"data": map_data,
"emphasis": {"label": {"show": True}},
}
],
}