Add config menu, and supoprt for csv input file with word type

This commit is contained in:
Hugo 2022-08-13 22:57:37 +02:00
parent c46f8a809e
commit a5d25ada57
1 changed files with 95 additions and 33 deletions

View File

@ -1,4 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import re
import csv
from random import random, randint, choice from random import random, randint, choice
from datetime import timedelta from datetime import timedelta
from kivy.app import App 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.graphics import Color, Ellipse, Line, Rectangle
from kivy.core.window import Window from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.clock import Clock from kivy.clock import Clock
from kivy.uix.popup import Popup from kivy.uix.popup import Popup
from kivy.uix.colorpicker import ColorPicker from kivy.uix.colorpicker import ColorPicker
from kivy.uix.scrollview import ScrollView from kivy.uix.scrollview import ScrollView
from kivy.properties import StringProperty, BooleanProperty from kivy.properties import StringProperty, BooleanProperty
from kivy.lang import Builder from kivy.lang import Builder
from kivy.uix.textinput import TextInput
PASS_PENALTY = 4 PASS_PENALTY = 4
DRAWING_TIME = 60 DRAWING_TIME = 60
WORDS_FILE = "words.txt"
Builder.load_string(''' Builder.load_string('''
<ScrollableLabel>: <ScrollableLabel>:
@ -35,6 +38,19 @@ class ScrollableLabel(ScrollView):
markup = BooleanProperty(False) 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): class MyPaintWidget(Label):
_game_state = {"game_started": False, _game_state = {"game_started": False,
@ -43,7 +59,7 @@ class MyPaintWidget(Label):
"word passed": timedelta(0), "word passed": timedelta(0),
"word found": timedelta(0) "word found": timedelta(0)
} }
_game_wordlists = {"possible_wordlist": set(), _game_wordlists = {"possible_wordlist": dict(),
"found_words": set(), "found_words": set(),
"unfound_words": set() "unfound_words": set()
} }
@ -57,18 +73,34 @@ class MyPaintWidget(Label):
def __init__(self, text="", **kwargs): def __init__(self, text="", **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
self._keyboard = Window.request_keyboard( self._keyboard = None
self._keyboard_closed, self, 'text') self._get_keyboard()
if self._keyboard.widget: self._load_words()
# 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.reset_game() 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): def _keyboard_closed(self):
print('My keyboard has been closed!') print('My keyboard has been closed!')
self._keyboard.unbind(on_key_down=self._on_keyboard_down) 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 not self._game_state["game_started"]:
if keycode[0] == 32: if keycode[0] == 32:
self.start_game() self.start_game()
elif keycode[1] == 'c':
self.open_config()
elif keycode[1] == 'p': elif keycode[1] == 'p':
self.toggle_pause() self.toggle_pause()
@ -129,26 +163,10 @@ class MyPaintWidget(Label):
self.message_label.text = f'"{self.current_word}" a été trouvé !' self.message_label.text = f'"{self.current_word}" a été trouvé !'
self.current_word = choice(list(self._game_wordlists["possible_wordlist"])) self.current_word = choice(list(self._game_wordlists["possible_wordlist"]))
self._game_wordlists["possible_wordlist"].discard(self.current_word) value = self._game_wordlists["possible_wordlist"].pop(self.current_word)
self.clear_drawing() 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() self.clear_drawing()
def pass_word(self): def pass_word(self):
@ -191,6 +209,48 @@ class MyPaintWidget(Label):
elif self.collide_point(touch.x, touch.ud['line'].points[-1]): elif self.collide_point(touch.x, touch.ud['line'].points[-1]):
touch.ud['line'].points += [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): def recap(self):
found_words = self._game_wordlists['found_words'] found_words = self._game_wordlists['found_words']
unfound_words =self._game_wordlists['unfound_words'] unfound_words =self._game_wordlists['unfound_words']
@ -214,6 +274,8 @@ class MyPaintWidget(Label):
def reset_game(self): def reset_game(self):
if self._popup: if self._popup:
self._popup.dismiss() self._popup.dismiss()
if self.message_label:
self.message_label.text = ""
self.color = (0,0,0,1) self.color = (0,0,0,1)
self.text = "Appuyer sur 'espace' pour commencer à jouer" self.text = "Appuyer sur 'espace' pour commencer à jouer"
self.time = timedelta(seconds=DRAWING_TIME) self.time = timedelta(seconds=DRAWING_TIME)
@ -284,7 +346,7 @@ class MyPaintApp(App):
self.word_label.bind(size=redraw) self.word_label.bind(size=redraw)
self.time_label = Label(text=f"{self.painter.time}", color=[0,0,0,1]) 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(self.word_label)
top_row.add_widget(message_label) top_row.add_widget(message_label)
top_row.add_widget(self.time_label) top_row.add_widget(self.time_label)