Python/Lab_6/example.py

183 lines
8.5 KiB
Python
Raw Normal View History

2024-03-09 17:38:18 +02:00
import random
import curses
import copy
class Participant:
def __init__(self, surname, gender, drugs, weight_category, result):
self.surname = surname
self.gender = gender
self.drugs = drugs
self.weight_category = weight_category
self.result = result
class CompetitionContainer:
def __init__(self):
self.participants = []
def clamp_result(self, result):
if 0 <= result <= 100:
return result
elif result > 100:
return 100
else:
return 0
@property
def max_len(self):
return max( [len(j.surname) for j in self.participants] )
def generate_random_participant(self, max_surname_len = 10):
surname = chr(random.randint(1040, 1066)) + "".join([chr(random.randint(1072, 1098)) for i in range(random.randint(4, max_surname_len))])
gender = random.choice(["чоловік", "жінка"])
drugs = (random.random() <= 0.04)
weight_category = random.choice(["мінімальна", "найлегша", "легка", "напівсередня", "середня", "напівважка", "важка"])
result = round(random.random() * 100, 2)
return Participant(surname, gender, drugs, weight_category, self.clamp_result(result + int(drugs)*random.randint(0, round(100 - result))))
def add_new_participants(self, amount = 40):
self.participants += [self.generate_random_participant() for i in range(amount)]
self.participants.sort(key = lambda x: x.result, reverse = True)
def get_table(self, params):
p = copy.deepcopy(self.participants)
for i in params:
p = [j for j in p if getattr(j, i[0], False) == i[1]]
return "Таблиця найкращих результатів за фільтрами: {}\n".format(", ".join([ "{} - {}".format(k[0], k[1]) for k in params ])) + "\n".join( [ "{}: {} балів".format(i.surname.rjust(self.max_len), i.result) for i in p if (not i.drugs) ] )
def get_disqualified(self):
return ["Дискваліфіковані:"] + ["{}: {} балів".format(k.surname.rjust(self.max_len), k.result) for k in self.participants if k.drugs]
class ScreenManager:
def __init__(self):
self.buffered_result = ["Вітаємо у інтерактивній консолі!", "Наявні команди:", "лідери [жінки/чоловіки] [мінімальна/найлегша/легка/напівсередня/середня/напівважка/важка]", "учасники [жінки/чоловіки] [мінімальна/найлегша/легка/напівсередня/середня/напівважка/важка]", "дискваліфіковані"]
self.input_buffer = []
self.suggests_buffer = ["учасник", "найращі", "додати_учасників", "очистити_учасників", "дискваліфіковані", "вихід"]
self.screen = curses.initscr()
self.LINES, self.COLS = self.screen.getmaxyx()
curses.noecho()
self.running = True
self.possible_parameters = {"gender": {"жінка", "чоловік"}, "weight_category": {"мінімальна", "найлегша", "легка", "напівсередня", "середня", "напівважка", "важка"}}
self.suggest_base_commands = ["учасник", "найкращі", "додати_учасників", "очистити_учасників", "дискваліфіковані", "вихід"]
self.suggest_types = ["жінка", "чоловік", "мінімальна", "найлегша", "легка", "напівсередня", "середня", "напівважка", "важка"]
self.render_buffer()
while self.running:
self.process_input()
curses.endwin()
def process_input(self):
c = self.screen.get_wch()
if c == '\x0a':
self.buffer_results()
del self.input_buffer[:]
elif c == '\x7f':
if len(self.input_buffer):
self.input_buffer.pop()
elif c == '\x09':
if len(self.suggests_buffer) > 0:
self.input_buffer = list("".join("".join(self.input_buffer).rsplit(" ", 1)[:-1]) + " " + self.suggests_buffer[0])
else:
self.input_buffer.append(c)
self.auto_suggest()
self.render_buffer()
def render_buffer(self):
self.screen.clear()
# rendering results of previous command
for i in range(min(len(self.buffered_result), self.LINES-13)):
self.screen.addstr(i, 0, self.buffered_result[i])
# auto-completion (missing at the moment)
for i in range(min(len(self.suggests_buffer), 10)):
overflow = max(len(self.suggests_buffer[i]) - (self.COLS - len(self.input_buffer)) + 5, 0)
self.screen.addstr(self.LINES-2-i, len(self.input_buffer) + 2, self.suggests_buffer[i][overflow:])
# rendering user input string
if len(self.input_buffer) < self.COLS - 6:
self.screen.addstr(self.LINES-1, 0, "> " + "".join(list(map(lambda x: str(x), self.input_buffer))))
else:
overflow_amount = len(self.input_buffer) - (self.COLS - 6)
self.screen.addstr(self.LINES-1, 0, "> ..." + "".join(list(map(lambda x: str(x), self.input_buffer[overflow_amount:]))))
# flush the screen buffers
self.screen.refresh()
def auto_suggest(self):
if len(self.input_buffer) > 0:
cs = [i for i in "".join(self.input_buffer).split(" ") if i != ""]
if len(cs) == 1:
self.suggests_buffer = [j for j in self.suggest_base_commands if j.startswith(cs[0])]
elif len(cs) == 2:
if cs[0] == "учасник":
self.suggests_buffer = [k.surname for k in cc.participants if k.surname.startswith(cs[1])]
elif len(cs) > 1:
if cs[0] == "найкращі":
self.suggests_buffer = [i for i in self.suggest_types if i.startswith(cs[-1])]
def buffer_results(self):
command = "".join(self.input_buffer)
if len(command) > 0:
cs = command.split(" ")
while "" in cs:
cs.remove("")
if len(cs) == 0:
self.buffered_result = ["Команда не введена!"]
return 0
params = {}
if cs[0] == "найкращі":
if len(cs) == 1:
self.buffered_result = cc.get_table([]).split("\n")
else:
for i in cs[1:]:
for j in self.possible_parameters:
if i in self.possible_parameters[j]:
params[j] = i
self.buffered_result = cc.get_table(list(params.items())).split("\n")
elif cs[0] == "учасник":
if len(cs) == 2:
if cs[1] in [i.surname for i in cc.participants]:
self.buffered_result = [ "{}: {} балів".format(i.surname.rjust(len(i.surname)), i.result) for i in cc.participants if i.surname == cs[1]]
else:
self.buffered_result = ["Помилка!", "Невідомий учасник"]
elif cs[0] == "дискваліфіковані":
self.buffered_result = cc.get_disqualified()
elif cs[0] == "вихід":
self.running = False
elif cs[0] == "очистити_учасників":
cc.participants.clear()
self.buffered_result = ["Успіх!", "Список учасників було очищено"]
elif cs[0] == "додати_учасників":
if (len(cs) == 2) and (cs[1].isdigit()):
cc.add_new_participants(int(cs[1]))
elif (len(cs) == 1):
cc.add_new_participants()
else:
self.buffered_result = ["Помилка!", "Ви ввели неправильну кількість аргументів для команди додати_учасників"]
else:
self.buffered_result = ["Такої команди не існує!"]
else:
self.buffered_result = ["Команда не введена!"]
if __name__ == "__main__":
cc = CompetitionContainer()
cc.add_new_participants()
sm = ScreenManager()