File size: 2,485 Bytes
8ab6a5f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19b4563
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import re

import pandas as pd

from tasks.base_task import BaseTask


class CityRevenueShareTask(BaseTask):
    """Medium task: identify the city with the highest revenue and its percentage share.

    The agent must group by city, compute total revenue per city,
    find the top city, and calculate what percentage of overall revenue it represents.
    """

    @property
    def task_id(self) -> int:
        return 2

    @property
    def difficulty(self) -> str:
        return "medium"

    @property
    def description(self) -> str:
        return (
            "Which city generates the most revenue? What percentage of total revenue "
            "does it represent? Round to 2 decimal places. "
            "Submit your answer in the format: 'City: <name>, Percentage: <X.XX>%'"
        )

    def expected_answer(self) -> str:
        """Compute the top city and its revenue share.

        Returns:
            Formatted string like 'City: London, Percentage: 10.81%'.
        """
        city_rev = self.df.groupby("city")["total_price"].sum()
        top_city = city_rev.idxmax()
        pct = round(city_rev[top_city] / city_rev.sum() * 100, 2)
        return f"City: {top_city}, Percentage: {pct}%"

    def grade(self, answer: str) -> float:
        """Grade the answer with partial credit for city and percentage.

        Scoring:
            - 0.5 for correct city name (case-insensitive)
            - 0.5 for percentage within ±0.1 of expected

        Args:
            answer: The agent's submitted answer string.

        Returns:
            A score between 0.0 and 1.0.
        """
        score = 0.0
        city_rev = self.df.groupby("city")["total_price"].sum()
        expected_city = city_rev.idxmax()
        expected_pct = round(city_rev[expected_city] / city_rev.sum() * 100, 2)

        # Check city
        city_match = re.search(r"City:\s*([^,]+)", answer, re.IGNORECASE)
        if city_match:
            submitted_city = city_match.group(1).strip()
            if submitted_city.lower() == expected_city.lower():
                score += 0.5

        # Check percentage
        pct_match = re.search(r"Percentage:\s*([\d.]+)%?", answer, re.IGNORECASE)
        if pct_match:
            try:
                submitted_pct = float(pct_match.group(1))
                if abs(submitted_pct - expected_pct) <= 0.1:
                    score += 0.5
            except ValueError:
                pass

        return max(0.05, min(0.95, score))