"""GenericAgent · Three donut (pie) charts of tool-usage distribution.

Reproduction of GenericAgent Figure 3 (Tool usage distribution across
Claude Code, OpenClaw, and GenericAgent).
Source: GenericAgent: A Token-Efficient Self-Evolving LLM Agent via
Contextual Information Density Maximization, arXiv:2604.17091.

Each donut summarises the proportion of tool calls attributed to each
major tool category in the corresponding agent system. The hollow centre
keeps the layout light; tiny slices have leader-line callouts.
"""

import matplotlib.pyplot as plt
import numpy as np

plt.rcParams.update({
    "font.family": "sans-serif",
    "font.sans-serif": ["DejaVu Sans", "Arial"],
})

PALETTE = ["#A8D0E6", "#3F88C5", "#A6D8A8", "#5DAE5D",
           "#F4D58D", "#EFAB6E", "#9C9C9C"]

CLAUDE_CODE = {
    "title": "Claude Code",
    "labels": ["AgentTool", "BashTool", "FileReadTool", "FileWriteTool",
               "WebFetchTool", "WebSearchTool", "others(47)"],
    "values": [50.4, 22.1, 10.6, 8.9, 7.1, 0.9, 0.0],
}
OPENCLAW = {
    "title": "OpenClaw",
    "labels": ["browser", "web_fetch", "exec", "read",
               "write", "process", "others(16)"],
    "values": [32.5, 15.7, 20.5, 14.5, 9.6, 7.2, 0.0],
}
GENERICAGENT = {
    "title": "GenericAgent",
    "labels": ["file_read", "file_write", "code_run", "web_scan",
               "web_execute_js", "update_working_checkpoint", "others(2)"],
    "values": [31.2, 3.1, 34.4, 17.2, 10.9, 0.0, 3.1],
}

CHARTS = [CLAUDE_CODE, OPENCLAW, GENERICAGENT]

fig, axes = plt.subplots(1, 3, figsize=(13, 5.2))

def draw_donut(ax, data):
    sizes = [v if v > 0 else 1e-3 for v in data["values"]]

    wedges, _ = ax.pie(
        sizes,
        startangle=90,
        counterclock=False,
        colors=PALETTE[: len(sizes)],
        wedgeprops=dict(width=0.36, edgecolor="white", linewidth=1.2),
    )

    for w, label, v in zip(wedges, data["labels"], data["values"]):
        ang = (w.theta2 + w.theta1) / 2.0
        x = np.cos(np.deg2rad(ang))
        y = np.sin(np.deg2rad(ang))
        if v < 1.0:
            xt = 1.25 * x
            yt = 1.25 * y
            ax.annotate(
                f"{label}: {v:.1f}%".replace(".0%", "%"),
                xy=(0.82 * x, 0.82 * y),
                xytext=(xt, yt),
                ha="center" if abs(x) < 0.3 else ("left" if x > 0 else "right"),
                va="center", fontsize=9,
                arrowprops=dict(arrowstyle="-", color="#666", lw=0.7),
            )
        else:
            ax.text(0.82 * x, 0.82 * y, f"{v:.1f}%",
                    ha="center", va="center", fontsize=10,
                    color="#222", fontweight="normal")

    ax.set_title(data["title"], fontsize=12, pad=18)

    legend_handles = [plt.Rectangle((0, 0), 1, 1, color=PALETTE[i])
                      for i in range(len(data["labels"]))]
    ax.legend(legend_handles, data["labels"],
              loc="upper center", bbox_to_anchor=(0.5, -0.05),
              ncol=2, fontsize=8.5, frameon=False, handlelength=1.2)

for ax, data in zip(axes, CHARTS):
    draw_donut(ax, data)

plt.subplots_adjust(left=0.04, right=0.96, top=0.92, bottom=0.18, wspace=0.4)

plt.savefig("genericagent_tool_donut.png", dpi=300, bbox_inches="tight",
            facecolor="white")
plt.close()
print("saved: genericagent_tool_donut.png")
