Example #1
0
def results(request):
    base = base_ctx('Results', 'By Date', request)

    try:
        day = datetime.strptime(get_param(request, 'd', None),
                                '%Y-%m-%d').date()
    except:
        day = date.today()

    bounds = Match.objects.aggregate(Min('date'), Max('date'))
    day = min(max(bounds['date__min'], day), bounds['date__max'])
    base.update({
        'mindate': bounds['date__min'],
        'maxdate': bounds['date__max'],
        'td': day,
    })

    matches = (Match.objects.filter(date=day).order_by(
        'eventobj__idx', 'eventobj__latest', 'event',
        'id').prefetch_related('message_set', 'rta', 'rtb', 'pla', 'plb',
                               'eventobj').annotate(Count('eventobj__match')))

    add_links = request.user.is_authenticated() and request.user.is_staff

    base['matches'] = display_matches(matches,
                                      date=False,
                                      ratings=True,
                                      messages=True,
                                      eventcount=True,
                                      add_links=add_links)

    return render_to_response('results.djhtml', base)
Example #2
0
def add_matches(request):
    base = base_ctx('Submit', 'Matches', request)
    login_message(base)

    if request.method == 'POST' and 'submit' in request.POST:
        form = AddMatchesForm(base['adm'], request=request)
        base['matches'] = display_matches(form.parse_matches(request.user), messages=False)
        base['messages'] += form.messages
    else:
        form = AddMatchesForm(base['adm'])
        try:
            get_event = Event.objects.get(id=request.GET['eventid'])
            if get_event.closed:
                get_event.open()
                base['messages'].append(Message(_("Reopened '%s'.") % get_event.fullname, type=Message.SUCCESS))
            form['eventobj'].field.choices.append((get_event.id, get_event.fullname))
            form['eventobj'].field.choices.sort(key=lambda e: e[1])
            base['event_override'] = get_event.id
        except:
            pass

    base['form'] = form

    base.update({"title": _("Submit results")})

    return render_to_response('add.html', base)
Example #3
0
def add_matches(request):
    base = base_ctx('Submit', 'Matches', request)
    login_message(base)

    if request.method == 'POST' and 'submit' in request.POST:
        form = AddMatchesForm(base['adm'], request=request)
        base['matches'] = display_matches(form.parse_matches(request.user),
                                          messages=False)
        base['messages'] += form.messages
    else:
        form = AddMatchesForm(base['adm'])
        try:
            get_event = Event.objects.get(id=request.GET['eventid'])
            if get_event.closed:
                get_event.open()
                base['messages'].append(
                    Message(_("Reopened '%s'.") % get_event.fullname,
                            type=Message.SUCCESS))
            form['eventobj'].field.choices.append(
                (get_event.id, get_event.fullname))
            form['eventobj'].field.choices.sort(key=lambda e: e[1])
            base['event_override'] = get_event.id
        except:
            pass

    base['form'] = form

    return render_to_response('add.djhtml', base)
Example #4
0
def review_matches(request):
    base = base_ctx('Submit', 'Review', request)
    if not base['adm']:
        return redirect('/login/')
    login_message(base)

    if request.method == 'POST':
        form = ReviewMatchesForm(request=request, submitter=request.user)
        base['messages'] += form.messages
    else:
        form = ReviewMatchesForm()

    base['form'] = form

    base['groups'] = (
        PreMatchGroup.objects.filter(prematch__isnull=False)
            .prefetch_related('prematch_set')
            .order_by('id', 'event')
            .distinct()
    )

    for g in base['groups']:
        g.prematches = display_matches(g.prematch_set.all(), messages=False, no_events=True)

    return render_to_response('review.djhtml', base)
Example #5
0
def review_matches(request):
    base = base_ctx('Submit', 'Review', request)
    if not base['adm']:
        return redirect('/login/')
    login_message(base)

    if request.method == 'POST':
        form = ReviewMatchesForm(request=request, submitter=request.user)
        base['messages'] += form.messages
    else:
        form = ReviewMatchesForm()

    base['form'] = form

    base['groups'] = (
        PreMatchGroup.objects.filter(prematch__isnull=False)
            .prefetch_related('prematch_set')
            .order_by('id', 'event')
            .distinct()
    )

    for g in base['groups']:
        g.prematches = display_matches(g.prematch_set.all(), messages=False)

    base.update({"title": _("Review results")})

    return render_to_response('review.html', base)
Example #6
0
def player_results(request, player_id):
    player = get_object_or_404(Player, id=int(player_id))
    matches = Match.objects.filter(Q(pla=player) | Q(plb=player))

    base = base_ctx('Ranking', 'Match history', request, context=player)

    if 'race' in request.GET:
        q = None
        for r in request.GET['race']:
            try:
                q |= Q(pla=player, rcb=r)
                q |= Q(plb=player, rca=r)
            except:
                q = Q(pla=player, rcb=r)
                q |= Q(plb=player, rca=r)
        matches = matches.filter(q)
        base['race'] = request.GET['race']
    else:
        base['race'] = 'ptzr'

    if 'nats' in request.GET:
        if request.GET['nats'] == 'foreigners':
            matches = matches.exclude(Q(pla=player, plb__country='KR') | Q(plb=player, pla__country='KR'))
        elif request.GET['nats'] == 'kr':
            matches = matches.filter(Q(pla=player, plb__country='KR') | Q(plb=player, pla__country='KR'))
        base['nats'] = request.GET['nats']
    else:
        base['nats'] = 'all'

    if 'bo' in request.GET:
        if request.GET['bo'] == '3':
            matches = matches.filter(Q(sca__gte=2) | Q(scb__gte=2))
        elif request.GET['bo'] == '5':
            matches = matches.filter(Q(sca__gte=3) | Q(scb__gte=3))
        base['bo'] = request.GET['bo']
    else:
        base['bo'] = 'all'
    
    if 'offline' in request.GET:
        if request.GET['offline'] == 'online':
            matches = matches.filter(offline=0)
        elif request.GET['offline'] == 'offline':
            matches = matches.filter(offline=1)
        base['offline'] = request.GET['offline']
    else:
        base['offline'] = 'both'
    
    matches = matches.order_by('-date', '-eventobj__lft', 'event', '-id')
    matches = matches.select_related('pla__rating').select_related('plb__rating').select_related('period')

    base['matches'] = display_matches(matches, fix_left=player, ratings=True)
    
    base['sc_my'] = sum([m.pla_score for m in base['matches']])
    base['sc_op'] = sum([m.plb_score for m in base['matches']])
    base['msc_my'] = sum([1 if m.pla_score > m.plb_score else 0 for m in base['matches']])
    base['msc_op'] = sum([1 if m.plb_score > m.pla_score else 0 for m in base['matches']])
    
    base['player'] = player
    
    return render_to_response('player_results.html', base)
Example #7
0
def results(request):
    base = base_ctx('Results', 'By Date', request)

    try:
        day = datetime.strptime(get_param(request, 'd', None), '%Y-%m-%d').date()
    except:
        day = date.today()

    bounds = Match.objects.aggregate(Min('date'), Max('date'))
    day = min(max(bounds['date__min'], day), bounds['date__max'])
    base.update({
        'mindate': bounds['date__min'],
        'maxdate': bounds['date__max'],
        'td':      day,
    })

    matches = (
        Match.objects.filter(date=day).order_by('eventobj__idx', 'eventobj__latest', 'event', 'id')
            .prefetch_related('message_set', 'rta', 'rtb', 'pla', 'plb', 'eventobj')
            .annotate(Count('eventobj__match'))
    )

    add_links = request.user.is_authenticated() and request.user.is_staff

    base['matches'] = display_matches(matches, date=False, ratings=True, messages=True,
                                      eventcount=True, add_links=add_links)

    return render_to_response('results.djhtml', base)
Example #8
0
def integrity(request):
    base = base_ctx('Submit', 'Integrity', request)

    if not base['adm']:
        base.update(csrf(request))
        return render_to_response('login.html', base)

    add_login_message(base)
    base.update(csrf(request))

    with open(M_WARNINGS, 'r') as f:
        warnings = pickle.load(f)
    with open(M_APPROVED, 'r') as f:
        approved = pickle.load(f)

    if 'del' in request.POST or 'del_ok' in request.POST:
        ndel = 0
        for key in request.POST:
            if request.POST[key] != 'y':
                continue
            if key[0:6] == 'match-':
                try:
                    Match.objects.get(id=int(key.split('-')[-1])).delete()
                    ndel += 1
                except:
                    pass
        base['messages'].append(Message('Deleted %i match(es).' % ndel, type=Message.SUCCESS))

    if 'del_ok' in request.POST or 'false' in request.POST:
        warning = tuple([int(f) for f in request.POST['warning'].split(',')])
        warnings.remove(warning)
        approved.add(warning)

        with open(M_WARNINGS, 'w') as f:
            pickle.dump(warnings, f)
        with open(M_APPROVED, 'w') as f:
            pickle.dump(approved, f)
        base['messages'].append(Message('Resolved one integrity warning.', type=Message.SUCCESS))

    matches = []
    for w in warnings:
        block = []
        for id in w:
            try:
                block.append(Match.objects.get(id=id))
            except:
                pass
        matches.append((','.join(str(k) for k in list(w)), display_matches(block, messages=False)))

        if len(matches) == 50:
            break

    base['matches'] = matches
    if len(matches) == 0:
        base['messages'].append(Message('There are currently no warnings pending resolution.', 
                                        type=Message.INFO))
    base['num'] = len(warnings)

    return render_to_response('integrity.html', base)
Example #9
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'])
    # }}}

    # {{{ Statistics
    base['matches'] = display_matches(matches, fix_left=player)
    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 if m['pla_score'] > m['plb_score'] else 0 for m in base['matches']]),
        'msc_op': sum([1 if m['plb_score'] > m['pla_score'] else 0 for m in base['matches']]),
    })
    # }}}

    base.update({"title": player.tag})
    
    return render_to_response('player_results.html', base)
