64 lines
1.8 KiB
Python
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}},
|
|
}
|
|
],
|
|
}
|