2021-05-23 16:04:09 +02:00
|
|
|
#!/usr/bin/python3
|
|
|
|
|
|
|
|
import pathlib
|
2021-05-24 17:17:28 +02:00
|
|
|
import argparse
|
2021-05-23 16:04:09 +02:00
|
|
|
import os
|
|
|
|
import random
|
2021-06-17 14:51:43 +02:00
|
|
|
import time
|
2021-05-23 16:04:09 +02:00
|
|
|
from rich.console import Console
|
|
|
|
from rich.markdown import Markdown
|
2021-06-18 15:42:02 +02:00
|
|
|
from rich.table import Table
|
2021-05-23 16:04:09 +02:00
|
|
|
from ccpq.lib_ccpq import Question, Database, Game
|
|
|
|
|
2021-05-24 15:38:11 +02:00
|
|
|
MSG = {
|
|
|
|
True: [
|
|
|
|
"Yes!",
|
|
|
|
"Good one!",
|
|
|
|
"Super!",
|
|
|
|
"Excellent job!"
|
|
|
|
],
|
|
|
|
False: [
|
|
|
|
"Sorry, that's wrong",
|
|
|
|
"No, that's not right",
|
|
|
|
"Damn it! That's not the right answer",
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
2021-06-18 15:42:02 +02:00
|
|
|
DIFFICULTY = {
|
|
|
|
"easy": "010-160",
|
|
|
|
"medium": "101-500",
|
|
|
|
"hard": "102-500",
|
|
|
|
}
|
|
|
|
|
2021-10-14 00:07:26 +02:00
|
|
|
LEVELS = [
|
2021-10-11 23:21:57 +02:00
|
|
|
"010-160",
|
|
|
|
"101-400",
|
|
|
|
"101-500",
|
|
|
|
"102-400",
|
|
|
|
"102-500",
|
|
|
|
]
|
|
|
|
|
2021-05-24 15:38:11 +02:00
|
|
|
|
2021-05-23 16:04:09 +02:00
|
|
|
class Tui(object):
|
|
|
|
def __init__(self):
|
|
|
|
self._console = Console()
|
|
|
|
self._stats = []
|
|
|
|
|
|
|
|
def ask_question(self, question):
|
2021-05-24 15:38:11 +02:00
|
|
|
os.system("clear")
|
2021-05-23 16:04:09 +02:00
|
|
|
md = Markdown("# {}".format(question.get_question()))
|
|
|
|
self._console.print(md)
|
2021-10-14 00:07:26 +02:00
|
|
|
md = Markdown("level: {}".format(question.get_level()))
|
|
|
|
self._console.print(md)
|
2021-05-23 16:04:09 +02:00
|
|
|
md = ""
|
|
|
|
for possibility in question.get_possibilities():
|
|
|
|
md += "1. {}\n".format(possibility)
|
|
|
|
md = Markdown(md)
|
|
|
|
self._console.print(md)
|
|
|
|
|
2021-10-14 00:07:26 +02:00
|
|
|
def prompt_for_answer(self, name):
|
2021-05-24 15:38:11 +02:00
|
|
|
#md = Markdown("What's your answer?")
|
|
|
|
#self._console.print(md)
|
2021-10-14 00:07:26 +02:00
|
|
|
answer = self._parse_input(name)
|
2021-05-23 16:04:09 +02:00
|
|
|
return answer
|
|
|
|
|
2021-10-14 00:07:26 +02:00
|
|
|
def _parse_input(self, name):
|
2021-05-23 16:04:09 +02:00
|
|
|
"""
|
|
|
|
"""
|
2021-05-24 15:38:11 +02:00
|
|
|
answers = []
|
2021-10-14 00:07:26 +02:00
|
|
|
results = input("\n {}, what's your answer? (only numbers, separated by a SPACE) ".format(name))
|
2021-05-24 15:38:11 +02:00
|
|
|
results = results.split()
|
|
|
|
for result in results:
|
2021-05-23 16:04:09 +02:00
|
|
|
if result.isdigit():
|
2021-05-24 15:38:11 +02:00
|
|
|
answers.append(result)
|
|
|
|
else:
|
|
|
|
md = Markdown("**only digits please**")
|
|
|
|
self._console.print(md)
|
|
|
|
return answers
|
2021-05-23 16:04:09 +02:00
|
|
|
|
2021-06-17 14:51:43 +02:00
|
|
|
def signal_player(self, player):
|
|
|
|
os.system("clear")
|
|
|
|
md = "# {}".format(player.name)
|
|
|
|
md = Markdown(md)
|
|
|
|
self._console.print(md)
|
|
|
|
time.sleep(2)
|
|
|
|
os.system("clear")
|
|
|
|
|
2021-05-23 16:04:09 +02:00
|
|
|
def show_response(self, question):
|
|
|
|
answers = question.get_right_answers()
|
|
|
|
if len(answers) == 1:
|
|
|
|
answer = answers[0]
|
|
|
|
md = Markdown("### The right answer is: {}".format(answer))
|
|
|
|
else:
|
|
|
|
md = "### The right answers are:\n"
|
|
|
|
for answer in answers:
|
|
|
|
md += "* {}\n".format(answer)
|
|
|
|
md = Markdown(md)
|
|
|
|
self._console.print(md)
|
|
|
|
|
2021-05-27 21:28:04 +02:00
|
|
|
def show_explanation(self, question):
|
2021-06-17 14:20:30 +02:00
|
|
|
md = "--- \n {} \n \n ---".format(question.get_explication())
|
|
|
|
md = Markdown(md)
|
|
|
|
self._console.print(md)
|
2021-05-27 21:28:04 +02:00
|
|
|
|
2021-05-24 15:38:11 +02:00
|
|
|
def show_success(self, success):
|
|
|
|
md = "# {}".format(random.choice(MSG[success]))
|
|
|
|
md = Markdown(md)
|
|
|
|
self._console.print(md)
|
|
|
|
|
2021-05-23 16:04:09 +02:00
|
|
|
def show_stats(self, stats):
|
2021-06-17 14:51:43 +02:00
|
|
|
md = "{}, you have {} out of {} right!\n".format(stats[0], stats[1], stats[1] + stats[2])
|
2021-05-23 16:04:09 +02:00
|
|
|
md = Markdown(md)
|
|
|
|
self._console.print(md)
|
2021-06-18 15:42:02 +02:00
|
|
|
md = "### press **enter** to get a new question, s for stats and **CTRL-C** to quit"
|
2021-05-23 16:04:09 +02:00
|
|
|
md = Markdown(md)
|
|
|
|
self._console.print(md)
|
2021-06-18 15:42:02 +02:00
|
|
|
result = input()
|
|
|
|
return result
|
2021-05-23 16:04:09 +02:00
|
|
|
|
2021-06-18 15:42:02 +02:00
|
|
|
def show_game_stats(self, players):
|
|
|
|
os.system("clear")
|
|
|
|
table = Table("Player")
|
|
|
|
table.add_column("Right")
|
|
|
|
table.add_column("Wrong")
|
|
|
|
table.add_column("Total")
|
|
|
|
for player in players:
|
|
|
|
name, right, wrong = player.get_stats()
|
|
|
|
table.add_row(str(name), str(right), str(wrong), str(right + wrong))
|
|
|
|
self._console.print(table)
|
|
|
|
md = "### press **enter** to continue"
|
|
|
|
md = Markdown(md)
|
|
|
|
self._console.print(md)
|
|
|
|
input()
|
|
|
|
|
2021-05-23 16:04:09 +02:00
|
|
|
def goodbye(self):
|
|
|
|
md = Markdown("# Goodbye!")
|
|
|
|
self._console.print(md)
|
|
|
|
|
|
|
|
|
|
|
|
class Application(object):
|
2021-06-18 15:42:02 +02:00
|
|
|
def __init__(self, filepath_csv, filepath_players, interface, number, level):
|
|
|
|
self._db = Database(filepath_csv, level)
|
2021-06-17 14:51:43 +02:00
|
|
|
self._session = Game(filepath_players)
|
2021-10-11 23:21:57 +02:00
|
|
|
self._number = number * len(self._session.get_all_players())
|
2021-05-23 16:04:09 +02:00
|
|
|
self._interface = interface
|
|
|
|
|
2021-05-24 17:17:28 +02:00
|
|
|
def start(self):
|
|
|
|
pass
|
|
|
|
|
2021-05-23 16:04:09 +02:00
|
|
|
def run(self):
|
2021-05-24 17:17:28 +02:00
|
|
|
while self._number > 0:
|
2021-06-17 14:51:43 +02:00
|
|
|
player = self._session.get_random_player()
|
2021-10-14 00:07:26 +02:00
|
|
|
if len(self._session.get_all_players()) > 1:
|
|
|
|
self._interface.signal_player(player)
|
2021-05-23 16:04:09 +02:00
|
|
|
question = self._db.get_question()
|
|
|
|
self._interface.ask_question(question)
|
2021-10-14 00:07:26 +02:00
|
|
|
answer = self._interface.prompt_for_answer(player)
|
2021-05-23 16:04:09 +02:00
|
|
|
stat = question.verify(answer)
|
2021-06-17 14:51:43 +02:00
|
|
|
player.stats.update_stats(stat)
|
2021-05-24 15:38:11 +02:00
|
|
|
self._interface.show_success(stat)
|
2021-05-23 16:04:09 +02:00
|
|
|
self._interface.show_response(question)
|
2021-06-17 14:51:43 +02:00
|
|
|
self._interface.show_explanation(question)
|
2021-06-18 15:42:02 +02:00
|
|
|
result = self._interface.show_stats(player.get_stats())
|
|
|
|
if result.startswith("s"):
|
|
|
|
players = self._session.get_all_players()
|
|
|
|
self._interface.show_game_stats(players)
|
2021-05-24 17:17:28 +02:00
|
|
|
self._number -= 1
|
|
|
|
self.quit()
|
2021-05-23 16:04:09 +02:00
|
|
|
|
|
|
|
def quit(self):
|
2021-06-18 15:42:02 +02:00
|
|
|
players = self._session.get_all_players()
|
|
|
|
self._interface.show_game_stats(players)
|
2021-05-23 16:04:09 +02:00
|
|
|
self._interface.goodbye()
|
|
|
|
|
|
|
|
|
2021-10-14 00:07:26 +02:00
|
|
|
def level_logic(level, difficulty):
|
|
|
|
if level is None and difficulty is None:
|
|
|
|
level = "lpic1_part1"
|
|
|
|
elif level is not None:
|
2021-10-21 14:51:57 +02:00
|
|
|
# level = LEVELS[0:LEVELS.index(DIFFICULTY[level]) + 1]
|
|
|
|
level = (level)
|
2021-10-14 00:07:26 +02:00
|
|
|
elif difficulty is not None:
|
|
|
|
level = LEVELS[0:LEVELS.index(DIFFICULTY[difficulty]) + 1]
|
|
|
|
return level
|
|
|
|
|
|
|
|
|
2021-05-23 16:04:09 +02:00
|
|
|
if __name__ == "__main__":
|
2021-05-24 17:17:28 +02:00
|
|
|
parser = argparse.ArgumentParser()
|
2021-10-14 00:07:26 +02:00
|
|
|
parser.add_argument(
|
|
|
|
"-f",
|
|
|
|
"--file",
|
|
|
|
required=False,
|
|
|
|
default="data",
|
|
|
|
help="path to specific CSV file or directory",
|
|
|
|
action="store"
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"-p",
|
|
|
|
"--players",
|
|
|
|
required=False,
|
|
|
|
default="",
|
|
|
|
help="file with list of players",
|
|
|
|
action="store"
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"-n",
|
|
|
|
"--number",
|
|
|
|
default=20,
|
|
|
|
help="number of questions to ask",
|
|
|
|
type=int,
|
|
|
|
action="store"
|
|
|
|
)
|
|
|
|
group_level = parser.add_mutually_exclusive_group()
|
|
|
|
group_level.add_argument(
|
|
|
|
"-d",
|
|
|
|
"--difficulty",
|
|
|
|
choices=DIFFICULTY.keys(),
|
|
|
|
help="easy, medium or hard"
|
|
|
|
)
|
|
|
|
group_level.add_argument(
|
|
|
|
"-l",
|
|
|
|
"--level",
|
|
|
|
choices=LEVELS,
|
|
|
|
help="LPI level to test"
|
|
|
|
)
|
2021-05-24 17:17:28 +02:00
|
|
|
args = parser.parse_args()
|
2021-10-14 00:07:26 +02:00
|
|
|
|
2021-06-17 14:51:43 +02:00
|
|
|
filepath_csv = pathlib.Path(args.file)
|
|
|
|
filepath_players = pathlib.Path(args.players)
|
2021-10-11 23:21:57 +02:00
|
|
|
if not filepath_csv.exists():
|
|
|
|
print("no such file or directory!")
|
2021-05-24 17:24:46 +02:00
|
|
|
exit(1)
|
2021-10-14 00:07:26 +02:00
|
|
|
|
|
|
|
level = level_logic(args.level, args.difficulty)
|
2021-05-23 16:04:09 +02:00
|
|
|
interface = Tui()
|
2021-06-18 15:42:02 +02:00
|
|
|
app = Application(filepath_csv, filepath_players, interface, args.number, level)
|
2021-05-23 16:04:09 +02:00
|
|
|
try:
|
|
|
|
app.run()
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
app.quit()
|