183 lines
8.5 KiB
Python
183 lines
8.5 KiB
Python
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()
|