-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
152 lines (128 loc) · 5.92 KB
/
main.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import urllib.request as req
import json
from typing import Any, Union
import matplotlib.pyplot as plt
try:
import japanize_matplotlib
except ModuleNotFoundError:
plt.rcParams["font.family"] = "meiryo"
plt.rcParams["font.sans-serif"] = ["Yu Gothic", "Meirio", "Noto Sans CJK JP"]
class CloudVariable:
def __init__(
self,
project_id: int,
limit: int = 100,
offset: int = 0,
backup: Union[list[dict], str] = [],
username: str = None
) -> None:
api_responce = req.urlopen(
f"https://clouddata.scratch.mit.edu/logs?projectid={project_id}&limit={limit}&offset={offset}"
)
self.user_name = username
self.params = {"project_id": project_id, "limit": limit, "offset": offset}
api_responce = json.loads(api_responce.read().decode())
if not backup == []:
backup = list(filter(lambda x:x not in api_responce, backup))
vote_data = api_responce + backup
self._logs = list(
filter(lambda x: "☁ @scratchattach" not in x.values(), vote_data)
)
self.__graph_created = False
if username:
self._logs = [i for i in self._logs if not i["user"] == username]
def latest_results(self, remove_duplicates: bool = True, allow_different_item: bool = True) -> dict:
"""Returns the latest vote results.
Args:
remove_duplicates (bool, optional): If a user voted for the same item, it will be removed.
allow_different_item (bool, optional): Allow the same user to vote on different items.If the ``remove_duplicates`` argument is false, it is ignored.
Returns:
dict: Dictionaries of item names and vote counts
"""
data = sorted(self._logs, key=lambda x: x["timestamp"], reverse=False)
if remove_duplicates:
data = self._remove_duplicates(data, allow_different_item)
result = dict()
for i in data:
if (var := i["name"][2:]) in result.keys():
result[var] += 1
else:
result.update({var: int(i["value"])})
return result
@property
def most_vote_key(self, remove_duplicates: bool = True) -> str:
"""Returns the name of the item with the most votes.
Args:
remove_duplicates (bool, optional): If a user voted for the same item, it will be removed.
allow_different_item: (bool, optional): Allow the same user to vote on different items.
If the ``remove_duplicates`` argument is false, it is ignored.
Returns:
str: Name of most common item
"""
vote_result = self.latest_results(remove_duplicates=remove_duplicates)
return max(vote_result, key=vote_result.get)
@property
def keys(self) -> list:
log_keys = [d["name"] for d in self._logs if "@scratchattach" not in d["name"]]
log_keys = list(set(log_keys))
return log_keys
def create_graph(
self,
digit: int = 2,
remove_duplicates: bool = True,
allow_different_item: bool = True,
sort_list: list = None,
colors: Union[list, tuple] = None,
startangle: int = 90,
title: str = "結果"
) -> None:
"""Create a graph of the voting results.
Args:
digit (int, optional): Number of digits to display the percentage
remove_duplicates (bool, optional): If a user voted for the same item, it will be removed.
allow_different_item: (bool, optional): Allow the same user to vote on different items.
If the ``remove_duplicates`` argument is false, it is ignored.
sort_list (list, optional): The order in which the graphs are displayed
colors (Union[list, tuple], optional): Graph Color
startangle (int, optional): Starting angle of pie chart
title (str, optional): Graph title
"""
data = self.latest_results(remove_duplicates, allow_different_item)
graph_digit = f"%1.{digit}f%%"
# 辞書の順番でグラフが変わる
if not sort_list is None:
data = sorted(data.items(), key=lambda x:list(map(lambda x:x.lower(), sort_list)).index(x[0].lower()))
data = dict((x, y) for x, y in data)
plt.pie(data.values(), labels=data.keys(),
counterclock=False, startangle=startangle,
colors=colors, autopct=graph_digit
)
plt.title(title)
self.__graph_created = True
def save_graph(self, name: str = "result.svg", dpi: int = 300):
if self.__graph_created:
plt.savefig(name, dpi=dpi)
else:
raise Exception("Use the \"create_graph\" method to create a graph before executing.")
@staticmethod
def _remove_duplicates(json_list: list[dict], allow_different_item: bool = True) -> list[dict]:
all = list()
for index, data in enumerate(json_list):
if allow_different_item:
vote_data = (data["user"], data["name"])
else:
vote_data = data["user"]
if vote_data not in all:
all.append(vote_data)
else:
json_list.pop(index)
return json_list
if __name__ == "__main__":
bkup = open(r"C:\Users\username\Desktop\data.json", "r", encoding="utf8")
cloud_var = json.load(bkup)
bkup.close()
cloud_var = CloudVariable(643164196, username="henji243", backup=cloud_var)
print("start")
print(cloud_var.latest_results(remove_duplicates=True, allow_different_item=False))
cloud_var.create_graph(remove_duplicates=True, sort_list=["windows", "mac", "linux", "chrome os", "その他"])
cloud_var.save_graph("test.svg")