aboutsummaryrefslogtreecommitdiffstats
path: root/cogs/plot.py
diff options
context:
space:
mode:
authorsalmonik <raisersoft@proton.me>2026-04-18 00:29:07 +0200
committersalmonik <raisersoft@proton.me>2026-04-18 00:29:07 +0200
commit27724fc7756e61ed04a859698f10dee0248bd95e (patch)
treea1cf5c3b47eb391b35af60093d1128f9b2bc60a2 /cogs/plot.py
parentrefactor + preparing bot for public use (diff)
downloadsenator-sperma-27724fc7756e61ed04a859698f10dee0248bd95e.tar.gz
senator-sperma-27724fc7756e61ed04a859698f10dee0248bd95e.zip
add support for x^2+y^2=0,4 and alike
Signed-off-by: salmonik <raisersoft@proton.me>
Diffstat (limited to '')
-rw-r--r--cogs/plot.py61
1 files changed, 61 insertions, 0 deletions
diff --git a/cogs/plot.py b/cogs/plot.py
index 65dcae4..4fcde44 100644
--- a/cogs/plot.py
+++ b/cogs/plot.py
@@ -39,9 +39,22 @@ def parse_expression(expr: str) -> str:
39 expr = expr.replace("^", "**") 39 expr = expr.replace("^", "**")
40 expr = re.sub(r"(\d)([x])", r"\1*\2", expr) 40 expr = re.sub(r"(\d)([x])", r"\1*\2", expr)
41 expr = re.sub(r"([x])(\d)", r"\1*\2", expr) 41 expr = re.sub(r"([x])(\d)", r"\1*\2", expr)
42 expr = re.sub(r"(\d)([y])", r"\1*\2", expr)
43 expr = re.sub(r"([y])(\d)", r"\1*\2", expr)
42 return expr 44 return expr
43 45
44 46
47def is_implicit(expr: str) -> bool:
48 return "=" in expr and "y" in expr and "x" in expr
49
50
51def parse_implicit(expr: str) -> tuple[str, str]:
52 lhs, rhs = expr.split("=", 1)
53 lhs = parse_expression(lhs.strip())
54 rhs = parse_expression(rhs.strip())
55 return lhs, rhs
56
57
45class Plot(commands.Cog): 58class Plot(commands.Cog):
46 def __init__(self, bot): 59 def __init__(self, bot):
47 self.bot = bot 60 self.bot = bot
@@ -53,6 +66,11 @@ class Plot(commands.Cog):
53 raise RuntimeError("matplotlib not available") 66 raise RuntimeError("matplotlib not available")
54 67
55 plt = _plt_module 68 plt = _plt_module
69
70 if is_implicit(func_expr):
71 self._generate_implicit_plot(func_expr, output_path)
72 return
73
56 parsed_expr = parse_expression(func_expr) 74 parsed_expr = parse_expression(func_expr)
57 75
58 x = [i * 0.1 for i in range(-100, 101)] 76 x = [i * 0.1 for i in range(-100, 101)]
@@ -96,6 +114,49 @@ class Plot(commands.Cog):
96 plt.savefig(output_path, dpi=100, bbox_inches="tight") 114 plt.savefig(output_path, dpi=100, bbox_inches="tight")
97 plt.close() 115 plt.close()
98 116
117 def _generate_implicit_plot(self, func_expr: str, output_path: str):
118 global _plt_module
119 plt = _plt_module
120
121 lhs, rhs = parse_implicit(func_expr)
122
123 x_range = 20
124 y_range = 20
125
126 x_vals = []
127 y_vals = []
128
129 for xi in range(-x_range * 10, x_range * 10 + 1):
130 x = xi / 10.0
131 for yi in range(-y_range * 10, y_range * 10 + 1):
132 y = yi / 10.0
133 try:
134 left_val = eval(lhs, {"x": x, "y": y, "math": math, "sqrt": math.sqrt, "pi": math.pi, "e": math.e})
135 right_val = eval(rhs, {"x": x, "y": y, "math": math, "sqrt": math.sqrt, "pi": math.pi, "e": math.e})
136 diff = abs(left_val - right_val)
137 if math.isfinite(diff) and diff < 0.3:
138 x_vals.append(x)
139 y_vals.append(y)
140 except Exception:
141 pass
142
143 fig, ax = plt.subplots(figsize=(10, 10))
144 ax.scatter(x_vals, y_vals, s=1, color="#00ff00", alpha=0.5)
145 ax.set_title(f"{func_expr}", fontsize=14)
146 ax.set_xlabel("x", fontsize=12)
147 ax.set_ylabel("y", fontsize=12)
148 ax.grid(True, alpha=0.3)
149 ax.axhline(y=0, color="white", linewidth=0.5)
150 ax.axvline(x=0, color="white", linewidth=0.5)
151 ax.set_xlim(-x_range, x_range)
152 ax.set_ylim(-y_range, y_range)
153 ax.set_aspect("equal")
154 ax.set_facecolor("#1a1a1a")
155 fig.patch.set_facecolor("#1a1a1a")
156
157 plt.savefig(output_path, dpi=100, bbox_inches="tight")
158 plt.close()
159
99 @commands.slash_command(name="funkcja", description="Generuje wykres funkcji matematycznej") 160 @commands.slash_command(name="funkcja", description="Generuje wykres funkcji matematycznej")
100 async def plot(self, ctx, funkcja: str = discord.Option(str, "Funkcja np. x^3, sin(x), x^2 + 2*x - 1", required=True)): 161 async def plot(self, ctx, funkcja: str = discord.Option(str, "Funkcja np. x^3, sin(x), x^2 + 2*x - 1", required=True)):
101 if not _ensure_plot(): 162 if not _ensure_plot():