Example #10
0
def integrity(request):
    base = base_ctx('Submit', 'Integrity', request)

    if not base['adm']:
        base.update(csrf(request))
        return render_to_response('login.html', base)

    base['user'] = request.user.username
    base.update(csrf(request))

    with open(M_WARNINGS, 'r') as f:
        warnings = pickle.load(f)
    with open(M_APPROVED, 'r') as f:
        approved = pickle.load(f)

    if 'del' in request.POST or 'del_ok' in request.POST:
        for key in request.POST:
            if request.POST[key] != 'y':
                continue
            if key[0:6] == 'match-':
                try:
                    Match.objects.get(id=int(key.split('-')[-1])).delete()
                except:
                    pass

    if 'del_ok' in request.POST or 'false' in request.POST:
        warning = tuple([int(f) for f in request.POST['warning'].split(',')])
        warnings.remove(warning)
        approved.add(warning)

        with open(M_WARNINGS, 'w') as f:
            pickle.dump(warnings, f)
        with open(M_APPROVED, 'w') as f:
            pickle.dump(approved, f)

    matches = []
    for w in warnings:
        block = []
        for id in w:
            try:
                block.append(Match.objects.get(id=id))
            except:
                pass
        matches.append((','.join(str(k) for k in list(w)), display_matches(block)))

        if len(matches) == 50:
            break
    base['matches'] = matches
    base['num'] = len(warnings)

    return render_to_response('integrity.html', base)
Example #11
0
def results(request):
    base = base_ctx('Results', 'By Date', request)

    try:
        ints = [int(x) for x in request.GET['d'].split('-')]
        td = datetime.date(ints[0], ints[1], ints[2])
    except:
        td = datetime.date.today()

    matches = Match.objects.filter(date=td).order_by('eventobj__lft', 'event', 'id')

    base['matches'] = display_matches(matches, date=False, ratings=True)
    base['td'] = td

    return render_to_response('results.html', base)
Example #12
0
def clocks(request):
    ctx = base_ctx('Misc', 'Days Since…', request)

    ctx["title"] = _("Number of days since…")
    ctx["clocks"] = list()
    for desc, alt_desc, q, t in CLOCKS:
        obj = None
        extra = None
        date = None

        if t == "match":
            q = q.prefetch_related("pla", "plb", "eventobj")
            matches = list(q[:10])

            extra = display_matches(matches)

            obj = matches[0]
            date = obj.date

        elif t == "event_winner":
            q = q.prefetch_related("earnings_set")
            events = list(q[:10])
            obj = events[0]
            extra = list()
            for e in events:
                pearnings = list(
                    e.earnings_set
                    .exclude(placement=0)
                    .order_by("placement")
                    .prefetch_related("player")[:2]
                )
                extra.append((e, pearnings))

            date = obj.latest

        elif t == "one_time":
            date = q()

        diff = datetime.today().date() - date
        years = diff.days // 365
        days = diff.days % 365
        c = Clock(desc, alt_desc, obj, t, date, years, days, extra)

        ctx["clocks"].append(c)

    ctx["clocks"].sort(key=lambda c: c.date, reverse=True)

    return render_to_response("clocks.html", ctx)
Example #13
0
def clocks(request):
    ctx = base_ctx('Misc', 'Days Since…', request)

    ctx["clocks"] = list()
    for desc, alt_desc, q, t in CLOCKS:
        obj = None
        extra = None
        date = None

        if t == "match":
            q = q.prefetch_related("pla", "plb", "eventobj", "message_set")
            matches = q[:10]

            extra = display_matches(matches)

            date = extra[0]["date"]

        elif t == "event_winner":
            q = q.prefetch_related("earnings_set")
            events = list(q[:10])
            obj = events[0]
            extra = list()
            for e in events:
                pearnings = list(
                    e.earnings_set.exclude(placement=0).order_by(
                        "placement").prefetch_related("player")[:2])
                extra.append((e, pearnings))

            date = obj.latest

        elif t == "one_time":
            date = q()

        diff = datetime.today().date() - date
        years = diff.days // 365
        days = diff.days % 365
        c = Clock(desc, alt_desc, obj, t, date, years, days, extra)

        ctx["clocks"].append(c)

    ctx["clocks"].sort(key=lambda c: c.date, reverse=True)

    return render_to_response("clocks.djhtml", ctx)
Example #14
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)
Example #15
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)
Example #16
0
def events(request, event_id=None):
    # {{{ Get base context, redirect if necessary
    if 'goto' in request.GET:
        return redirect('/results/events/' + request.GET['goto'])

    base = base_ctx('Results', 'By Event', request)
    # }}}

    # {{{ Display the main table if event ID is not given
    if event_id is None:
        root_events = (
            Event.objects
                .annotate(num_uplinks=Count("uplink"))
                .filter(num_uplinks=1)
                .order_by('name')
                .only('id', 'name', 'big', 'category', 'fullname')
        )
        base.update({
            'ind_bigs':    collect(root_events.filter(big=True, category=CAT_INDIVIDUAL), 2),
            'ind_smalls':  root_events.filter(big=False, category=CAT_INDIVIDUAL).order_by('name'),
            'team_bigs':   collect(root_events.filter(big=True, category=CAT_TEAM), 2),
            'team_smalls': root_events.filter(big=False, category=CAT_TEAM).order_by('name'),
            'freq_bigs':   collect(root_events.filter(big=True, category=CAT_FREQUENT), 2),
            'freq_smalls': root_events.filter(big=False, category=CAT_FREQUENT).order_by('name'),
        })

        return render_to_response('events.html', base)
    # }}}

    # {{{ Get object, generate messages, and ensure big is set. Find familial relationships.
    event = get_object_or_404(Event, id=event_id)
    base['messages'] += generate_messages(event)

    matches = event.get_matchset()
    if matches.count() > 200 and not event.big:
        event.set_big(True)

    base.update({
        'event':            event,
        'siblings':         event.get_parent().get_immediate_children().exclude(id=event.id)
                                if event.get_parent() else None,
        'path':             event.get_ancestors(id=True),
        'children':         event.get_immediate_children(),
    })
    # }}}

    # {{{ Make forms
    if base['adm']:
        def check_form(formname, cl, check):
            if request.method == 'POST' and check in request.POST:
                f = cl(request=request, event=event)
                base['messages'] += f.update_event(event)
            else:
                f = cl(event=event)
            base[formname] = f

        check_form('form', EventModForm, 'modevent')
        check_form('addform', AddForm, 'addevent')
        if event.has_children():
            check_form('reorderform', ReorderForm, 'reorder')
        if event.type == TYPE_EVENT:
            check_form('ppform', PrizepoolModForm, 'modpp')
        if not event.has_children() and event.get_immediate_matchset().exists():
            check_form('stform', StoryModForm, 'modstories')
    # }}}

    # {{{ Prizepool information for the public
    total_earnings = Earnings.objects.filter(event__uplink__parent=event)
    currencies = list({r['currency'] for r in total_earnings.values('currency').distinct()})
    base.update({
        'prizepool':     total_earnings.aggregate(Sum('earnings'))['earnings__sum'],
        'nousdpp':       len(currencies) > 1 or len(currencies) == 1 and currencies[0] != 'USD',
        'prizepoolorig': [{
            'pp':  total_earnings.filter(currency=k).aggregate(Sum('origearnings'))['origearnings__sum'],
            'cur': k,
        } for k in currencies],
    })
    # }}}

    # {{{ Other easy statistics
    base.update({
        'game':      etn(lambda: dict(Match.GAMES)[matches.values('game').distinct()[0]['game']]),
        'offline':   etn(lambda: matches.values('offline').distinct()[0]['offline']),
        'nmatches':  matches.count(),
        'ngames':    sum(count_winloss_games(matches)),
        'pvp_games': count_mirror_games(matches, 'P'),
        'tvt_games': count_mirror_games(matches, 'T'),
        'zvz_games': count_mirror_games(matches, 'Z'),
        'matches':   display_matches(
            matches.prefetch_related('message_set')
                .prefetch_related('pla', 'plb', 'eventobj')
                .annotate(Count('eventobj__match'))
                .order_by('-eventobj__latest', '-eventobj__idx', '-date', '-id')[0:200],
            eventcount=True,
        ),
        'nplayers':  Player.objects.filter(
            Q(id__in=matches.values('pla')) | Q(id__in=matches.values('plb'))
        ).count(),
    })

    base['pvt_wins'], base['pvt_loss'] = count_matchup_games(matches, 'P', 'T')
    base['pvz_wins'], base['pvz_loss'] = count_matchup_games(matches, 'P', 'Z')
    base['tvz_wins'], base['tvz_loss'] = count_matchup_games(matches, 'T', 'Z')
    base['tot_mirror'] = base['pvp_games'] + base['tvt_games'] + base['zvz_games']
    # }}}

    base.update({"title": event})

    return render_to_response('eventres.html', base)
Example #17
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)
Example #18
0
def review(request):
    base = base_ctx('Submit', 'Review', request)

    if not base['adm']:
        base.update(csrf(request))
        return render_to_response('login.html', base)

    add_login_message(base)
    base['events'] = Event.objects.filter(closed=False, rgt=F('lft')+1).order_by('lft')

    if 'act' in request.POST and base['adm'] == True:
        if int(request.POST['eobj']) != 2:
            eobj = Event.objects.get(id=int(request.POST['eobj']))
            base['eobj'] = eobj.id

        delete = True if request.POST['act'] == 'reject' else False

        success = []
        ndel = 0

        for key in sorted(request.POST.keys()):
            if request.POST[key] != 'y':
                continue
            if key[0:6] == 'match-':
                pm = PreMatch.objects.get(id=int(key.split('-')[-1]))

                if delete:
                    group = pm.group
                    pm.delete()
                    if not group.prematch_set.all().exists():
                        group.delete()
                    ndel += 1
                    continue
                
                if pm.pla == None:
                    pm.pla_string = request.POST['match-%i-pla' % pm.id]
                if pm.plb == None:
                    pm.plb_string = request.POST['match-%i-plb' % pm.id]

                if pm.pla == None or pm.plb == None:
                    review_treat_players(pm, base)

                if pm.pla and not pm.rca:
                    pm.pla = None
                if pm.plb and not pm.rcb:
                    pm.plb = None

                pm.save()

                if pm.pla and pm.plb and pm.rca and pm.rcb:
                    m = Match()
                    m.pla = pm.pla
                    m.plb = pm.plb
                    m.sca = pm.sca
                    m.scb = pm.scb
                    m.rca = pm.rca
                    m.rcb = pm.rcb
                    if request.POST['date'].strip() == '':
                        m.date = pm.group.date
                    else:
                        m.date = request.POST['date']
                    m.event = pm.group.event
                    m.eventobj = eobj
                    m.submitter = request.user
                    m.set_period()
                    m.offline = pm.group.offline
                    m.game = pm.group.game
                    m.save()
                    
                    success.append(m)

                    group = pm.group
                    pm.delete()
                    if not group.prematch_set.all().exists():
                        group.delete()

        base['success'] = display_matches(success, messages=False)
        if len(success) > 0:
            base['messages'].append(Message('Approved %i match(es).' % len(success), type=Message.SUCCESS))
        
        if ndel > 0:
            base['messages'].append(Message('Rejected %i match(es).' % ndel, type=Message.SUCCESS))

    groups = PreMatchGroup.objects.filter(prematch__isnull=False)\
            .select_related('prematch').order_by('id', 'event').distinct()
    for g in groups:
        g.prematches = display_matches(g.prematch_set.all(), messages=False)
    base['groups'] = groups

    base.update(csrf(request))
    return render_to_response('review.html', base)
