Jeopardy: add templates.

This commit is contained in:
oddluck 2020-02-11 20:36:13 +00:00
parent 4621a29894
commit b9f47f446c
3 changed files with 76 additions and 49 deletions

View File

@ -75,10 +75,6 @@ conf.registerChannelValue(Jeopardy, 'flexibility',
registry.Float(0.92, _("""The minimum flexibility of the answer registry.Float(0.92, _("""The minimum flexibility of the answer
checker. Uses jaro-winkler distance, 1.0 is identical"""))) checker. Uses jaro-winkler distance, 1.0 is identical""")))
conf.registerChannelValue(Jeopardy, 'color',
registry.PositiveInteger(10, _("""The IRC color to use for questions. Valid color
values are 0-98. Set 99 to disable""")))
conf.registerChannelValue(Jeopardy, 'inactiveShutoff', conf.registerChannelValue(Jeopardy, 'inactiveShutoff',
registry.Integer(5, _("""The number of questions that can go registry.Integer(5, _("""The number of questions that can go
unanswered before the game stops automatically."""))) unanswered before the game stops automatically.""")))
@ -114,3 +110,24 @@ conf.registerChannelValue(Jeopardy, 'autoRestart',
conf.registerChannelValue(Jeopardy, 'keepHistory', conf.registerChannelValue(Jeopardy, 'keepHistory',
registry.Boolean(True, _("""Keep a history of previously asked questions per registry.Boolean(True, _("""Keep a history of previously asked questions per
channel and don't repeat them."""))) channel and don't repeat them.""")))
conf.registerGroup(Jeopardy, 'template')
conf.registerChannelValue(Jeopardy.template, 'question',
registry.String("\x02\x0310#{{number}} of {{total}}: ({{airdate}}) [${{points}}] {% filter upper %}{{category}}{% endfilter %}: {{clue}}",
_("""The template used to render questions.""")))
conf.registerChannelValue(Jeopardy.template, 'hint',
registry.String("\x02HINT: {{hint}}", _("""The template used to render hints.""")))
conf.registerChannelValue(Jeopardy.template, 'correct',
registry.String("\x02{{nick}} got it! The full answer was: {{answer}}. Points: {{points}} | Round Score: {{round}} | Total: {{total}}",
_("""The template used to render correct answer replies.""")))
conf.registerChannelValue(Jeopardy.template, 'skip',
registry.String("\x02Skipping question. (Answer: {{answer}})",
_("""The template used to render skip replies.""")))
conf.registerChannelValue(Jeopardy.template, 'stop',
registry.String("\x02Jeopardy! stopped.{% if answer %} (Answer: {{answer}}){% endif %}",
_("""The template used to render stop replies.""")))

View File

@ -47,6 +47,7 @@ import supybot.conf as conf
import requests import requests
from ftfy import fix_text from ftfy import fix_text
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from jinja2 import Template
import textdistance import textdistance
from supybot.i18n import PluginInternationalization, internationalizeDocstring from supybot.i18n import PluginInternationalization, internationalizeDocstring
_ = PluginInternationalization('Jeopardy') _ = PluginInternationalization('Jeopardy')
@ -103,11 +104,11 @@ class Jeopardy(callbacks.Plugin):
self.history = [] self.history = []
self.question = '' self.question = ''
self.currentHint = '' self.currentHint = ''
self.color = self.registryValue('color', channel) self.question_template = Template(self.registryValue("template.question", channel))
if self.color > 98: self.hint_template = Template(self.registryValue("template.hint", channel))
self.color = '' self.correct_template = Template(self.registryValue("template.correct", channel))
else: self.skip_template = Template(self.registryValue("template.skip", channel))
self.color = "\x03{0}".format(self.color) self.stop_template = Template(self.registryValue("template.stop", channel))
self.directory = conf.supybot.directories.data.dirize("jeopardy/") self.directory = conf.supybot.directories.data.dirize("jeopardy/")
self.historyFile = "{0}/history_{1}.txt".format(self.directory, channel) self.historyFile = "{0}/history_{1}.txt".format(self.directory, channel)
self.scoreFile = "{0}/scores_{1}.txt".format(self.directory, channel) self.scoreFile = "{0}/scores_{1}.txt".format(self.directory, channel)
@ -152,7 +153,7 @@ class Jeopardy(callbacks.Plugin):
clue = item['question'].strip() clue = item['question'].strip()
airdate = item['airdate'].split('T')[0] airdate = item['airdate'].split('T')[0]
answer = item['answer'].strip() answer = item['answer'].strip()
category = item['category']['title'].strip().upper() category = item['category']['title'].strip()
invalid = item['invalid_count'] invalid = item['invalid_count']
points = self.points points = self.points
if item['value']: if item['value']:
@ -160,9 +161,9 @@ class Jeopardy(callbacks.Plugin):
else: else:
points = self.points points = self.points
if self.registryValue('keepHistory', channel): if self.registryValue('keepHistory', channel):
if len(clue) > 1 and airdate and answer and category and not invalid and id not in asked and id not in self.history: if clue and airdate and answer and category and not invalid and id not in asked and id not in self.history:
q = "{0}*({1}) [${2}] \x02{3}: {4}\x0F*{5}*{6}".format(id, airdate, points, category, clue, answer, points) q = "{0}|{1}|{2}|{3}|{4}|{5}".format(id, airdate, points, category, clue, answer)
q = re.sub('<[^<]+?>', '', fix_text(q, normalization='NFKC')).encode('utf-8').decode('unicode_escape') q = re.sub('<[^<]+?>', '', fix_text(q, normalization='NFKC')).replace(r"\'", "'").replace(r'\"', '"')
q = re.sub('([,;:.!?])(\w|\"|\'|\()(?!\.)', '\g<1> \g<2>', q) q = re.sub('([,;:.!?])(\w|\"|\'|\()(?!\.)', '\g<1> \g<2>', q)
q = re.sub('(\$\d+[,.]) (\d+)', '\g<1>\g<2>', q) q = re.sub('(\$\d+[,.]) (\d+)', '\g<1>\g<2>', q)
q = " ".join(q.split()) q = " ".join(q.split())
@ -170,9 +171,9 @@ class Jeopardy(callbacks.Plugin):
asked.append(id) asked.append(id)
n += 1 n += 1
else: else:
if len(clue) > 1 and airdate and answer and category and not invalid and id not in asked: if clue and airdate and answer and category and not invalid and id not in asked:
q = "{0}*({1}) [${2}] \x02{3}: {4}\x0F*{5}*{6}".format(id, airdate, points, category, clue, answer, points) q = "{0}|{1}|{2}|{3}|{4}|{5}".format(id, airdate, points, category, clue, answer)
q = re.sub('<[^<]+?>', '', fix_text(q, normalization='NFKC')).encode('utf-8').decode('unicode_escape') q = re.sub('<[^<]+?>', '', fix_text(q, normalization='NFKC')).replace(r"\'", "'").replace(r'\"', '"')
q = re.sub('([,;:.!?])(\w|\"|\'|\()(?!\.)', '\g<1> \g<2>', q) q = re.sub('([,;:.!?])(\w|\"|\'|\()(?!\.)', '\g<1> \g<2>', q)
q = re.sub('(\$\d+[,.]) (\d+)', '\g<1>\g<2>', q) q = re.sub('(\$\d+[,.]) (\d+)', '\g<1>\g<2>', q)
q = " ".join(q.split()) q = " ".join(q.split())
@ -221,7 +222,7 @@ class Jeopardy(callbacks.Plugin):
clue = item['question'].strip() clue = item['question'].strip()
airdate = item['airdate'].split('T')[0] airdate = item['airdate'].split('T')[0]
answer = item['answer'].strip() answer = item['answer'].strip()
category = item['category']['title'].strip().upper() category = item['category']['title'].strip()
invalid = item['invalid_count'] invalid = item['invalid_count']
points = self.points points = self.points
if item['value']: if item['value']:
@ -229,9 +230,9 @@ class Jeopardy(callbacks.Plugin):
else: else:
points = self.points points = self.points
if self.registryValue('keepHistory', channel): if self.registryValue('keepHistory', channel):
if len(clue) > 1 and airdate and answer and category and not invalid and id not in asked and id not in self.history: if clue and airdate and answer and category and not invalid and id not in asked and id not in self.history:
q = "{0}*({1}) [${2}] \x02{3}: {4}\x0F*{5}*{6}".format(id, airdate, points, category, clue, answer, points) q = "{0}|{1}|{2}|{3}|{4}|{5}".format(id, airdate, points, category, clue, answer)
q = re.sub('<[^<]+?>', '', fix_text(q, normalization='NFKC')).encode('utf-8').decode('unicode_escape') q = re.sub('<[^<]+?>', '', fix_text(q, normalization='NFKC')).replace(r"\'", "'").replace(r'\"', '"')
q = re.sub('([,;:.!?])(\w|\"|\'|\()(?!\.)', '\g<1> \g<2>', q) q = re.sub('([,;:.!?])(\w|\"|\'|\()(?!\.)', '\g<1> \g<2>', q)
q = re.sub('(\$\d+[,.]) (\d+)', '\g<1>\g<2>', q) q = re.sub('(\$\d+[,.]) (\d+)', '\g<1>\g<2>', q)
q = " ".join(q.split()) q = " ".join(q.split())
@ -240,9 +241,9 @@ class Jeopardy(callbacks.Plugin):
n += 1 n += 1
j += 1 j += 1
else: else:
if len(clue) > 1 and airdate and answer and category and not invalid and id not in asked: if clue and airdate and answer and category and not invalid and id not in asked:
q = "{0}*({1}) [${2}] \x02{3}: {4}\x0F*{5}*{6}".format(id, airdate, points, category, clue, answer, points) q = "{0}|{1}|{2}|{3}|{4}|{5}".format(id, airdate, points, category, clue, answer)
q = re.sub('<[^<]+?>', '', fix_text(q, normalization='NFKC')).encode('utf-8').decode('unicode_escape') q = re.sub('<[^<]+?>', '', fix_text(q, normalization='NFKC')).replace(r"\'", "'").replace(r'\"', '"')
q = re.sub('([,;:.!?])(\w|\"|\'|\()(?!\.)', '\g<1> \g<2>', q) q = re.sub('([,;:.!?])(\w|\"|\'|\()(?!\.)', '\g<1> \g<2>', q)
q = re.sub('(\$\d+[,.]) (\d+)', '\g<1>\g<2>', q) q = re.sub('(\$\d+[,.]) (\d+)', '\g<1>\g<2>', q)
q = " ".join(q.split()) q = " ".join(q.split())
@ -267,15 +268,15 @@ class Jeopardy(callbacks.Plugin):
if not self.active: if not self.active:
return return
inactiveShutoff = self.registryValue('inactiveShutoff', self.channel) inactiveShutoff = self.registryValue('inactiveShutoff', self.channel)
if self.num == 0 or self.answered == self.total or self.numAsked == self.total: if len(self.questions) == 0:
self.reply('Oops! I ran out of questions!')
self.stop()
return
elif self.num == 0 or self.answered == self.total or self.numAsked == self.total:
self.stop() self.stop()
return return
elif self.unanswered > inactiveShutoff and inactiveShutoff > 0: elif self.unanswered > inactiveShutoff and inactiveShutoff > 0:
self.reply('Seems like no one\'s playing any more.') self.reply('Seems like no one\'s playing any more. Jeopardy! stopped.')
self.stop()
return
elif len(self.questions) == 0:
self.reply('Oops! I ran out of questions!')
self.stop() self.stop()
return return
self.id = None self.id = None
@ -283,18 +284,19 @@ class Jeopardy(callbacks.Plugin):
self.shown = 0 self.shown = 0
self.num -= 1 self.num -= 1
self.numAsked += 1 self.numAsked += 1
q = self.questions.pop(len(self.questions)-1).split('*') q = self.questions.pop(len(self.questions)-1).split('|')
question = {}
self.id = q[0] self.id = q[0]
self.q = q[1] question['airdate'] = q[1]
self.a = q[2] self.p = int(q[2])
self.p = int(q[3]) question['category'] = q[3]
question['clue'] = q[4]
self.a = q[5]
question['points'], question['number'], question['total'] = self.p, self.numAsked, self.total
def next_question(): def next_question():
if not self.active: if not self.active:
return return
if not self.registryValue('autoRestart', self.channel): self.question = self.question_template.render(question)
self.question = "{0}#{1} of {2}: {3}".format(self.color, self.numAsked, self.total, self.q)
else:
self.question = "{0}{1}".format(self.color, self.q)
self.reply(self.question) self.reply(self.question)
self.history.append(int(self.id)) self.history.append(int(self.id))
ans = re.sub('\(\d of\)', '', self.a) ans = re.sub('\(\d of\)', '', self.a)
@ -306,7 +308,7 @@ class Jeopardy(callbacks.Plugin):
self.a.append(a2) self.a.append(a2)
if self.numHints > 0: if self.numHints > 0:
blank = re.sub('\w', self.blankChar, ans) blank = re.sub('\w', self.blankChar, ans)
self.currentHint = "HINT: {0}".format(blank) self.currentHint = self.hint_template.render(hint = blank)
self.reply(self.currentHint) self.reply(self.currentHint)
def event(): def event():
self.timedEvent() self.timedEvent()
@ -348,16 +350,16 @@ class Jeopardy(callbacks.Plugin):
for i in range(0, max): for i in range(0, max):
item = sorted[i] item = sorted[i]
s = _('%s (%s: %s)') % (s, item[0], item[1]) s = _('%s (%s: %s)') % (s, item[0], item[1])
self.reply(s) self.reply('{0}'.format(s))
self.active = False self.active = False
try: try:
del self.games[self.channel].questions, self.games[self.channel].roundscores del self.games[self.channel].questions, self.games[self.channel].roundscores
except KeyError: except:
return return
else: else:
try: try:
del self.games[self.channel].questions, self.games[self.channel].roundscores del self.games[self.channel].questions, self.games[self.channel].roundscores
except KeyError: except:
return return
@ -398,7 +400,8 @@ class Jeopardy(callbacks.Plugin):
i += 1 i += 1
except: except:
break break
self.currentHint = "HINT: {0}".format(''.join(self.show[self.id])) hint = "{0}".format(''.join(self.show[self.id]))
self.currentHint = self.hint_template.render(hint = hint)
self.reply(self.currentHint) self.reply(self.currentHint)
self.p -= int(self.p * reduction) self.p -= int(self.p * reduction)
def event(): def event():
@ -446,7 +449,8 @@ class Jeopardy(callbacks.Plugin):
self.roundscores[msg.nick] = 0 self.roundscores[msg.nick] = 0
self.roundscores[msg.nick] += self.p self.roundscores[msg.nick] += self.p
self.unanswered = 0 self.unanswered = 0
self.reply("{0} got it! The full answer was: {1}. Points: {2} | Round Score: {3} | Total: {4}".format(msg.nick, self.a[0], self.p, self.roundscores[msg.nick], self.scores[msg.nick])) reply = self.correct_template.render(nick = msg.nick, answer = self.a[0], points = self.p, round = self.roundscores[msg.nick], total = self.scores[msg.nick])
self.reply(reply)
self.correct = True self.correct = True
self.answered += 1 self.answered += 1
try: try:
@ -571,12 +575,14 @@ class Jeopardy(callbacks.Plugin):
channel = msg.channel channel = msg.channel
if self.registryValue('requireOps', channel) and msg.nick not in irc.state.channels[channel].ops and not ircdb.checkCapability(msg.prefix, 'admin'): if self.registryValue('requireOps', channel) and msg.nick not in irc.state.channels[channel].ops and not ircdb.checkCapability(msg.prefix, 'admin'):
return return
if self.games[channel]: if self.games.get(channel):
if self.games[channel].active: if self.games[channel].active:
if self.games[channel].correct: if self.games[channel].correct:
irc.reply("Jeopardy! stopped.") reply = self.games[channel].stop_template.render()
irc.reply(reply, prefixNick=False)
else: else:
irc.reply("Jeopardy! stopped. (Answer: {0})".format(self.games[channel].a[0])) reply = self.games[channel].stop_template.render(answer = self.games[channel].a[0])
irc.reply(reply, prefixNick=False)
try: try:
self.games[channel].active = False self.games[channel].active = False
self.games[channel].stop() self.games[channel].stop()
@ -696,10 +702,11 @@ class Jeopardy(callbacks.Plugin):
channel = msg.channel channel = msg.channel
if channel in self.games: if channel in self.games:
if self.games[channel].active and self.games[channel].numHints > 0: if self.games[channel].active and self.games[channel].numHints > 0:
irc.reply("Hint: {0}".format(self.games[channel].currentHint), prefixNick=False) irc.reply("{0}".format(self.games[channel].currentHint), prefixNick=False)
elif self.games[channel].active and self.games[channel].numHints == 0: elif self.games[channel].active and self.games[channel].numHints == 0:
blank = re.sub('\w', self.games[channel].blankChar, self.games[channel].a[0]) blank = re.sub('\w', self.games[channel].blankChar, self.games[channel].a[0])
irc.reply("HINT: {0}".format(blank), prefixNick=False) hint = self.hint_template.render(hint = blank)
irc.reply(hint, prefixNick=False)
if self.games[channel].shown == 0: if self.games[channel].shown == 0:
reduction = self.registryValue('hintReduction', channel) reduction = self.registryValue('hintReduction', channel)
self.games[channel].p -= int(self.games[channel].p * reduction) self.games[channel].p -= int(self.games[channel].p * reduction)
@ -749,7 +756,8 @@ class Jeopardy(callbacks.Plugin):
return return
if channel in self.games: if channel in self.games:
if self.games[channel].active: if self.games[channel].active:
irc.reply('Skipping question. (Answer: {0})'.format(self.games[channel].a[0]), prefixNick=False) reply = self.games[channel].skip_template.render(answer = self.games[channel].a[0])
irc.reply(reply, prefixNick=False)
self.games[channel].unanswered = 0 self.games[channel].unanswered = 0
self.games[channel].correct = True self.games[channel].correct = True
self.games[channel].answered += 1 self.games[channel].answered += 1
@ -766,3 +774,4 @@ class Jeopardy(callbacks.Plugin):
Class = Jeopardy Class = Jeopardy

View File

@ -3,3 +3,4 @@ ftfy
beautifulsoup4 beautifulsoup4
numpy numpy
textdistance[extras] textdistance[extras]
jinja2