365 lines
16 KiB
Python
365 lines
16 KiB
Python
import asyncio
|
|
from question import QuestionHandler
|
|
from PyQt5.QtGui import QFont, QPixmap, QPalette, QColor, QFontMetrics
|
|
from PyQt5.QtWidgets import QWidget, QPushButton, QLabel, QProgressBar, QGridLayout
|
|
from PyQt5.QtWidgets import QFrame, QSpacerItem, QSizePolicy
|
|
from PyQt5.QtCore import QRect, Qt, QEasingCurve, pyqtSignal, QPropertyAnimation, QUrl
|
|
import vlc
|
|
import re
|
|
|
|
def getPropertyAnimation(self, name, duration, start, end, keyValues={}):
|
|
animation = QPropertyAnimation(self, bytes(str.encode(name)))
|
|
animation.setDuration(duration)
|
|
animation.setStartValue(start)
|
|
animation.setEndValue(end)
|
|
for k, v in keyValues.items():
|
|
animation.setKeyValueAt(k, v)
|
|
return animation
|
|
|
|
class VideoFrame(QFrame):
|
|
def resizeEvent(self, event):
|
|
super().resizeEvent(event)
|
|
print(event.size())
|
|
self.setFixedWidth((300/535) * event.size().height())
|
|
|
|
class HQApp(QWidget):
|
|
nextGameInfo = pyqtSignal([str, str])
|
|
streamLive = pyqtSignal(str)
|
|
streamStop = pyqtSignal()
|
|
getTrivia = pyqtSignal()
|
|
|
|
def __init__(self, q):
|
|
super().__init__()
|
|
|
|
self.q = q
|
|
self.googleAnswers = []
|
|
self.webpageAnswers = []
|
|
self.animations = []
|
|
self.streaming = False
|
|
|
|
self.vlc = vlc.Instance()
|
|
self.player = self.vlc.media_player_new()
|
|
|
|
self.setupUI()
|
|
self.setupSignals()
|
|
|
|
def setupUI(self):
|
|
self.resize(1300, 600)#.setFixedSize(1300, 440)
|
|
self.setObjectName('HQApp')
|
|
self.setStyleSheet('QWidget#HQApp { background-color: #36399A; } QLabel { color: white; }')
|
|
layout = QGridLayout(self)
|
|
layout.setContentsMargins(9, 9, 200, 9)
|
|
|
|
self.hqLogo = QLabel(self)
|
|
self.hqLogo.setPixmap(QPixmap('images/hqlogo.jpg'))
|
|
self.hqLogo.setMaximumSize(300, 300)
|
|
self.hqLogo.setScaledContents(True)
|
|
layout.addWidget(self.hqLogo, 1, 0, 1, 1)
|
|
|
|
self.showStatus = QLabel(self)
|
|
self.showStatus.setText('NEXT GAME')
|
|
self.showStatus.hide()
|
|
self.showStatus.setAlignment(Qt.AlignCenter)
|
|
layout.addWidget(self.showStatus, 2, 0, 1, 1)
|
|
|
|
font = QFont()
|
|
font.setPointSize(10)
|
|
font.setBold(True)
|
|
font.setWeight(75)
|
|
|
|
self.showTime = QLabel(self)
|
|
self.showTime.setText('2PM CDT')
|
|
self.showTime.hide()
|
|
self.showTime.setAlignment(Qt.AlignCenter)
|
|
self.showTime.setFont(font)
|
|
layout.addWidget(self.showTime, 3, 0, 1, 1)
|
|
|
|
self.showPrize = QLabel(self)
|
|
self.showPrize.setText('$5,000 Prize')
|
|
self.showPrize.hide()
|
|
self.showPrize.setAlignment(Qt.AlignCenter)
|
|
self.showPrize.setFont(font)
|
|
layout.addWidget(self.showPrize, 4, 0, 1, 1)
|
|
|
|
self.videoFrame = VideoFrame()
|
|
self.videoFrame.resize(300, 420)
|
|
p = self.videoFrame.palette()
|
|
p.setColor(QPalette.Window, QColor(0, 0, 0))
|
|
self.videoFrame.setPalette(p)
|
|
self.videoFrame.setAutoFillBackground(True)
|
|
self.videoFrame.hide()
|
|
layout.addWidget(self.videoFrame, 0, 0, 6, 1)
|
|
|
|
topSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
|
bottomSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
|
layout.addItem(topSpacer, 0, 0, 1, 1)
|
|
layout.addItem(bottomSpacer, 5, 0, 1, 1)
|
|
|
|
rlayout = QGridLayout()
|
|
layout.addLayout(rlayout, 0, 1, 6, 1)
|
|
|
|
topSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
|
bottomSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
|
rlayout.addItem(topSpacer, 0, 0, 1, 1)
|
|
rlayout.addItem(bottomSpacer, 3, 0, 1, 1)
|
|
|
|
self.googleBG = QWidget(self)
|
|
self.googleBG.setStyleSheet('QWidget#GooglePanel { background-color: white; border-radius: 10px; }')
|
|
#sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
|
|
#sizePolicy.setHorizontalStretch(1)
|
|
#sizePolicy.setVerticalStretch(1)
|
|
#sizePolicy.setHeightForWidth(self.googleBG.sizePolicy().hasHeightForWidth())
|
|
#self.googleBG.setSizePolicy(sizePolicy)
|
|
self.googleBG.setObjectName('GooglePanel')
|
|
googleLayout = QGridLayout(self.googleBG)
|
|
rlayout.addWidget(self.googleBG, 2, 0, 1, 1)
|
|
|
|
self.webpageBG = QWidget(self)
|
|
self.webpageBG.setStyleSheet('QWidget#WebpagePanel { background-color: white; border-radius: 10px; }')
|
|
#sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
|
|
#sizePolicy.setHorizontalStretch(1)
|
|
#sizePolicy.setVerticalStretch(1)
|
|
#sizePolicy.setHeightForWidth(self.webpageBG.sizePolicy().hasHeightForWidth())
|
|
#self.webpageBG.setSizePolicy(sizePolicy)
|
|
self.webpageBG.setObjectName('WebpagePanel')
|
|
webpageLayout = QGridLayout(self.webpageBG)
|
|
rlayout.addWidget(self.webpageBG, 2, 1, 1, 1)
|
|
|
|
self.googleLogo = QLabel(self.googleBG)
|
|
self.googleLogo.setPixmap(QPixmap('images/google.png'))
|
|
self.googleLogo.setMaximumSize(300, 100)
|
|
self.googleLogo.setScaledContents(True)
|
|
googleLayout.addWidget(self.googleLogo, 0, 1, 1, 1)
|
|
leftSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
|
rightSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
|
googleLayout.addItem(leftSpacer, 0, 0, 1, 1)
|
|
googleLayout.addItem(rightSpacer, 0, 2, 1, 1)
|
|
|
|
self.webpageLogo = QLabel(self.webpageBG)
|
|
self.webpageLogo.setPixmap(QPixmap('images/webpage.png'))
|
|
self.webpageLogo.setMaximumSize(100, 100)
|
|
self.webpageLogo.setScaledContents(True)
|
|
self.webpageText = QLabel('Website Search', self.webpageBG)
|
|
font = QFont()
|
|
font.setPointSize(13)
|
|
self.webpageText.setFont(font)
|
|
self.webpageText.setStyleSheet('color: black;')
|
|
webpageLayout.addWidget(self.webpageLogo, 0, 1, 1, 1)
|
|
webpageLayout.addWidget(self.webpageText, 0, 2, 1, 1)
|
|
leftSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
|
rightSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
|
webpageLayout.addItem(leftSpacer, 0, 0, 1, 1)
|
|
webpageLayout.addItem(rightSpacer, 0, 3, 1, 1)
|
|
|
|
#self.galWidget = QWidget(self)
|
|
#self.galWidget.setGeometry(QRect(360, 300, 341, 171))
|
|
self.googleAnswerLayout = QGridLayout()
|
|
self.googleAnswerLayout.setContentsMargins(0, 0, 0, 0)
|
|
self.googleAnswerA = AnswerBar('A', self)
|
|
self.googleAnswerB = AnswerBar('B', self)
|
|
self.googleAnswerC = AnswerBar('C', self)
|
|
self.googleAnswers = [self.googleAnswerA, self.googleAnswerB, self.googleAnswerC]
|
|
for answer in self.googleAnswers:
|
|
answer.hide()
|
|
self.googleAnswerLayout.addWidget(self.googleAnswerA, 0, 0, 1, 1)
|
|
self.googleAnswerLayout.addWidget(self.googleAnswerB, 1, 0, 1, 1)
|
|
self.googleAnswerLayout.addWidget(self.googleAnswerC, 2, 0, 1, 1)
|
|
self.googleExplanation = QLabel(
|
|
"Google answers come straight from Google results themselves, meaning that when it works, it's often the most realiable. " \
|
|
"If Google's confident, it may be because of it's smart card / feedback system... a definite sign that it has the correct answer.\n\nBoth answer " \
|
|
"sources return the reverse order of its findings if the question has a negative term in it -- such as \"NOT\"," \
|
|
" which may be inaccurate if the Google search also considers the \"NOT\" when it's returning results. Be wary."
|
|
)
|
|
self.googleExplanation.setStyleSheet('color: black;')
|
|
self.googleExplanation.setWordWrap(True)
|
|
self.googleAnswerLayout.addWidget(self.googleExplanation, 0, 0, 3, 1)
|
|
googleLayout.addLayout(self.googleAnswerLayout, 1, 0, 1, 3)
|
|
|
|
#self.walWidget = QWidget(self)
|
|
#self.walWidget.setGeometry(QRect(750, 300, 341, 171))
|
|
self.webpageAnswerLayout = QGridLayout()
|
|
self.webpageAnswerLayout.setContentsMargins(0, 0, 0, 0)
|
|
self.webpageAnswerA = AnswerBar('A', self)
|
|
self.webpageAnswerB = AnswerBar('B', self)
|
|
self.webpageAnswerC = AnswerBar('C', self)
|
|
self.webpageAnswers = [self.webpageAnswerA, self.webpageAnswerB, self.webpageAnswerC]
|
|
for answer in self.webpageAnswers:
|
|
answer.hide()
|
|
self.webpageAnswerLayout.addWidget(self.webpageAnswerA, 0, 0, 1, 1)
|
|
self.webpageAnswerLayout.addWidget(self.webpageAnswerB, 1, 0, 1, 1)
|
|
self.webpageAnswerLayout.addWidget(self.webpageAnswerC, 2, 0, 1, 1)
|
|
self.webpageExplanation = QLabel(
|
|
"Webpage results is the plain text of the sites in the Google results split into keywords and compared " \
|
|
"against the available answers. This can be helpful for questions that are not so straightforward, " \
|
|
"since websites contain the complete text of what they have to say, rather than Google's small previews and compact card information. " \
|
|
"\n\nUsually if Google " \
|
|
"and the website search have eliminated one answer but can't decide between the other two, whichever one is " \
|
|
"chosen by both Google and the website search is correct."
|
|
)
|
|
self.webpageExplanation.setStyleSheet('color: black;')
|
|
self.webpageExplanation.setWordWrap(True)
|
|
self.webpageAnswerLayout.addWidget(self.webpageExplanation, 0, 0, 3, 1)
|
|
webpageLayout.addLayout(self.webpageAnswerLayout, 1, 0, 1, 4)
|
|
|
|
self.questionBG = QWidget(self)
|
|
self.questionBG.setStyleSheet('background-color: white; border-radius: 10px; color: black;')
|
|
#sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
|
|
#sizePolicy.setHorizontalStretch(1)
|
|
#sizePolicy.setVerticalStretch(1)
|
|
#sizePolicy.setHeightForWidth(self.googleBG.sizePolicy().hasHeightForWidth())
|
|
#self.googleBG.setSizePolicy(sizePolicy)
|
|
questionLayout = QGridLayout(self.questionBG)
|
|
rlayout.addWidget(self.questionBG, 1, 0, 1, 2)
|
|
|
|
font = QFont()
|
|
font.setPointSize(20)
|
|
font.setBold(True)
|
|
font.setWeight(75)
|
|
self.question = QLabel(self.questionBG)
|
|
self.question.setFont(font)
|
|
self.question.setAlignment(Qt.AlignCenter)
|
|
self.question.setText('HQ Trivia')
|
|
questionLayout.addWidget(self.question, 0, 0, 1, 1)
|
|
|
|
self.button = QPushButton('Get Trivia', self)
|
|
layout.addWidget(self.button, 6, 0, 1, 1)
|
|
|
|
#self.videoFrame.show()
|
|
self.show()
|
|
|
|
for answer in self.googleAnswers + self.webpageAnswers:
|
|
answer.setValue(0)
|
|
|
|
def setupSignals(self):
|
|
self.nextGameInfo.connect(self.setNextGame)
|
|
self.streamLive.connect(self.startStream)
|
|
self.streamStop.connect(self.stopStream)
|
|
#self.button.clicked.connect(self.resetCount)
|
|
self.q.searching.connect(self.newSearch)
|
|
self.q.googleResults.connect(self.setGoogleResults)
|
|
self.q.pageResults.connect(self.setWebpageResults)
|
|
|
|
def setNextGame(self, time, prize):
|
|
self.showTime.setText(time)
|
|
self.showPrize.setText(prize + ' Prize')
|
|
self.showStatus.show()
|
|
self.showTime.show()
|
|
self.showPrize.show()
|
|
|
|
def newSearch(self, qn, newQuestion, answers, formattedAnswers):
|
|
self.animations.clear()
|
|
|
|
questionText = '[Q{}] {}'.format(qn, newQuestion)
|
|
textWidth = self.questionBG.width() - 10
|
|
textSize = 20
|
|
while textWidth >= self.questionBG.width() - 10:
|
|
font = QFont()
|
|
font.setPointSize(textSize)
|
|
font.setBold(True)
|
|
font.setWeight(75)
|
|
textWidth = QFontMetrics(font).width(questionText)
|
|
textSize -= 1
|
|
self.question.setFont(font)
|
|
self.question.setText(questionText)
|
|
|
|
self.answers = {answers[0]: formattedAnswers[0], answers[1]: formattedAnswers[1], answers[2]: formattedAnswers[2]}
|
|
|
|
self.googleExplanation.hide()
|
|
self.webpageExplanation.hide()
|
|
for answer in self.googleAnswers + self.webpageAnswers:
|
|
if answer.letter == 'A': answer.setAnswer(answers[0])
|
|
elif answer.letter == 'B': answer.setAnswer(answers[1])
|
|
elif answer.letter == 'C': answer.setAnswer(answers[2])
|
|
answer.show()
|
|
|
|
if answer.maximum() == 0:
|
|
answer.setValue(0)
|
|
answer.setMaximum(1)
|
|
else:
|
|
animation = getPropertyAnimation(answer, 'value', 1000, answer.value(), 0)
|
|
animation.setEasingCurve(QEasingCurve.OutQuad)
|
|
self.animations.append(animation)
|
|
animation.start()
|
|
|
|
def setGoogleResults(self, results, reverse):
|
|
if any([type(v) == dict for v in results.values()]):
|
|
formattedResults = {}
|
|
for a, d in results.items():
|
|
formattedResults[a] = sum(d.values())
|
|
results = formattedResults
|
|
|
|
total = sum(results.values()) * 1000
|
|
for answer in self.googleAnswers:
|
|
answer.setMaximum(total)
|
|
for orgAnswer, formatAnswer in self.answers.items():
|
|
if answer.text() == orgAnswer:
|
|
for rname, count in results.items():
|
|
if re.sub('[^a-zA-Z0-9 ]', '', rname).lower() == re.sub('[^a-zA-Z0-9 ]', '', orgAnswer).lower():
|
|
if reverse:
|
|
if count == max(results.values()):
|
|
count = min(results.values())
|
|
elif count == min(results.values()):
|
|
count = max(results.values())
|
|
animation = getPropertyAnimation(answer, 'value', 1000, 0, count * 1000)
|
|
animation.setEasingCurve(QEasingCurve.OutQuad)
|
|
self.animations.append(animation)
|
|
animation.start()
|
|
|
|
def setWebpageResults(self, results, reverse):
|
|
total = sum(results.values()) * 1000
|
|
for answer in self.webpageAnswers:
|
|
answer.setMaximum(total)
|
|
for orgAnswer, formatAnswer in self.answers.items():
|
|
if answer.text() == orgAnswer:
|
|
for rname, count in results.items():
|
|
if re.sub('[^a-zA-Z0-9 ]', '', rname).lower() == re.sub('[^a-zA-Z0-9 ]', '', orgAnswer).lower():
|
|
if reverse:
|
|
if count == max(results.values()):
|
|
count = min(results.values())
|
|
elif count == min(results.values()):
|
|
count = max(results.values())
|
|
animation = getPropertyAnimation(answer, 'value', 1000, 0, count * 1000)
|
|
animation.setEasingCurve(QEasingCurve.OutQuad)
|
|
self.animations.append(animation)
|
|
animation.start()
|
|
|
|
def startStream(self, url):
|
|
if self.streaming:
|
|
return
|
|
self.media = self.vlc.media_new(url)
|
|
self.player.set_media(self.media)
|
|
self.player.set_hwnd(self.videoFrame.winId())
|
|
self.streaming = True
|
|
self.player.play()
|
|
self.videoFrame.show()
|
|
|
|
def stopStream(self):
|
|
self.streaming = False
|
|
self.player.stop()
|
|
self.videoFrame.hide()
|
|
|
|
class AnswerBar(QProgressBar):
|
|
def __init__(self, letter, parent):
|
|
super().__init__(parent)
|
|
#self.setAnswer('Answer {}'.format(letter.upper()))
|
|
self.letter = letter
|
|
self.setAnswer('')
|
|
self.setAlignment(Qt.AlignCenter)
|
|
self.setCount(0, 100)
|
|
self.setStyleSheet("QProgressBar { border: 2px solid grey; border-radius: 5px; }\n"
|
|
"QProgressBar::chunk { background-color: #50C994; width: 1px; }")
|
|
|
|
def setAnswer(self, answer):
|
|
self.setFormat(answer)
|
|
|
|
def setCount(self, count, total):
|
|
self.setMaximum(total)
|
|
self.setValue(count)
|
|
|
|
if __name__ == '__main__':
|
|
from PyQt5.QtWidgets import QApplication
|
|
import sys
|
|
app = QApplication(sys.argv)
|
|
hq = HQApp()
|
|
hq.setupUI()
|
|
app.exec_() |