Example #19
0
def events(request, event_id=None):
    # {{{ Get base context, redirect if necessary
    if 'goto' in request.GET:
        return redirect('/results/events/' + request.GET['goto'])

    base = base_ctx('Results', 'By Event', request)
    # }}}

    # {{{ Display the main table if event ID is not given
    if event_id is None:
        root_events = (
            Event.objects
                  .annotate(num_uplinks=Count("uplink"))
                  .filter(num_uplinks=1)
                  .order_by('name')
                  .only('id', 'name', 'big', 'category', 'fullname')
        )
        base.update({
            'bigs': (
                list(root_events.filter(big=True, category=CAT_INDIVIDUAL)) +
                list(root_events.filter(big=True, category=CAT_TEAM)) +
                list(root_events.filter(big=True, category=CAT_FREQUENT))
            ),
            'smalls': (
                list(root_events.filter(big=False, category=CAT_INDIVIDUAL).order_by('name')) +
                list(root_events.filter(big=False, category=CAT_TEAM).order_by('name')) +
                list(root_events.filter(big=False, category=CAT_FREQUENT).order_by('name'))
            )
        })

        base['messages'].append(Message(
            _('The events are organized in a hierarchical fashion. Thus, all GSL tournaments '
              'are filed under GSL, all Code S under their respective seasons, all groups under '
              'their respective Code S event, and so on.'),
            type=Message.INFO
        ))

        return render_to_response('events.djhtml', base)
    # }}}

    # {{{ Get object, generate messages, and ensure big is set. Find familial relationships.
    event = get_object_or_404(Event, id=event_id)
    base['messages'] += generate_messages(event)

    matches = event.get_matchset()
    if matches.count() > 200 and not event.big:
        event.set_big(True)

    base.update({
        'event':            event,
        'siblings':         event.get_parent().get_immediate_children().exclude(id=event.id)
                                if event.get_parent() else None,
        'path':             event.get_ancestors(id=True),
        'children':         event.get_immediate_children(),
    })
    # }}}

    # {{{ Make forms
    if base['adm']:
        def check_form(formname, cl, check):
            if request.method == 'POST' and check in request.POST:
                f = cl(request=request, event=event)
                base['messages'] += f.update_event(event)
            else:
                f = cl(event=event)
            base[formname] = f

        check_form('form', EventModForm, 'modevent')
        check_form('addform', AddForm, 'addevent')
        if event.has_children():
            check_form('reorderform', ReorderForm, 'reorder')
        if event.type == TYPE_EVENT:
            check_form('ppform', PrizepoolModForm, 'modpp')
            check_form('wcsform', WCSModForm, 'modwcs')
        if not event.has_children() and event.get_immediate_matchset().exists():
            check_form('stform', StoriesForm, 'modstory')

        if 'close' in request.GET and request.GET['close'] == '1':
            event.close()
            base['messages'].append(Message(_('Sucessfully closed event.'), type=Message.SUCCESS))
    # }}}

    # {{{ Prizepool information for the public
    total_earnings = Earnings.objects.filter(event__uplink__parent=event)

    local_earnings = Earnings.objects.filter(event=event)

    ranked_prize = local_earnings.exclude(placement=0)\
                                 .order_by('-earnings', 'placement')
    unranked_prize = list(
        local_earnings.filter(placement=0).order_by('-earnings')
    )

    placements = get_placements(event)
    prize_pool_table = list()
    for k, g in groupby(ranked_prize, key=lambda x: x.earnings):
        gl = list(g)
        prize_pool_table.append((k, placements[k], gl, len(gl)))

    if len(prize_pool_table) > 0:
        base['ranked_prize'] = prize_pool_table
    if len(unranked_prize) > 0:
        base['unranked_prize'] = unranked_prize

    currencies = list({r['currency'] for r in total_earnings.values('currency').distinct()})
    base.update({
        'prizepool':     total_earnings.aggregate(Sum('earnings'))['earnings__sum'],
        'nousdpp':       len(currencies) > 1 or len(currencies) == 1 and currencies[0] != 'USD',
        'prizepoolorig': [{
            'pp':  total_earnings.filter(currency=k).aggregate(Sum('origearnings'))['origearnings__sum'],
            'cur': k,
        } for k in currencies],
    })
    # }}}

    # {{{ Other easy statistics

    add_links = request.user.is_authenticated() and request.user.is_staff

    base.update({
        'game':      etn(lambda: dict(GAMES)[matches.values('game').distinct()[0]['game']]),
        'nmatches':  matches.count(),
        'ngames':    sum(count_winloss_games(matches)),
        'pvp_games': count_mirror_games(matches, 'P'),
        'tvt_games': count_mirror_games(matches, 'T'),
        'zvz_games': count_mirror_games(matches, 'Z'),
        'matches':   display_matches(
            matches.prefetch_related('message_set')
                .prefetch_related('pla', 'plb', 'eventobj')
                .annotate(Count('eventobj__match'))
                .order_by('-eventobj__latest', '-eventobj__idx', '-date', '-id')[0:200],
            eventcount=True,
            add_links=add_links
        ),
        'nplayers':  Player.objects.filter(
            Q(id__in=matches.values('pla')) | Q(id__in=matches.values('plb'))
        ).count(),
    })

    offlines = list(matches.values('offline').distinct())
    if len(offlines) > 1:
        base['offline'] = _('Both')
    elif len(offlines) == 1:
        base['offline'] = _('Offline') if offlines[0]['offline'] else _('Online')

    base['pvt_wins'], base['pvt_loss'] = count_matchup_games(matches, 'P', 'T')
    base['pvz_wins'], base['pvz_loss'] = count_matchup_games(matches, 'P', 'Z')
    base['tvz_wins'], base['tvz_loss'] = count_matchup_games(matches, 'T', 'Z')
    base['tot_mirror'] = base['pvp_games'] + base['tvt_games'] + base['zvz_games']
    # }}}

    return render_to_response('eventres.djhtml', base)
Example #20
0
def player(request, player_id):
    player = get_object_or_404(Player, id=player_id)
    base = base_ctx('Ranking', '%s:' % player.tag, request, context=player)
    base.update(csrf(request)) 
    
    # Make modifications
    if 'op' in request.POST and request.POST['op'] == 'Submit' and base['adm'] == True:
        tag = request.POST['tag']
        country = request.POST['country']
        name = request.POST['fullname']
        if name == '':
            name = None
        akas = request.POST['AKA']
        if akas != '':
            aka = [s for s in akas.split(',')]
        else:
            aka = None
        birthday = request.POST['birthday']
        if birthday == '':
            birthday = None
        sc2c = request.POST['SC2C']
        if sc2c == '':
            sc2c = None
        tlpdkr = request.POST['TLPDKR']
        if tlpdkr == '':
            tlpdkr = None
        tlpdin = request.POST['TLPDIN']
        if tlpdin == '':
            tlpdin = None
        sc2e = request.POST['SC2E']
        if sc2e == '':
            sc2e = None
        lp = request.POST['LP']
        if lp == '':
            lp = None

        if tag != '':
            player.set_tag(tag)        
        player.set_country(country)
        player.set_name(name)
        player.set_birthday(birthday)
        player.set_aliases(aka)
        player.update_external_links(sc2c, tlpdkr, tlpdin, sc2e, lp)

    countries = []
    for k, v in data.ccn_to_cn.iteritems():
        countries.append([k, v, data.ccn_to_cca2[k]])
    countries.sort(key=lambda a: a[1])
    base['countries'] = countries

    try:
        base['team'] = Team.objects.filter(active=True, teammembership__player=player, teammembership__current=True)[0]
    except:
        pass

    try:
        base['first'] = Match.objects.filter(Q(pla=player) | Q(plb=player)).order_by('date')[0]
        base['last'] = Match.objects.filter(Q(pla=player) | Q(plb=player)).order_by('-date')[0]
    except:
        pass

    base['totalmatches'] = Match.objects.filter(Q(pla=player) | Q(plb=player)).count()
    base['offlinematches'] = Match.objects.filter(Q(pla=player) | Q(plb=player), offline=True).count()
    base['aliases'] = Alias.objects.filter(player=player)
    
    earnings = Earnings.objects.filter(player=player)
    base['earnings'] = earnings.aggregate(Sum('earnings'))['earnings__sum']

    # Winrates
    matches_a = Match.objects.filter(pla=player)
    matches_b = Match.objects.filter(plb=player)

    def ntz(n):
        return n if n is not None else 0

    a = matches_a.aggregate(Sum('sca'), Sum('scb'))
    b = matches_b.aggregate(Sum('sca'), Sum('scb'))
    base['total'] = (ntz(a['sca__sum']) + ntz(b['scb__sum']), ntz(a['scb__sum']) + ntz(b['sca__sum']))

    a = matches_a.filter(rcb='P').aggregate(Sum('sca'), Sum('scb'))
    b = matches_b.filter(rca='P').aggregate(Sum('sca'), Sum('scb'))
    base['vp'] = (ntz(a['sca__sum']) + ntz(b['scb__sum']), ntz(a['scb__sum']) + ntz(b['sca__sum']))

    a = matches_a.filter(rcb='T').aggregate(Sum('sca'), Sum('scb'))
    b = matches_b.filter(rca='T').aggregate(Sum('sca'), Sum('scb'))
    base['vt'] = (ntz(a['sca__sum']) + ntz(b['scb__sum']), ntz(a['scb__sum']) + ntz(b['sca__sum']))

    a = matches_a.filter(rcb='Z').aggregate(Sum('sca'), Sum('scb'))
    b = matches_b.filter(rca='Z').aggregate(Sum('sca'), Sum('scb'))
    base['vz'] = (ntz(a['sca__sum']) + ntz(b['scb__sum']), ntz(a['scb__sum']) + ntz(b['sca__sum']))

    # Career highs
    try:
        base['highs'] = (Rating.objects.filter(player=player).order_by('-rating')[0],\
                 Rating.objects.filter(player=player).extra(select={'d':'rating+rating_vp'}).order_by('-d')[0],\
                 Rating.objects.filter(player=player).extra(select={'d':'rating+rating_vt'}).order_by('-d')[0],\
                 Rating.objects.filter(player=player).extra(select={'d':'rating+rating_vz'}).order_by('-d')[0])
    except:
        pass

    try:
        countryfull = transformations.cc_to_cn(player.country)
    except:
        countryfull = ''

    rating = Rating.objects.filter(player=player).order_by('period').select_related('period')
    base['charts'] = rating.count >= 2
    if base['charts']:
        try:
            last_adjust = Rating.objects.filter(player=player, decay=0).order_by('-period')[0]
            rating = rating.filter(period_id__lte=last_adjust.period_id)
        except:
            pass
        base['ratings'] = rating
        base['patches'] = PATCHES

    recentchange = Rating.objects.filter(player=player, decay=0).order_by('-period')
    if recentchange.exists():
        base['recentchange'] = recentchange[0]

    firstrating = Rating.objects.filter(player=player).order_by('period')
    if firstrating.exists():
        base['firstrating'] = firstrating[0]

    if not rating.exists():
        base.update({'player': player, 'countryfull': countryfull})
        return render_to_response('player.html', base)
    rating = rating.order_by('-period')[0]

    matches = Match.objects.filter(Q(pla=player) | Q(plb=player))\
            .select_related('pla__rating').select_related('plb__rating')\
            .select_related('period')\
            .extra(where=['abs(datediff(date,\'%s\')) < 90' % datetime.datetime.now()])\
            .order_by('-date', '-id')[0:10]

    if matches.exists():
        base['matches'] = display_matches(matches, fix_left=player, ratings=True)

    def meandate(tm):
        if tm.start != None and tm.end != None:
            return (tm.start.toordinal() + tm.end.toordinal())/2
        elif tm.start != None:
            return tm.start.toordinal()
        elif tm.end != None:
            return tm.end.toordinal()
        else:
            return 1000000

    teammems = list(TeamMembership.objects.filter(player=player).extra(select={'mid': '(start+end)/2'}))
    teammems = sorted(teammems, key=lambda t: t.id, reverse=True)
    teammems = sorted(teammems, key=meandate, reverse=True)
    teammems = sorted(teammems, key=lambda t: t.current, reverse=True)

    base.update({'player': player, 'countryfull': countryfull, 'rating': rating, 'teammems': teammems})
    return render_to_response('player.html', base)
