Пример #1
0
 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)}
Пример #2
0
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)
Пример #3
0
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)
Пример #4
0
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)
Пример #5
0
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)
Пример #6
0
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)
Пример #7
0
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)
Пример #8
0
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)
Пример #9
0
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)
Пример #10
0
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)