Files
hq_bot/hq_gui.py
2020-06-23 23:17:05 -05:00

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_()