Example #21
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)
Example #22
0
def add_matches(request):
    # This view is the default redirect for login requests
    if 'username' in request.POST and 'password' in request.POST:
        user = authenticate(username=request.POST['username'], password=request.POST['password'])
        if user != None and user.is_active:
            login(request, user)

    base = base_ctx('Submit', 'Matches', request)
    add_login_message(base, extra='Submitted results will be pending review before inclusion.')

    # If the user is logged in, the template needs a username and a list of event objects
    if base['adm']:
        base['events'] = Event.objects.filter(closed=False, rgt=F('lft')+1).order_by('lft')

    if 'matches' in request.POST:
        # Collect various information from the form
        try:
            event = request.POST['event'].strip()
        except:
            event = None

        date = request.POST['date']
        matches = request.POST['matches'].splitlines()
        offline = not (request.POST['type'] != 'offline')
        game = request.POST['game']
        if game not in ['WoL', 'HotS']:
            game = 'WoL'

        base['game'] = game
        base['type'] = 'offline' if offline else 'online'
        base['matches'] = '\n'.join(matches)
        base['date'] = date
        base['event'] = event

        # Get event object. If not admin, an exception will be thrown and eventobj = None.
        try:
            eventobj = Event.objects.get(id=int(request.POST['eobj']))
            if eventobj.id == 2:
                eventobj = None
        except:
            eventobj = None

        if eventobj is not None:
            base['eobj'] = eventobj.id

        # Get extra data needed if not admin.
        try:
            source = request.POST['source']
            contact = request.POST['contact']
            notes = request.POST['notes']
            base['source'] = source
            base['contact'] = contact
            base['notes'] = notes
        except:
            pass

        # Check various requirements for non-admins
        if not base['adm'] and len(matches) > 100:
            base['messages'].append(Message('Please do not submit more than 100 results at a time.',
                                         'Too many entries', Message.ERROR))
            base.update(csrf(request))
            return render_to_response('add.html', base)
        if not base['adm'] and source.strip() == '':
            base['messages'].append(Message('Please include a source.', 'Source missing', Message.ERROR))
            base.update(csrf(request))
            return render_to_response('add.html', base)

        # If not admin, make a PreMatchGroup.
        if not base['adm']:
            pmgroup = PreMatchGroup(date=date, event=event, source=source, contact=contact, notes=notes,\
                    game=game, offline=offline)
            pmgroup.save()

        # Lists of successes and failures
        success = []
        failure = []

        # Loop through match entries
        for s in matches:
            if s.strip() == '':
                continue

            try:
                # Parse and collect the components
                collect = parse_match(s.strip())
                pla = collect[0]
                plb = collect[1]
                sca = int(collect[2][0])
                scb = int(collect[2][1])

                # Check for !DUP and !MAKE switches if user is logged in
                dup_switch = False
                make_switch = False
                while collect[2][-1][0] == '!':
                    if collect[2][-1] == '!MAKE':
                        make_switch = True
                    elif collect[2][-1] == '!DUP':
                        dup_switch = True
                    collect[2] = collect[2][:-1]

                if not base['adm']:
                    make_switch = False

                # Check for race overrides
                def get_race(lst):
                    if lst[-1][:2].upper() == 'R:':
                        r = lst[-1][2:].upper() if lst[-1][2:].upper() in 'PTZR' else None
                        return r, lst[:-1]
                    else:
                        return None, lst
                rca, pla = get_race(pla)
                rcb, plb = get_race(plb)

                # Find players
                def get_player(lst, failure, base, make, adm):
                    #try:
                    pls = find_player(lst, make=make)
                    #except Exception as e:
                        #failure.append(s)
                        #base['messages'].append(Message('Could not parse: ' + e.message,
                                                        #s, Message.ERROR))
                        #return None
                    if not pls.exists() and adm:
                        # Player not found, and user logged in. Add failure message and return None.
                        failure.append(s)
                        base['messages'].append(Message(
                            'Could not find player \'%s\', add !MAKE switch to create.' % ' '.join(lst),
                            s, Message.ERROR))
                        return None
                    if pls.count() > 1 and adm:
                        # Too many players found, and used logged in. Add failure message and return None.
                        failure.append(s)
                        base['messages'].append(NotUniquePlayerMessage(' '.join(lst), pls))
                        return None
                    if not pls.exists() or pls.count() > 1:
                        # Too many or too few players found, and user not logged in. Just return None.
                        return None
                    return pls[0]

                # If the user is logged in and some players were not found, abort.
                pla_obj = get_player(pla, failure, base, make_switch, base['adm'])
                if pla_obj == None and base['adm']:
                    continue

                plb_obj = get_player(plb, failure, base, make_switch, base['adm'])
                if plb_obj == None and base['adm']:
                    continue

                # If both players are known, check for duplicates
                if pla_obj and plb_obj:
                    n = find_duplicates(pla_obj, plb_obj, sca, scb, date)
                    if n > 0 and not dup_switch:
                        failure.append(s)
                        base['messages'].append(Message(
                            '%i possible duplicate(s) found, add !DUP switch to force.' % n,
                            s, Message.ERROR))
                        continue

                # If the user is not logged in, we now have enough information to create a prematch.
                if not base['adm']:
                    pm = PreMatch(group=pmgroup, sca=sca, scb=scb, pla=pla_obj, plb=plb_obj,\
                            pla_string=' '.join(pla), plb_string=' '.join(plb), date=pmgroup.date)
                    if rca:
                        pm.rca = rca
                    elif pla_obj:
                        pm.rca = pla_obj.race
                    else:
                        pm.rca = None

                    if rcb:
                        pm.rcb = rcb
                    elif plb_obj:
                        pm.rcb = plb_obj.race
                    else:
                        pm.rcb = None

                    pm.save()
                    success.append(pm)
                    continue

                # Abort if race information is incorrect
                if pla_obj.race == 'S' and rca == None:
                    failure.append(s)
                    base['messages'].append(Message(
                        '%s is Random or Switcher, need race information.' % pla_obj.tag,
                        s, Message.ERROR))
                    continue

                if plb_obj.race == 'S' and rcb == None:
                    failure.append(s)
                    base['messages'].append(Message(
                        '%s is Random or Switcher, need race information.' % plb_obj.tag,
                        s, Message.ERROR))
                    continue

                # Add match
                m = Match()
                m.pla = pla_obj
                m.plb = plb_obj
                m.sca = sca
                m.scb = scb
                m.rca = pla_obj.race if rca == None else rca
                m.rcb = plb_obj.race if rcb == None else rcb
                m.date = date
                m.submitter = request.user
                m.set_period()
                m.eventobj = eventobj
                m.offline = offline
                m.game = game
                m.save()

                success.append(m)

            except Exception as e:
                failure.append(s)
                base['messages'].append(Message('Could not parse: ' + e.message, s, Message.ERROR))
                continue

        success = display_matches(success, messages=False)
        if len(success) > 0:
            base['messages'].append(Message('Added %i match(es).' % len(success), type=Message.SUCCESS))

        base.update({'matches': '\n'.join(failure), 'success': success})

    elif 'eventid' in request.GET:
        try:
            event = Event.objects.get(id=int(request.GET['eventid']))
            if event.closed:
                event.closed = False
                event.save()
                base['messages'].append(Message('Reopened \'%s\'.' % event.fullname, type=Message.SUCCESS))
            base['eobj'] = event.id
        except:
            base['messages'].append(Message('Couldn\'t find event ID %s.' % request.GET['eventid'], 
                type=Message.ERROR))

    try:
        if base['adm'] and request.POST['action'] == 'Add and close event' and eventobj is not None:
            if len(failure) == 0:
                eventobj.close()
                base['messages'].append(Message('Event \'%s\' closed.' % eventobj.fullname, 
                                                type=Message.SUCCESS))
            else:
                base['messages'].append(Message('Event \'%s\' was NOT closed.' % eventobj.fullname,
                                                type=Message.WARNING))
    except:
        pass

    base.update(csrf(request))
    return render_to_response('add.html', base)
