From a5d25ada57829345043e2e8a8c522da499fbd02e Mon Sep 17 00:00:00 2001 From: Hugo Date: Sat, 13 Aug 2022 22:57:37 +0200 Subject: [PATCH] Add config menu, and supoprt for csv input file with word type --- test_kivy_draw.py | 128 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 95 insertions(+), 33 deletions(-) diff --git a/test_kivy_draw.py b/test_kivy_draw.py index 71edb32..218f0d2 100755 --- a/test_kivy_draw.py +++ b/test_kivy_draw.py @@ -1,4 +1,6 @@ #!/usr/bin/env python3 +import re +import csv from random import random, randint, choice from datetime import timedelta from kivy.app import App @@ -8,17 +10,18 @@ from kivy.uix.label import Label from kivy.graphics import Color, Ellipse, Line, Rectangle from kivy.core.window import Window from kivy.uix.boxlayout import BoxLayout +from kivy.uix.gridlayout import GridLayout from kivy.clock import Clock from kivy.uix.popup import Popup from kivy.uix.colorpicker import ColorPicker from kivy.uix.scrollview import ScrollView from kivy.properties import StringProperty, BooleanProperty from kivy.lang import Builder - +from kivy.uix.textinput import TextInput PASS_PENALTY = 4 DRAWING_TIME = 60 - +WORDS_FILE = "words.txt" Builder.load_string(''' : @@ -35,6 +38,19 @@ class ScrollableLabel(ScrollView): markup = BooleanProperty(False) +class NumberInput(TextInput): + def __init__(self, init_value, **kwargs): + self.init_value = init_value + kwargs["text"] = str(init_value) + super().__init__(**kwargs) + + pat = r"^[0-9]+$" + def insert_text(self, substring, from_undo=False): + if not re.match(self.pat, substring): + s='' + else: + s = substring + super().insert_text(s, from_undo=from_undo) class MyPaintWidget(Label): _game_state = {"game_started": False, @@ -43,7 +59,7 @@ class MyPaintWidget(Label): "word passed": timedelta(0), "word found": timedelta(0) } - _game_wordlists = {"possible_wordlist": set(), + _game_wordlists = {"possible_wordlist": dict(), "found_words": set(), "unfound_words": set() } @@ -57,18 +73,34 @@ class MyPaintWidget(Label): def __init__(self, text="", **kwargs): super().__init__(**kwargs) - self._keyboard = Window.request_keyboard( - self._keyboard_closed, self, 'text') - if self._keyboard.widget: - # If it exists, this widget is a VKeyboard object which you can use - # to change the keyboard layout. - pass - self._keyboard.bind(on_key_down=self._on_keyboard_down) - with open("words.txt", "r") as wordfile: - self._wordlist = (word.strip() for word in wordfile.readlines()) - self._game_wordlists["possible_wordlist"] = set(self._wordlist) + self._keyboard = None + self._get_keyboard() + self._load_words() self.reset_game() + def _load_words(self): + if WORDS_FILE.endswith(".csv"): + # read a CSV file + with open(WORDS_FILE, "r", newline='') as wordfile: + my_reader = csv.reader(wordfile) + self._game_wordlists["possible_wordlist"] = {line[0]: + line[1] for line in my_reader} + else: + # read a plain text file + with open(WORDS_FILE, "r") as wordfile: + self._wordlist = (word.strip() for word in wordfile.readlines()) + self._game_wordlists["possible_wordlist"] = dict.fromkeys(self._wordlist) + + def _get_keyboard(self): + if self._keyboard is None: + self._keyboard = Window.request_keyboard( + self._keyboard_closed, self, 'text') + if self._keyboard.widget: + # If it exists, this widget is a VKeyboard object which you can use + # to change the keyboard layout. + pass + self._keyboard.bind(on_key_down=self._on_keyboard_down) + def _keyboard_closed(self): print('My keyboard has been closed!') self._keyboard.unbind(on_key_down=self._on_keyboard_down) @@ -81,6 +113,8 @@ class MyPaintWidget(Label): if not self._game_state["game_started"]: if keycode[0] == 32: self.start_game() + elif keycode[1] == 'c': + self.open_config() elif keycode[1] == 'p': self.toggle_pause() @@ -129,26 +163,10 @@ class MyPaintWidget(Label): self.message_label.text = f'"{self.current_word}" a été trouvé !' self.current_word = choice(list(self._game_wordlists["possible_wordlist"])) - self._game_wordlists["possible_wordlist"].discard(self.current_word) - self.clear_drawing() + value = self._game_wordlists["possible_wordlist"].pop(self.current_word) + if value: + self.message_label.text += '\n'+f'Le prochain mot est de type: {value}' - def pass_word(self): - self._game_wordlists["unfound_words"].add(self.current_word) - self.next_word(True) - if self.time - timedelta(seconds=PASS_PENALTY) > timedelta(0): - self.time -= timedelta(seconds=PASS_PENALTY) - else: - self.time = timedelta(0) - - @property - def is_game_playing(self): - return (self._game_state["game_started"] - and not self._game_state["game_paused"] - and not self._game_state["game_finished"]) - - - self.current_word = choice(list(self._game_wordlists["possible_wordlist"])) - self._game_wordlists["possible_wordlist"].discard(self.current_word) self.clear_drawing() def pass_word(self): @@ -191,6 +209,48 @@ class MyPaintWidget(Label): elif self.collide_point(touch.x, touch.ud['line'].points[-1]): touch.ud['line'].points += [touch.x, touch.ud['line'].points[-1]] + def open_config(self): + layout = GridLayout() + layout.cols=2 + layout.add_widget(Label(text="Chemin vers la liste de mots")) + layout.add_widget(TextInput(text=WORDS_FILE, multiline=False)) + layout.add_widget(Label(text="Temps de dessin\n(secondes")) + layout.add_widget(NumberInput(DRAWING_TIME, multiline=False)) + layout.add_widget(Label(text="Temps de pénalité\nquand on passe\n(secondes)")) + layout.add_widget(NumberInput(PASS_PENALTY, multiline=False)) + conf_popup = Popup(title='Configuration', content=layout, size_hint=(0.5, 0.5)) + conf_popup.bind(on_dismiss=self.apply_conf) + conf_popup.open() + + def apply_conf(self, obj): + global DRAWING_TIME + global PASS_PENALTY + global WORDS_FILE + try: + drawing_time = int(obj.content.children[2].text) + if drawing_time > 0: + DRAWING_TIME = drawing_time + except ValueError: + Popup(title="Error", content=Label(text="Mauvaise valeur pour temps de dessin")).open() + try: + pass_penalty = int(obj.content.children[0].text) + if pass_penalty > 0 and pass_penalty < drawing_time: + PASS_PENALTY = pass_penalty + except ValueError: + Popup(title="Error", content=Label(text="Mauvaise valeur pour pénalité")).open() + self.reset_game() + if obj.content.children[4].text != WORDS_FILE: + old_file = WORDS_FILE + WORDS_FILE = obj.content.children[4].text + try: + self._load_words() + except OSError: + Popup(title="Error", content=Label(text=f"Erreur de lecture du fichier '{WORDS_FILE}'")).open() + WORDS_FILE = old_file + self._get_keyboard() + + + def recap(self): found_words = self._game_wordlists['found_words'] unfound_words =self._game_wordlists['unfound_words'] @@ -214,6 +274,8 @@ class MyPaintWidget(Label): def reset_game(self): if self._popup: self._popup.dismiss() + if self.message_label: + self.message_label.text = "" self.color = (0,0,0,1) self.text = "Appuyer sur 'espace' pour commencer à jouer" self.time = timedelta(seconds=DRAWING_TIME) @@ -284,7 +346,7 @@ class MyPaintApp(App): self.word_label.bind(size=redraw) self.time_label = Label(text=f"{self.painter.time}", color=[0,0,0,1]) - message_label = Label(color=[0,0,0,1]) + message_label = Label(color=[0,0,0,1], halign="center") top_row.add_widget(self.word_label) top_row.add_widget(message_label) top_row.add_widget(self.time_label)