Skip to content

Commit b22d507

Browse files
committed
initial commit - remade branch
1 parent 51a7723 commit b22d507

4 files changed

Lines changed: 59478 additions & 0 deletions

File tree

PyPortal_Trivia_Time/code.py

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
"""
2+
This example uses the Open Trivia Database API to display multiple choice trivia questions.
3+
Tap the screen to start, then a question will appear and a 30 second timer will start.
4+
The first player to hit their button will get 10 seconds to answer.
5+
Hit button again to reveal answer. Tap screen to move to next question.
6+
This program assumes two buttons are attached to D3 and D4 on the Adafruit PyPortal.
7+
"""
8+
9+
import time
10+
import random
11+
import board
12+
from adafruit_pyportal import PyPortal
13+
from digitalio import DigitalInOut, Direction, Pull
14+
from adafruit_display_text import label
15+
from adafruit_bitmap_font import bitmap_font
16+
17+
# initialize harware
18+
led = DigitalInOut(board.L) # For debugging
19+
led.direction = Direction.OUTPUT
20+
button1 = DigitalInOut(board.D4)
21+
button2 = DigitalInOut(board.D3)
22+
button1.direction = Direction.INPUT
23+
button2.direction = Direction.INPUT
24+
button1.pull = Pull.UP
25+
button2.pull = Pull.UP
26+
display = board.DISPLAY
27+
28+
# determine the current working directory
29+
# needed so we know where to find files
30+
cwd = ("/"+__file__).rsplit('/', 1)[0]
31+
32+
# Set up where we'll be fetching data from
33+
DATA_SOURCE = "https://opentdb.com/api.php?amount=1&type=multiple"
34+
Q_LOCATION = ['results', 0, 'question']
35+
WA_LOCATION1 = ['results', 0, 'incorrect_answers', 0]
36+
WA_LOCATION2 = ['results', 0, 'incorrect_answers', 1]
37+
WA_LOCATION3 = ['results', 0, 'incorrect_answers', 2]
38+
CA_LOCATION = ['results', 0, 'correct_answer']
39+
40+
# Text info
41+
trivia_font = bitmap_font.load_font("/fonts/Arial-ItalicMT-17.bdf")
42+
answerChoices = ("A","B","C","D")
43+
a1f_text = ''
44+
a2f_text = ''
45+
a3f_text = ''
46+
a4f_text = ''
47+
player1_text = "Player 1!"
48+
player2_text = "Player 2!"
49+
timesup_text = "TIME'S UP!"
50+
loading_text = "loading question..."
51+
tapagain_text = "Tap again for \n next question."
52+
# Text locations (screen is 320 x 240)
53+
loading_position = tapagain_position = (100,120)
54+
player_position = timesup_position = answerReveal_position = (120, 75)
55+
answerReveal_position = (25, 75)
56+
q_position = (25, 70)
57+
a1_position = (25, 135)
58+
a2_position = (25, 155)
59+
a3_position = (25, 175)
60+
a4_position = (25, 195)
61+
loading_color = q_color = 0x8080FF
62+
a_color = 0xFFFFFF
63+
64+
# Clear screen of all elements but background
65+
def clear_splash():
66+
for _ in range(len(pyportal.splash) - 1):
67+
pyportal.splash.pop()
68+
69+
# A function to shuffle trivia questions
70+
def shuffle(aList):
71+
for i in range(len(aList)-1, 0, -1):
72+
# Pick a random index from 0 to i
73+
j = random.randint(0, i + 1)
74+
# Swap arr[i] with the element at random index
75+
aList[i], aList[j] = aList[j], aList[i]
76+
return aList
77+
78+
#convert html codes to normal text
79+
def unescape(s):
80+
s = s.replace(""", "''")
81+
s = s.replace("'", "'")
82+
s = s.replace("&", "&")
83+
return s
84+
85+
# A function to handle the timer and determine which player answers first
86+
def faceOff(timerLength):
87+
timerStart = time.monotonic()
88+
print(time.monotonic() - timerStart)
89+
while time.monotonic() - timerStart < timerLength:
90+
if button1.value:
91+
led.value = False # For debugging
92+
else: # If button 1 pressed, print player 1 on screen and exit function
93+
pyportal.splash.pop() # make room for player that wins
94+
player1_text_area = label.Label(trivia_font, text=player1_text, color=loading_color)
95+
player1_text_area.x = player_position[0]
96+
player1_text_area.y = player_position[1]
97+
pyportal.splash.append(player1_text_area)
98+
led.value = True # For debugging
99+
break
100+
if button2.value:
101+
led.value = False # For debugging
102+
else: # If button 2 pressed, print player 1 on screen and exit function
103+
led.value = True # For debugging
104+
pyportal.splash.pop() # make room for player that wins
105+
player2_text_area = label.Label(trivia_font, text=player2_text, color=loading_color)
106+
player2_text_area.x = player_position[0]
107+
player2_text_area.y = player_position[1]
108+
pyportal.splash.append(player2_text_area) # push 5
109+
break
110+
if time.monotonic() - timerStart > (timerLength - 0.5): # Timer runs out
111+
pyportal.splash.pop() # make room for player that wins
112+
timesup_text_area = label.Label(trivia_font, text=timesup_text, color=loading_color)
113+
timesup_text_area.x = timesup_position[0]
114+
timesup_text_area.y = timesup_position[1]
115+
pyportal.splash.append(timesup_text_area)
116+
print(time.monotonic() - timerStart)
117+
time.sleep(0.05) # debounce delay
118+
119+
#function to format trivia question content
120+
def format_trivia():
121+
pyportal.splash.pop()
122+
pyportal.splash.append(loading_text_area)
123+
# Formatting with display text library
124+
q_text = unescape(value[0])
125+
q_text_formatted = pyportal.wrap_nicely(q_text, 35)
126+
qf_text = ''
127+
for wrp in range (len(q_text_formatted)):
128+
qf_text = qf_text + q_text_formatted[wrp] +"\n"
129+
q_text = qf_text
130+
q_text_area = label.Label(trivia_font, text=q_text,
131+
color=q_color, line_spacing = 1)
132+
q_text_area.x = q_position[0]
133+
q_text_area.y = q_position[1]
134+
a1_text = unescape(value[1])
135+
a1_text_area = label.Label(trivia_font, text="A. "+a1_text,
136+
color=a_color, line_spacing = 1.5)
137+
a1_text_area.x = a1_position[0]
138+
a1_text_area.y = a1_position[1]
139+
a2_text = unescape(value[2])
140+
a2_text_area = label.Label(trivia_font, text="B. "+a2_text,
141+
color=a_color, line_spacing = 1.5)
142+
a2_text_area.x = a2_position[0]
143+
a2_text_area.y = a2_position[1]
144+
a3_text = unescape(value[3])
145+
a3_text_area = label.Label(trivia_font, text="C. "+a3_text,
146+
color=a_color, line_spacing = 1.5)
147+
a3_text_area.x = a3_position[0]
148+
a3_text_area.y = a3_position[1]
149+
a4_text = unescape(value[4])
150+
a4_text_area = label.Label(trivia_font, text="D. "+a4_text,
151+
color=a_color, line_spacing = 1.5)
152+
a4_text_area.x = a4_position[0]
153+
a4_text_area.y = a4_position[1]
154+
pyportal.splash.pop() # take off loading...
155+
pyportal.splash.append(a1_text_area)
156+
pyportal.splash.append(a2_text_area)
157+
pyportal.splash.append(a3_text_area)
158+
pyportal.splash.append(a4_text_area)
159+
# append question last so it can be removed more easily later
160+
pyportal.splash.append(q_text_area)
161+
162+
# PyPortal constructor
163+
pyportal = PyPortal(url=DATA_SOURCE,
164+
status_neopixel=board.NEOPIXEL,
165+
default_bg=cwd+"/trivia_title.bmp")
166+
167+
pyportal.preload_font() # speed things up by preloading font
168+
169+
while True:
170+
# Load new question when screen is touched
171+
if pyportal.touchscreen.touch_point:
172+
clear_splash() # clear all besides background screen
173+
pyportal.set_background(cwd+"/trivia.bmp")
174+
loading_text_area = label.Label(trivia_font, text=loading_text, color=loading_color)
175+
loading_text_area.x = loading_position[0]
176+
loading_text_area.y = loading_position[1]
177+
pyportal.splash.append(loading_text_area) #loading...
178+
answerList = [WA_LOCATION1, WA_LOCATION2, WA_LOCATION3, CA_LOCATION]
179+
# For catching potential index error when shuffling question
180+
try:
181+
shuffle(answerList) # Shuffle answers
182+
except IndexError:
183+
print("Index Error")
184+
tapagain_text_area = label.Label(trivia_font, text=tapagain_text, color=loading_color)
185+
tapagain_text_area.x = tapagain_position[0]
186+
tapagain_text_area.y = tapagain_position[1]
187+
pyportal.splash.pop() # take off loading...
188+
pyportal.splash.append(tapagain_text_area)
189+
continue
190+
try:
191+
# set the JSON path here, now that answers are shuffled
192+
# pylint: disable=protected-access
193+
pyportal._json_path=(Q_LOCATION,
194+
answerList[0],
195+
answerList[1],
196+
answerList[2],
197+
answerList[3],)
198+
value = pyportal.fetch()
199+
print("Response is", value)
200+
format_trivia()
201+
except RuntimeError as e:
202+
print("Some error occured, retrying! -", e)
203+
faceOff(30) # 30 seconds with question
204+
time.sleep(2) # pause for 2 seconds to show which player tapped first
205+
faceOff(10) # 10 seconds to answer
206+
# Show the correct answer
207+
for ansr in range(len(answerList)):
208+
if answerList[ansr] is CA_LOCATION:
209+
print(answerChoices[ansr])
210+
correctAnswerChoice = answerChoices[ansr]
211+
break
212+
answerReveal_text="Correct Answer: "+str(correctAnswerChoice)+"\n(Tap for next question.)"
213+
answerReveal_text_area = label.Label(trivia_font, text=answerReveal_text,
214+
color=loading_color)
215+
answerReveal_text_area.x = answerReveal_position[0]
216+
answerReveal_text_area.y = answerReveal_position[1]
217+
pyportal.splash.pop() # Make room for answer
218+
pyportal.splash.append(answerReveal_text_area)

0 commit comments

Comments
 (0)