diff --git a/fascinating-fools/README.md b/fascinating-fools/README.md index 75203f1e..5d4708bd 100644 --- a/fascinating-fools/README.md +++ b/fascinating-fools/README.md @@ -15,3 +15,8 @@ Please use this README to document your team's project. Make sure to include a g All projects will merged into our Code Jam repository, which uses the [MIT license](../LICENSE). Please make sure that if you add assets, the licenses of those assets are compatible with the MIT license. We have just forked and about to pull request. (brookatlas) + +## Design +the uml/code design is done via draw.io for simplicity. +shareable link: +https://drive.google.com/file/d/1ROL2zcVeL4X6blnyTknbPK-NI8sEVUyy/view?usp=sharing diff --git a/fascinating-fools/app.py b/fascinating-fools/app.py new file mode 100644 index 00000000..13e79c8c --- /dev/null +++ b/fascinating-fools/app.py @@ -0,0 +1,52 @@ +from kivy.app import App +from kivy.lang import Builder +from kivy.uix.screenmanager import ScreenManager, FadeTransition +from triviaGameScreens import gameScreens +from triviaGameObjects.quiz import Quiz + +import json +import os + +class TriviaScreenManager(ScreenManager): + def __init__(self, **kwargs): + ScreenManager.__init__(self, **kwargs) + # Will be set after the quiz category was selected + self.quiz_category: str = "" + self.active_quiz: Quiz = None + + def load_questions_for_category(self, category: str): + json_file_path = f"triviaQuestions/{category}.json" + assert os.path.isfile(json_file_path), f"Selected category was {category}, but file {json_file_path} could not be found." + with open(json_file_path) as f: + return json.load(f) + + +class TriviaGame(App): + """ + documentation here. + """ + + def __init__(self, **kwargs): + App.__init__(self, **kwargs) + self.screen_manager = TriviaScreenManager(transition=FadeTransition()) + + def build(self): + """ + :return: + """ + Builder.load_file("kvFiles/StartTriviaHomeLayout.kv") + Builder.load_file("kvFiles/TriviaCategoryScreen.kv") + Builder.load_file("kvFiles/PlayScreen.kv") + + self.screen_manager.add_widget( + gameScreens.StartTriviaHomeLayout(name="start_page") + ) + self.screen_manager.add_widget( + gameScreens.TriviaCategoryScreen(name="home_screen") + ) + self.screen_manager.add_widget(gameScreens.PlayScreen(name="play_screen")) + return self.screen_manager + + +if __name__ == "__main__": + TriviaGame().run() diff --git a/fascinating-fools/code jam 6 - python - fascinating fools.jpg b/fascinating-fools/code jam 6 - python - fascinating fools.jpg new file mode 100644 index 00000000..76926f84 Binary files /dev/null and b/fascinating-fools/code jam 6 - python - fascinating fools.jpg differ diff --git a/fascinating-fools/kvFiles/PlayScreen.kv b/fascinating-fools/kvFiles/PlayScreen.kv new file mode 100644 index 00000000..8188b837 --- /dev/null +++ b/fascinating-fools/kvFiles/PlayScreen.kv @@ -0,0 +1,19 @@ +: + GridLayout: + rows: 5 + padding: (200,0,200,100) + spacing: [20,10] + Label: + text: 'question here' + Button: + text: 'firstAnswer' + on_press: root.answer_button_pressed(0) + Button: + text: 'secondAnswer' + on_press: root.answer_button_pressed(1) + Button: + text: 'thirdAnswer' + on_press: root.answer_button_pressed(2) + Button: + text: 'FourthAnswer' + on_press: root.answer_button_pressed(3) diff --git a/fascinating-fools/kvFiles/ResultsScreen.kv b/fascinating-fools/kvFiles/ResultsScreen.kv new file mode 100644 index 00000000..e69de29b diff --git a/fascinating-fools/kvFiles/StartTriviaHomeLayout.kv b/fascinating-fools/kvFiles/StartTriviaHomeLayout.kv new file mode 100644 index 00000000..70b877a2 --- /dev/null +++ b/fascinating-fools/kvFiles/StartTriviaHomeLayout.kv @@ -0,0 +1,65 @@ + + +: + GridLayout: + rows: 4 + padding: (0,0,0,0) + spacing: [20,10] + FirstGridRow + SecondGridRow + ThirdGridRow + FourthGridRow + + +: + BoxLayout: + padding: 0,0,0,0 + Button: + text: "File" + font_size: 25 + size_hint: .2,.2 + Button: + text: "Help" + font_size: 25 + size_hint: .2,.2 + Button: + text: "Fullscreen" + font_size: 25 + size_hint: .2,.2 + +: + BoxLayout: + BoxLayout: + Label: + text: 'Welcome to the ancient trivia tech' + font_size: 30 + size_hint: .7, 1 +: + BoxLayout: + SoundButton: + text: 'Medicine' + sound_file: 'sounds/button-press-whoosh.wav' + on_press: root.parent.parent.handle_category_selection(self.text) + SoundButton: + text: 'Automobiles' + sound_file: 'sounds/button-press-whoosh.wav' + on_press: root.parent.parent.handle_category_selection(self.text) + SoundButton: + text: 'Music' + sound_file: 'sounds/button-press-whoosh.wav' + on_press: root.parent.parent.handle_category_selection(self.text) + + BoxLayout: + SoundButton: + text: 'Food' + sound_file: 'sounds/button-press-whoosh.wav' + on_press: root.parent.parent.handle_category_selection(self.text) + SoundButton: + text: 'Construction' + sound_file: 'sounds/button-press-whoosh.wav' + on_press: root.parent.parent.handle_category_selection(self.text) + SoundButton: + text: 'Telecommunications' + sound_file: 'sounds/button-press-whoosh.wav' + on_press: root.parent.parent.handle_category_selection(self.text) + diff --git a/fascinating-fools/kvFiles/TriviaCategoryScreen.kv b/fascinating-fools/kvFiles/TriviaCategoryScreen.kv new file mode 100644 index 00000000..257feec6 --- /dev/null +++ b/fascinating-fools/kvFiles/TriviaCategoryScreen.kv @@ -0,0 +1,16 @@ +: + GridLayout: + rows: 3 + padding: (200,0,200,100) + spacing: [20,10] + Label: + text: 'Ready to go? Hit Start below.' + size_hint_x: 1 + Button: + text: 'Start' + size_hint: .5,.5 + on_press: root.press_start_button() + Button: + text: 'Home' + size_hint: .5,.5 + on_press: root.go_back_home() \ No newline at end of file diff --git a/fascinating-fools/project_structure.txt b/fascinating-fools/project_structure.txt new file mode 100644 index 00000000..e69de29b diff --git a/fascinating-fools/requirements.txt b/fascinating-fools/requirements.txt new file mode 100644 index 00000000..4f8a03cf --- /dev/null +++ b/fascinating-fools/requirements.txt @@ -0,0 +1,15 @@ +certifi==2019.11.28 +chardet==3.0.4 +docutils==0.16 +idna==2.8 +Kivy==1.11.1 +kivy-deps.angle==0.2.0 +kivy-deps.glew==0.2.0 +kivy-deps.gstreamer==0.2.0 +kivy-deps.sdl2==0.2.0 +Kivy-Garden==0.1.4 +Pygments==2.5.2 +pypiwin32==223 +pywin32==227 +requests==2.22.0 +urllib3==1.25.8 diff --git a/fascinating-fools/sounds/button-press-whoosh.wav b/fascinating-fools/sounds/button-press-whoosh.wav new file mode 100644 index 00000000..43e7ae63 Binary files /dev/null and b/fascinating-fools/sounds/button-press-whoosh.wav differ diff --git a/fascinating-fools/sounds/correct.wav b/fascinating-fools/sounds/correct.wav new file mode 100644 index 00000000..ccb8c517 Binary files /dev/null and b/fascinating-fools/sounds/correct.wav differ diff --git a/fascinating-fools/sounds/error.wav b/fascinating-fools/sounds/error.wav new file mode 100644 index 00000000..c75e6fbb Binary files /dev/null and b/fascinating-fools/sounds/error.wav differ diff --git a/fascinating-fools/sounds/tech-whoosh.wav b/fascinating-fools/sounds/tech-whoosh.wav new file mode 100644 index 00000000..74ffb199 Binary files /dev/null and b/fascinating-fools/sounds/tech-whoosh.wav differ diff --git a/fascinating-fools/triviaGameObjects/__init__.py b/fascinating-fools/triviaGameObjects/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fascinating-fools/triviaGameObjects/answer.py b/fascinating-fools/triviaGameObjects/answer.py new file mode 100644 index 00000000..a0ad6396 --- /dev/null +++ b/fascinating-fools/triviaGameObjects/answer.py @@ -0,0 +1,14 @@ +class Answer: + """ + documentation here. + """ + + def __init__(self, answer_text, is_right): + self.answer_text = answer_text + self.isRight = is_right + + def get_answer_text(self): + return self.answer_text + + def is_answer_right(self): + return self.isRight diff --git a/fascinating-fools/triviaGameObjects/question.py b/fascinating-fools/triviaGameObjects/question.py new file mode 100644 index 00000000..4c2a10f9 --- /dev/null +++ b/fascinating-fools/triviaGameObjects/question.py @@ -0,0 +1,26 @@ +class Question: + """ + documentation here + """ + + def __init__(self, question_text, answer_list): + self.question_text = question_text + self.answer_list = answer_list + + def get_answer_by_text(self, answer_text): + """ + gets an answer from the quiz, by the matching answer_text iself + :param answer_text: + + :return: + """ + for answer in self.answer_list: + if answer.get_answer_text() == answer_text: + return answer + return None + + def answer(self, answer_text): + matching_answer = self.get_answer_by_text(answer_text) + if matching_answer.is_answer_right(): + return True + return False diff --git a/fascinating-fools/triviaGameObjects/quiz.py b/fascinating-fools/triviaGameObjects/quiz.py new file mode 100644 index 00000000..0ab5884c --- /dev/null +++ b/fascinating-fools/triviaGameObjects/quiz.py @@ -0,0 +1,68 @@ +from typing import List + + +class Quiz: + """ + documentation here. + """ + + def __init__(self, questions): + # See 'triviaQuestions' folder for the structure of the quiz + self.questions = questions["questions"] + self.question_index = 0 + self.right_answers = 0 + self.wrong_answers = 0 + self.chosen_answer_index = 0 + self.quiz_done = False + + @property + def question_title(self) -> str: + return self.questions[self.question_index]["question"] + + @property + def answers(self) -> List[str]: + return self.questions[self.question_index]["answers"] + + @property + def correct_answer_index(self) -> int: + return self.questions[self.question_index]["correct_answer_index"] + + @property + def correct_answer(self) -> str: + return self.questions[self.question_index]["answers"] + + def is_quiz_done(self): + """ + checks if the quiz instance was done by the user + :return: a boolean, indicating if the quiz has been done. + """ + return self.quiz_done + + def get_current_question(self): + """ + gets the question object of the current question in the quiz + :return: + a question object of the current question in the quiz + """ + return self.questions[self.question_index] + + def answer(self, answer_index): + """ + answers a question of the quiz. + if the answer is right, the quiz moves + :param answer_text: + a text of the answer + :return: + """ + correct_answer_index = self.correct_answer_index + if len(self.questions) == self.question_index + 1: + self.quiz_done = True + else: + self.question_index += 1 + + if answer_index == correct_answer_index: + self.right_answers += 1 + return True + else: + self.wrong_answers += 1 + return False diff --git a/fascinating-fools/triviaGameObjects/quiz_view.py b/fascinating-fools/triviaGameObjects/quiz_view.py new file mode 100644 index 00000000..3b02e6a3 --- /dev/null +++ b/fascinating-fools/triviaGameObjects/quiz_view.py @@ -0,0 +1,9 @@ +from kivy.uix.widget import Widget + + +class QuizView(Widget): + """ + documentation here. + """ + + pass diff --git a/fascinating-fools/triviaGameScreens/__init__.py b/fascinating-fools/triviaGameScreens/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fascinating-fools/triviaGameScreens/gameScreens.py b/fascinating-fools/triviaGameScreens/gameScreens.py new file mode 100644 index 00000000..2fd5ae9f --- /dev/null +++ b/fascinating-fools/triviaGameScreens/gameScreens.py @@ -0,0 +1,125 @@ +from kivy.core.audio import SoundLoader +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.button import Button +from kivy.uix.screenmanager import Screen +from kivy.properties import StringProperty +from kivy.clock import Clock + +from triviaGameObjects.quiz import Quiz + +from typing import List + + +class StartTriviaHomeLayout(Screen): + def __init__(self, **kwargs): + """ + + :param kwargs: + """ + Screen.__init__(self, **kwargs) + + def handle_category_selection(self, categoryName): + self.manager.quiz_category = categoryName + self.manager.current = "home_screen" + + +class SoundButton(Button): + sound_file = StringProperty("assets/button-press-whoosh.wav") + + def on_press(self): + sound = SoundLoader.load(self.sound_file) + sound.play() + + +class FirstGridRow(BoxLayout): + pass + + +class SecondGridRow(BoxLayout): + pass + + +class ThirdGridRow(BoxLayout): + pass + + +class FourthGridRow(BoxLayout): + pass + + +class TriviaCategoryScreen(Screen): + category = StringProperty("UnknownCategory") + + def go_back_home(self): + self.manager.current = "start_page" + + def press_start_button(self): + quiz_questions = self.manager.load_questions_for_category( + self.manager.quiz_category + ) + self.manager.active_quiz = Quiz(quiz_questions) + self.manager.current = "play_screen" + + +class PlayScreen(Screen): + def __init__(self, **kw): + Screen.__init__(self, **kw) + # While the transition is active, the player should not be able to select the answer before the question is visible + self.locked = False + + def on_pre_enter(self, *args): + """ Called when animation starts. """ + # See events: https://kivy.org/doc/stable/api-kivy.uix.screenmanager.html?highlight=screen#kivy.uix.screenmanager.Screen + # Update the strings on the new scene, e.g. label and buttons text + self.setup_question_text() + self.setup_answer_text() + self.locked = True + + def on_enter(self, *args): + """ Called when animation is completed.""" + self.locked = False + + def setup_question_text(self): + """ Set up the question label text. """ + self.children[0].children[4].text = self.manager.active_quiz.question_title + + def setup_answer_text(self): + """ Set up the answer text and change button background to default color. """ + answers: List[str] = self.manager.active_quiz.answers + # Fourth answer has index 0, first answer has index 3 + for i, answer in enumerate(answers): + self.children[0].children[3 - i].text = answer + # After highlighting wrong and correct answers, change the background color to default color + self.children[0].children[3 - i].background_color = [1, 1, 1, 1] + + def highlight_correct_answer(self): + """ Highlight correct answer in green. """ + correct_answer_index = self.manager.active_quiz.correct_answer_index + self.children[0].children[3 - correct_answer_index].background_color = [ + 0, + 255, + 0, + 100, + ] + + def highlight_wrong_answer(self, selected_answer: int): + """ Highlight wrong answer in red. """ + self.children[0].children[3 - selected_answer].background_color = [ + 255, + 0, + 0, + 100, + ] + + def answer_button_pressed(self, pressed_button_index: int): + if not self.locked: + self.highlight_correct_answer() + answer_is_correct = self.manager.active_quiz.answer(pressed_button_index) + if not answer_is_correct: + self.highlight_wrong_answer(pressed_button_index) + # TODO: sleep for 1-5 seconds (highlight correct answer and wrong answer), then display next question + # perhaps fade out the current scene, then fade it back in and display new + + quiz_is_done = self.manager.active_quiz.quiz_done + # TODO if quiz is completed, change screne to 'quiz is over' or 'quiz summary' scene and show summary of how well the player did, which answers were correctly answered and which wrong + # self.manager.current = "summary_screen" diff --git a/fascinating-fools/triviaQuestions/Medicine.json b/fascinating-fools/triviaQuestions/Medicine.json new file mode 100644 index 00000000..f10eb53b --- /dev/null +++ b/fascinating-fools/triviaQuestions/Medicine.json @@ -0,0 +1,14 @@ +{ + "questions": [ + { + "question": "Some first question", + "answers": ["firstAnswer", "secondAnswer", "thirdAnswer", "fourthAnswer"], + "correct_answer_index": 0 + }, + { + "question": "Some second question", + "answers": ["firstAnswer", "secondAnswer", "thirdAnswer", "fourthAnswer"], + "correct_answer_index": 1 + } + ] +} \ No newline at end of file