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()