def _get_prizes(team): """Private method to process the prizes half of the page. Takes the user's team and returns a dictionary to be used in the template.""" prize_dict = {} today = datetime.datetime.today() rounds = challenge_mgr.get_all_round_info()["rounds"] round_name = None for prize in Prize.objects.all(): if prize.round: if round_name != prize.round.name: # a new round round_name = prize.round.name prize_dict[round_name] = [] if today < rounds[round_name]["start"]: # If the round happens in the future, we don't care who the leader is. prize.current_leader = "TBD" else: # If we are in the middle of the round, display the current leader. if today < rounds[round_name]["end"]: prize.current_leader = prize.leader(team) else: prize.winner = prize.leader(team) prize_dict[round_name].append(prize) return prize_dict
def supply(request, page_name): """Supply the view_objects content for this widget, which is all the scoreboard data.""" user = request.user team = user.get_profile().team num_results = 10 if page_name != "status" else None round_standings = {} current_round = challenge_mgr.get_round_name() rounds = challenge_mgr.get_all_round_info()["rounds"] for key in rounds.keys(): if key == current_round or page_name == "status": round_standings[key] = { "team_standings": team_mgr.team_points_leaders(num_results, key), "profile_standings": player_mgr.points_leaders(num_results, key), "team_participation": team_mgr.team_active_participation(num_results, key) if \ page_name == "status" else None, "user_team_standings": team.points_leaders(num_results, key) if \ team and page_name != "status" else None, } count = len(rounds) return { "profile": user.get_profile(), "team": team, "current_round": current_round, "round_standings": round_standings, "no_carousel": page_name == "status", "range": count, "user": user, }
def supply(request, page_name): """supply view_objects for user status.""" _ = page_name _ = request todays_users = Profile.objects.filter(last_visit_date=datetime.datetime.today()) # Approximate logins by their first points transaction. rounds_info = challenge_mgr.get_all_round_info() start = rounds_info["competition_start"] today = datetime.datetime.today() users_anno = User.objects.annotate(login_date=Min('pointstransaction__transaction_date')) logins = [] while start <= today: result = {} result['date'] = start.strftime("%m/%d") result['logins'] = users_anno.filter(login_date__gte=start, login_date__lt=start + datetime.timedelta(days=1)).count() logins.append(result) start += datetime.timedelta(days=1) # Find referrals. referrals = Profile.objects.filter(referring_user__isnull=False).values( 'referring_user__profile__name', 'referring_user__username').annotate( referrals=Count('referring_user') ) return { "todays_users": todays_users, 'logins': logins, "referrals": referrals, }
def resource_supply(request, resource, page_name): """Supply the view_objects content. :return: team, goals_scoreboard, resource_round_ranks""" user = request.user team = user.profile.team round_resource_ranks = {} round_group_resource_ranks = {} round_resource_goal_ranks = {} today = datetime.datetime.today() rounds = challenge_mgr.get_all_round_info()["rounds"] for key in rounds.keys(): if rounds[key]["start"] <= today and\ (rounds[key]["display_scoreboard"] or page_name == "status"): round_resource_ranks[key] = resource_mgr.resource_ranks(resource, key) round_group_resource_ranks[key] = resource_mgr.group_resource_ranks(resource, key) round_resource_goal_ranks[key] = resource_goal.resource_goal_ranks(resource, key) round_resource_ranks["Overall"] = resource_mgr.resource_ranks(resource, "Overall") round_group_resource_ranks["Overall"] = resource_mgr.group_resource_ranks(resource, "Overall") round_resource_goal_ranks["Overall"] = resource_goal.resource_goal_ranks(resource, "Overall") resource_setting = resource_mgr.get_resource_setting(resource) return { "profile": user.profile, "team": team, "resource": resource_setting, "round_resource_goal_ranks": round_resource_goal_ranks, "round_resource_ranks": round_resource_ranks, "round_group_resource_ranks": round_group_resource_ranks, }
def resource_ranks(name, round_name=None): """Return the ranking of resource use for all teams.""" cache_key = "%s_ranks-%s" % (name, slugify(round_name)) ranks = cache_mgr.get_cache(cache_key) if ranks is None: resource_usage = _get_resource_usage(name) resource_setting = get_resource_setting(name) rate = resource_setting.conversion_rate if resource_setting.winning_order == "Ascending": ordering = "total" else: ordering = "-total" round_info = challenge_mgr.get_round_info(round_name) if not round_info: return None all_rounds_info = challenge_mgr.get_all_round_info() usage_ranks = resource_usage.objects.filter( date__lte=round_info["end"].date, date__gte=all_rounds_info["competition_start"]).values("team__name").annotate( total=Sum("usage")).order_by(ordering) ranks = [] for rank in usage_ranks: ranks.append({"team__name": rank["team__name"], "total": utils.format_usage(rank["total"], rate)}) cache_mgr.set_cache(cache_key, ranks, 600) return ranks
def notify_round_started(): """Notify the user of a start of a round.""" if not challenge_mgr.in_competition(): return today = datetime.datetime.today() current_round = None previous_round = None rounds = challenge_mgr.get_all_round_info()["rounds"] for key in rounds.keys(): # We're looking for a round that ends today and another that starts # today (or overall) start = rounds[key]["start"] end = rounds[key]["end"] # Check yesterday's round and check for the current round. if start < (today - datetime.timedelta(days=1)) < end: previous_round = key if start < today < end: current_round = key print "Previous Round: %s" % previous_round print "Current Round: %s" % current_round if current_round and previous_round and current_round != previous_round: print "Sending out round transition notices." template = NoticeTemplate.objects.get(notice_type="round-transition") message = template.render({"PREVIOUS_ROUND": previous_round, "CURRENT_ROUND": current_round}) for user in User.objects.all(): UserNotification.create_info_notification(user, message, display_alert=True)
def _get_round_start_end(round_name=None): """return the start and end date of a round regarding the round_reset.""" if round_name == "Overall": all_round_info = challenge_mgr.get_all_round_info() start = all_round_info["competition_start"] end = all_round_info["competition_end"] else: round_info = challenge_mgr.get_round_info(round_name) if not round_info: return None end = round_info["end"].date if round_info["round_reset"]: start = round_info["start"].date else: # if no round reset, use the competition_start as start date start = challenge_mgr.get_all_round_info()["competition_start"] return start, end
def supply(request, page_name): """Supply the view_objects content for this widget, which is all the scoreboard data.""" user = request.user team = user.profile.team num_results = 10 if page_name != "status" else None round_standings = {} current_round = challenge_mgr.get_round_name() today = datetime.datetime.today() rounds = challenge_mgr.get_all_round_info()["rounds"] for key in rounds.keys(): # 1. always display current round # 2. if not future round # a. display the round with the "display_scoreboard" flag # b. display in the status page if rounds[key]["start"] <= today and \ (rounds[key]["display_scoreboard"] or page_name == "status"): round_standings[key] = { #"group_standings": team_mgr.group_points_leaders(num_results, key), "team_standings": team_mgr.team_points_leaders(num_results, key), "profile_standings": player_mgr.points_leaders(num_results, key), #"group_participation": team_mgr.group_active_participation(num_results, key) if \ # page_name == "status" else None, "team_participation": team_mgr.team_active_participation(num_results, key) if \ page_name == "status" else None, "user_team_standings": team.points_leaders(num_results, key) if \ team and page_name != "status" else None, } """ # add an overall scoreboard round_standings["Overall"] = { #"group_standings": team_mgr.group_points_leaders(num_results, "Overall"), "team_standings": team_mgr.team_points_leaders(num_results, "Overall"), "profile_standings": player_mgr.points_leaders(num_results, "Overall"), #"group_participation": team_mgr.group_active_participation(num_results, "Overall") if\ # page_name == "status" else None, "team_participation": team_mgr.team_active_participation(num_results, "Overall") if \ page_name == "status" else None, } """ count = len(rounds) return { "profile": user.profile, "team": team, "current_round": current_round, "round_standings": round_standings, "no_carousel": page_name == "status", "range": count, "user": user, }
def supply(request, page_name): """Supply the view_objects content for this widget, which is all the scoreboard data.""" user = request.user team = user.get_profile().team num_results = 10 if page_name != "status" else None round_standings = {} current_round = challenge_mgr.get_round_name() today = datetime.datetime.today() rounds = challenge_mgr.get_all_round_info()["rounds"] for key in rounds.keys(): # 1. always display current round # 2. if not future round # a. display the round with the "display_scoreboard" flag # b. display in the status page if rounds[key]["start"] <= today and \ (rounds[key]["display_scoreboard"] or page_name == "status"): round_standings[key] = { "group_standings": team_mgr.group_points_leaders(num_results, key), "team_standings": team_mgr.team_points_leaders(num_results, key), "profile_standings": player_mgr.points_leaders(num_results, key), "group_participation": team_mgr.group_active_participation(num_results, key) if \ page_name == "status" else None, "team_participation": team_mgr.team_active_participation(num_results, key) if \ page_name == "status" else None, "user_team_standings": team.points_leaders(num_results, key) if \ team and page_name != "status" else None, } # add an overall scoreboard round_standings["Overall"] = { "group_standings": team_mgr.group_points_leaders(num_results, "Overall"), "team_standings": team_mgr.team_points_leaders(num_results, "Overall"), "profile_standings": player_mgr.points_leaders(num_results, "Overall"), "group_participation": team_mgr.group_active_participation(num_results, "Overall") if\ page_name == "status" else None, "team_participation": team_mgr.team_active_participation(num_results, "Overall") if \ page_name == "status" else None, } count = len(rounds) return { "profile": user.get_profile(), "team": team, "current_round": current_round, "round_standings": round_standings, "no_carousel": page_name == "status", "range": count, "user": user, }
def restricted(request): """The view when they have logged in before the competition begins.""" # If we are in the competition, bring them back to the home page. if challenge_mgr.in_competition(): return HttpResponseRedirect(reverse('home_index')) rounds_info = challenge_mgr.get_all_round_info() start = rounds_info["competition_start"] end = rounds_info["competition_end"] return render_to_response("widgets/home/templates/restricted.html", { "before": datetime.datetime.today() < start, "start": start, "end": end, }, context_instance=RequestContext(request))
def notify_round_started(): """Notify the user of a start of a round.""" if not challenge_mgr.in_competition(): return today = datetime.datetime.today() current_round = None previous_round = None all_round_info = challenge_mgr.get_all_round_info() rounds = all_round_info["rounds"] for key in rounds.keys(): # We're looking for a round that ends today and another that starts # today (or overall) start = rounds[key]["start"] end = rounds[key]["end"] # Check yesterday's round and check for the current round. if start < (today - datetime.timedelta(days=1)) < end: previous_round = key if start < today < end: current_round = key print 'Previous Round: %s' % previous_round print 'Current Round: %s' % current_round if current_round and previous_round and current_round != previous_round: # only carry over the scoreboard entry if the round don't need to be reset if not rounds[current_round]["round_reset"]: print "carry over scoreboard entry to new round." score_mgr.copy_scoreboard_entry(previous_round, current_round) # if there is a gap, previous_round is null, check if it is not out of round if current_round and current_round != previous_round and\ all_round_info["competition_start"] <= today <= all_round_info["competition_end"]: print 'Sending out round transition notices.' template = NoticeTemplate.objects.get(notice_type="round-transition") message = template.render({ "PREVIOUS_ROUND": previous_round, "CURRENT_ROUND": current_round, }) for user in User.objects.all(): UserNotification.create_info_notification( user, message, display_alert=True, )
def supply(request, page_name): """supply view_objects for prize status.""" _ = page_name _ = request # get the raffle_prizes for all rounds raffle_prizes = {} for round_name in challenge_mgr.get_all_round_info()["rounds"]: raffle_prizes[round_name] = RafflePrize.objects.filter(round_name=round_name).all() # Calculate unused raffle tickets for every user. elig_entries = ScoreboardEntry.objects.filter( points__gte=25, round_name=challenge_mgr.get_round_name()) unused = 0 errors = [] for entry in elig_entries: available = (entry.points / 25) - entry.profile.user.raffleticket_set.count() if available < 0: errors.append(entry.profile) unused += available # get user/ticket pairings unused_tickets = {} temp = {} for item in ScoreboardEntry.objects.all(): if(item.profile.id in temp): temp[item.profile.id] = (item.profile, temp[item.profile.id][1] + item.points) else: temp[item.profile.id] = (item.profile, item.points) for item, key in temp.iteritems(): unused_tickets[key[0]] = key[1] / 25 - key[0].user.raffleticket_set.count() sorted_list = sorted(unused_tickets.iteritems(), key=operator.itemgetter(1)) sorted_list.reverse() return { "raffle_prizes": raffle_prizes, "unused": unused, "unused_tickets": sorted_list, "has_error": len(errors) > 0, "errors": errors, }
def supply(request, page_name): """supply view_objects for prize status.""" _ = page_name _ = request # get the raffle_prizes for all rounds raffle_prizes = {} today = datetime.datetime.today() rounds = challenge_mgr.get_all_round_info()["rounds"] for key in rounds.keys(): if rounds[key]["start"] <= today: raffle_prizes[key] = RafflePrize.objects.filter( round__name=key).annotate(count=Count('raffleticket')).order_by('-count') return { "raffle_prizes": raffle_prizes, }
def supply(request, page_name): """supply view_objects for user status.""" _ = page_name _ = request #todays_users = Profile.objects.filter(last_visit_date=datetime.datetime.today()) rounds_info = challenge_mgr.get_all_round_info() start = rounds_info["competition_start"] daily_status = DailyStatus.objects.filter(short_date__gte=start).order_by('short_date') prior_day_users = 0 for status in daily_status: status.display_date = "%d/%d" % (status.short_date.month, status.short_date.day) status.new_users = status.setup_users - prior_day_users prior_day_users = status.setup_users return { "daily_status": daily_status, }
def supply(request, page_name): """supply view_objects for prize status.""" _ = page_name _ = request # get the raffle_prizes for all rounds raffle_prizes = {} today = datetime.datetime.today() rounds = challenge_mgr.get_all_round_info()["rounds"] for key in rounds.keys(): if rounds[key]["start"] <= today: raffle_prizes[key] = RafflePrize.objects.filter( round__name=key).annotate( count=Count('raffleticket')).order_by('-count') return { "raffle_prizes": raffle_prizes, }
def supply(request, page_name): """Supply the view_objects content for this widget, which is participation data.""" _ = request _ = page_name round_participation_ranks = {} today = datetime.datetime.today() rounds = challenge_mgr.get_all_round_info()["rounds"] for key in rounds.keys(): if rounds[key]["start"] <= today and\ (rounds[key]["display_scoreboard"] or page_name == "status"): round_participation_ranks[key] = participation.participation_ranks(key) round_participation_ranks["Overall"] = participation.participation_ranks("Overall") return { "round_participation_ranks": round_participation_ranks, }
def notify_round_started(): """Notify the user of a start of a round.""" if not challenge_mgr.in_competition(): return today = datetime.datetime.today() current_round = None previous_round = None all_round_info = challenge_mgr.get_all_round_info() rounds = all_round_info["rounds"] for key in rounds.keys(): # We're looking for a round that ends today and another that starts # today (or overall) start = rounds[key]["start"] end = rounds[key]["end"] # Check yesterday's round and check for the current round. if start < (today - datetime.timedelta(days=1)) < end: previous_round = key if start < today < end: current_round = key print 'Previous Round: %s' % previous_round print 'Current Round: %s' % current_round if current_round and previous_round and current_round != previous_round: # only carry over the scoreboard entry if the round don't need to be reset if not rounds[current_round]["round_reset"]: print "carry over scoreboard entry to new round." score_mgr.copy_scoreboard_entry(previous_round, current_round) # if there is a gap, previous_round is null, check if it is not out of round if current_round and current_round != previous_round and\ all_round_info["competition_start"] <= today <= all_round_info["competition_end"]: print 'Sending out round transition notices.' template = NoticeTemplate.objects.get(notice_type="round-transition") message = template.render({"PREVIOUS_ROUND": previous_round, "CURRENT_ROUND": current_round, }) for user in User.objects.all(): UserNotification.create_info_notification(user, message, display_alert=True,)
def restricted(request): """The view when they have logged in before the competition begins.""" # If we are in the competition, bring them back to the home page. if challenge_mgr.in_competition(): return HttpResponseRedirect(reverse('home_index')) rounds_info = challenge_mgr.get_all_round_info() today = datetime.datetime.today() start = rounds_info["competition_start"] before = today < start end = today > rounds_info["competition_end"] if not before: next_round = challenge_mgr.get_next_round_info() if next_round: start = next_round["start"] return render_to_response("widgets/home/templates/restricted.html", { "before": before, "start": start, "end": end, }, context_instance=RequestContext(request))
def resource_supply(request, resource, page_name): """Supply the view_objects content. :return: team, goals_scoreboard, resource_round_ranks""" user = request.user team = user.get_profile().team round_resource_ranks = {} round_resource_goal_ranks = {} current_round = challenge_mgr.get_round_name() rounds = challenge_mgr.get_all_round_info()["rounds"] for key in rounds.keys(): if key == current_round or page_name == "status": round_resource_ranks[key] = resource_mgr.resource_ranks(resource, key) round_resource_goal_ranks[key] = resource_goal.resource_goal_ranks(resource, key) resource_setting = resource_mgr.get_resource_setting(resource) return { "profile": user.get_profile(), "team": team, "resource": resource_setting, "round_resource_goal_ranks": round_resource_goal_ranks, "round_resource_ranks": round_resource_ranks, }
def save(self, *args, **kwargs): """Custom save method.""" super(TeamParticipation, self).save(*args, **kwargs) for round_name in challenge_mgr.get_all_round_info()["rounds"].keys(): cache_mgr.delete("p_ranks-%s" % slugify(round_name))
def check_daily_resource_goal(team, resource): """Check the daily goal, award points to the team members if the goal is met. Returns the number of players in the team that got the award.""" # because the check is scheduled at midnight, we should check the previous day's data today = datetime.datetime.today() if today.hour == 0: today = today - datetime.timedelta(hours=1) # do nothing if out of round rounds_info = challenge_mgr.get_all_round_info() if not rounds_info["competition_start"] < today < rounds_info["competition_end"]: return 0 date = today.date() actual_usage = None resource_data = resource_mgr.team_resource_data(date, team, resource) if resource_data: goal_settings = team_goal_settings(team, resource) goal_usage = team_daily_goal_usage(date, team, resource, goal_settings) # check if the manual entry time is within the target time, # otherwise can not determine the actual usage if not goal_settings.manual_entry or \ (goal_settings.manual_entry_time.hour <= resource_data.time.hour and\ resource_data.time.hour <= (goal_settings.manual_entry_time.hour + 1)): actual_usage = resource_data.usage count = 0 goal = _get_resource_goal(resource) goal, _ = goal.objects.get_or_create(team=team, date=date) if actual_usage: if actual_usage <= goal_usage: # if already awarded, do nothing if goal.goal_status != "Below the goal": goal.goal_status = "Below the goal" # record the reduction percentage goal.percent_reduction = (goal_usage - actual_usage) * 100 / goal_usage # adjust the current goal percentage _adjust_goal_percent(date, team, resource, goal_settings, goal) # Award points to the members of the team. goal_points = goal_settings.goal_points for profile in team.profile_set.all(): if profile.setup_complete: today = datetime.datetime.today() # Hack to get around executing this script at midnight. We want to award # points earlier to ensure they are within the round they were completed. if today.hour == 0: today = today - datetime.timedelta(hours=1) date = "%d/%d/%d" % (today.month, today.day, today.year) profile.add_points(goal_points, today, "Team %s Goal for %s" % (resource, date), goal) profile.save() count += 1 else: goal.goal_status = "Over the goal" else: # if can not determine the actual usage, set the status to unknown goal.goal_status = "Unknown" goal.save() return count