forked from GamesDoneQuick/donation-tracker
-
Notifications
You must be signed in to change notification settings - Fork 1
/
prizeutil.py
60 lines (54 loc) · 2.65 KB
/
prizeutil.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import datetime
import pytz
import random
from . import util
from .models import *
from functools import reduce
def draw_prize(prize, seed=None):
eligible = prize.eligible_donors()
if prize.maxed_winners():
if prize.maxwinners == 1:
return False, {"error": "Prize: " + prize.name + " already has a winner."}
else:
return False, {"error": "Prize: " + prize.name + " already has the maximum number of winners allowed."}
if not eligible:
return False, {"error": "Prize: " + prize.name + " has no eligible donors."}
else:
try:
rand = random.Random(seed)
except TypeError: # not sure how this could happen but hey
return False, {'error': 'Seed parameter was unhashable'}
psum = reduce(lambda a, b: a + b['weight'], eligible, 0.0)
result = rand.random() * psum
ret = {'sum': psum, 'result': result}
for d in eligible:
if result < d['weight']:
try:
donor = Donor.objects.get(pk=d['donor'])
acceptDeadline = datetime.datetime.today().replace(tzinfo=util.anywhere_on_earth_tz(), hour=23,
minute=59, second=59) + datetime.timedelta(days=prize.event.prize_accept_deadline_delta)
winRecord, created = PrizeWinner.objects.get_or_create(
prize=prize, winner=donor, defaults=dict(acceptdeadline=acceptDeadline))
if not created:
winRecord.pendingcount += 1
ret['winner'] = winRecord.winner.id
winRecord.save()
if prize.announce_winners_to_chat:
winRecord.announce_to_chat()
except Exception as e:
return False, {"error": "Error drawing prize: " + prize.name + ", " + str(e)}
return True, ret
result -= d['weight']
return False, {"error": "Prize drawing algorithm failed."}
def get_past_due_prize_winners(event):
now = datetime.datetime.utcnow().replace(tzinfo=pytz.utc)
return PrizeWinner.objects.filter(acceptdeadline__lte=now, pendingcount__gte=1)
def close_past_due_prize_winners(event, verbosity=0, dry_run=False):
for prizewinner in get_past_due_prize_winners(event):
if verbosity > 0:
print("Closing Prize Winner #{0} with {1} pending".format(
prizewinner.id, prizewinner.pendingcount))
if not dry_run:
prizewinner.declinecount += prizewinner.pendingcount
prizewinner.pendingcount = 0
prizewinner.save()