Compare commits
No commits in common. "f78d407d4cbfa6c5a17ba611c0ddb367b54e72ce" and "058993913747f62edfc1dea24a72d446a9770b2c" have entirely different histories.
f78d407d4c
...
0589939137
@ -1,5 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.10.5 on 2017-02-23 02:25
|
# Generated by Django 1.10.5 on 2017-02-23 02:25
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.10.5 on 2017-02-24 01:06
|
# Generated by Django 1.10.5 on 2017-02-24 01:06
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.10.5 on 2017-02-24 01:12
|
# Generated by Django 1.10.5 on 2017-02-24 01:12
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,28 +1,36 @@
|
|||||||
"""Roll dice when asked, intended for RPGs."""
|
"""Roll dice when asked, intended for RPGs."""
|
||||||
|
|
||||||
|
# this breaks yacc, but ply might be happy in py3
|
||||||
|
#from __future__ import unicode_literals
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import math
|
||||||
import re
|
import re
|
||||||
import random
|
import random
|
||||||
|
|
||||||
from irc.client import NickMask
|
from irc.client import NickMask
|
||||||
|
|
||||||
from dice.roller import DiceRoller
|
import ply.lex as lex
|
||||||
|
import ply.yacc as yacc
|
||||||
|
|
||||||
from ircbot.lib import Plugin
|
from ircbot.lib import Plugin
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Dice(Plugin):
|
class Dice(Plugin):
|
||||||
"""Roll simple or complex dice strings."""
|
|
||||||
|
|
||||||
def __init__(self):
|
"""Roll simple or complex dice strings."""
|
||||||
"""Set up the plugin."""
|
|
||||||
super(Dice, self).__init__()
|
|
||||||
self.roller = DiceRoller()
|
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""Set up the handlers."""
|
"""Set up the handlers."""
|
||||||
|
|
||||||
|
self.roller = DiceRoller()
|
||||||
|
|
||||||
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!roll\s+(.*)$',
|
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!roll\s+(.*)$',
|
||||||
self.handle_roll, -20)
|
self.handle_roll, -20)
|
||||||
|
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!ctech\s+(.*)$',
|
||||||
|
self.handle_ctech, -20)
|
||||||
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!random\s+(.*)$',
|
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!random\s+(.*)$',
|
||||||
self.handle_random, -20)
|
self.handle_random, -20)
|
||||||
|
|
||||||
@ -30,7 +38,9 @@ class Dice(Plugin):
|
|||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""Tear down handlers."""
|
"""Tear down handlers."""
|
||||||
|
|
||||||
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_roll)
|
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_roll)
|
||||||
|
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_ctech)
|
||||||
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_random)
|
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_random)
|
||||||
|
|
||||||
super(Dice, self).stop()
|
super(Dice, self).stop()
|
||||||
@ -58,17 +68,368 @@ class Dice(Plugin):
|
|||||||
dicestr = match.group(1)
|
dicestr = match.group(1)
|
||||||
|
|
||||||
logger.debug(event.recursing)
|
logger.debug(event.recursing)
|
||||||
try:
|
|
||||||
reply_str = self.roller.do_roll(dicestr)
|
|
||||||
except AssertionError as aex:
|
|
||||||
reply_str = f"Could not roll dice: {aex}"
|
|
||||||
except ValueError:
|
|
||||||
reply_str = "Unable to parse roll"
|
|
||||||
|
|
||||||
if event.recursing:
|
if event.recursing:
|
||||||
reply = "{0:s}".format(reply_str)
|
reply = "{0:s}".format(self.roller.do_roll(dicestr))
|
||||||
else:
|
else:
|
||||||
reply = "{0:s}: {1:s}".format(nick, reply_str)
|
reply = "{0:s}: {1:s}".format(nick, self.roller.do_roll(dicestr))
|
||||||
return self.bot.reply(event, re.sub(r'(\d+)(.*?\s+)(\(.*?\))', r'\1\214\3', reply))
|
return self.bot.reply(event, re.sub(r'(\d+)(.*?\s+)(\(.*?\))', r'\1\214\3', reply))
|
||||||
|
|
||||||
|
def handle_ctech(self, connection, event, match):
|
||||||
|
"""Handle cthulhutech dice rolls."""
|
||||||
|
|
||||||
|
nick = NickMask(event.source).nick
|
||||||
|
rollitrs = re.split(';\s*', match.group(1))
|
||||||
|
reply = ""
|
||||||
|
for count, roll in enumerate(rollitrs):
|
||||||
|
pattern = '^(\d+)d(?:(\+|\-)(\d+))?(?:\s+(.*))?'
|
||||||
|
regex = re.compile(pattern)
|
||||||
|
matches = regex.search(roll)
|
||||||
|
if matches is not None:
|
||||||
|
dice = int(matches.group(1))
|
||||||
|
modifier = 0
|
||||||
|
|
||||||
|
if matches.group(2) is not None and matches.group(3) is not None:
|
||||||
|
if str(matches.group(2)) == '-':
|
||||||
|
modifier = -1 * int(matches.group(3))
|
||||||
|
else:
|
||||||
|
modifier = int(matches.group(3))
|
||||||
|
|
||||||
|
result = roll + ': '
|
||||||
|
|
||||||
|
rolls = []
|
||||||
|
for d in range(dice):
|
||||||
|
rolls.append(random.randint(1, 10))
|
||||||
|
rolls.sort()
|
||||||
|
rolls.reverse()
|
||||||
|
|
||||||
|
# highest single die method
|
||||||
|
method1 = rolls[0]
|
||||||
|
|
||||||
|
# highest set method
|
||||||
|
method2 = 0
|
||||||
|
rolling_sum = 0
|
||||||
|
for i, r in enumerate(rolls):
|
||||||
|
# if next roll is same as current, sum and continue, else see if sum is best so far
|
||||||
|
if i+1 < len(rolls) and rolls[i+1] == r:
|
||||||
|
if rolling_sum == 0:
|
||||||
|
rolling_sum = r
|
||||||
|
rolling_sum += r
|
||||||
|
else:
|
||||||
|
if rolling_sum > method2:
|
||||||
|
method2 = rolling_sum
|
||||||
|
rolling_sum = 0
|
||||||
|
# check for set in progress (e.g. lots of 1s)
|
||||||
|
if rolling_sum > method2:
|
||||||
|
method2 = rolling_sum
|
||||||
|
|
||||||
|
# straight method
|
||||||
|
method3 = 0
|
||||||
|
rolling_sum = 0
|
||||||
|
count = 0
|
||||||
|
for i, r in enumerate(rolls):
|
||||||
|
# if next roll is one less as current, sum and continue, else check len and see if sum is best so far
|
||||||
|
if i+1 < len(rolls) and rolls[i+1] == r-1:
|
||||||
|
if rolling_sum == 0:
|
||||||
|
rolling_sum = r
|
||||||
|
count += 1
|
||||||
|
rolling_sum += r-1
|
||||||
|
count += 1
|
||||||
|
else:
|
||||||
|
if count >= 3 and rolling_sum > method3:
|
||||||
|
method3 = rolling_sum
|
||||||
|
rolling_sum = 0
|
||||||
|
# check for straight in progress (e.g. straight ending in 1)
|
||||||
|
if count >= 3 and rolling_sum > method3:
|
||||||
|
method3 = rolling_sum
|
||||||
|
|
||||||
|
# get best roll
|
||||||
|
best = max([method1, method2, method3])
|
||||||
|
|
||||||
|
# check for critical failure
|
||||||
|
botch = False
|
||||||
|
ones = 0
|
||||||
|
for r in rolls:
|
||||||
|
if r == 1:
|
||||||
|
ones += 1
|
||||||
|
if ones >= math.ceil(float(len(rolls))/2):
|
||||||
|
botch = True
|
||||||
|
|
||||||
|
if botch:
|
||||||
|
result += 'BOTCH'
|
||||||
|
else:
|
||||||
|
result += str(best + modifier)
|
||||||
|
rollres = ''
|
||||||
|
for i,r in enumerate(rolls):
|
||||||
|
rollres += str(r)
|
||||||
|
if i is not len(rolls)-1:
|
||||||
|
rollres += ','
|
||||||
|
result += ' [' + rollres
|
||||||
|
if modifier != 0:
|
||||||
|
if modifier > 0:
|
||||||
|
result += ' +' + str(modifier)
|
||||||
|
else:
|
||||||
|
result += ' -' + str(modifier * -1)
|
||||||
|
result += ']'
|
||||||
|
|
||||||
|
reply += result
|
||||||
|
if count is not len(rollitrs)-1:
|
||||||
|
reply += "; "
|
||||||
|
if reply is not "":
|
||||||
|
msg = "{0:s}: {1:s}".format(nick, reply)
|
||||||
|
return self.bot.reply(event, msg)
|
||||||
|
|
||||||
|
|
||||||
|
class DiceRoller(object):
|
||||||
|
|
||||||
|
tokens = ['NUMBER', 'TEXT', 'ROLLSEP']
|
||||||
|
literals = ['#', '/', '+', '-', 'd']
|
||||||
|
|
||||||
|
t_TEXT = r'\s+[^;]+'
|
||||||
|
t_ROLLSEP = r';\s*'
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
lex.lex(module=self)
|
||||||
|
yacc.yacc(module=self)
|
||||||
|
|
||||||
|
def t_NUMBER(self, t):
|
||||||
|
r'\d+'
|
||||||
|
t.value = int(t.value)
|
||||||
|
return t
|
||||||
|
|
||||||
|
def t_error(self, t):
|
||||||
|
t.lexer.skip(1)
|
||||||
|
|
||||||
|
precedence = (
|
||||||
|
('left', 'ROLLSEP'),
|
||||||
|
('left', '+', '-'),
|
||||||
|
('right', 'd'),
|
||||||
|
('left', '#'),
|
||||||
|
('left', '/')
|
||||||
|
)
|
||||||
|
|
||||||
|
output = ""
|
||||||
|
|
||||||
|
def roll_dice(self, keep, dice, size):
|
||||||
|
"""Takes the parsed dice string for a single roll (eg 3/4d20) and performs
|
||||||
|
the actual roll. Returns a string representing the result.
|
||||||
|
"""
|
||||||
|
|
||||||
|
a = list(range(dice))
|
||||||
|
for i in range(dice):
|
||||||
|
a[i] = random.randint(1, size)
|
||||||
|
if keep != dice:
|
||||||
|
b = sorted(a, reverse=True)
|
||||||
|
b = b[0:keep]
|
||||||
|
else:
|
||||||
|
b = a
|
||||||
|
total = sum(b)
|
||||||
|
outstr = "[" + ",".join(str(i) for i in a) + "]"
|
||||||
|
|
||||||
|
return (total, outstr)
|
||||||
|
|
||||||
|
def process_roll(self, trials, mods, comment):
|
||||||
|
"""Processes rolls coming from the parser.
|
||||||
|
|
||||||
|
This generates the inputs for the roll_dice() command, and returns
|
||||||
|
the full string representing the whole current dice string (the part
|
||||||
|
up to a semicolon or end of line).
|
||||||
|
"""
|
||||||
|
|
||||||
|
output = ""
|
||||||
|
repeat = 1
|
||||||
|
if trials != None:
|
||||||
|
repeat = trials
|
||||||
|
for i in range(repeat):
|
||||||
|
mode = 1
|
||||||
|
total = 0
|
||||||
|
curr_str = ""
|
||||||
|
if i > 0:
|
||||||
|
output += ", "
|
||||||
|
for m in mods:
|
||||||
|
keep = 0
|
||||||
|
dice = 1
|
||||||
|
res = 0
|
||||||
|
# if m is a tuple, then it is a die roll
|
||||||
|
# m[0] = (keep, num dice)
|
||||||
|
# m[1] = num faces on the die
|
||||||
|
if type(m) == tuple:
|
||||||
|
if m[0] != None:
|
||||||
|
if m[0][0] != None:
|
||||||
|
keep = m[0][0]
|
||||||
|
dice = m[0][1]
|
||||||
|
size = m[1]
|
||||||
|
if keep > dice or keep == 0:
|
||||||
|
keep = dice
|
||||||
|
if size < 1:
|
||||||
|
output = "# of sides for die is incorrect: %d" % size
|
||||||
|
return output
|
||||||
|
if dice < 1:
|
||||||
|
output = "# of dice is incorrect: %d" % dice
|
||||||
|
return output
|
||||||
|
res = self.roll_dice(keep, dice, size)
|
||||||
|
curr_str += "%d%s" % (res[0], res[1])
|
||||||
|
res = res[0]
|
||||||
|
elif m == "+":
|
||||||
|
mode = 1
|
||||||
|
curr_str += "+"
|
||||||
|
elif m == "-":
|
||||||
|
mode = -1
|
||||||
|
curr_str += "-"
|
||||||
|
else:
|
||||||
|
res = m
|
||||||
|
curr_str += str(m)
|
||||||
|
total += mode * res
|
||||||
|
if repeat == 1:
|
||||||
|
if comment != None:
|
||||||
|
output = "%d %s (%s)" % (total, comment.strip(), curr_str)
|
||||||
|
else:
|
||||||
|
output = "%d (%s)" % (total, curr_str)
|
||||||
|
else:
|
||||||
|
output += "%d (%s)" % (total, curr_str)
|
||||||
|
if i == repeat - 1:
|
||||||
|
if comment != None:
|
||||||
|
output += " (%s)" % (comment.strip())
|
||||||
|
return output
|
||||||
|
|
||||||
|
def p_roll_r(self, p):
|
||||||
|
# Chain rolls together.
|
||||||
|
|
||||||
|
# General idea I had when creating this grammar: A roll string is a chain
|
||||||
|
# of modifiers, which may be repeated for a certain number of trials. It can
|
||||||
|
# have a comment that describes the roll
|
||||||
|
# Multiple roll strings can be chained with semicolon
|
||||||
|
|
||||||
|
'roll : roll ROLLSEP roll'
|
||||||
|
global output
|
||||||
|
p[0] = p[1] + "; " + p[3]
|
||||||
|
output = p[0]
|
||||||
|
|
||||||
|
def p_roll(self, p):
|
||||||
|
# Parse a basic roll string.
|
||||||
|
|
||||||
|
'roll : trial modifier comment'
|
||||||
|
global output
|
||||||
|
mods = []
|
||||||
|
if type(p[2]) == list:
|
||||||
|
mods = p[2]
|
||||||
|
else:
|
||||||
|
mods = [p[2]]
|
||||||
|
p[0] = self.process_roll(p[1], mods, p[3])
|
||||||
|
output = p[0]
|
||||||
|
|
||||||
|
def p_roll_no_trials(self, p):
|
||||||
|
# Parse a roll string without trials.
|
||||||
|
|
||||||
|
'roll : modifier comment'
|
||||||
|
global output
|
||||||
|
mods = []
|
||||||
|
if type(p[1]) == list:
|
||||||
|
mods = p[1]
|
||||||
|
else:
|
||||||
|
mods = [p[1]]
|
||||||
|
p[0] = self.process_roll(None, mods, p[2])
|
||||||
|
output = p[0]
|
||||||
|
|
||||||
|
def p_comment(self, p):
|
||||||
|
# Parse a comment.
|
||||||
|
|
||||||
|
'''comment : TEXT
|
||||||
|
|'''
|
||||||
|
if len(p) == 2:
|
||||||
|
p[0] = p[1]
|
||||||
|
else:
|
||||||
|
p[0] = None
|
||||||
|
|
||||||
|
def p_modifier(self, p):
|
||||||
|
# Parse a modifier on a roll string.
|
||||||
|
|
||||||
|
'''modifier : modifier "+" modifier
|
||||||
|
| modifier "-" modifier'''
|
||||||
|
# Use append to prevent nested lists (makes dealing with this easier)
|
||||||
|
if type(p[1]) == list:
|
||||||
|
p[1].append(p[2])
|
||||||
|
p[1].append(p[3])
|
||||||
|
p[0] = p[1]
|
||||||
|
elif type(p[3]) == list:
|
||||||
|
p[3].insert(0, p[2])
|
||||||
|
p[3].insert(0, p[1])
|
||||||
|
p[0] = p[3]
|
||||||
|
else:
|
||||||
|
p[0] = [p[1], p[2], p[3]]
|
||||||
|
|
||||||
|
def p_die(self, p):
|
||||||
|
# Return the left side before the "d", and the number of faces.
|
||||||
|
|
||||||
|
'modifier : left NUMBER'
|
||||||
|
p[0] = (p[1], p[2])
|
||||||
|
|
||||||
|
def p_die_num(self, p):
|
||||||
|
'modifier : NUMBER'
|
||||||
|
p[0] = p[1]
|
||||||
|
|
||||||
|
def p_left(self, p):
|
||||||
|
# Parse the number of dice we are rolling, and how many we are keeping.
|
||||||
|
'left : keep dice'
|
||||||
|
if p[1] == None:
|
||||||
|
p[0] = [None, p[2]]
|
||||||
|
else:
|
||||||
|
p[0] = [p[1], p[2]]
|
||||||
|
|
||||||
|
def p_left_all(self, p):
|
||||||
|
'left : dice'
|
||||||
|
p[0] = [None, p[1]]
|
||||||
|
|
||||||
|
def p_left_e(self, p):
|
||||||
|
'left :'
|
||||||
|
p[0] = None
|
||||||
|
|
||||||
|
def p_total(self, p):
|
||||||
|
'trial : NUMBER "#"'
|
||||||
|
if len(p) > 1:
|
||||||
|
p[0] = p[1]
|
||||||
|
else:
|
||||||
|
p[0] = None
|
||||||
|
|
||||||
|
def p_keep(self, p):
|
||||||
|
'keep : NUMBER "/"'
|
||||||
|
if p[1] != None:
|
||||||
|
p[0] = p[1]
|
||||||
|
else:
|
||||||
|
p[0] = None
|
||||||
|
|
||||||
|
def p_dice(self, p):
|
||||||
|
'dice : NUMBER "d"'
|
||||||
|
p[0] = p[1]
|
||||||
|
|
||||||
|
def p_dice_one(self, p):
|
||||||
|
'dice : "d"'
|
||||||
|
p[0] = 1
|
||||||
|
|
||||||
|
def p_error(self, p):
|
||||||
|
# Provide the user with something (albeit not much) when the roll can't be parsed.
|
||||||
|
global output
|
||||||
|
output = "Unable to parse roll"
|
||||||
|
|
||||||
|
def get_result(self):
|
||||||
|
global output
|
||||||
|
return output
|
||||||
|
|
||||||
|
def do_roll(self, dicestr):
|
||||||
|
"""
|
||||||
|
Roll some dice and get the result (with broken out rolls).
|
||||||
|
|
||||||
|
Keyword arguments:
|
||||||
|
dicestr - format:
|
||||||
|
N#X/YdS+M label
|
||||||
|
N#: do the following roll N times (optional)
|
||||||
|
X/: take the top X rolls of the Y times rolled (optional)
|
||||||
|
Y : roll the die specified Y times (optional, defaults to 1)
|
||||||
|
dS: roll a S-sided die
|
||||||
|
+M: add M to the result (-M for subtraction) (optional)
|
||||||
|
"""
|
||||||
|
self.build()
|
||||||
|
yacc.parse(dicestr)
|
||||||
|
return self.get_result()
|
||||||
|
|
||||||
|
|
||||||
plugin = Dice
|
plugin = Dice
|
||||||
|
263
dice/roller.py
263
dice/roller.py
@ -1,263 +0,0 @@
|
|||||||
"""Dice rollers used by the views, bots, etc."""
|
|
||||||
import logging
|
|
||||||
import random
|
|
||||||
|
|
||||||
import ply.lex as lex
|
|
||||||
import ply.yacc as yacc
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class DiceRoller(object):
|
|
||||||
|
|
||||||
tokens = ['NUMBER', 'TEXT', 'ROLLSEP']
|
|
||||||
literals = ['#', '/', '+', '-', 'd']
|
|
||||||
|
|
||||||
t_TEXT = r'\s+[^;]+'
|
|
||||||
t_ROLLSEP = r';\s*'
|
|
||||||
|
|
||||||
def build(self):
|
|
||||||
lex.lex(module=self)
|
|
||||||
yacc.yacc(module=self)
|
|
||||||
|
|
||||||
def t_NUMBER(self, t):
|
|
||||||
r'\d+'
|
|
||||||
t.value = int(t.value)
|
|
||||||
return t
|
|
||||||
|
|
||||||
def t_error(self, t):
|
|
||||||
t.lexer.skip(1)
|
|
||||||
|
|
||||||
precedence = (
|
|
||||||
('left', 'ROLLSEP'),
|
|
||||||
('left', '+', '-'),
|
|
||||||
('right', 'd'),
|
|
||||||
('left', '#'),
|
|
||||||
('left', '/')
|
|
||||||
)
|
|
||||||
|
|
||||||
output = ""
|
|
||||||
|
|
||||||
def roll_dice(self, keep, dice, size):
|
|
||||||
"""Takes the parsed dice string for a single roll (eg 3/4d20) and performs
|
|
||||||
the actual roll. Returns a string representing the result.
|
|
||||||
"""
|
|
||||||
|
|
||||||
a = list(range(dice))
|
|
||||||
for i in range(dice):
|
|
||||||
a[i] = random.randint(1, size)
|
|
||||||
if keep != dice:
|
|
||||||
b = sorted(a, reverse=True)
|
|
||||||
b = b[0:keep]
|
|
||||||
else:
|
|
||||||
b = a
|
|
||||||
total = sum(b)
|
|
||||||
outstr = "[" + ",".join(str(i) for i in a) + "]"
|
|
||||||
|
|
||||||
return (total, outstr)
|
|
||||||
|
|
||||||
def process_roll(self, trials, mods, comment):
|
|
||||||
"""Processes rolls coming from the parser.
|
|
||||||
|
|
||||||
This generates the inputs for the roll_dice() command, and returns
|
|
||||||
the full string representing the whole current dice string (the part
|
|
||||||
up to a semicolon or end of line).
|
|
||||||
"""
|
|
||||||
rolls = mods[0][0][1] if mods[0][0][1] else 1
|
|
||||||
assert trials <= 10, "Too many rolls (max: 10)."
|
|
||||||
assert rolls <= 50, "Too many dice (max: 50) in roll."
|
|
||||||
|
|
||||||
output = ""
|
|
||||||
repeat = 1
|
|
||||||
if trials != None:
|
|
||||||
repeat = trials
|
|
||||||
for i in range(repeat):
|
|
||||||
mode = 1
|
|
||||||
total = 0
|
|
||||||
curr_str = ""
|
|
||||||
if i > 0:
|
|
||||||
output += ", "
|
|
||||||
for m in mods:
|
|
||||||
keep = 0
|
|
||||||
dice = 1
|
|
||||||
res = 0
|
|
||||||
# if m is a tuple, then it is a die roll
|
|
||||||
# m[0] = (keep, num dice)
|
|
||||||
# m[1] = num faces on the die
|
|
||||||
if type(m) == tuple:
|
|
||||||
if m[0] != None:
|
|
||||||
if m[0][0] != None:
|
|
||||||
keep = m[0][0]
|
|
||||||
dice = m[0][1]
|
|
||||||
size = m[1]
|
|
||||||
if keep > dice or keep == 0:
|
|
||||||
keep = dice
|
|
||||||
if size < 1:
|
|
||||||
output = "# of sides for die is incorrect: %d" % size
|
|
||||||
return output
|
|
||||||
if dice < 1:
|
|
||||||
output = "# of dice is incorrect: %d" % dice
|
|
||||||
return output
|
|
||||||
res = self.roll_dice(keep, dice, size)
|
|
||||||
curr_str += "%d%s" % (res[0], res[1])
|
|
||||||
res = res[0]
|
|
||||||
elif m == "+":
|
|
||||||
mode = 1
|
|
||||||
curr_str += "+"
|
|
||||||
elif m == "-":
|
|
||||||
mode = -1
|
|
||||||
curr_str += "-"
|
|
||||||
else:
|
|
||||||
res = m
|
|
||||||
curr_str += str(m)
|
|
||||||
total += mode * res
|
|
||||||
if repeat == 1:
|
|
||||||
if comment != None:
|
|
||||||
output = "%d %s (%s)" % (total, comment.strip(), curr_str)
|
|
||||||
else:
|
|
||||||
output = "%d (%s)" % (total, curr_str)
|
|
||||||
else:
|
|
||||||
output += "%d (%s)" % (total, curr_str)
|
|
||||||
if i == repeat - 1:
|
|
||||||
if comment != None:
|
|
||||||
output += " (%s)" % (comment.strip())
|
|
||||||
return output
|
|
||||||
|
|
||||||
def p_roll_r(self, p):
|
|
||||||
# Chain rolls together.
|
|
||||||
|
|
||||||
# General idea I had when creating this grammar: A roll string is a chain
|
|
||||||
# of modifiers, which may be repeated for a certain number of trials. It can
|
|
||||||
# have a comment that describes the roll
|
|
||||||
# Multiple roll strings can be chained with semicolon
|
|
||||||
|
|
||||||
'roll : roll ROLLSEP roll'
|
|
||||||
global output
|
|
||||||
p[0] = p[1] + "; " + p[3]
|
|
||||||
output = p[0]
|
|
||||||
|
|
||||||
def p_roll(self, p):
|
|
||||||
# Parse a basic roll string.
|
|
||||||
|
|
||||||
'roll : trial modifier comment'
|
|
||||||
global output
|
|
||||||
mods = []
|
|
||||||
if type(p[2]) == list:
|
|
||||||
mods = p[2]
|
|
||||||
else:
|
|
||||||
mods = [p[2]]
|
|
||||||
p[0] = self.process_roll(p[1], mods, p[3])
|
|
||||||
output = p[0]
|
|
||||||
|
|
||||||
def p_roll_no_trials(self, p):
|
|
||||||
# Parse a roll string without trials.
|
|
||||||
|
|
||||||
'roll : modifier comment'
|
|
||||||
global output
|
|
||||||
mods = []
|
|
||||||
if type(p[1]) == list:
|
|
||||||
mods = p[1]
|
|
||||||
else:
|
|
||||||
mods = [p[1]]
|
|
||||||
p[0] = self.process_roll(None, mods, p[2])
|
|
||||||
output = p[0]
|
|
||||||
|
|
||||||
def p_comment(self, p):
|
|
||||||
# Parse a comment.
|
|
||||||
|
|
||||||
'''comment : TEXT
|
|
||||||
|'''
|
|
||||||
if len(p) == 2:
|
|
||||||
p[0] = p[1]
|
|
||||||
else:
|
|
||||||
p[0] = None
|
|
||||||
|
|
||||||
def p_modifier(self, p):
|
|
||||||
# Parse a modifier on a roll string.
|
|
||||||
|
|
||||||
'''modifier : modifier "+" modifier
|
|
||||||
| modifier "-" modifier'''
|
|
||||||
# Use append to prevent nested lists (makes dealing with this easier)
|
|
||||||
if type(p[1]) == list:
|
|
||||||
p[1].append(p[2])
|
|
||||||
p[1].append(p[3])
|
|
||||||
p[0] = p[1]
|
|
||||||
elif type(p[3]) == list:
|
|
||||||
p[3].insert(0, p[2])
|
|
||||||
p[3].insert(0, p[1])
|
|
||||||
p[0] = p[3]
|
|
||||||
else:
|
|
||||||
p[0] = [p[1], p[2], p[3]]
|
|
||||||
|
|
||||||
def p_die(self, p):
|
|
||||||
# Return the left side before the "d", and the number of faces.
|
|
||||||
|
|
||||||
'modifier : left NUMBER'
|
|
||||||
p[0] = (p[1], p[2])
|
|
||||||
|
|
||||||
def p_die_num(self, p):
|
|
||||||
'modifier : NUMBER'
|
|
||||||
p[0] = p[1]
|
|
||||||
|
|
||||||
def p_left(self, p):
|
|
||||||
# Parse the number of dice we are rolling, and how many we are keeping.
|
|
||||||
'left : keep dice'
|
|
||||||
if p[1] == None:
|
|
||||||
p[0] = [None, p[2]]
|
|
||||||
else:
|
|
||||||
p[0] = [p[1], p[2]]
|
|
||||||
|
|
||||||
def p_left_all(self, p):
|
|
||||||
'left : dice'
|
|
||||||
p[0] = [None, p[1]]
|
|
||||||
|
|
||||||
def p_left_e(self, p):
|
|
||||||
'left :'
|
|
||||||
p[0] = None
|
|
||||||
|
|
||||||
def p_total(self, p):
|
|
||||||
'trial : NUMBER "#"'
|
|
||||||
if len(p) > 1:
|
|
||||||
p[0] = p[1]
|
|
||||||
else:
|
|
||||||
p[0] = None
|
|
||||||
|
|
||||||
def p_keep(self, p):
|
|
||||||
'keep : NUMBER "/"'
|
|
||||||
if p[1] != None:
|
|
||||||
p[0] = p[1]
|
|
||||||
else:
|
|
||||||
p[0] = None
|
|
||||||
|
|
||||||
def p_dice(self, p):
|
|
||||||
'dice : NUMBER "d"'
|
|
||||||
p[0] = p[1]
|
|
||||||
|
|
||||||
def p_dice_one(self, p):
|
|
||||||
'dice : "d"'
|
|
||||||
p[0] = 1
|
|
||||||
|
|
||||||
def p_error(self, p):
|
|
||||||
"""Raise ValueError on unparseable strings."""
|
|
||||||
raise ValueError("Error occurred in parser")
|
|
||||||
|
|
||||||
def get_result(self):
|
|
||||||
global output
|
|
||||||
return output
|
|
||||||
|
|
||||||
def do_roll(self, dicestr):
|
|
||||||
"""
|
|
||||||
Roll some dice and get the result (with broken out rolls).
|
|
||||||
|
|
||||||
Keyword arguments:
|
|
||||||
dicestr - format:
|
|
||||||
N#X/YdS+M label
|
|
||||||
N#: do the following roll N times (optional)
|
|
||||||
X/: take the top X rolls of the Y times rolled (optional)
|
|
||||||
Y : roll the die specified Y times (optional, defaults to 1)
|
|
||||||
dS: roll a S-sided die
|
|
||||||
+M: add M to the result (-M for subtraction) (optional)
|
|
||||||
"""
|
|
||||||
self.build()
|
|
||||||
yacc.parse(dicestr)
|
|
||||||
return self.get_result()
|
|
@ -29,6 +29,6 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='dispatcheraction',
|
model_name='dispatcheraction',
|
||||||
name='dispatcher',
|
name='dispatcher',
|
||||||
field=models.ForeignKey(to='dispatch.Dispatcher', on_delete=models.CASCADE),
|
field=models.ForeignKey(to='dispatch.Dispatcher'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -17,6 +17,6 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='dispatcheraction',
|
model_name='dispatcheraction',
|
||||||
name='dispatcher',
|
name='dispatcher',
|
||||||
field=models.ForeignKey(related_name='actions', to='dispatch.Dispatcher', on_delete=models.CASCADE),
|
field=models.ForeignKey(related_name='actions', to='dispatch.Dispatcher'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ class DispatcherAction(models.Model):
|
|||||||
(FILE_TYPE, "Write to file"),
|
(FILE_TYPE, "Write to file"),
|
||||||
)
|
)
|
||||||
|
|
||||||
dispatcher = models.ForeignKey('Dispatcher', related_name='actions', on_delete=models.CASCADE)
|
dispatcher = models.ForeignKey('Dispatcher', related_name='actions')
|
||||||
type = models.CharField(max_length=16, choices=TYPE_CHOICES)
|
type = models.CharField(max_length=16, choices=TYPE_CHOICES)
|
||||||
destination = models.CharField(max_length=200)
|
destination = models.CharField(max_length=200)
|
||||||
include_key = models.BooleanField(default=False)
|
include_key = models.BooleanField(default=False)
|
||||||
|
@ -11,7 +11,7 @@ https://docs.djangoproject.com/en/1.6/ref/settings/
|
|||||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from django.urls import reverse_lazy
|
from django.core.urlresolvers import reverse_lazy
|
||||||
|
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||||
|
|
||||||
@ -57,11 +57,12 @@ INSTALLED_APPS = (
|
|||||||
'twitter',
|
'twitter',
|
||||||
)
|
)
|
||||||
|
|
||||||
MIDDLEWARE = (
|
MIDDLEWARE_CLASSES = (
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
@ -20,5 +20,5 @@ urlpatterns = [
|
|||||||
url(r'^races/', include('races.urls')),
|
url(r'^races/', include('races.urls')),
|
||||||
|
|
||||||
url(r'^accounts/', include('registration.backends.default.urls')),
|
url(r'^accounts/', include('registration.backends.default.urls')),
|
||||||
url(r'^admin/', admin.site.urls),
|
url(r'^admin/', include(admin.site.urls)),
|
||||||
]
|
]
|
||||||
|
@ -26,6 +26,6 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='fact',
|
model_name='fact',
|
||||||
name='category',
|
name='category',
|
||||||
field=models.ForeignKey(to='facts.FactCategory', on_delete=models.CASCADE),
|
field=models.ForeignKey(to='facts.FactCategory'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.10.5 on 2017-02-11 15:00
|
# Generated by Django 1.10.5 on 2017-02-11 15:00
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ class Fact(models.Model):
|
|||||||
"""Define facts."""
|
"""Define facts."""
|
||||||
|
|
||||||
fact = models.TextField()
|
fact = models.TextField()
|
||||||
category = models.ForeignKey(FactCategory, on_delete=models.CASCADE)
|
category = models.ForeignKey(FactCategory)
|
||||||
nickmask = models.CharField(max_length=200, default='', blank=True)
|
nickmask = models.CharField(max_length=200, default='', blank=True)
|
||||||
time = models.DateTimeField(auto_now_add=True)
|
time = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
@ -25,7 +27,7 @@ class Migration(migrations.Migration):
|
|||||||
('code_reviews_necessary', models.PositiveSmallIntegerField(default=0)),
|
('code_reviews_necessary', models.PositiveSmallIntegerField(default=0)),
|
||||||
('code_reviewers', models.TextField(blank=True, default='')),
|
('code_reviewers', models.TextField(blank=True, default='')),
|
||||||
('code_review_final_merge_assignees', models.TextField(blank=True, default='')),
|
('code_review_final_merge_assignees', models.TextField(blank=True, default='')),
|
||||||
('gitlab_config', models.ForeignKey(to='gitlab_bot.GitlabConfig', null=True, on_delete=models.CASCADE)),
|
('gitlab_config', models.ForeignKey(to='gitlab_bot.GitlabConfig', null=True)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ class GitlabProjectConfig(models.Model):
|
|||||||
|
|
||||||
"""Maintain settings for a particular project in GitLab."""
|
"""Maintain settings for a particular project in GitLab."""
|
||||||
|
|
||||||
gitlab_config = models.ForeignKey('GitlabConfig', null=True, on_delete=models.CASCADE)
|
gitlab_config = models.ForeignKey('GitlabConfig', null=True)
|
||||||
project_id = models.CharField(max_length=64, unique=True)
|
project_id = models.CharField(max_length=64, unique=True)
|
||||||
|
|
||||||
manage_merge_request_code_reviews = models.BooleanField(default=False)
|
manage_merge_request_code_reviews = models.BooleanField(default=False)
|
||||||
|
@ -15,7 +15,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='botadmin',
|
model_name='botadmin',
|
||||||
name='user',
|
name='user',
|
||||||
field=models.ForeignKey(default=1, to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
|
field=models.ForeignKey(default=1, to=settings.AUTH_USER_MODEL),
|
||||||
preserve_default=False,
|
preserve_default=False,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ class BotUser(models.Model):
|
|||||||
"""Configure bot users, which can do things through the bot and standard Django auth."""
|
"""Configure bot users, which can do things through the bot and standard Django auth."""
|
||||||
|
|
||||||
nickmask = models.CharField(max_length=200, unique=True)
|
nickmask = models.CharField(max_length=200, unique=True)
|
||||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
|
user = models.ForeignKey(settings.AUTH_USER_MODEL)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (
|
||||||
|
@ -23,7 +23,7 @@ class Migration(migrations.Migration):
|
|||||||
('delta', models.SmallIntegerField()),
|
('delta', models.SmallIntegerField()),
|
||||||
('nickmask', models.CharField(default='', max_length=200, blank=True)),
|
('nickmask', models.CharField(default='', max_length=200, blank=True)),
|
||||||
('created', models.DateTimeField(auto_now_add=True)),
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
('key', models.ForeignKey(to='karma.KarmaKey', on_delete=models.CASCADE)),
|
('key', models.ForeignKey(to='karma.KarmaKey')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -115,7 +115,7 @@ class KarmaLogEntryManager(models.Manager):
|
|||||||
class KarmaLogEntry(models.Model):
|
class KarmaLogEntry(models.Model):
|
||||||
"""Track each karma increment/decrement."""
|
"""Track each karma increment/decrement."""
|
||||||
|
|
||||||
key = models.ForeignKey('KarmaKey', on_delete=models.CASCADE)
|
key = models.ForeignKey('KarmaKey')
|
||||||
delta = models.SmallIntegerField()
|
delta = models.SmallIntegerField()
|
||||||
nickmask = models.CharField(max_length=200, default='', blank=True)
|
nickmask = models.CharField(max_length=200, default='', blank=True)
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
@ -27,7 +27,7 @@ class Migration(migrations.Migration):
|
|||||||
('k2', models.CharField(max_length=128)),
|
('k2', models.CharField(max_length=128)),
|
||||||
('v', models.CharField(max_length=128)),
|
('v', models.CharField(max_length=128)),
|
||||||
('count', models.IntegerField(default=0)),
|
('count', models.IntegerField(default=0)),
|
||||||
('context', models.ForeignKey(to='markov.MarkovContext', on_delete=models.CASCADE)),
|
('context', models.ForeignKey(to='markov.MarkovContext')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'permissions': set([('teach_line', 'Can teach lines'), ('import_log_file', 'Can import states from a log file')]),
|
'permissions': set([('teach_line', 'Can teach lines'), ('import_log_file', 'Can import states from a log file')]),
|
||||||
@ -40,7 +40,7 @@ class Migration(migrations.Migration):
|
|||||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
('name', models.CharField(unique=True, max_length=64)),
|
('name', models.CharField(unique=True, max_length=64)),
|
||||||
('chatter_chance', models.IntegerField(default=0)),
|
('chatter_chance', models.IntegerField(default=0)),
|
||||||
('context', models.ForeignKey(to='markov.MarkovContext', on_delete=models.CASCADE)),
|
('context', models.ForeignKey(to='markov.MarkovContext')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ class MarkovTarget(models.Model):
|
|||||||
"""Define IRC targets that relate to a context, and can occasionally be talked to."""
|
"""Define IRC targets that relate to a context, and can occasionally be talked to."""
|
||||||
|
|
||||||
name = models.CharField(max_length=200, unique=True)
|
name = models.CharField(max_length=200, unique=True)
|
||||||
context = models.ForeignKey(MarkovContext, on_delete=models.CASCADE)
|
context = models.ForeignKey(MarkovContext)
|
||||||
|
|
||||||
chatter_chance = models.IntegerField(default=0)
|
chatter_chance = models.IntegerField(default=0)
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ class MarkovState(models.Model):
|
|||||||
v = models.CharField(max_length=128)
|
v = models.CharField(max_length=128)
|
||||||
|
|
||||||
count = models.IntegerField(default=0)
|
count = models.IntegerField(default=0)
|
||||||
context = models.ForeignKey(MarkovContext, on_delete=models.CASCADE)
|
context = models.ForeignKey(MarkovContext)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
index_together = [
|
index_together = [
|
||||||
|
@ -29,7 +29,7 @@ class Migration(migrations.Migration):
|
|||||||
('joined', models.BooleanField(default=False)),
|
('joined', models.BooleanField(default=False)),
|
||||||
('started', models.BooleanField(default=False)),
|
('started', models.BooleanField(default=False)),
|
||||||
('finished', models.BooleanField(default=False)),
|
('finished', models.BooleanField(default=False)),
|
||||||
('race', models.ForeignKey(to='races.Race', on_delete=models.CASCADE)),
|
('race', models.ForeignKey(to='races.Race')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
},
|
},
|
||||||
@ -41,8 +41,8 @@ class Migration(migrations.Migration):
|
|||||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
('update', models.TextField()),
|
('update', models.TextField()),
|
||||||
('event_time', models.DateTimeField(default=django.utils.timezone.now)),
|
('event_time', models.DateTimeField(default=django.utils.timezone.now)),
|
||||||
('race', models.ForeignKey(to='races.Race', on_delete=models.CASCADE)),
|
('race', models.ForeignKey(to='races.Race')),
|
||||||
('racer', models.ForeignKey(to='races.Racer', on_delete=models.CASCADE)),
|
('racer', models.ForeignKey(to='races.Racer')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'ordering': ['event_time'],
|
'ordering': ['event_time'],
|
||||||
|
@ -28,7 +28,7 @@ class Racer(models.Model):
|
|||||||
"""Track a racer in a race."""
|
"""Track a racer in a race."""
|
||||||
|
|
||||||
nick = models.CharField(max_length=64)
|
nick = models.CharField(max_length=64)
|
||||||
race = models.ForeignKey(Race, on_delete=models.CASCADE)
|
race = models.ForeignKey(Race)
|
||||||
|
|
||||||
joined = models.BooleanField(default=False)
|
joined = models.BooleanField(default=False)
|
||||||
started = models.BooleanField(default=False)
|
started = models.BooleanField(default=False)
|
||||||
@ -47,8 +47,8 @@ class RaceUpdate(models.Model):
|
|||||||
|
|
||||||
"""Periodic updates for a racer."""
|
"""Periodic updates for a racer."""
|
||||||
|
|
||||||
race = models.ForeignKey(Race, on_delete=models.CASCADE)
|
race = models.ForeignKey(Race)
|
||||||
racer = models.ForeignKey(Racer, on_delete=models.CASCADE)
|
racer = models.ForeignKey(Racer)
|
||||||
update = models.TextField()
|
update = models.TextField()
|
||||||
event_time = models.DateTimeField(default=timezone.now)
|
event_time = models.DateTimeField(default=timezone.now)
|
||||||
|
|
||||||
|
@ -2,68 +2,64 @@
|
|||||||
# This file is autogenerated by pip-compile
|
# This file is autogenerated by pip-compile
|
||||||
# To update, run:
|
# To update, run:
|
||||||
#
|
#
|
||||||
# pip-compile --output-file=requirements-dev.txt requirements-dev.in
|
# pip-compile --output-file requirements-dev.txt requirements-dev.in
|
||||||
#
|
#
|
||||||
astroid==2.2.5 # via pylint, pylint-celery, pylint-flask, requirements-detector
|
appdirs==1.4.0 # via setuptools
|
||||||
certifi==2019.6.16 # via requests
|
astroid==1.4.9 # via pylint, pylint-celery, pylint-flask, pylint-plugin-utils, requirements-detector
|
||||||
chardet==3.0.4 # via requests
|
click==6.7 # via pip-tools
|
||||||
click==7.0 # via pip-tools
|
|
||||||
django-adminplus==0.5
|
django-adminplus==0.5
|
||||||
django-bootstrap3==11.0.0
|
django-bootstrap3==8.1.0
|
||||||
django-extensions==2.1.9
|
django-extensions==1.7.6
|
||||||
django-registration-redux==2.6
|
django-registration-redux==1.4
|
||||||
django==2.2.2
|
django==1.10.5
|
||||||
djangorestframework==3.9.4
|
djangorestframework==3.5.3
|
||||||
dodgy==0.1.9 # via prospector
|
dodgy==0.1.9 # via prospector
|
||||||
future==0.17.1 # via parsedatetime
|
first==2.0.1 # via pip-tools
|
||||||
idna==2.8 # via requests
|
future==0.16.0 # via parsedatetime
|
||||||
importlib-metadata==0.18 # via irc
|
inflect==0.2.5 # via jaraco.itertools
|
||||||
inflect==2.1.0 # via jaraco.itertools
|
irc==15.0.6
|
||||||
irc==17.1
|
isort==4.2.5 # via pylint
|
||||||
isort==4.3.20 # via pylint
|
jaraco.classes==1.4 # via jaraco.collections
|
||||||
jaraco.classes==2.0 # via jaraco.collections
|
jaraco.collections==1.5 # via irc, jaraco.text
|
||||||
jaraco.collections==2.0 # via irc
|
jaraco.functools==1.15.1 # via irc, jaraco.text
|
||||||
jaraco.functools==2.0 # via irc, jaraco.text, tempora
|
jaraco.itertools==2.0 # via irc
|
||||||
jaraco.itertools==4.4.2 # via irc
|
jaraco.logging==1.5 # via irc
|
||||||
jaraco.logging==2.0 # via irc
|
jaraco.stream==1.1.1 # via irc
|
||||||
jaraco.stream==2.0 # via irc
|
jaraco.text==1.9 # via irc, jaraco.collections
|
||||||
jaraco.text==3.0 # via irc, jaraco.collections
|
lazy-object-proxy==1.2.2 # via astroid
|
||||||
lazy-object-proxy==1.4.1 # via astroid
|
logilab-common==1.3.0
|
||||||
logilab-common==1.4.2
|
|
||||||
mccabe==0.6.1 # via prospector, pylint
|
mccabe==0.6.1 # via prospector, pylint
|
||||||
more-itertools==7.0.0 # via irc, jaraco.functools, jaraco.itertools
|
more-itertools==2.5.0 # via irc, jaraco.functools, jaraco.itertools
|
||||||
oauthlib==3.0.1 # via requests-oauthlib
|
oauthlib==2.0.1 # via requests-oauthlib
|
||||||
parsedatetime==2.4
|
packaging==16.8 # via setuptools
|
||||||
|
parsedatetime==2.2
|
||||||
pep8-naming==0.4.1 # via prospector
|
pep8-naming==0.4.1 # via prospector
|
||||||
pip-tools==3.8.0
|
pip-tools==1.8.0
|
||||||
ply==3.11
|
ply==3.10
|
||||||
prospector==1.1.6.4
|
prospector==0.12.4
|
||||||
pycodestyle==2.4.0 # via prospector
|
pycodestyle==2.0.0 # via prospector
|
||||||
pydocstyle==3.0.0 # via prospector
|
pydocstyle==1.0.0 # via prospector
|
||||||
pyflakes==1.6.0 # via prospector
|
pyflakes==1.5.0 # via prospector
|
||||||
pylint-celery==0.3 # via prospector
|
pylint-celery==0.3 # via prospector
|
||||||
pylint-django==2.0.9 # via prospector
|
pylint-common==0.2.2 # via prospector
|
||||||
pylint-flask==0.6 # via prospector
|
pylint-django==0.7.2 # via prospector
|
||||||
pylint-plugin-utils==0.5 # via prospector, pylint-celery, pylint-django, pylint-flask
|
pylint-flask==0.5 # via prospector
|
||||||
pylint==2.3.1 # via prospector, pylint-celery, pylint-django, pylint-flask, pylint-plugin-utils
|
pylint-plugin-utils==0.2.4 # via prospector, pylint-celery, pylint-django, pylint-flask
|
||||||
python-dateutil==2.8.0
|
pylint==1.6.5 # via prospector, pylint-celery, pylint-common, pylint-django, pylint-flask, pylint-plugin-utils
|
||||||
python-gitlab==1.9.0
|
pyparsing==2.1.10 # via packaging
|
||||||
python-mpd2==1.0.0
|
python-dateutil==2.6.0
|
||||||
pytz==2019.1
|
python-gitlab==0.18
|
||||||
pyyaml==5.1.1 # via prospector
|
python-mpd2==0.5.5
|
||||||
requests-oauthlib==1.2.0 # via twython
|
pytz==2016.10
|
||||||
requests==2.22.0 # via python-gitlab, requests-oauthlib, twython
|
pyyaml==3.12 # via prospector
|
||||||
requirements-detector==0.6 # via prospector
|
requests-oauthlib==0.7.0 # via twython
|
||||||
|
requests==2.13.0 # via python-gitlab, requests-oauthlib, twython
|
||||||
|
requirements-detector==0.5.2 # via prospector
|
||||||
setoptconf==0.2.0 # via prospector
|
setoptconf==0.2.0 # via prospector
|
||||||
six==1.12.0 # via astroid, django-extensions, jaraco.classes, jaraco.collections, jaraco.itertools, jaraco.logging, jaraco.stream, logilab-common, pip-tools, pydocstyle, python-dateutil, python-gitlab, tempora
|
six==1.10.0 # via astroid, django-extensions, irc, jaraco.classes, jaraco.collections, jaraco.itertools, jaraco.logging, jaraco.stream, logilab-common, more-itertools, packaging, pip-tools, pylint, python-dateutil, python-gitlab, setuptools, tempora
|
||||||
snowballstemmer==1.2.1 # via pydocstyle
|
tempora==1.6.1 # via irc, jaraco.logging
|
||||||
sqlparse==0.3.0 # via django
|
twython==3.4.0
|
||||||
tempora==1.14.1 # via irc, jaraco.logging
|
wrapt==1.10.8 # via astroid
|
||||||
twython==3.7.0
|
|
||||||
typed-ast==1.4.0 # via astroid
|
|
||||||
urllib3==1.25.3 # via requests
|
|
||||||
wrapt==1.11.2 # via astroid
|
|
||||||
zipp==0.5.1 # via importlib-metadata
|
|
||||||
|
|
||||||
# The following packages are considered to be unsafe in a requirements file:
|
# The following packages are considered to be unsafe in a requirements file:
|
||||||
# setuptools==41.0.1 # via logilab-common
|
# setuptools # via logilab-common
|
||||||
|
3
requirements-server.in
Normal file
3
requirements-server.in
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
-r requirements.in
|
||||||
|
|
||||||
|
psycopg2
|
36
requirements-server.txt
Normal file
36
requirements-server.txt
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#
|
||||||
|
# This file is autogenerated by pip-compile
|
||||||
|
# To update, run:
|
||||||
|
#
|
||||||
|
# pip-compile --output-file requirements-server.txt requirements-server.in
|
||||||
|
#
|
||||||
|
django-adminplus==0.5
|
||||||
|
django-bootstrap3==8.1.0
|
||||||
|
django-extensions==1.7.6
|
||||||
|
django-registration-redux==1.4
|
||||||
|
django==1.10.5
|
||||||
|
djangorestframework==3.5.3
|
||||||
|
future==0.16.0 # via parsedatetime
|
||||||
|
inflect==0.2.5 # via jaraco.itertools
|
||||||
|
irc==15.0.6
|
||||||
|
jaraco.classes==1.4 # via jaraco.collections
|
||||||
|
jaraco.collections==1.5 # via irc, jaraco.text
|
||||||
|
jaraco.functools==1.15.1 # via irc, jaraco.text
|
||||||
|
jaraco.itertools==2.0 # via irc
|
||||||
|
jaraco.logging==1.5 # via irc
|
||||||
|
jaraco.stream==1.1.1 # via irc
|
||||||
|
jaraco.text==1.9 # via irc, jaraco.collections
|
||||||
|
more-itertools==2.5.0 # via irc, jaraco.functools, jaraco.itertools
|
||||||
|
oauthlib==2.0.1 # via requests-oauthlib
|
||||||
|
parsedatetime==2.2
|
||||||
|
ply==3.10
|
||||||
|
psycopg2==2.6.2
|
||||||
|
python-dateutil==2.6.0
|
||||||
|
python-gitlab==0.18
|
||||||
|
python-mpd2==0.5.5
|
||||||
|
pytz==2016.10
|
||||||
|
requests-oauthlib==0.7.0 # via twython
|
||||||
|
requests==2.13.0 # via python-gitlab, requests-oauthlib, twython
|
||||||
|
six==1.10.0 # via django-extensions, irc, jaraco.classes, jaraco.collections, jaraco.itertools, jaraco.logging, jaraco.stream, more-itertools, python-dateutil, python-gitlab, tempora
|
||||||
|
tempora==1.6.1 # via irc, jaraco.logging
|
||||||
|
twython==3.4.0
|
@ -2,41 +2,34 @@
|
|||||||
# This file is autogenerated by pip-compile
|
# This file is autogenerated by pip-compile
|
||||||
# To update, run:
|
# To update, run:
|
||||||
#
|
#
|
||||||
# pip-compile --output-file=requirements.txt requirements.in
|
# pip-compile --output-file requirements.txt requirements.in
|
||||||
#
|
#
|
||||||
certifi==2019.6.16 # via requests
|
|
||||||
chardet==3.0.4 # via requests
|
|
||||||
django-adminplus==0.5
|
django-adminplus==0.5
|
||||||
django-bootstrap3==11.0.0
|
django-bootstrap3==8.1.0
|
||||||
django-extensions==2.1.9
|
django-extensions==1.7.6
|
||||||
django-registration-redux==2.6
|
django-registration-redux==1.4
|
||||||
django==2.2.2
|
django==1.10.5
|
||||||
djangorestframework==3.9.4
|
djangorestframework==3.5.3
|
||||||
future==0.17.1 # via parsedatetime
|
future==0.16.0 # via parsedatetime
|
||||||
idna==2.8 # via requests
|
inflect==0.2.5 # via jaraco.itertools
|
||||||
importlib-metadata==0.18 # via irc
|
irc==15.0.6
|
||||||
inflect==2.1.0 # via jaraco.itertools
|
jaraco.classes==1.4 # via jaraco.collections
|
||||||
irc==17.1
|
jaraco.collections==1.5 # via irc, jaraco.text
|
||||||
jaraco.classes==2.0 # via jaraco.collections
|
jaraco.functools==1.15.1 # via irc, jaraco.text
|
||||||
jaraco.collections==2.0 # via irc
|
jaraco.itertools==2.0 # via irc
|
||||||
jaraco.functools==2.0 # via irc, jaraco.text, tempora
|
jaraco.logging==1.5 # via irc
|
||||||
jaraco.itertools==4.4.2 # via irc
|
jaraco.stream==1.1.1 # via irc
|
||||||
jaraco.logging==2.0 # via irc
|
jaraco.text==1.9 # via irc, jaraco.collections
|
||||||
jaraco.stream==2.0 # via irc
|
more-itertools==2.5.0 # via irc, jaraco.functools, jaraco.itertools
|
||||||
jaraco.text==3.0 # via irc, jaraco.collections
|
oauthlib==2.0.1 # via requests-oauthlib
|
||||||
more-itertools==7.0.0 # via irc, jaraco.functools, jaraco.itertools
|
parsedatetime==2.2
|
||||||
oauthlib==3.0.1 # via requests-oauthlib
|
ply==3.10
|
||||||
parsedatetime==2.4
|
python-dateutil==2.6.0
|
||||||
ply==3.11
|
python-gitlab==0.18
|
||||||
python-dateutil==2.8.0
|
python-mpd2==0.5.5
|
||||||
python-gitlab==1.9.0
|
pytz==2016.10
|
||||||
python-mpd2==1.0.0
|
requests-oauthlib==0.7.0 # via twython
|
||||||
pytz==2019.1
|
requests==2.13.0 # via python-gitlab, requests-oauthlib, twython
|
||||||
requests-oauthlib==1.2.0 # via twython
|
six==1.10.0 # via django-extensions, irc, jaraco.classes, jaraco.collections, jaraco.itertools, jaraco.logging, jaraco.stream, more-itertools, python-dateutil, python-gitlab, tempora
|
||||||
requests==2.22.0 # via python-gitlab, requests-oauthlib, twython
|
tempora==1.6.1 # via irc, jaraco.logging
|
||||||
six==1.12.0 # via django-extensions, jaraco.classes, jaraco.collections, jaraco.itertools, jaraco.logging, jaraco.stream, python-dateutil, python-gitlab, tempora
|
twython==3.4.0
|
||||||
sqlparse==0.3.0 # via django
|
|
||||||
tempora==1.14.1 # via irc, jaraco.logging
|
|
||||||
twython==3.7.0
|
|
||||||
urllib3==1.25.3 # via requests
|
|
||||||
zipp==0.5.1 # via importlib-metadata
|
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
"""Use dr.botzo's Dispatch to send mpd notifications."""
|
"""Use dr.botzo's Dispatch to send mpd notifications."""
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import getpass
|
import getpass
|
||||||
import logging
|
import logging
|
||||||
|
@ -29,7 +29,7 @@ class Migration(migrations.Migration):
|
|||||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
('line', models.TextField(default='')),
|
('line', models.TextField(default='')),
|
||||||
('time', models.DateTimeField(auto_now_add=True)),
|
('time', models.DateTimeField(auto_now_add=True)),
|
||||||
('game', models.ForeignKey(to='storycraft.StorycraftGame', on_delete=models.CASCADE)),
|
('game', models.ForeignKey(to='storycraft.StorycraftGame')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
@ -38,12 +38,12 @@ class Migration(migrations.Migration):
|
|||||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
('nick', models.CharField(max_length=64)),
|
('nick', models.CharField(max_length=64)),
|
||||||
('nickmask', models.CharField(max_length=200)),
|
('nickmask', models.CharField(max_length=200)),
|
||||||
('game', models.ForeignKey(to='storycraft.StorycraftGame', on_delete=models.CASCADE)),
|
('game', models.ForeignKey(to='storycraft.StorycraftGame')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='storycraftline',
|
model_name='storycraftline',
|
||||||
name='player',
|
name='player',
|
||||||
field=models.ForeignKey(to='storycraft.StorycraftPlayer', on_delete=models.CASCADE),
|
field=models.ForeignKey(to='storycraft.StorycraftPlayer'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -13,16 +13,16 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='storycraftline',
|
model_name='storycraftline',
|
||||||
name='game',
|
name='game',
|
||||||
field=models.ForeignKey(related_name='lines', to='storycraft.StorycraftGame', on_delete=models.CASCADE),
|
field=models.ForeignKey(related_name='lines', to='storycraft.StorycraftGame'),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='storycraftline',
|
model_name='storycraftline',
|
||||||
name='player',
|
name='player',
|
||||||
field=models.ForeignKey(related_name='lines', to='storycraft.StorycraftPlayer', on_delete=models.CASCADE),
|
field=models.ForeignKey(related_name='lines', to='storycraft.StorycraftPlayer'),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='storycraftplayer',
|
model_name='storycraftplayer',
|
||||||
name='game',
|
name='game',
|
||||||
field=models.ForeignKey(related_name='players', to='storycraft.StorycraftGame', on_delete=models.CASCADE),
|
field=models.ForeignKey(related_name='players', to='storycraft.StorycraftGame'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -89,7 +89,7 @@ class StorycraftPlayer(models.Model):
|
|||||||
|
|
||||||
"""Contain entire games of storycraft."""
|
"""Contain entire games of storycraft."""
|
||||||
|
|
||||||
game = models.ForeignKey('StorycraftGame', related_name='players', on_delete=models.CASCADE)
|
game = models.ForeignKey('StorycraftGame', related_name='players')
|
||||||
nick = models.CharField(max_length=64)
|
nick = models.CharField(max_length=64)
|
||||||
nickmask = models.CharField(max_length=200)
|
nickmask = models.CharField(max_length=200)
|
||||||
|
|
||||||
@ -103,8 +103,8 @@ class StorycraftLine(models.Model):
|
|||||||
|
|
||||||
"""Handle requests to dispatchers and do something with them."""
|
"""Handle requests to dispatchers and do something with them."""
|
||||||
|
|
||||||
game = models.ForeignKey('StorycraftGame', related_name='lines', on_delete=models.CASCADE)
|
game = models.ForeignKey('StorycraftGame', related_name='lines')
|
||||||
player = models.ForeignKey('StorycraftPlayer', related_name='lines', on_delete=models.CASCADE)
|
player = models.ForeignKey('StorycraftPlayer', related_name='lines')
|
||||||
line = models.TextField(default="")
|
line = models.TextField(default="")
|
||||||
time = models.DateTimeField(auto_now_add=True)
|
time = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
@ -17,6 +19,6 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='twitterclient',
|
model_name='twitterclient',
|
||||||
name='mentions_output_channel',
|
name='mentions_output_channel',
|
||||||
field=models.ForeignKey(blank=True, related_name='mentions_twitter_client', null=True, to='ircbot.IrcChannel', default=None, on_delete=models.CASCADE),
|
field=models.ForeignKey(blank=True, related_name='mentions_twitter_client', null=True, to='ircbot.IrcChannel', default=None),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ class TwitterClient(models.Model):
|
|||||||
oauth_token_secret = models.CharField(max_length=256, default='', blank=True)
|
oauth_token_secret = models.CharField(max_length=256, default='', blank=True)
|
||||||
|
|
||||||
mentions_output_channel = models.ForeignKey(IrcChannel, related_name='mentions_twitter_client', default=None,
|
mentions_output_channel = models.ForeignKey(IrcChannel, related_name='mentions_twitter_client', default=None,
|
||||||
null=True, blank=True, on_delete=models.CASCADE)
|
null=True, blank=True)
|
||||||
mentions_since_id = models.PositiveIntegerField(default=1, blank=True)
|
mentions_since_id = models.PositiveIntegerField(default=1, blank=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user