Example #23
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)
Example #24
0
def adjustment(request, player_id, period_id):
    # {{{ Get objects
    period = get_object_or_404(Period, id=period_id, computed=True)
    player = get_object_or_404(Player, id=player_id)
    rating = get_object_or_404(Rating, player=player, period=period)
    base = base_ctx("Ranking", "Adjustments", request, context=player)

    base.update(
        {
            "period": period,
            "player": player,
            "rating": rating,
            "prevlink": etn(lambda: player.rating_set.filter(period__lt=period, decay=0).latest("period")),
            "nextlink": etn(lambda: player.rating_set.filter(period__gt=period, decay=0).earliest("period")),
        }
    )
    # }}}

    # {{{ Matches
    matches = player.get_matchset(related=["rta", "rtb", "pla", "plb", "eventobj"]).filter(period=period)

    # If there are no matches, we don't need to continue
    if not matches.exists():
        return render_to_response("ratingdetails.djhtml", base)

    base.update(
        {
            "matches": display_matches(matches, fix_left=player, ratings=True),
            "has_treated": False,
            "has_nontreated": False,
        }
    )
    # }}}

    # {{{ Perform calculations
    tot_rating = {"M": 0.0, "P": 0.0, "T": 0.0, "Z": 0.0}
    ngames = {"M": 0.0, "P": 0.0, "T": 0.0, "Z": 0.0}
    expwins = {"M": 0.0, "P": 0.0, "T": 0.0, "Z": 0.0}
    nwins = {"M": 0.0, "P": 0.0, "T": 0.0, "Z": 0.0}

    for m in base["matches"]:
        if not m["match"].treated:
            base["has_nontreated"] = True
            continue
        base["has_treated"] = True

        total_score = m["pla"]["score"] + m["plb"]["score"]

        scale = sqrt(1 + m["pla"]["dev"] ** 2 + m["plb"]["dev"] ** 2)
        expected = total_score * cdf(m["pla"]["rating"] - m["plb"]["rating"], scale=scale)

        ngames["M"] += total_score
        tot_rating["M"] += m["plb"]["rating"] * total_score
        expwins["M"] += expected
        nwins["M"] += m["pla"]["score"]

        vs_races = [m["plb"]["race"]] if m["plb"]["race"] in "PTZ" else "PTZ"
        weight = 1 / len(vs_races)
        for r in vs_races:
            ngames[r] += weight * total_score
            tot_rating[r] += weight * m["plb"]["rating"] * total_score
            expwins[r] += weight * expected
            nwins[r] += weight * m["pla"]["score"]

    for r in "MPTZ":
        if ngames[r] > 0:
            tot_rating[r] /= ngames[r]

    base.update({"ngames": ngames, "tot_rating": tot_rating, "expwins": expwins, "nwins": nwins})
    # }}}

    return render_to_response("ratingdetails.djhtml", base)
Example #25
0
def adjustment(request, player_id, period_id):
    # {{{ Get objects
    period = get_object_or_404(Period, id=period_id, computed=True)
    player = get_object_or_404(Player, id=player_id)
    rating = get_object_or_404(Rating, player=player, period=period)
    base = base_ctx('Ranking', 'Adjustments', request, context=player)

    base.update({
        'period':    period,
        'player':    player,
        'rating':    rating,
        'prevlink':  etn(lambda: player.rating_set.filter(period__lt=period, decay=0).latest('period')),
        'nextlink':  etn(lambda: player.rating_set.filter(period__gt=period, decay=0).earliest('period')),
    })
    # }}}

    # {{{ Matches
    matches = player.get_matchset(related=['rta','rtb','pla','plb','eventobj']).filter(period=period)

    base.update({"title": player.tag})

    # If there are no matches, we don't need to continue
    if not matches.exists():
        return render_to_response('ratingdetails.html', base)

    base.update({
        'matches': display_matches(matches, fix_left=player, ratings=True),
        'has_treated': False,
        'has_nontreated': False,
    })
    # }}}

    # {{{ Perform calculations
    tot_rating = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0}
    ngames     = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0}
    expwins    = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0}
    nwins      = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0}

    for m in base['matches']:
        if not m['match'].treated:
            base['has_nontreated'] = True
            continue
        base['has_treated'] = True

        total_score = m['pla']['score'] + m['plb']['score']

        scale = sqrt(1 + m['pla']['dev']**2 + m['plb']['dev']**2)
        expected = total_score * cdf(m['pla']['rating'] - m['plb']['rating'], scale=scale)

        ngames['M']     += total_score
        tot_rating['M'] += m['plb']['rating'] * total_score
        expwins['M']    += expected
        nwins['M']      += m['pla']['score']

        vs_races = [m['plb']['race']] if m['plb']['race'] in 'PTZ' else 'PTZ'
        weight = 1/len(vs_races)
        for r in vs_races:
            ngames[r]     += weight * total_score
            tot_rating[r] += weight * m['plb']['rating'] * total_score
            expwins[r]    += weight * expected
            nwins[r]      += weight * m['pla']['score']

    for r in 'MPTZ':
        if ngames[r] > 0:
            tot_rating[r] /= ngames[r]

    base.update({
        'ngames':      ngames,
        'tot_rating':  tot_rating,
        'expwins':     expwins,
        'nwins':       nwins,
    })
    # }}}

    return render_to_response('ratingdetails.html', base)
Example #26
0
    def search(self, adm):
        # {{{ Check validity (lol)
        if not self.is_valid():
            msgs = []
            msgs.append(
                Message(_('Entered data was invalid, no changes made.'),
                        type=Message.ERROR))
            for field, errors in self.errors.items():
                for error in errors:
                    msgs.append(
                        Message(error=error, field=self.fields[field].label))
            return {'messages': msgs}
        # }}}

        matches = (Match.objects.all().prefetch_related(
            'message_set').prefetch_related('pla', 'plb', 'period',
                                            'eventobj').annotate(
                                                Count('eventobj__match')))

        # {{{ All the easy filtering
        if self.cleaned_data['after'] is not None:
            matches = matches.filter(date__gte=self.cleaned_data['after'])

        if self.cleaned_data['before'] is not None:
            matches = matches.filter(date__lte=self.cleaned_data['before'])

        if self.cleaned_data['unassigned'] and adm:
            matches = matches.filter(eventobj__isnull=True)

        if self.cleaned_data['bestof'] == '3':
            matches = matches.filter(Q(sca__gte=2) | Q(scb__gte=2))
        elif self.cleaned_data['bestof'] == '5':
            matches = matches.filter(Q(sca__gte=3) | Q(scb__gte=3))

        if self.cleaned_data['offline'] != 'both':
            matches = matches.filter(
                offline=(self.cleaned_data['offline'] == 'offline'))

        if self.cleaned_data['game'] != 'all':
            matches = matches.filter(game=self.cleaned_data['game'])
        # }}}

        # {{{ Filter by event
        if self.cleaned_data['event'] != None:
            lex = shlex.shlex(self.cleaned_data['event'], posix=True)
            lex.wordchars += "'"
            lex.quotes = '"'

            terms = [s.strip() for s in list(lex) if s.strip() != '']

            no_eventobj_q = Q(eventobj__isnull=True)

            for term in terms:
                no_eventobj_q &= Q(event__icontains=term)

            matches = matches.filter(no_eventobj_q
                                     | Q(eventobj__isnull=False,
                                         eventobj__fullname__iregex=(
                                             r"\s".join(r".*{}.*".format(term)
                                                        for term in terms))))

        # }}}

        ret = {'messages': []}

        # {{{ Filter by players
        lines = self.cleaned_data['players'].splitlines()
        lineno, ok, players = -1, True, []
        for line in lines:
            lineno += 1
            if line.strip() == '':
                continue

            pls = find_player(query=line, make=False)
            if not pls.exists():
                ret['messages'].append(
                    Message(
                        # Translators: Matches here as in search matches.
                        _("No matches found: '%s'.") % line.strip(),
                        type=Message.ERROR))
                ok = False
            else:
                if pls.count() > 1:
                    ret['messages'].append(
                        NotUniquePlayerMessage(line.strip(),
                                               pls,
                                               update=self['players'].auto_id,
                                               updateline=lineno,
                                               type=Message.WARNING))

                players.append(list(pls))

        if not ok:
            return ret

        pls = []
        for p in players:
            pls += p

        if len(pls) > 1:
            matches = matches.filter(pla__in=pls, plb__in=pls)
        elif len(pls) == 1:
            matches = matches.filter(Q(pla__in=pls) | Q(plb__in=pls))
        # }}}

        # {{{ Collect data
        ret['count'] = matches.count()
        if ret['count'] > 1000:
            ret['messages'].append(
                Message(_('Too many results (%i). Please add restrictions.') %
                        ret['count'],
                        type=Message.ERROR))
            return ret

        matches = matches.order_by('-eventobj__latest', '-eventobj__idx',
                                   '-date', 'event', 'id')
        if 1 <= len(pls) <= 2:
            ret['matches'] = display_matches(matches,
                                             date=True,
                                             fix_left=pls[0],
                                             eventcount=True)
            ret['sc_my'], ret['sc_op'] = (
                sum([m['pla']['score'] for m in ret['matches']]),
                sum([m['plb']['score'] for m in ret['matches']]),
            )
            ret['msc_my'], ret['msc_op'] = (
                sum([
                    1 if m['pla']['score'] > m['plb']['score'] else 0
                    for m in ret['matches']
                ]),
                sum([
                    1 if m['plb']['score'] > m['pla']['score'] else 0
                    for m in ret['matches']
                ]),
            )
            ret['left'] = pls[0]
            if len(pls) == 2:
                ret['right'] = pls[1]
        else:
            ret['matches'] = display_matches(matches,
                                             date=True,
                                             eventcount=True)

        return ret
