-
Notifications
You must be signed in to change notification settings - Fork 0
/
drawpi.py
111 lines (89 loc) · 3.2 KB
/
drawpi.py
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
"""DrawPi entry point
This file is part of the DrawPi project, Copyright © 2023 JonLiuFYI
SPDX-License-Identifier: Apache-2.0
"""
from dataclasses import dataclass
import logging
from statistics import fmean
import pyxel as px
import calc
from point import Point
@dataclass
class Results:
circ: float
dia: float
pi: float
class DrawPi:
drawing = False
show_results = False
result = Results(0, 0, 0)
pi_msg = ""
prev_point: Point | None = None
points: list[Point] = []
pi_attempts: list[float] = []
def __init__(self) -> None:
logging.basicConfig(level=logging.DEBUG)
px.init(256, 256, title="Draw Pi!", fps=120, capture_scale=3)
px.run(self.update, self.draw)
def update(self):
# when press starts
if px.btnp(px.MOUSE_BUTTON_LEFT):
px.cls(0)
self.points = []
self.drawing = True
self.prev_point = None
logging.debug("Drawing now!")
# while keeping pressed
if px.btn(px.MOUSE_BUTTON_LEFT):
self.points.append(Point(px.mouse_x, px.mouse_y))
logging.debug(f"{Point(px.mouse_x, px.mouse_y)} - [len {len(self.points)}]")
# when released
if px.btnr(px.MOUSE_BUTTON_LEFT):
self.drawing = False
px.mouse(True)
self.show_results = True
self.result.circ = calc.circumference(self.points)
self.result.dia = calc.diameter(self.points)
try:
self.result.pi = self.result.circ / self.result.dia
self.pi_attempts.append(self.result.pi)
except ZeroDivisionError:
self.pi_msg = "Draw a circle first, silly"
else:
self.pi_msg = f"Latest attempt at pi: {self.result.pi}"
logging.debug("Drawing stopped")
def draw(self):
px.mouse(True)
if self.drawing:
px.mouse(False)
if self.prev_point is not None:
px.line(px.mouse_x, px.mouse_y, *self.prev_point, 9)
self.prev_point = Point(px.mouse_x, px.mouse_y)
else:
px.cls(0)
instructions = (
" Find pi with your mouse!\n"
" Draw the best circle you can.\n"
"Draw more to improve the approximation."
)
tip = (
" (Tip: for best results, release the\n"
" mouse button as close to your start\n"
" point as you can)"
)
px.text(50, 208, instructions, 9)
px.text(50, 234, tip, 15)
self.draw_last_drawing()
if self.show_results:
px.text(5, 5, f"Circumference: {self.result.circ}\nDiameter: {self.result.dia}", 9) # fmt: skip
px.text(5, 20, self.pi_msg, 15)
if len(self.pi_attempts) > 0:
px.text(5, 35, f"Pi: {fmean(self.pi_attempts)}", 7)
def draw_last_drawing(self):
pts = self.points
for i, this_point in enumerate(pts):
if i == 0:
continue
prev_point = pts[i - 1]
px.line(*this_point, *prev_point, 9)
DrawPi()