File size: 2,939 Bytes
948d678
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Offline/simple tools: exact calculator and weather."""
import ast
import operator

import requests

_OPS = {ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul, ast.Div: operator.truediv,
        ast.FloorDiv: operator.floordiv, ast.Mod: operator.mod, ast.Pow: operator.pow,
        ast.USub: operator.neg, ast.UAdd: operator.pos}


def _eval(node):
    if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)):
        return node.value
    if isinstance(node, ast.BinOp) and type(node.op) in _OPS:
        if isinstance(node.op, ast.Pow) and abs(_eval(node.right)) > 1000:
            raise ValueError("exponent too large")
        return _OPS[type(node.op)](_eval(node.left), _eval(node.right))
    if isinstance(node, ast.UnaryOp) and type(node.op) in _OPS:
        return _OPS[type(node.op)](_eval(node.operand))
    raise ValueError("unsupported expression")


def calculator(expression: str) -> str:
    """Evaluate an arithmetic expression exactly. Supports + - * / // % ** and parentheses.

    Args:
        expression: The arithmetic expression, for example '(1500 * 18) / 100'.
    """
    try:
        expr = expression.replace("×", "*").replace("÷", "/").replace("^", "**").replace(",", "")
        r = _eval(ast.parse(expr, mode="eval").body)
        return str(round(r, 10) if isinstance(r, float) else r)
    except Exception as e:
        return f"Could not calculate: {e}"


def weather(place: str) -> str:
    """Get the current weather and a 3-day forecast for a town or city.

    Args:
        place: Town or city name, for example 'Aluva' or 'Kochi'.
    """
    try:
        g = requests.get("https://geocoding-api.open-meteo.com/v1/search", timeout=10,
                         params={"name": place, "count": 1}).json().get("results")
        if not g:
            return f"Place not found: {place}"
        g = g[0]
        w = requests.get("https://api.open-meteo.com/v1/forecast", timeout=10, params={
            "latitude": g["latitude"], "longitude": g["longitude"], "timezone": "auto", "forecast_days": 3,
            "current": "temperature_2m,relative_humidity_2m,precipitation,wind_speed_10m",
            "daily": "temperature_2m_max,temperature_2m_min,precipitation_sum,precipitation_probability_max"}).json()
        c, d = w["current"], w["daily"]
        lines = [f"{g['name']}, {g.get('admin1', '')}, {g.get('country', '')}",
                 f"Now: {c['temperature_2m']}°C, humidity {c['relative_humidity_2m']}%, "
                 f"rain {c['precipitation']} mm, wind {c['wind_speed_10m']} km/h"]
        for i, day in enumerate(d["time"]):
            lines.append(f"{day}: {d['temperature_2m_min'][i]}–{d['temperature_2m_max'][i]}°C, "
                         f"rain {d['precipitation_sum'][i]} mm ({d['precipitation_probability_max'][i]}%)")
        return "\n".join(lines)
    except Exception as e:
        return f"Weather lookup failed: {e}"