def dehydrate_form(self, bundle): matches = bundle.obj.get_matchset() recent = matches.filter(date__gte=(date.today() - relativedelta(months=2))) return {'total': count_winloss_player(recent, bundle.obj), 'P': count_matchup_player(recent, bundle.obj, P), 'T': count_matchup_player(recent, bundle.obj, T), 'Z': count_matchup_player(recent, bundle.obj, Z)}
def player(request, player_id): # {{{ Get player object and base context, generate messages and make changes if needed player = get_object_or_404(Player, id=player_id) base = base_ctx('Ranking', 'Summary', request, context=player) if request.method == 'POST' and base['adm']: form = PlayerModForm(request) base['messages'] += form.update_player(player) else: form = PlayerModForm(player=player) base['messages'] += generate_messages(player) # }}} # {{{ Various easy data matches = player.get_matchset() recent = matches.filter(date__gte=(date.today() - relativedelta(months=2))) base.update({ 'player': player, 'form': form, 'first': etn(lambda: matches.earliest('date')), 'last': etn(lambda: matches.latest('date')), 'totalmatches': matches.count(), 'offlinematches': matches.filter(offline=True).count(), 'aliases': player.alias_set.all(), 'earnings': ntz(player.earnings_set.aggregate(Sum('earnings'))['earnings__sum']), 'team': player.get_current_team(), 'total': count_winloss_player(matches, player), 'vp': count_matchup_player(matches, player, P), 'vt': count_matchup_player(matches, player, T), 'vz': count_matchup_player(matches, player, Z), 'totalf': count_winloss_player(recent, player), 'vpf': count_matchup_player(recent, player, P), 'vtf': count_matchup_player(recent, player, T), 'vzf': count_matchup_player(recent, player, Z), }) if player.country is not None: base['countryfull'] = transformations.cc_to_cn(player.country) # }}} # {{{ Recent matches matches = player.get_matchset(related=['rta','rtb','pla','plb','eventobj'])[0:10] if matches.exists(): base['matches'] = display_matches(matches, fix_left=player, ratings=True) # }}} # {{{ Team memberships team_memberships = list(player.groupmembership_set.filter(group__is_team=True).select_related('group')) team_memberships.sort(key=lambda t: t.id, reverse=True) team_memberships.sort(key=meandate, reverse=True) team_memberships.sort(key=lambda t: t.current, reverse=True) base['teammems'] = team_memberships # }}} # {{{ If the player has at least one rating if player.current_rating: ratings = total_ratings(player.rating_set.filter(period__computed=True)).select_related('period') base.update({ 'highs': ( ratings.latest('rating'), ratings.latest('tot_vp'), ratings.latest('tot_vt'), ratings.latest('tot_vz'), ), 'recentchange': player.get_latest_rating_update(), 'firstrating': ratings.earliest('period'), 'rating': player.current_rating, }) if player.current_rating.decay >= INACTIVE_THRESHOLD: base['messages'].append(Message(msg_inactive % player.tag, 'Inactive', type=Message.INFO)) base['charts'] = base['recentchange'].period_id > base['firstrating'].period_id else: base['messages'].append(Message('%s has no rating yet.' % player.tag, type=Message.INFO)) base['charts'] = False # }}} # {{{ If the player has enough games to make a chart if base['charts']: ratings = ( total_ratings(player.rating_set.filter(period_id__lte=base['recentchange'].period_id)) .select_related('period__end') .prefetch_related('prev__rta', 'prev__rtb') .order_by('period') ) # {{{ Add stories and other extra information earliest = base['firstrating'] latest = base['recentchange'] # Look through team changes teampoints = [] for mem in base['teammems']: if mem.start and earliest.period.end < mem.start < latest.period.end: teampoints.append({ 'date': mem.start, 'rating': interp_rating(mem.start, ratings), 'data': [{'date': mem.start, 'team': mem.group, 'jol': 'joins'}], }) if mem.end and earliest.period.end < mem.end < latest.period.end: teampoints.append({ 'date': mem.end, 'rating': interp_rating(mem.end, ratings), 'data': [{'date': mem.end, 'team': mem.group, 'jol': 'leaves'}], }) teampoints.sort(key=lambda p: p['date']) # Condense if team changes happened within 14 days cur = 0 while cur < len(teampoints) - 1: if (teampoints[cur+1]['date'] - teampoints[cur]['date']).days <= 14: teampoints[cur]['data'].append(teampoints[cur+1]['data'][0]) del teampoints[cur+1] else: cur += 1 # Sort first by date, then by joined/left for point in teampoints: point['data'].sort(key=lambda a: a['jol'], reverse=True) point['data'].sort(key=lambda a: a['date']) # Look through stories stories = player.story_set.all().select_related('event__fullname') for s in stories: if earliest.period.start < s.date < latest.period.start: s.rating = interp_rating(s.date, ratings) else: s.skip = True # }}} base.update({ 'ratings': add_counts(ratings), 'patches': PATCHES, 'stories': stories, 'teampoints': teampoints, }) else: base['messages'].append(Message(msg_nochart % player.tag, type=Message.INFO)) # }}} base.update({"title": player.tag}) return render_to_response('player.html', base)
def match(request): base = base_ctx('Inference', 'Predict', request=request) # {{{ Get data, set up and simulate form = SetupForm(request.GET) if not form.is_valid(): return redirect('/inference/') result = MatchPredictionResult( dbpl=form.cleaned_data['ps'], bos=form.cleaned_data['bo'], s1=get_param(request, 's1', 0), s2=get_param(request, 's2', 0), ) # }}} # {{{ Postprocessing base.update({ 'form': form, 'dbpl': result.dbpl, 'rta': result.rta, 'rtb': result.rtb, 'proba': result.proba, 'probb': result.probb, 'match': result.obj, }) base.update({ 'max': max(base['proba'], base['probb']), 'fav': result.dbpl[0] if base['proba'] > base['probb'] else result.dbpl[1], }) resa = [oc for oc in result.outcomes if oc['sca'] > oc['scb']] resb = [oc for oc in result.outcomes if oc['scb'] > oc['sca']] if len(resa) < len(resb): resa = [None] * (len(resb) - len(resa)) + resa else: resb = [None] * (len(resa) - len(resb)) + resb base['res'] = list(zip(resa, resb)) # }}} # {{{ Scores and other data dbpl = result.dbpl thr = date.today() - relativedelta(months=2) pla_matches = dbpl[0].get_matchset() plb_matches = dbpl[1].get_matchset() base['tot_w_a'], base['tot_l_a'] = count_winloss_player(pla_matches, dbpl[0]) base['frm_w_a'], base['frm_l_a'] = count_winloss_player(pla_matches.filter(date__gte=thr), dbpl[0]) base['tot_w_b'], base['tot_l_b'] = count_winloss_player(plb_matches, dbpl[1]) base['frm_w_b'], base['frm_l_b'] = count_winloss_player(plb_matches.filter(date__gte=thr), dbpl[1]) if dbpl[1].race in 'PTZ': base['mu_w_a'], base['mu_l_a'] = count_matchup_player(pla_matches, dbpl[0], dbpl[1].race) base['fmu_w_a'], base['fmu_l_a'] = count_matchup_player( pla_matches.filter(date__gte=thr), dbpl[0], dbpl[1].race ) if dbpl[0].race in 'PTZ': base['mu_w_b'], base['mu_l_b'] = count_matchup_player(plb_matches, dbpl[1], dbpl[0].race) base['fmu_w_b'], base['fmu_l_b'] = count_matchup_player( plb_matches.filter(date__gte=thr), dbpl[1], dbpl[0].race ) wa_a, wb_a = count_winloss_games(Match.objects.filter(pla=dbpl[0], plb=dbpl[1])) wb_b, wa_b = count_winloss_games(Match.objects.filter(pla=dbpl[1], plb=dbpl[0])) base['vs_a'] = wa_a + wa_b base['vs_b'] = wb_a + wb_b base['matches'] = display_matches( Match.objects.filter(Q(pla=dbpl[0], plb=dbpl[1]) | Q(plb=dbpl[0], pla=dbpl[1])) .select_related('period', 'pla', 'plb') .order_by('-date', 'id'), fix_left=dbpl[0], ) # }}} postable_match(base, request) return render_to_response('pred_match.djhtml', base)
def results(request, player_id): # {{{ Get objects player = get_object_or_404(Player, id=player_id) base = base_ctx('Ranking', 'Match history', request, context=player) base['player'] = player # }}} # {{{ Filtering matches = player.get_matchset(related=['pla', 'plb', 'eventobj']) form = ResultsFilterForm(request.GET) base['form'] = form form.is_valid() q = Q() for r in form.cleaned_data['race'].upper(): q |= Q(pla=player, rcb=r) | Q(plb=player, rca=r) matches = matches.filter(q) if form.cleaned_data['country'] == 'foreigners': matches = matches.exclude( Q(pla=player, plb__country='KR') | Q(plb=player, pla__country='KR')) elif form.cleaned_data['country'] != 'all': matches = matches.filter( Q(pla=player, plb__country=form.cleaned_data['country']) | Q(plb=player, pla__country=form.cleaned_data['country'])) if form.cleaned_data['bestof'] != 'all': sc = int(form.cleaned_data['bestof']) // 2 + 1 matches = matches.filter(Q(sca__gte=sc) | Q(scb__gte=sc)) if form.cleaned_data['offline'] != 'both': matches = matches.filter( offline=(form.cleaned_data['offline'] == 'offline')) if form.cleaned_data['game'] != 'all': matches = matches.filter(game=form.cleaned_data['game']) if form.cleaned_data['wcs_season'] != '': if form.cleaned_data['wcs_season'] == 'all': matches = matches.filter( eventobj__uplink__parent__wcs_year__isnull=False) else: matches = matches.filter(eventobj__uplink__parent__wcs_year=int( form.cleaned_data['wcs_season'])) if form.cleaned_data['wcs_tier'] != '': tiers = list(map(int, form.cleaned_data['wcs_tier'])) matches = matches.filter(eventobj__uplink__parent__wcs_tier__in=tiers) if form.cleaned_data['after'] is not None: matches = matches.filter(date__gte=form.cleaned_data['after']) if form.cleaned_data['before'] is not None: matches = matches.filter(date__lte=form.cleaned_data['before']) if form.cleaned_data['event'] is not None: lex = shlex.shlex(form.cleaned_data['event'], posix=True) lex.wordchars += "'" lex.quotes = '"' terms = [s.strip() for s in list(lex) if s.strip() != ''] matches = matches.filter(eventobj__fullname__iregex=(r"\s".join( r".*{}.*".format(term) for term in terms))) matches = matches.distinct() # }}} # {{{ Statistics disp_matches = display_matches(matches, fix_left=player) base['matches'] = disp_matches base.update({ 'sc_my': sum(m['pla']['score'] for m in base['matches']), 'sc_op': sum(m['plb']['score'] for m in base['matches']), 'msc_my': sum(1 for m in base['matches'] if m['pla']['score'] > m['plb']['score']), 'msc_op': sum(1 for m in base['matches'] if m['plb']['score'] > m['pla']['score']), }) recent = matches.filter(date__gte=(date.today() - relativedelta(months=2))) base.update({ 'total': count_winloss_player(matches, player), 'vp': count_matchup_player(matches, player, P), 'vt': count_matchup_player(matches, player, T), 'vz': count_matchup_player(matches, player, Z), 'totalf': count_winloss_player(recent, player), 'vpf': count_matchup_player(recent, player, P), 'vtf': count_matchup_player(recent, player, T), 'vzf': count_matchup_player(recent, player, Z) }) # }}} # {{{ TL Postable has_after = form.cleaned_data['after'] is not None has_before = form.cleaned_data['before'] is not None if not has_after and not has_before: match_date = "" elif not has_after: # and has_before match_date = _(" before {}").format(form.cleaned_data['before']) elif not has_before: # and has_after match_date = _(" after {}").format(form.cleaned_data['after']) else: match_date = _(" between {} and {}").format( form.cleaned_data['after'], form.cleaned_data['before']) match_filter = "" def switcher(race): if race == "S": return "R" elif race == "s": return "r" return race def win(match): return match['pla']['score'] >= match['plb']['score'] def format_match(d): # TL only recognizes lower case country codes :( if d["pla"]["country"] is not None: d["pla_country_formatted"] = ":{}:".format( d["pla"]["country"].lower()) else: d["pla_country_formatted"] = "" if d["plb"]["country"] is not None: d["plb_country_formatted"] = ":{}:".format( d["plb"]["country"].lower()) else: d["plb_country_formatted"] = "" # and no race switchers d["pla_race"] = switcher(d["pla"]["race"]) d["plb_race"] = switcher(d["plb"]["race"]) # Check who won temp = {"plaws": "", "plawe": "", "plbws": "", "plbwe": ""} if win(d): temp["plaws"] = "[b]" temp["plawe"] = "[/b]" else: temp["plbws"] = "[b]" temp["plbwe"] = "[/b]" d.update(temp) d["pla_id"] = d["pla"]["id"] d["pla_tag"] = d["pla"]["tag"] d["pla_score"] = d["pla"]["score"] d["plb_id"] = d["plb"]["id"] d["plb_tag"] = d["plb"]["tag"] d["plb_score"] = d["plb"]["score"] return TL_HISTORY_MATCH_TEMPLATE.format(**d) recent_matches = disp_matches[:min(10, len(disp_matches))] recent = "\n".join(format_match(m) for m in recent_matches) recent_form = " ".join("W" if win(m) else "L" for m in reversed(recent_matches)) # Get the parameters and remove those with None value get_params = dict((k, form.cleaned_data[k]) for k in form.cleaned_data if form.cleaned_data[k] is not None) country = "" if player.country is not None: country = ":{}:".format(player.country.lower()) tl_params = { "player_tag": player.tag, "player_country_formatted": country, "player_race": switcher(player.race), "filter": match_filter, "date": match_date, "recent": recent, "pid": player_id, "get": urlencode(get_params), "url": "http://aligulac.com" } tl_params.update({ "sc_my": base["sc_my"], "sc_op": base["sc_op"], "msc_my": base["msc_my"], "msc_op": base["msc_op"], "form": recent_form }) def calc_percent(s): f, a = float(int(tl_params[s + "_my"])), int(tl_params[s + "_op"]) if f + a == 0: return " NaN" return round(100 * f / (f + a), 2) tl_params.update({ "sc_percent": calc_percent("sc"), "msc_percent": calc_percent("msc") }) tl_params.update(get_params) # Final clean up and translation if tl_params["bestof"] != "all": tl_params["bestof"] = _('best of') + ' {}'.format(tl_params["bestof"]) else: tl_params['bestof'] = _('all') if set(tl_params["race"]) == set('ptzr'): tl_params["race"] = _('all') else: tl_params['race'] = { 'p': _('Protoss'), 't': _('Terran'), 'z': _('Zerg'), 'ptr': _('No Zerg'), 'pzr': _('No Terran'), 'tzr': _('No Protoss'), }[tl_params['race']] if tl_params['country'] in ['all', 'foreigners']: tl_params['country'] = { 'all': _('all'), 'foreigners': _('foreigners'), }[tl_params['country']] else: tl_params['country'] = transformations.ccn_to_cn( transformations.cca2_to_ccn(tl_params['country'])) tl_params['offline'] = { 'offline': _('offline'), 'online': _('online'), 'both': _('both'), }[tl_params['offline']] if tl_params['game'] == 'all': tl_params['game'] = _('all') else: tl_params['game'] = dict(GAMES)[tl_params['game']] tl_params.update({ 'resfor': _('Results for'), 'games': _('Games'), 'matches': _('Matches'), 'curform': _('Current form'), 'recentmatches': _('Recent matches'), 'filters': _('Filters'), # Translators: These have to line up on the right! 'opprace': _('Opponent Race: '), # Translators: These have to line up on the right! 'oppcountry': _('Opponent Country: '), # Translators: These have to line up on the right! 'matchformat': _('Match Format: '), # Translators: These have to line up on the right! 'onoff': _('On/offline: '), # Translators: These have to line up on the right! 'version': _('Game Version: '), 'statslink': _('Stats by [url={url}]Aligulac[/url]'), # Translators: Link in the sense of a HTTP hyperlink. 'link': _('Link'), }) base.update({ # One of the replacement strings contain another string interpolation, # so do it twice. "postable_tl": TL_HISTORY_TEMPLATE.format(**tl_params).format(**tl_params) }) # }}} return render_to_response('player_results.djhtml', base)
def player(request, player_id): # {{{ Get player object and base context, generate messages and make changes if needed player = get_object_or_404(Player, id=player_id) base = base_ctx('Ranking', 'Summary', request, context=player) if request.method == 'POST' and 'modplayer' in request.POST and base['adm']: modform = PlayerModForm(request) base['messages'] += modform.update_player(player) else: modform = PlayerModForm(player=player) base['messages'] += generate_messages(player) # }}} # {{{ Various easy data matches = player.get_matchset() recent = matches.filter(date__gte=(date.today() - relativedelta(months=2))) base.update({ 'player': player, 'modform': modform, 'first': etn(lambda: matches.earliest('date')), 'last': etn(lambda: matches.latest('date')), 'totalmatches': matches.count(), 'offlinematches': matches.filter(offline=True).count(), 'aliases': player.alias_set.all(), 'earnings': ntz(player.earnings_set.aggregate(Sum('earnings'))['earnings__sum']), 'team': player.get_current_team(), 'total': count_winloss_player(matches, player), 'vp': count_matchup_player(matches, player, P), 'vt': count_matchup_player(matches, player, T), 'vz': count_matchup_player(matches, player, Z), 'totalf': count_winloss_player(recent, player), 'vpf': count_matchup_player(recent, player, P), 'vtf': count_matchup_player(recent, player, T), 'vzf': count_matchup_player(recent, player, Z), }) base['riv_nem_vic'] = zip_longest(player.rivals, player.nemesis, player.victim) if player.country is not None: base['countryfull'] = transformations.cc_to_cn(player.country) # }}} # {{{ Recent matches matches = player.get_matchset( related=['rta', 'rtb', 'pla', 'plb', 'eventobj'])[0:10] if matches.exists(): base['matches'] = display_matches(matches, fix_left=player, ratings=True) # }}} # {{{ Team memberships team_memberships = list( player.groupmembership_set.filter( group__is_team=True).select_related('group')) team_memberships.sort(key=lambda t: t.id, reverse=True) team_memberships.sort(key=meandate, reverse=True) team_memberships.sort(key=lambda t: t.current, reverse=True) base['teammems'] = team_memberships # }}} # {{{ If the player has at least one rating if player.current_rating: ratings = total_ratings(player.rating_set.filter( period__computed=True)).select_related('period') base.update({ 'highs': ( ratings.latest('rating'), ratings.latest('tot_vp'), ratings.latest('tot_vt'), ratings.latest('tot_vz'), ), 'recentchange': player.get_latest_rating_update(), 'firstrating': ratings.earliest('period'), 'rating': player.current_rating, }) if player.current_rating.decay >= INACTIVE_THRESHOLD: base['messages'].append( Message(msg_inactive % player.tag, 'Inactive', type=Message.INFO)) base['charts'] = base['recentchange'].period_id > base[ 'firstrating'].period_id else: base['messages'].append( Message(_('%s has no rating yet.') % player.tag, type=Message.INFO)) base['charts'] = False # }}} # {{{ If the player has enough games to make a chart if base['charts']: ratings = (total_ratings( player.rating_set.filter( period_id__lte=base['recentchange'].period_id)).select_related( 'period').prefetch_related('prev__rta', 'prev__rtb').order_by('period')) # {{{ Add stories and other extra information earliest = base['firstrating'] latest = base['recentchange'] # Look through team changes teampoints = [] for mem in base['teammems']: if mem.start and earliest.period.end < mem.start < latest.period.end: teampoints.append({ 'date': mem.start, 'rating': interp_rating(mem.start, ratings), 'data': [{ 'date': mem.start, 'team': mem.group, 'jol': _('joins') }], }) if mem.end and earliest.period.end < mem.end < latest.period.end: teampoints.append({ 'date': mem.end, 'rating': interp_rating(mem.end, ratings), 'data': [{ 'date': mem.end, 'team': mem.group, 'jol': _('leaves') }], }) teampoints.sort(key=lambda p: p['date']) # Condense if team changes happened within 14 days cur = 0 while cur < len(teampoints) - 1: if (teampoints[cur + 1]['date'] - teampoints[cur]['date']).days <= 14: teampoints[cur]['data'].append(teampoints[cur + 1]['data'][0]) del teampoints[cur + 1] else: cur += 1 # Sort first by date, then by joined/left for point in teampoints: point['data'].sort(key=lambda a: a['jol'], reverse=True) point['data'].sort(key=lambda a: a['date']) # Look through stories stories = player.story_set.all().select_related('event') for s in stories: if earliest.period.start < s.date < latest.period.start: s.rating = interp_rating(s.date, ratings) else: s.skip = True # }}} base.update({ 'ratings': add_counts(ratings), 'patches': PATCHES, 'stories': stories, 'teampoints': teampoints, }) else: base['messages'].append( Message(msg_nochart % player.tag, type=Message.INFO)) # }}} return render_to_response('player.djhtml', base)
def results(request, player_id): # {{{ Get objects player = get_object_or_404(Player, id=player_id) base = base_ctx("Ranking", "Match history", request, context=player) base["player"] = player # }}} # {{{ Filtering matches = player.get_matchset(related=["pla", "plb", "eventobj"]) form = ResultsFilterForm(request.GET) base["form"] = form form.is_valid() q = Q() for r in form.cleaned_data["race"].upper(): q |= Q(pla=player, rcb=r) | Q(plb=player, rca=r) matches = matches.filter(q) if form.cleaned_data["country"] == "foreigners": matches = matches.exclude(Q(pla=player, plb__country="KR") | Q(plb=player, pla__country="KR")) elif form.cleaned_data["country"] != "all": matches = matches.filter( Q(pla=player, plb__country=form.cleaned_data["country"]) | Q(plb=player, pla__country=form.cleaned_data["country"]) ) if form.cleaned_data["bestof"] != "all": sc = int(form.cleaned_data["bestof"]) // 2 + 1 matches = matches.filter(Q(sca__gte=sc) | Q(scb__gte=sc)) if form.cleaned_data["offline"] != "both": matches = matches.filter(offline=(form.cleaned_data["offline"] == "offline")) if form.cleaned_data["game"] != "all": matches = matches.filter(game=form.cleaned_data["game"]) if form.cleaned_data["after"] is not None: matches = matches.filter(date__gte=form.cleaned_data["after"]) if form.cleaned_data["before"] is not None: matches = matches.filter(date__lte=form.cleaned_data["before"]) if form.cleaned_data["event"] is not None: lex = shlex.shlex(form.cleaned_data["event"], posix=True) lex.wordchars += "'" lex.quotes = '"' terms = [s.strip() for s in list(lex) if s.strip() != ""] matches = matches.filter(eventobj__fullname__iregex=(r"\s".join(r".*{}.*".format(term) for term in terms))) # }}} # {{{ Statistics disp_matches = display_matches(matches, fix_left=player) base["matches"] = disp_matches base.update( { "sc_my": sum(m["pla"]["score"] for m in base["matches"]), "sc_op": sum(m["plb"]["score"] for m in base["matches"]), "msc_my": sum(1 for m in base["matches"] if m["pla"]["score"] > m["plb"]["score"]), "msc_op": sum(1 for m in base["matches"] if m["plb"]["score"] > m["pla"]["score"]), } ) recent = matches.filter(date__gte=(date.today() - relativedelta(months=2))) base.update( { "total": count_winloss_player(matches, player), "vp": count_matchup_player(matches, player, P), "vt": count_matchup_player(matches, player, T), "vz": count_matchup_player(matches, player, Z), "totalf": count_winloss_player(recent, player), "vpf": count_matchup_player(recent, player, P), "vtf": count_matchup_player(recent, player, T), "vzf": count_matchup_player(recent, player, Z), } ) # }}} # {{{ TL Postable has_after = form.cleaned_data["after"] is not None has_before = form.cleaned_data["before"] is not None if not has_after and not has_before: match_date = "" elif not has_after: # and has_before match_date = _(" before {}").format(form.cleaned_data["before"]) elif not has_before: # and has_after match_date = _(" after {}").format(form.cleaned_data["after"]) else: match_date = _(" between {} and {}").format(form.cleaned_data["after"], form.cleaned_data["before"]) match_filter = "" def switcher(race): if race == "S": return "R" elif race == "s": return "r" return race def win(match): return match["pla"]["score"] >= match["plb"]["score"] def format_match(d): # TL only recognizes lower case country codes :( if d["pla"]["country"] is not None: d["pla_country_formatted"] = ":{}:".format(d["pla"]["country"].lower()) else: d["pla_country_formatted"] = "" if d["plb"]["country"] is not None: d["plb_country_formatted"] = ":{}:".format(d["plb"]["country"].lower()) else: d["plb_country_formatted"] = "" # and no race switchers d["pla_race"] = switcher(d["pla"]["race"]) d["plb_race"] = switcher(d["plb"]["race"]) # Check who won temp = {"plaws": "", "plawe": "", "plbws": "", "plbwe": ""} if win(d): temp["plaws"] = "[b]" temp["plawe"] = "[/b]" else: temp["plbws"] = "[b]" temp["plbwe"] = "[/b]" d.update(temp) d["pla_id"] = d["pla"]["id"] d["pla_tag"] = d["pla"]["tag"] d["pla_score"] = d["pla"]["score"] d["plb_id"] = d["plb"]["id"] d["plb_tag"] = d["plb"]["tag"] d["plb_score"] = d["plb"]["score"] return TL_HISTORY_MATCH_TEMPLATE.format(**d) recent_matches = disp_matches[: min(10, len(disp_matches))] recent = "\n".join(format_match(m) for m in recent_matches) recent_form = " ".join("W" if win(m) else "L" for m in reversed(recent_matches)) # Get the parameters and remove those with None value get_params = dict((k, form.cleaned_data[k]) for k in form.cleaned_data if form.cleaned_data[k] is not None) country = "" if player.country is not None: country = ":{}:".format(player.country.lower()) tl_params = { "player_tag": player.tag, "player_country_formatted": country, "player_race": switcher(player.race), "filter": match_filter, "date": match_date, "recent": recent, "pid": player_id, "get": urlencode(get_params), "url": "http://aligulac.com", } tl_params.update( { "sc_my": base["sc_my"], "sc_op": base["sc_op"], "msc_my": base["msc_my"], "msc_op": base["msc_op"], "form": recent_form, } ) def calc_percent(s): f, a = float(int(tl_params[s + "_my"])), int(tl_params[s + "_op"]) if f + a == 0: return " NaN" return round(100 * f / (f + a), 2) tl_params.update({"sc_percent": calc_percent("sc"), "msc_percent": calc_percent("msc")}) tl_params.update(get_params) # Final clean up and translation if tl_params["bestof"] != "all": tl_params["bestof"] = _("best of") + " {}".format(tl_params["bestof"]) else: tl_params["bestof"] = _("all") if set(tl_params["race"]) == set("ptzr"): tl_params["race"] = _("all") else: tl_params["race"] = { "p": _("Protoss"), "t": _("Terran"), "z": _("Zerg"), "ptr": _("No Zerg"), "pzr": _("No Terran"), "tzr": _("No Protoss"), }[tl_params["race"]] if tl_params["country"] in ["all", "foreigners"]: tl_params["country"] = {"all": _("all"), "foreigners": _("foreigners")}[tl_params["country"]] else: tl_params["country"] = transformations.ccn_to_cn(transformations.cca2_to_ccn(tl_params["country"])) tl_params["offline"] = {"offline": _("offline"), "online": _("online"), "both": _("both")}[tl_params["offline"]] if tl_params["game"] == "all": tl_params["game"] = _("all") else: tl_params["game"] = dict(GAMES)[tl_params["game"]] tl_params.update( { "resfor": _("Results for"), "games": _("Games"), "matches": _("Matches"), "curform": _("Current form"), "recentmatches": _("Recent matches"), "filters": _("Filters"), # Translators: These have to line up on the right! "opprace": _("Opponent Race: "), # Translators: These have to line up on the right! "oppcountry": _("Opponent Country: "), # Translators: These have to line up on the right! "matchformat": _("Match Format: "), # Translators: These have to line up on the right! "onoff": _("On/offline: "), # Translators: These have to line up on the right! "version": _("Game Version: "), "statslink": _("Stats by [url={url}]Aligulac[/url]"), # Translators: Link in the sense of a HTTP hyperlink. "link": _("Link"), } ) base.update( { # One of the replacement strings contain another string interpolation, # so do it twice. "postable_tl": TL_HISTORY_TEMPLATE.format(**tl_params).format(**tl_params) } ) # }}} return render_to_response("player_results.djhtml", base)
def player(request, player_id): # {{{ Get player object and base context, generate messages and make changes if needed player = get_object_or_404(Player, id=player_id) base = base_ctx("Ranking", "Summary", request, context=player) if request.method == "POST" and "modplayer" in request.POST and base["adm"]: modform = PlayerModForm(request) base["messages"] += modform.update_player(player) else: modform = PlayerModForm(player=player) base["messages"] += generate_messages(player) # }}} # {{{ Various easy data matches = player.get_matchset() recent = matches.filter(date__gte=(date.today() - relativedelta(months=2))) base.update( { "player": player, "modform": modform, "first": etn(lambda: matches.earliest("date")), "last": etn(lambda: matches.latest("date")), "totalmatches": matches.count(), "offlinematches": matches.filter(offline=True).count(), "aliases": player.alias_set.all(), "earnings": ntz(player.earnings_set.aggregate(Sum("earnings"))["earnings__sum"]), "team": player.get_current_team(), "total": count_winloss_player(matches, player), "vp": count_matchup_player(matches, player, P), "vt": count_matchup_player(matches, player, T), "vz": count_matchup_player(matches, player, Z), "totalf": count_winloss_player(recent, player), "vpf": count_matchup_player(recent, player, P), "vtf": count_matchup_player(recent, player, T), "vzf": count_matchup_player(recent, player, Z), } ) riv = player.rivals or [] nem = player.nemesis or [] vic = player.victim or [] base["riv_nem_vic"] = zip_longest(riv, nem, vic) if player.country is not None: base["countryfull"] = transformations.cc_to_cn(player.country) # }}} # {{{ Recent matches matches = player.get_matchset(related=["rta", "rtb", "pla", "plb", "eventobj"])[0:10] if matches.exists(): base["matches"] = display_matches(matches, fix_left=player, ratings=True) # }}} # {{{ Team memberships team_memberships = list(player.groupmembership_set.filter(group__is_team=True).select_related("group")) team_memberships.sort(key=lambda t: t.id, reverse=True) team_memberships.sort(key=meandate, reverse=True) team_memberships.sort(key=lambda t: t.current, reverse=True) base["teammems"] = team_memberships # }}} # {{{ If the player has at least one rating if player.current_rating: ratings = total_ratings(player.rating_set.filter(period__computed=True)).select_related("period") base.update( { "highs": ( ratings.latest("rating"), ratings.latest("tot_vp"), ratings.latest("tot_vt"), ratings.latest("tot_vz"), ), "recentchange": player.get_latest_rating_update(), "firstrating": ratings.earliest("period"), "rating": player.current_rating, } ) if player.current_rating.decay >= INACTIVE_THRESHOLD: base["messages"].append(Message(msg_inactive % player.tag, "Inactive", type=Message.INFO)) base["charts"] = base["recentchange"].period_id > base["firstrating"].period_id else: base["messages"].append(Message(_("%s has no rating yet.") % player.tag, type=Message.INFO)) base["charts"] = False # }}} # {{{ If the player has enough games to make a chart if base["charts"]: ratings = ( total_ratings(player.rating_set.filter(period_id__lte=base["recentchange"].period_id)) .select_related("period__end") .prefetch_related("prev__rta", "prev__rtb") .order_by("period") ) # {{{ Add stories and other extra information earliest = base["firstrating"] latest = base["recentchange"] # Look through team changes teampoints = [] for mem in base["teammems"]: if mem.start and earliest.period.end < mem.start < latest.period.end: teampoints.append( { "date": mem.start, "rating": interp_rating(mem.start, ratings), "data": [{"date": mem.start, "team": mem.group, "jol": _("joins")}], } ) if mem.end and earliest.period.end < mem.end < latest.period.end: teampoints.append( { "date": mem.end, "rating": interp_rating(mem.end, ratings), "data": [{"date": mem.end, "team": mem.group, "jol": _("leaves")}], } ) teampoints.sort(key=lambda p: p["date"]) # Condense if team changes happened within 14 days cur = 0 while cur < len(teampoints) - 1: if (teampoints[cur + 1]["date"] - teampoints[cur]["date"]).days <= 14: teampoints[cur]["data"].append(teampoints[cur + 1]["data"][0]) del teampoints[cur + 1] else: cur += 1 # Sort first by date, then by joined/left for point in teampoints: point["data"].sort(key=lambda a: a["jol"], reverse=True) point["data"].sort(key=lambda a: a["date"]) # Look through stories stories = player.story_set.all().select_related("event__fullname") for s in stories: if earliest.period.start < s.date < latest.period.start: s.rating = interp_rating(s.date, ratings) else: s.skip = True # }}} base.update({"ratings": add_counts(ratings), "patches": PATCHES, "stories": stories, "teampoints": teampoints}) else: base["messages"].append(Message(msg_nochart % player.tag, type=Message.INFO)) # }}} return render_to_response("player.djhtml", base)
def match(request): base = base_ctx('Inference', 'Predict', request=request) # {{{ Get data, set up and simulate form = SetupForm(request.GET) if not form.is_valid(): return redirect('/inference/') result = MatchPredictionResult( dbpl=form.cleaned_data['ps'], bos=form.cleaned_data['bo'], s1=get_param(request, 's1', 0), s2=get_param(request, 's2', 0), ) # }}} # {{{ Postprocessing base.update({ 'form': form, 'dbpl': result.dbpl, 'rta': result.rta, 'rtb': result.rtb, 'proba': result.proba, 'probb': result.probb, 'match': result.obj, }) base.update({ 'max': max(base['proba'], base['probb']), 'fav': result.dbpl[0] if base['proba'] > base['probb'] else result.dbpl[1], }) resa = [oc for oc in result.outcomes if oc['sca'] > oc['scb']] resb = [oc for oc in result.outcomes if oc['scb'] > oc['sca']] if len(resa) < len(resb): resa = [None] * (len(resb) - len(resa)) + resa else: resb = [None] * (len(resa) - len(resb)) + resb base['res'] = list(zip(resa, resb)) # }}} # {{{ Scores and other data dbpl = result.dbpl thr = date.today() - relativedelta(months=2) pla_matches = dbpl[0].get_matchset() plb_matches = dbpl[1].get_matchset() base['tot_w_a'], base['tot_l_a'] = count_winloss_player( pla_matches, dbpl[0]) base['frm_w_a'], base['frm_l_a'] = count_winloss_player( pla_matches.filter(date__gte=thr), dbpl[0]) base['tot_w_b'], base['tot_l_b'] = count_winloss_player( plb_matches, dbpl[1]) base['frm_w_b'], base['frm_l_b'] = count_winloss_player( plb_matches.filter(date__gte=thr), dbpl[1]) if dbpl[1].race in 'PTZ': base['mu_w_a'], base['mu_l_a'] = count_matchup_player( pla_matches, dbpl[0], dbpl[1].race) base['fmu_w_a'], base['fmu_l_a'] = count_matchup_player( pla_matches.filter(date__gte=thr), dbpl[0], dbpl[1].race) if dbpl[0].race in 'PTZ': base['mu_w_b'], base['mu_l_b'] = count_matchup_player( plb_matches, dbpl[1], dbpl[0].race) base['fmu_w_b'], base['fmu_l_b'] = count_matchup_player( plb_matches.filter(date__gte=thr), dbpl[1], dbpl[0].race) wa_a, wb_a = count_winloss_games( Match.objects.filter(pla=dbpl[0], plb=dbpl[1])) wb_b, wa_b = count_winloss_games( Match.objects.filter(pla=dbpl[1], plb=dbpl[0])) base['vs_a'] = wa_a + wa_b base['vs_b'] = wb_a + wb_b base['matches'] = display_matches( Match.objects.filter( Q(pla=dbpl[0], plb=dbpl[1]) | Q(plb=dbpl[0], pla=dbpl[1])).select_related( 'period', 'pla', 'plb').order_by('-date', 'id'), fix_left=dbpl[0], ) # }}} postable_match(base, request) return render_to_response('pred_match.djhtml', base)
def match(request): base = base_ctx('Inference', 'Predict', request=request) # {{{ Get data, set up and simulate form = SetupForm(request.GET) if not form.is_valid(): return redirect('/inference/') num = form.cleaned_data['bo'][0] dbpl = form.cleaned_data['ps'] sipl = [make_player(p) for p in dbpl] match = MatchSim(num) match.set_players(sipl) match.modify( get_param_range(request, 's1', (0, num), 0), get_param_range(request, 's2', (0, num), 0), ) match.compute() # }}} # {{{ Postprocessing base.update({ 'form': form, 'dbpl': dbpl, 'rta': sipl[0].elo_vs_opponent(sipl[1]), 'rtb': sipl[1].elo_vs_opponent(sipl[0]), 'proba': match.get_tally()[sipl[0]][1], 'probb': match.get_tally()[sipl[1]][1], 'match': match, }) base.update({ 'max': max(base['proba'], base['probb']), 'fav': dbpl[0] if base['proba'] > base['probb'] else dbpl[1], }) resa, resb = [], [] outcomes = [ {'sca': outcome[1], 'scb': outcome[2], 'prob': outcome[0]} for outcome in match.instances_detail() ] resa = [oc for oc in outcomes if oc['sca'] > oc['scb']] resb = [oc for oc in outcomes if oc['scb'] > oc['sca']] if len(resa) < len(resb): resa = [None] * (len(resb) - len(resa)) + resa else: resb = [None] * (len(resa) - len(resb)) + resb base['res'] = list(zip(resa, resb)) # }}} # {{{ Scores and other data thr = date.today() - relativedelta(months=2) pla_matches = dbpl[0].get_matchset() plb_matches = dbpl[1].get_matchset() base['tot_w_a'], base['tot_l_a'] = count_winloss_player(pla_matches, dbpl[0]) base['frm_w_a'], base['frm_l_a'] = count_winloss_player(pla_matches.filter(date__gte=thr), dbpl[0]) base['tot_w_b'], base['tot_l_b'] = count_winloss_player(plb_matches, dbpl[1]) base['frm_w_b'], base['frm_l_b'] = count_winloss_player(plb_matches.filter(date__gte=thr), dbpl[1]) if dbpl[1].race in 'PTZ': base['mu_w_a'], base['mu_l_a'] = count_matchup_player(pla_matches, dbpl[0], dbpl[1].race) base['fmu_w_a'], base['fmu_l_a'] = count_matchup_player( pla_matches.filter(date__gte=thr), dbpl[0], dbpl[1].race ) if dbpl[0].race in 'PTZ': base['mu_w_b'], base['mu_l_b'] = count_matchup_player(plb_matches, dbpl[1], dbpl[0].race) base['fmu_w_b'], base['fmu_l_b'] = count_matchup_player( plb_matches.filter(date__gte=thr), dbpl[1], dbpl[0].race ) wa_a, wb_a = count_winloss_games(Match.objects.filter(pla=dbpl[0], plb=dbpl[1])) wb_b, wa_b = count_winloss_games(Match.objects.filter(pla=dbpl[1], plb=dbpl[0])) base['vs_a'] = wa_a + wa_b base['vs_b'] = wb_a + wb_b base['matches'] = display_matches( Match.objects.filter(Q(pla=dbpl[0], plb=dbpl[1]) | Q(plb=dbpl[0], pla=dbpl[1])) .select_related('period', 'pla', 'plb') .order_by('-date', 'id'), fix_left=dbpl[0], ) # }}} postable_match(base, request) base.update({"title": "{} vs. {}".format(dbpl[0].tag, dbpl[1].tag)}) return render_to_response('pred_match.html', base)
def results(request, player_id): # {{{ Get objects player = get_object_or_404(Player, id=player_id) base = base_ctx('Ranking', 'Match history', request, context=player) base['player'] = player # }}} # {{{ Filtering matches = player.get_matchset(related=['pla','plb','eventobj']) form = ResultsFilterForm(request.GET) base['form'] = form form.is_valid() q = Q() for r in form.cleaned_data['race'].upper(): q |= Q(pla=player, rcb=r) | Q(plb=player, rca=r) matches = matches.filter(q) if form.cleaned_data['country'] == 'foreigners': matches = matches.exclude(Q(pla=player, plb__country='KR') | Q(plb=player, pla__country='KR')) elif form.cleaned_data['country'] != 'all': matches = matches.filter( Q(pla=player, plb__country=form.cleaned_data['country']) | Q(plb=player, pla__country=form.cleaned_data['country']) ) if form.cleaned_data['bestof'] != 'all': sc = int(form.cleaned_data['bestof'])//2 + 1 matches = matches.filter(Q(sca__gte=sc) | Q(scb__gte=sc)) if form.cleaned_data['offline'] != 'both': matches = matches.filter(offline=(form.cleaned_data['offline']=='offline')) if form.cleaned_data['game'] != 'all': matches = matches.filter(game=form.cleaned_data['game']) if form.cleaned_data['wcs_season'] != '': if form.cleaned_data['wcs_season'] == 'all': matches = matches.filter( eventobj__uplink__parent__wcs_year__isnull=False ) else: matches = matches.filter( eventobj__uplink__parent__wcs_year=int(form.cleaned_data['wcs_season']) ) if form.cleaned_data['wcs_tier'] != '': tiers = list(map(int, form.cleaned_data['wcs_tier'])) matches = matches.filter( eventobj__uplink__parent__wcs_tier__in=tiers ) if form.cleaned_data['after'] is not None: matches = matches.filter(date__gte=form.cleaned_data['after']) if form.cleaned_data['before'] is not None: matches = matches.filter(date__lte=form.cleaned_data['before']) if form.cleaned_data['event'] is not None: lex = shlex.shlex(form.cleaned_data['event'], posix=True) lex.wordchars += "'" lex.quotes = '"' terms = [s.strip() for s in list(lex) if s.strip() != ''] matches = matches.filter( eventobj__fullname__iregex=( r"\s".join(r".*{}.*".format(term) for term in terms) ) ) matches = matches.distinct() # }}} # {{{ Statistics disp_matches = display_matches(matches, fix_left=player) base['matches'] = disp_matches base.update({ 'sc_my': sum(m['pla']['score'] for m in base['matches']), 'sc_op': sum(m['plb']['score'] for m in base['matches']), 'msc_my': sum(1 for m in base['matches'] if m['pla']['score'] > m['plb']['score']), 'msc_op': sum(1 for m in base['matches'] if m['plb']['score'] > m['pla']['score']), }) recent = matches.filter(date__gte=(date.today() - relativedelta(months=2))) base.update({ 'total': count_winloss_player(matches, player), 'vp': count_matchup_player(matches, player, P), 'vt': count_matchup_player(matches, player, T), 'vz': count_matchup_player(matches, player, Z), 'totalf': count_winloss_player(recent, player), 'vpf': count_matchup_player(recent, player, P), 'vtf': count_matchup_player(recent, player, T), 'vzf': count_matchup_player(recent, player, Z) }) # }}} # {{{ TL Postable has_after = form.cleaned_data['after'] is not None has_before = form.cleaned_data['before'] is not None if not has_after and not has_before: match_date = "" elif not has_after: # and has_before match_date = _(" before {}").format(form.cleaned_data['before']) elif not has_before: # and has_after match_date = _(" after {}").format(form.cleaned_data['after']) else: match_date = _(" between {} and {}").format(form.cleaned_data['after'], form.cleaned_data['before']) match_filter = "" def switcher(race): if race == "S": return "R" elif race == "s": return "r" return race def win(match): return match['pla']['score'] >= match['plb']['score'] def format_match(d): # TL only recognizes lower case country codes :( if d["pla"]["country"] is not None: d["pla_country_formatted"] = ":{}:".format(d["pla"]["country"].lower()) else: d["pla_country_formatted"] = "" if d["plb"]["country"] is not None: d["plb_country_formatted"] = ":{}:".format(d["plb"]["country"].lower()) else: d["plb_country_formatted"] = "" # and no race switchers d["pla_race"] = switcher(d["pla"]["race"]) d["plb_race"] = switcher(d["plb"]["race"]) # Check who won temp = { "plaws": "", "plawe": "", "plbws": "", "plbwe": "" } if win(d): temp["plaws"] = "[b]" temp["plawe"] = "[/b]" else: temp["plbws"] = "[b]" temp["plbwe"] = "[/b]" d.update(temp) d["pla_id"] = d["pla"]["id"] d["pla_tag"] = d["pla"]["tag"] d["pla_score"] = d["pla"]["score"] d["plb_id"] = d["plb"]["id"] d["plb_tag"] = d["plb"]["tag"] d["plb_score"] = d["plb"]["score"] return TL_HISTORY_MATCH_TEMPLATE.format(**d) recent_matches = disp_matches[:min(10, len(disp_matches))] recent = "\n".join(format_match(m) for m in recent_matches) recent_form = " ".join("W" if win(m) else "L" for m in reversed(recent_matches)) # Get the parameters and remove those with None value get_params = dict((k, form.cleaned_data[k]) for k in form.cleaned_data if form.cleaned_data[k] is not None) country = "" if player.country is not None: country = ":{}:".format(player.country.lower()) tl_params = { "player_tag": player.tag, "player_country_formatted": country, "player_race": switcher(player.race), "filter": match_filter, "date": match_date, "recent": recent, "pid": player_id, "get": urlencode(get_params), "url": "http://aligulac.com" } tl_params.update({ "sc_my": base["sc_my"], "sc_op": base["sc_op"], "msc_my": base["msc_my"], "msc_op": base["msc_op"], "form": recent_form }) def calc_percent(s): f, a = float(int(tl_params[s+"_my"])), int(tl_params[s+"_op"]) if f + a == 0: return " NaN" return round(100 * f / (f+a), 2) tl_params.update({ "sc_percent": calc_percent("sc"), "msc_percent": calc_percent("msc") }) tl_params.update(get_params) # Final clean up and translation if tl_params["bestof"] != "all": tl_params["bestof"] = _('best of') + ' {}'.format(tl_params["bestof"]) else: tl_params['bestof'] = _('all') if set(tl_params["race"]) == set('ptzr'): tl_params["race"] = _('all') else: tl_params['race'] = { 'p': _('Protoss'), 't': _('Terran'), 'z': _('Zerg'), 'ptr': _('No Zerg'), 'pzr': _('No Terran'), 'tzr': _('No Protoss'), }[tl_params['race']] if tl_params['country'] in ['all', 'foreigners']: tl_params['country'] = { 'all': _('all'), 'foreigners': _('foreigners'), }[tl_params['country']] else: tl_params['country'] = transformations.ccn_to_cn(transformations.cca2_to_ccn(tl_params['country'])) tl_params['offline'] = { 'offline': _('offline'), 'online': _('online'), 'both': _('both'), }[tl_params['offline']] if tl_params['game'] == 'all': tl_params['game'] = _('all') else: tl_params['game'] = dict(GAMES)[tl_params['game']] tl_params.update({ 'resfor': _('Results for'), 'games': _('Games'), 'matches': _('Matches'), 'curform': _('Current form'), 'recentmatches': _('Recent matches'), 'filters': _('Filters'), # Translators: These have to line up on the right! 'opprace': _('Opponent Race: '), # Translators: These have to line up on the right! 'oppcountry': _('Opponent Country: '), # Translators: These have to line up on the right! 'matchformat': _('Match Format: '), # Translators: These have to line up on the right! 'onoff': _('On/offline: '), # Translators: These have to line up on the right! 'version': _('Game Version: '), 'statslink': _('Stats by [url={url}]Aligulac[/url]'), # Translators: Link in the sense of a HTTP hyperlink. 'link': _('Link'), }) base.update({ # One of the replacement strings contain another string interpolation, # so do it twice. "postable_tl": TL_HISTORY_TEMPLATE.format(**tl_params).format(**tl_params) }) # }}} return render_to_response('player_results.djhtml', base)