Example #27
0
def results_search(request):
    base = base_ctx('Results', 'Search', request)
    base.update(csrf(request))

    if 'op' in request.POST and request.POST['op'] == 'Modify' and base['adm'] == True:
        num = 0
        if request.POST['event'] != 'nochange' and int(request.POST['event']) != 2:
            event = Event.objects.get(id=int(request.POST['event']))
        else:
            event = None

        for key in request.POST:
            if request.POST[key] != 'y':
                continue
            if key[0:6] == 'match-':
                match = Match.objects.get(id=int(key.split('-')[-1]))
                if request.POST['event'] != 'nochange':
                    match.eventobj = event
                    base['markevent'] = event
                if request.POST['date'].strip() != '':
                    match.date = request.POST['date']
                    base['markdate'] = request.POST['date']
                if request.POST['type'] != 'nochange':
                    match.offline = (request.POST['type'] == 'offline')
                    base['markoffline'] = request.POST['type']
                if request.POST['game'] != 'nochange':
                    match.game = request.POST['game']
                    base['markgame'] = request.POST['game']
                match.save()
                num += 1

        base['message'] = 'Modified %i matches.' % num

    if 'op' in request.GET and request.GET['op'] == 'search':
        matches = Match.objects.all()

        try:
            ints = [int(x) for x in request.GET['after'].split('-')]
            td = datetime.date(ints[0], ints[1], ints[2])
            matches = matches.filter(date__gte=td)
            base['after'] = request.GET['after']
        except:
            pass

        try:
            ints = [int(x) for x in request.GET['before'].split('-')]
            td = datetime.date(ints[0], ints[1], ints[2])
            matches = matches.filter(date__lte=td)
            base['before'] = request.GET['before']
        except:
            pass

        if 'unassigned' in request.GET and request.GET['unassigned'] == 'yes' and base['adm']:
            base['unassigned'] = True
            base['unassigned_get'] = 'yes'
            matches = matches.filter(eventobj__isnull=True)

        if 'eventtext' in request.GET and request.GET['eventtext'].strip() != '':
            base['eventtext'] = request.GET['eventtext'].strip()
            queries = [f.strip() for f in request.GET['eventtext'].strip().split(' ') if f.strip() != '']
            for query in queries:
                q = Q(eventobj__isnull=True, event__icontains=query) |\
                    Q(eventobj__isnull=False, eventobj__fullname__icontains=query)
                matches = matches.filter(q)

        if 'bo' in request.GET:
            if request.GET['bo'] == '3':
                matches = matches.filter(Q(sca__gte=2) | Q(scb__gte=2))
            elif request.GET['bo'] == '5':
                matches = matches.filter(Q(sca__gte=3) | Q(scb__gte=3))
            base['bo'] = request.GET['bo']
        else:
            base['bo'] = 'all'
        
        if 'offline' in request.GET:
            if request.GET['offline'] == 'online':
                matches = matches.filter(offline=0)
            elif request.GET['offline'] == 'offline':
                matches = matches.filter(offline=1)
            base['offline'] = request.GET['offline']
        else:
            base['offline'] = 'both'

        if 'game' in request.GET:
            if request.GET['game'] != 'all':
                matches = matches.filter(game=request.GET['game'])
            base['game'] = request.GET['game']
        else:
            base['game'] = 'all'

        players, failures = [], []
        base['errs'] = []
        base['pls'] = request.GET['players']
        for line in request.GET['players'].splitlines():
            if line.strip() == '':
                continue
            pls = find_player(line.strip().split(' '), make=False)
            if not pls.exists():
                base['errs'].append('No players matching the query \'%s\'.' % line.strip())
            else:
                players.append(pls)

        if len(base['errs']) > 0:
            return render_to_response('results_search.html', base)

        pls = []
        for p in players:
            pls += p

        if len(pls) > 1:
            qa, qb = Q(), Q()
            for p in pls:
                qa |= Q(pla=p)
                qb |= Q(plb=p)
            matches = matches.filter(qa & qb)
        elif len(pls) == 1:
            q = Q(pla=pls[0]) | Q(plb=pls[0])
            matches = matches.filter(q)

        base['count'] = matches.count()

        if base['count'] > 1000:
            base['errs'].append('Too many results (%i). Please add restrictions.' % base['count'])
            return render_to_response('results_search.html', base)

        matches = matches.order_by('-date', 'eventobj__lft', 'event', 'id')

        if 1 <= len(pls) <= 2:
            base['matches'] = display_matches(matches, date=True, fix_left=pls[0])
            base['sc_my'] = sum([m.pla_score for m in base['matches']])
            base['sc_op'] = sum([m.plb_score for m in base['matches']])
            base['msc_my'] = sum([(1 if m.pla_score > m.plb_score else 0) for m in base['matches']])
            base['msc_op'] = sum([(1 if m.pla_score < m.plb_score else 0) for m in base['matches']])
            base['left'] = pls[0]
            if len(pls) == 2:
                base['right'] = pls[1]
        else:
            base['matches'] = display_matches(matches, date=True)

        if base['adm']:
            base['events'] = Event.objects.filter(closed=False, rgt=F('lft')+1).order_by('lft')

    return render_to_response('results_search.html', base)
Example #28
0
    def search(self, adm):
        # {{{ Check validity (lol)
        if not self.is_valid():
            msgs = []
            msgs.append(Message(_('Entered data was invalid, no changes made.'), type=Message.ERROR))
            for field, errors in self.errors.items():
                for error in errors:
                    msgs.append(Message(error=error, field=self.fields[field].label))
            return {'messages': msgs}
        # }}}

        matches = (
            Match.objects.all().prefetch_related('message_set')
                .prefetch_related('pla', 'plb', 'period', 'eventobj')
                .annotate(Count('eventobj__match'))
        )

        # {{{ All the easy filtering
        if self.cleaned_data['after'] is not None:
            matches = matches.filter(date__gte=self.cleaned_data['after'])

        if self.cleaned_data['before'] is not None:
            matches = matches.filter(date__lte=self.cleaned_data['before'])

        if self.cleaned_data['unassigned'] and adm:
            matches = matches.filter(eventobj__isnull=True)

        if self.cleaned_data['bestof'] == '3':
            matches = matches.filter(Q(sca__gte=2) | Q(scb__gte=2))
        elif self.cleaned_data['bestof'] == '5':
            matches = matches.filter(Q(sca__gte=3) | Q(scb__gte=3))

        if self.cleaned_data['offline'] != 'both':
            matches = matches.filter(offline=(self.cleaned_data['offline']=='offline'))

        if self.cleaned_data['game'] != 'all':
            matches = matches.filter(game=self.cleaned_data['game'])
        # }}}

        # {{{ Filter by event
        if self.cleaned_data['event'] != None:
            lex = shlex.shlex(self.cleaned_data['event'], posix=True)
            lex.wordchars += "'"
            lex.quotes = '"'

            terms = [s.strip() for s in list(lex) if s.strip() != '']

            no_eventobj_q = Q(eventobj__isnull=True)

            for term in terms:
                no_eventobj_q &= Q(event__icontains=term)

            matches = matches.filter(
                no_eventobj_q |
                Q(
                    eventobj__isnull=False,
                    eventobj__fullname__iregex=(
                        r"\s".join(r".*{}.*".format(term) for term in terms)
                    )
                )
            )

        # }}}

        ret = {'messages': []}

        # {{{ Filter by players
        lines = self.cleaned_data['players'].splitlines()
        lineno, ok, players = -1, True, []
        for line in lines:
            lineno += 1
            if line.strip() == '':
                continue

            pls = find_player(query=line, make=False)
            if not pls.exists():
                ret['messages'].append(Message(
                    # Translators: Matches here as in search matches.
                    _("No matches found: '%s'.") % line.strip(), type=Message.ERROR
                ))
                ok = False
            else:
                if pls.count() > 1:
                    ret['messages'].append(NotUniquePlayerMessage(
                        line.strip(), pls, update=self['players'].auto_id,
                        updateline=lineno, type=Message.WARNING
                    ))

                players.append(list(pls))

        if not ok:
            return ret

        pls = []
        for p in players:
            pls += p

        if len(pls) > 1:
            matches = matches.filter(pla__in=pls, plb__in=pls)
        elif len(pls) == 1:
            matches = matches.filter(Q(pla__in=pls) | Q(plb__in=pls))
        # }}}

        # {{{ Collect data
        ret['count'] = matches.count()
        if ret['count'] > 1000:
            ret['messages'].append(Message(
                _('Too many results (%i). Please add restrictions.') % ret['count'],
                type=Message.ERROR
            ))
            return ret

        matches = matches.order_by('-eventobj__latest', '-eventobj__idx', '-date', 'event', 'id')
        if 1 <= len(pls) <= 2:
            ret['matches'] = display_matches(matches, date=True, fix_left=pls[0], eventcount=True)
            ret['sc_my'], ret['sc_op'] = (
                sum([m['pla']['score'] for m in ret['matches']]),
                sum([m['plb']['score'] for m in ret['matches']]),
            )
            ret['msc_my'], ret['msc_op'] = (
                sum([1 if m['pla']['score'] > m['plb']['score'] else 0 for m in ret['matches']]),
                sum([1 if m['plb']['score'] > m['pla']['score'] else 0 for m in ret['matches']]),
            )
            ret['left'] = pls[0]
            if len(pls) == 2:
                ret['right'] = pls[1]
        else:
            ret['matches'] = display_matches(matches, date=True, eventcount=True)

        return ret
Example #29
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)
Example #30
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)
Example #31
0
def adjustment(request, player_id, period_id):
    # {{{ Get objects
    period = get_object_or_404(Period, id=period_id, computed=True)
    player = get_object_or_404(Player, id=player_id)
    rating = get_object_or_404(Rating, player=player, period=period)
    base = base_ctx('Ranking', 'Adjustments', request, context=player)

    base.update({
        'period':
        period,
        'player':
        player,
        'rating':
        rating,
        'prevlink':
        etn(lambda: player.rating_set.filter(period__lt=period, decay=0).
            latest('period')),
        'nextlink':
        etn(lambda: player.rating_set.filter(period__gt=period, decay=0).
            earliest('period')),
    })
    # }}}

    # {{{ Matches
    matches = player.get_matchset(
        related=['rta', 'rtb', 'pla', 'plb', 'eventobj']).filter(period=period)

    # If there are no matches, we don't need to continue
    if not matches.exists():
        return render_to_response('ratingdetails.djhtml', base)

    base.update({
        'matches':
        display_matches(matches, fix_left=player, ratings=True),
        'has_treated':
        False,
        'has_nontreated':
        False,
    })
    # }}}

    # {{{ Perform calculations
    tot_rating = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0}
    ngames = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0}
    expwins = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0}
    nwins = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0}

    for m in base['matches']:
        if not m['match'].treated:
            base['has_nontreated'] = True
            continue
        base['has_treated'] = True

        total_score = m['pla']['score'] + m['plb']['score']

        scale = sqrt(1 + m['pla']['dev']**2 + m['plb']['dev']**2)
        expected = total_score * cdf(m['pla']['rating'] - m['plb']['rating'],
                                     scale=scale)

        ngames['M'] += total_score
        tot_rating['M'] += m['plb']['rating'] * total_score
        expwins['M'] += expected
        nwins['M'] += m['pla']['score']

        vs_races = [m['plb']['race']] if m['plb']['race'] in 'PTZ' else 'PTZ'
        weight = 1 / len(vs_races)
        for r in vs_races:
            ngames[r] += weight * total_score
            tot_rating[r] += weight * m['plb']['rating'] * total_score
            expwins[r] += weight * expected
            nwins[r] += weight * m['pla']['score']

    for r in 'MPTZ':
        if ngames[r] > 0:
            tot_rating[r] /= ngames[r]

    base.update({
        'ngames': ngames,
        'tot_rating': tot_rating,
        'expwins': expwins,
        'nwins': nwins,
    })
    # }}}

    return render_to_response('ratingdetails.djhtml', base)
Example #32
0
def events(request, event_id=None):
    # Redirect to proper URL if there's a ?goto=... present
    if 'goto' in request.GET:
        return redirect('/results/events/' + request.GET['goto'])

    base = base_ctx('Results', 'By Event', request)
    base.update(csrf(request))
    
    try:
        event = Event.objects.get(id=int(event_id))
    except:
        # This is executed for invalid event IDs or the root table
        ind_bigs = collect(Event.objects.filter(parent__isnull=True, big=True, category='individual').\
                select_related('event').order_by('lft'), 2)
        ind_smalls = Event.objects.filter(parent__isnull=True, big=False, category='individual').\
                select_related('event').order_by('name')

        team_bigs = collect(Event.objects.filter(parent__isnull=True, big=True, category='team').\
                select_related('event').order_by('lft'), 2)
        team_smalls = Event.objects.filter(parent__isnull=True, big=False, category='team').\
                select_related('event').order_by('name')

        freq_bigs = collect(Event.objects.filter(parent__isnull=True, big=True, category='frequent').\
                select_related('event').order_by('lft'), 2)
        freq_smalls = Event.objects.filter(parent__isnull=True, big=False, category='frequent').\
                select_related('event').order_by('name')

        base.update({'ind_bigs': ind_bigs,   'ind_smalls': ind_smalls,\
                     'team_bigs': team_bigs, 'team_smalls': team_smalls,\
                     'freq_bigs': freq_bigs, 'freq_smalls': freq_smalls})
        return render_to_response('events.html', base)

    # Number of matches (set event to big if too large)
    matches = Match.objects.filter(eventobj__lft__gte=event.lft, eventobj__rgt__lte=event.rgt)
    if matches.count() > 200 and not event.big:
        event.big = True
        event.save()
        
    # Get parent, ancestors and siblings
    if event.parent != None:
        siblings = event.parent.event_set.exclude(id=event.id).order_by('lft')
    else:
        siblings = None

    # Make modifications if neccessary
    if base['adm'] == True:
        if 'op' in request.POST and request.POST['op'] == 'Modify':
            if request.POST['type'] != 'nochange':
                event.change_type(request.POST['type'])
                if 'siblings' in request.POST.keys() and siblings is not None:
                    for sibling in siblings:
                        sibling.change_type(request.POST['type'])
                        
            if request.POST['name'] != '' and request.POST['name'] != event.name:
                event.name = request.POST['name']
                event.update_name()
                event.save()
                for e in event.get_children():
                    e.update_name()

            if request.POST['date'].strip() != 'No change':
                matches.update(date=request.POST['date'])
                base['message'] = 'Modified all matches.'

            if request.POST['offline'] != 'nochange':
                matches.update(offline=(request.POST['offline'] == 'offline'))
                base['message'] = 'Modified all matches.'

            if request.POST['game'] != 'nochange':
                matches.update(game=request.POST['game'])
                base['message'] = 'Modified all matches.'

            if request.POST['homepage'] != event.get_homepage():
                event.set_homepage(request.POST['homepage'])

            if request.POST['tlpd_in_id'] != event.get_tlpd_in_id():
                event.set_tlpd_in_id(request.POST['tlpd_in_id'])

            if request.POST['tlpd_kr_id'] != event.get_tlpd_kr_id():
                event.set_tlpd_kr_id(request.POST['tlpd_kr_id'])

            if request.POST['tl_thread'] != event.get_tl_thread():
                event.set_tl_thread(request.POST['tl_thread'])

            if request.POST['lp_name'] != event.get_lp_name():
                event.set_lp_name(request.POST['lp_name'])
                        
        elif 'add' in request.POST and request.POST['add'] == 'Add':
            parent = event
            for q in request.POST['subevent'].strip().split(','):
                type = request.POST['type']
                parent.add_child(q.strip(), type, 'noprint' in request.POST, 'closed' in request.POST)
                
        elif 'move' in request.POST and request.POST['move'] == 'Move':
            eventid = request.POST['moveevent']
            newparent = Event.objects.get(id=eventid)

            if event.lft > newparent.rgt:
                diff = newparent.rgt - event.lft
            else:
                diff = newparent.rgt - event.rgt - 1
            event_shift(event, diff)

            event.set_parent(newparent)
            event.update_name()

            for e in event.get_children():
                e.update_name()

        elif 'earnings' in request.POST and request.POST['earnings'] == 'Add':
            amount = int(request.POST['amount'])
            currency = request.POST['currency']
            
            players = []
            amounts = []
            placements = []
            
            for i in range(0, amount):
                player = request.POST['player-' + str(i)]
                player = Player.objects.get(id=player)
                
                amount = request.POST['amount-' + str(i)]
                amount = amount.replace(',', '').replace('.', '').replace(' ', '')
                
                players.append(player)
                amounts.append(amount)
                placements.append(i)
            
            success = Earnings.set_earnings(event, players, amounts, currency, placements)
            if success:
                base['message'] = 'Updated tournament prizepool.'
            else:
                base['message'] = 'There was an error updating the tournament prizepool.'

    base['event'] = event
    base['path'] = Event.objects.filter(lft__lte=event.lft, rgt__gte=event.rgt).order_by('lft')
    base['children'] = Event.objects.filter(parent=event).order_by('lft')
    if event.parent != None:
        base['siblings'] = event.parent.event_set.exclude(id=event.id).order_by('lft')

    # Used for moving events
    base['surroundingevents'] = event.get_parent(1).get_children().exclude(lft__gte=event.lft, rgt__lte=event.rgt)

    # Determine WoL/HotS and Online/Offline and event type
    if matches.values("game").distinct().count() == 1:
        base['game'] = matches[0].game
        if base['game'] == 'WoL':
            base['game'] = 'Wings of Liberty'
        elif base['game'] == 'HotS':
            base['game'] = 'Heart of the Swarm'
        #elif base['game'] = 'LotV':
            #base['game'] = 'Legacy of the Void'
    
    # Get list of players and earnings for prizepools
    base['players'] = Player.objects.filter(Q(id__in=matches.values('pla')) | Q(id__in=matches.values('plb')))
    
    earnings = Earnings.objects.filter(event=event).order_by('placement')
    base['earnings'] = earnings
    
    base['prizepool'] = earnings.aggregate(Sum('earnings'))['earnings__sum']
    base['prizepoolorig'] = earnings.aggregate(Sum('origearnings'))['origearnings__sum']
    
    try:
        base['prizepoolcur'] = earnings.values('currency')[0]['currency']
    except:
        base['prizepoolcur'] = "USD"
    
    # Get list of currencies
    currencies = []
    sortedcurrencies = sorted(ccy.currencydb(), key=operator.itemgetter(0))

    for currency in sortedcurrencies:
        dict = {}
        dict["name"] = ccy.currency(currency).name
        dict["code"] = ccy.currency(currency).code
        currencies.append(dict)
    base['currencies'] = currencies
    
    base['offline'] = None
    if matches.values("offline").distinct().count() == 1:
        base['offline'] = matches[0].offline

    # Statistics
    base['nmatches'] = matches.count()
    if base['nmatches'] > 0:
        qset = matches.aggregate(Sum('sca'), Sum('scb'))
        base['ngames'] = qset['sca__sum'] + qset['scb__sum']
    else:
        base['ngames'] = 0

    # Matchup wins and losses
    nti = lambda x: 0 if x is None else x
    qseta = matches.filter(rca='P', rcb='T').aggregate(Sum('sca'), Sum('scb'))
    qsetb = matches.filter(rcb='P', rca='T').aggregate(Sum('sca'), Sum('scb'))
    base['pvt_wins'] = nti(qseta['sca__sum']) + nti(qsetb['scb__sum'])
    base['pvt_loss'] = nti(qsetb['sca__sum']) + nti(qseta['scb__sum'])

    qseta = matches.filter(rca='P', rcb='Z').aggregate(Sum('sca'), Sum('scb'))
    qsetb = matches.filter(rcb='P', rca='Z').aggregate(Sum('sca'), Sum('scb'))
    base['pvz_wins'] = nti(qseta['sca__sum']) + nti(qsetb['scb__sum'])
    base['pvz_loss'] = nti(qsetb['sca__sum']) + nti(qseta['scb__sum'])

    qseta = matches.filter(rca='T', rcb='Z').aggregate(Sum('sca'), Sum('scb'))
    qsetb = matches.filter(rcb='T', rca='Z').aggregate(Sum('sca'), Sum('scb'))
    base['tvz_wins'] = nti(qseta['sca__sum']) + nti(qsetb['scb__sum'])
    base['tvz_loss'] = nti(qsetb['sca__sum']) + nti(qseta['scb__sum'])

    # Dates
    base['earliest'] = event.get_earliest()
    base['latest'] = event.get_latest()

    matches = matches.order_by('-date', '-eventobj__lft', '-id')[0:200]
    base['matches'] = display_matches(matches)

    return render_to_response('eventres.html', base)
Example #33
0
def events(request, event_id=None):
    # {{{ Get base context, redirect if necessary
    if 'goto' in request.GET:
        return redirect('/results/events/' + request.GET['goto'])

    base = base_ctx('Results', 'By Event', request)
    # }}}

    # {{{ Display the main table if event ID is not given
    if event_id is None:
        root_events = (Event.objects.annotate(
            num_uplinks=Count("uplink")).filter(
                num_uplinks=1).order_by('name').only('id', 'name', 'big',
                                                     'category', 'fullname'))
        base.update({
            'bigs':
            (list(root_events.filter(big=True, category=CAT_INDIVIDUAL)) +
             list(root_events.filter(big=True, category=CAT_TEAM)) +
             list(root_events.filter(big=True, category=CAT_FREQUENT))),
            'smalls':
            (list(
                root_events.filter(big=False,
                                   category=CAT_INDIVIDUAL).order_by('name')) +
             list(
                 root_events.filter(big=False,
                                    category=CAT_TEAM).order_by('name')) +
             list(
                 root_events.filter(big=False,
                                    category=CAT_FREQUENT).order_by('name')))
        })

        base['messages'].append(
            Message(_(
                'The events are organized in a hierarchical fashion. Thus, all GSL tournaments '
                'are filed under GSL, all Code S under their respective seasons, all groups under '
                'their respective Code S event, and so on.'),
                    type=Message.INFO))

        return render_to_response('events.djhtml', base)
    # }}}

    # {{{ Get object, generate messages, and ensure big is set. Find familial relationships.
    event = get_object_or_404(Event, id=event_id)
    base['messages'] += generate_messages(event)

    matches = event.get_matchset()
    if matches.count() > 200 and not event.big:
        event.set_big(True)

    base.update({
        'event':
        event,
        'siblings':
        event.get_parent().get_immediate_children().exclude(
            id=event.id) if event.get_parent() else None,
        'path':
        event.get_ancestors(id=True),
        'children':
        event.get_immediate_children(),
    })
    # }}}

    # {{{ Make forms
    if base['adm']:

        def check_form(formname, cl, check):
            if request.method == 'POST' and check in request.POST:
                f = cl(request=request, event=event)
                base['messages'] += f.update_event(event)
            else:
                f = cl(event=event)
            base[formname] = f

        check_form('form', EventModForm, 'modevent')
        check_form('addform', AddForm, 'addevent')
        if event.has_children():
            check_form('reorderform', ReorderForm, 'reorder')
        if event.type == TYPE_EVENT:
            check_form('ppform', PrizepoolModForm, 'modpp')
        if not event.has_children() and event.get_immediate_matchset().exists(
        ):
            check_form('stform', StoriesForm, 'modstory')
    # }}}

    # {{{ Prizepool information for the public
    total_earnings = Earnings.objects.filter(event__uplink__parent=event)

    local_earnings = Earnings.objects.filter(event=event)

    ranked_prize = local_earnings.exclude(placement=0)\
                                 .order_by('-earnings', 'placement')
    unranked_prize = list(
        local_earnings.filter(placement=0).order_by('-earnings'))

    placements = get_placements(event)
    prize_pool_table = list()
    for k, g in groupby(ranked_prize, key=lambda x: x.earnings):
        gl = list(g)
        prize_pool_table.append((k, placements[k], gl, len(gl)))

    if len(prize_pool_table) > 0:
        base['ranked_prize'] = prize_pool_table
    if len(unranked_prize) > 0:
        base['unranked_prize'] = unranked_prize

    currencies = list(
        {r['currency']
         for r in total_earnings.values('currency').distinct()})
    base.update({
        'prizepool':
        total_earnings.aggregate(Sum('earnings'))['earnings__sum'],
        'nousdpp':
        len(currencies) > 1 or len(currencies) == 1 and currencies[0] != 'USD',
        'prizepoolorig': [{
            'pp':
            total_earnings.filter(currency=k).aggregate(
                Sum('origearnings'))['origearnings__sum'],
            'cur':
            k,
        } for k in currencies],
    })
    # }}}

    # {{{ Other easy statistics

    add_links = request.user.is_authenticated() and request.user.is_staff

    base.update({
        'game':
        etn(lambda: dict(GAMES)[matches.values('game').distinct()[0]['game']]),
        'nmatches':
        matches.count(),
        'ngames':
        sum(count_winloss_games(matches)),
        'pvp_games':
        count_mirror_games(matches, 'P'),
        'tvt_games':
        count_mirror_games(matches, 'T'),
        'zvz_games':
        count_mirror_games(matches, 'Z'),
        'matches':
        display_matches(
            matches.prefetch_related('message_set').prefetch_related(
                'pla', 'plb',
                'eventobj').annotate(Count('eventobj__match')).order_by(
                    '-eventobj__latest', '-eventobj__idx', '-date',
                    '-id')[0:200],
            eventcount=True,
            add_links=add_links),
        'nplayers':
        Player.objects.filter(
            Q(id__in=matches.values('pla'))
            | Q(id__in=matches.values('plb'))).count(),
    })

    offlines = list(matches.values('offline').distinct())
    if len(offlines) > 1:
        base['offline'] = _('Both')
    elif len(offlines) == 1:
        base['offline'] = _('Offline') if offlines[0]['offline'] else _(
            'Online')

    base['pvt_wins'], base['pvt_loss'] = count_matchup_games(matches, 'P', 'T')
    base['pvz_wins'], base['pvz_loss'] = count_matchup_games(matches, 'P', 'Z')
    base['tvz_wins'], base['tvz_loss'] = count_matchup_games(matches, 'T', 'Z')
    base['tot_mirror'] = base['pvp_games'] + base['tvt_games'] + base[
        'zvz_games']
    # }}}

    return render_to_response('eventres.djhtml', base)
Example #34
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)
Example #35
0
def rating_details(request, player_id, period_id):
    period_id = int(period_id)
    player_id = int(player_id)

    period = get_object_or_404(Period, id=period_id, computed=True)
    player = get_object_or_404(Player, id=player_id, rating__period=period)
    rating = get_object_or_404(Rating, player=player, period=period)

    base = base_ctx('Ranking', 'Adjustments', request, context=player)

    try:
        nextlink = Rating.objects.filter(player=player, period__id__gt=period_id,\
                decay=0).order_by('period__id')[0]
    except:
        nextlink = None

    try:
        prevlink = Rating.objects.filter(player=player, period__id__lt=period_id,\
                decay=0).order_by('-period__id')[0]
    except:
        prevlink = None

    races = ['P','T','Z']

    prev = rating.get_prev()
    if prev != None:
        prevrat = [prev.get_rating(), {}]
        prevdev = [prev.get_dev(), {}]
        for r in races:
            prevrat[1][r] = prev.get_totalrating(r)
            prevdev[1][r] = prev.get_totaldev(r)
    else:
        prevrat = [0., {'P': 0., 'T': 0., 'Z': 0.}]
        prevdev = [RATINGS_INIT_DEV, {'P': RATINGS_INIT_DEV, 'T': RATINGS_INIT_DEV, 'Z': RATINGS_INIT_DEV}]

    matches = Match.objects.filter(Q(pla=player) | Q(plb=player)).filter(period=period)\
            .select_related('pla__rating').select_related('plb__rating').order_by('-date', '-id')
    if not matches.exists():
        base.update({'period': period, 'player': player, 'prevlink': prevlink, 'nextlink': nextlink})
        return render_to_response('ratingdetails.html', base)

    matches = display_matches(matches, fix_left=player, ratings=True)

    tot_rating = [0.0, {'P': 0.0, 'T': 0.0, 'Z': 0.0}]
    ngames = [0, {'P': 0, 'T': 0, 'Z': 0}]
    nwins = [0, {'P': 0, 'T': 0, 'Z': 0}]
    nlosses = [0, {'P': 0, 'T': 0, 'Z': 0}]
    expwins = [0.0, {'P': 0.0, 'T': 0.0, 'Z': 0.0}]

    treated = False
    nontreated = False
    for m in matches:
        if not m.treated:
            nontreated = True
            continue
        treated = True

        tot_rating[0] += m.plb_rating * (m.pla_score + m.plb_score)
        ngames[0] += m.pla_score + m.plb_score
        nwins[0] += m.pla_score
        nlosses[0] += m.plb_score

        scale = sqrt(1 + m.pla_dev**2 + m.pla_dev**2)

        races = [m.plb_race] if m.plb_race in ['P','T','Z'] else ['P','T','Z']
        weight = float(1)/len(races)
        for sr in races:
            ew = (m.pla_score + m.plb_score) * cdf(m.pla_rating - m.plb_rating, scale=scale)
            expwins[0] += weight * ew
            expwins[1][sr] += weight * ew

            tot_rating[1][sr] += weight * m.plb_rating * (m.pla_score + m.plb_score)
            ngames[1][sr] += weight * (m.pla_score + m.plb_score)
            nwins[1][sr] += weight * m.pla_score
            nlosses[1][sr] += weight * m.plb_score

    base.update({'period': period, 'player': player, 'rating': rating, 'matches': matches, 'treated': treated,\
            'nontreated': nontreated, 'prevlink': prevlink, 'nextlink': nextlink})
    if not treated:
        return render_to_response('ratingdetails.html', base)
    else:
        tot_rating[0] /= ngames[0]
        for r in ['P','T','Z']:
            if ngames[1][r] > 0:
                tot_rating[1][r] /= ngames[1][r]
        explosses = [ngames[0]-expwins[0], {}]
        exppctg = [expwins[0]/ngames[0]*100, {}]
        pctg = [float(nwins[0])/ngames[0]*100, {}]
        diff = [rating.rating-prevrat[0], {}]
        modded = False
        for r in ['P','T','Z']:
            explosses[1][r] = ngames[1][r] - expwins[1][r]
            if ngames[1][r] > 0:
                exppctg[1][r] = expwins[1][r]/ngames[1][r]*100
                pctg[1][r] = float(nwins[1][r])/ngames[1][r]*100
            diff[1][r] = rating.get_totalrating(r) - prevrat[1][r]
            if (nwins[1][r] != 0) != (nlosses[1][r] != 0):
                modded = True

        base.update({'tot_rating': tot_rating, 'ngames': ngames, 'nwins': nwins, 'nlosses': nlosses,\
                     'prevrat': prevrat, 'pctg': pctg,\
                     'exppctg': exppctg, 'diff': diff, 'expwins': expwins, 'explosses': explosses,\
                     'prevdev': prevdev, 'modded': modded})
        return render_to_response('ratingdetails.html', base)
Example #36
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'])
    # }}}

    # {{{ Statistics
    matches = display_matches(matches, fix_left=player)
    base['matches'] = 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']),
    })
    # }}}

    
    # {{{ 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 = matches[:min(10, len(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"])
        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

    if tl_params["bestof"] != "all":
        tl_params["bestof"] = "Bo{}+".format(tl_params["bestof"])

    if set(tl_params["race"]) == set('ptzr'):
        tl_params["race"] = "all"

    base.update({
        "postable_tl": TL_HISTORY_TEMPLATE.format(**tl_params)
    })
    
    # }}}

    base.update({"title": player.tag})
    
    return render_to_response('player_results.html', base)
Example #37
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)