Ejemplo n.º 1
0
class PlayerInfoForm(forms.Form):
    id = forms.IntegerField(required=True)
    name = StrippedCharField(required=False, label=_('Name'))
    romanized_name = StrippedCharField(
        required=False,
        label=_('Romanized name')
    )
    birthday = forms.DateField(required=False, label=_('Birthday'))
    country = forms.ChoiceField(
        choices=data.countries,
        required=False,
        label=_('Country')
    )

    def commit(self):
        data = dict(self.cleaned_data)
        player = Player.objects.get(id=data['id'])

        for k, v in data.items():
            if getattr(player, k) != v:
                setattr(player, k, v)
                print(k, v)

        player.save()

        return player
Ejemplo n.º 2
0
class ReorderForm(forms.Form):
    order = StrippedCharField(max_length=10000, required=True)

    # {{{ Constructor
    def __init__(self, request=None, event=None):
        if request is not None:
            super(ReorderForm, self).__init__(request.POST)
        else:
            super(ReorderForm, self).__init__()
    # }}}

    # {{{ Custom validation
    def clean_order(self):
        try:
            ids = [int(s) for s in self.cleaned_data['order'].split(',') if s.strip() != '']
            events = Event.objects.in_bulk(ids)
        except:
            raise ValidationError(_('Unable to get these events.'))

        return [events[i] for i in ids]
    # }}}

    # {{{ update_event: Pushes changes
    def update_event(self, event):
        ret = []

        if not self.is_valid():
            ret.append(Message(_('Entered data was invalid, no changes made.'), type=Message.ERROR))
            for field, errors in self.errors.items():
                for error in errors:
                    ret.append(Message(error=error, field=self.fields[field].label))
            return ret

        if len(self.cleaned_data['order']) != event.get_immediate_children().count():
            # Translate: Order as in an ordering, e.g. 2, 7, 5…
            return [Message(_('Order invalid, try again?'), type=Message.ERROR)]

        for e in self.cleaned_data['order']:
            if e.parent != event:
                return [Message(_('Non-child event found. This should never happen.'), type=Message.ERROR)]

        min_idx = min([e.idx for idx in self.cleaned_data['order']])
        for idx, e in enumerate(self.cleaned_data['order']):
            e.set_idx(min_idx + idx)

        return [Message(_(
            # Translators: Children as in sub-events.
            'Successfully reordered %i children. Any inconsistencies will be fixed next update '
            '(no more than six hours away).'
        ) % len(self.cleaned_data['order']), type=Message.SUCCESS)]
Ejemplo n.º 3
0
class AddForm(forms.Form):
    name = StrippedCharField(max_length=100, required=True, label=_('Name'))
    type = forms.ChoiceField(choices=EVENT_TYPES,
                             required=True,
                             label=_('Type'))
    noprint = forms.BooleanField(required=False, label=_('No Print'))
    closed = forms.BooleanField(required=False, label=_('Closed'))

    # {{{ Constructor
    def __init__(self, request=None, event=None):
        if request is not None:
            super(AddForm, self).__init__(request.POST)
        else:
            super(AddForm, self).__init__(
                initial={
                    'type': TYPE_EVENT if event.type ==
                    TYPE_CATEGORY else TYPE_ROUND,
                    'noprint': False,
                    'closed': event.closed
                })

        self.label_suffix = ''

    # }}}

    # {{{ update_event: Pushes changes
    def update_event(self, event):
        ret = []

        if not self.is_valid():
            ret.append(
                Message(_('Entered data was invalid, no changes made.'),
                        type=Message.ERROR))
            for field, errors in self.errors.items():
                for error in errors:
                    ret.append(
                        Message(error=error, field=self.fields[field].label))
            return ret

        event.add_child(
            self.cleaned_data['name'],
            self.cleaned_data['type'],
            self.cleaned_data['noprint'],
            self.cleaned_data['closed'],
        )

        ret.append(Message(_('Added a subevent.'), type=Message.SUCCESS))

        return ret
Ejemplo n.º 4
0
class StoryModForm(forms.Form):
    player = forms.ChoiceField(required=True, label=_('Player'))
    date = forms.DateField(required=True, label=_('Date'))
    text = StrippedCharField(max_length=200, required=True, label=_('Text'))

    # {{{ Constructor
    def __init__(self, request=None, event=None):
        if request is not None:
            super(StoryModForm, self).__init__(request.POST)
        else:
            super(StoryModForm, self).__init__(initial={'date': event.latest})

        matches = event.get_immediate_matchset()
        players = Player.objects.filter(
            Q(id__in=matches.values('pla')) | Q(id__in=matches.values('plb')))
        self.fields['player'].choices = [(str(p.id), str(p)) for p in players]

        self.label_suffix = ''

        self.existing_stories = Player.objects.filter(story__event=event)

    # }}}

    # {{{ update_event: Pushes changes
    def update_event(self, event):
        ret = []

        if not self.is_valid():
            ret.append(
                Message(_('Entered data was invalid, no changes made.'),
                        type=Message.ERROR))
            for field, errors in self.errors.items():
                for error in errors:
                    ret.append(
                        Message(error=error, field=self.fields[field].label))
            return ret

        story = Story(
            event=event,
            player_id=self.cleaned_data['player'],
            date=self.cleaned_data['date'],
            text=self.cleaned_data['text'],
        )
        story.save()

        # Translators: Stories are the dots on a player's rating chart
        ret.append(Message(_('Added a story.'), type=Message.SUCCESS))

        return ret
Ejemplo n.º 5
0
class APIKeyForm(forms.Form):
    organization = StrippedCharField(max_length=200,
                                     required=True,
                                     label=_('Name/organization'))
    contact = forms.EmailField(max_length=200,
                               required=True,
                               label=_('Contact'))

    # {{{ Constructor
    def __init__(self, request=None, player=None):
        if request is not None:
            super(APIKeyForm, self).__init__(request.POST)
        else:
            super(APIKeyForm, self).__init__()

        self.label_suffix = ''

    # }}}

    # {{{ add_key: Adds key if valid, returns messages
    def add_key(self):
        ret = []

        if not self.is_valid():
            ret.append(
                Message(_('Entered data was invalid.'), type=Message.ERROR))
            for field, errors in self.errors.items():
                for error in errors:
                    ret.append(
                        Message(error=error, field=self.fields[field].label))
            return ret

        key = APIKey(organization=self.cleaned_data['organization'],
                     contact=self.cleaned_data['contact'],
                     requests=0)

        key.generate_key()
        key.save()

        ret.append(
            Message(
                _("Your API key is <code>%s</code>. Please keep it safe.") %
                key.key,
                type=Message.SUCCESS))

        return ret
Ejemplo n.º 6
0
class AddEventsForm(forms.Form):
    parent_id = forms.IntegerField(required=True, label=_('Parent ID'))
    predef_names = forms.ChoiceField(choices=[
        ('other', _('Other')),
        ('Group Stage, Playoffs', _('Group stage and playoffs')),
        ('Group A,Group B,Group C,Group D', _('Groups A through D')),
        ('Group A,Group B,Group C,Group D,Group E,Group F,Group G,Group H',
         _('Groups A through H')),
        ('Ro64,Ro32,Ro16,Ro8,Ro4,Final', _('Ro64→Final')),
        ('Ro32,Ro16,Ro8,Ro4,Final', _('Ro32→Final')),
        ('Ro16,Ro8,Ro4,Final', _('Ro16→Final')),
        ('Ro8,Ro4,Final', _('Ro8→Final')),
        ('Ro4,Final', _('Ro4→Final')),
        ('Ro64,Ro32,Ro16,Ro8,Ro4,Third place match,Final',
         _('Ro64→Final + 3rd place')),
        ('Ro32,Ro16,Ro8,Ro4,Third place match,Final',
         _('Ro32→Final + 3rd place')),
        ('Ro16,Ro8,Ro4,Third place match,Final', _('Ro16→Final + 3rd place')),
        ('Ro8,Ro4,Third place match,Final', _('Ro8→Final + 3rd place')),
        ('Ro4,Third place match,Final', _('Ro4→Final + 3rd place')),
        ('Early rounds,Ro64,Ro32,Ro16,Ro8,Ro4,Final',
         _('Ro64→Final + early rounds')),
        ('Early rounds,Ro32,Ro16,Ro8,Ro4,Final',
         _('Ro32→Final + early rounds')),
        ('Early rounds,Ro16,Ro8,Ro4,Final', _('Ro16→Final + early rounds')),
        ('Early rounds,Ro8,Ro4,Final', _('Ro8→Final + early rounds')),
        ('Early rounds,Ro4,Final', _('Ro4→Final + early rounds')),
        ('Early rounds,Ro64,Ro32,Ro16,Ro8,Ro4,Third place match,Final',
         _('Ro64→Final + 3rd place and early rounds')),
        ('Early rounds,Ro32,Ro16,Ro8,Ro4,Third place match,Final',
         _('Ro32→Final + 3rd place and early rounds')),
        ('Early rounds,Ro16,Ro8,Ro4,Third place match,Final',
         _('Ro16→Final + 3rd place and early rounds')),
        ('Early rounds,Ro8,Ro4,Third place match,Final',
         _('Ro8→Final + 3rd place and early rounds')),
        ('Early rounds,Ro4,Third place match,Final',
         _('Ro4→Final + 3rd place and early rounds')),
        ('WB,LB,Final', _('WB, LB, Final')),
        ('Round 1,Round 2', _('LB: Round 1->Round 2')),
        ('Round 1,Round 2,Round 3,Round 4', _('LB: Round 1->Round 4')),
        ('Round 1,Round 2,Round 3,Round 4,Round 5,Round 6',
         _('LB: Round 1->Round 6')),
        ('Round 1,Round 2,Round 3,Round 4,Round 5,Round 6,Round 7,Round 8',
         _('LB: Round 1->Round 8')),
    ],
                                     required=True,
                                     label=_('Predefined names'))
    custom_names = StrippedCharField(max_length=400,
                                     required=False,
                                     label=_('Custom names'))
    type = forms.ChoiceField(choices=EVENT_TYPES,
                             required=True,
                             label=_('Type'))
    big = forms.BooleanField(required=False, label=_('Big'), initial=False)
    noprint = forms.BooleanField(required=False,
                                 label=_('No print'),
                                 initial=False)

    def __init__(self, request=None):
        if request is None:
            super(AddEventsForm, self).__init__()
        else:
            super(AddEventsForm, self).__init__(request.POST)
            if 'commit' in request.POST:
                self.action = 'add'
            else:
                self.action = 'close'

        self.label_suffix = ''

    # Custom validation
    def clean_parent_id(self):
        try:
            if int(self.cleaned_data['parent_id']) != -1:
                return Event.objects.get(
                    id=int(self.cleaned_data['parent_id']))
            return None
        except:
            raise ValidationError(
                _('Could not find event ID %s.') %
                self.cleaned_data['parent_id'])

    def clean(self):
        if self.action != 'add':
            if self.cleaned_data['parent_id'] is None:
                raise ValidationError(_('Must specify an event to close.'))
            return self.cleaned_data

        if self.cleaned_data['predef_names'] == 'other' and self.cleaned_data[
                'custom_names'] in ['', None]:
            raise ValidationError(_('No event names specified.'))

        names = (self.cleaned_data['predef_names']
                 if self.cleaned_data['predef_names'] != 'other' else
                 self.cleaned_data['custom_names'])

        self.cleaned_data['names'] = [
            s.strip() for s in names.split(',') if s.strip() != ''
        ]
        return self.cleaned_data

    # Commit changes
    def commit(self):
        ret = []

        if not self.is_valid():
            ret.append(
                Message(_('Entered data was invalid, no changes made.'),
                        type=Message.ERROR))
            for field, errors in self.errors.items():
                for error in errors:
                    if field == '__all__':
                        ret.append(Message(error, type=Message.ERROR))
                    else:
                        ret.append(
                            Message(error=error,
                                    field=self.fields[field].label))
            return ret

        if self.action == 'add':
            adder = (self.cleaned_data['parent_id'].add_child
                     if self.cleaned_data['parent_id'] is not None else
                     Event.add_root)
            for name in self.cleaned_data['names']:
                adder(
                    name=name,
                    type=self.cleaned_data['type'],
                    big=self.cleaned_data['big'],
                    noprint=self.cleaned_data['noprint'],
                )
            ret.append(
                Message(ungettext_lazy('Successfully created %i new event.',
                                       'Successfully created %i new events.',
                                       len(self.cleaned_data['names'])) %
                        len(self.cleaned_data['names']),
                        type=Message.SUCCESS))
        elif self.action == 'close':
            self.cleaned_data['parent_id'].close()
            ret.append(
                Message(_('Successfully closed event.'), type=Message.SUCCESS))

        return ret
Ejemplo n.º 7
0
class AddMatchesForm(forms.Form):
    eventtext = StrippedCharField(max_length=200,
                                  required=False,
                                  label=_('Event'))
    date = forms.DateField(required=True, label=_('Date'))
    game = forms.ChoiceField(choices=GAMES,
                             label=_('Game version'),
                             initial=LOTV)
    offline = forms.BooleanField(required=False,
                                 label=_('Offline'),
                                 initial=False)
    source = StrippedCharField(max_length=1000,
                               required=False,
                               label=_('Source'))
    contact = StrippedCharField(max_length=1000,
                                required=False,
                                label=_('Contact'))
    notes = forms.CharField(max_length=10000,
                            required=False,
                            label=_('Notes'),
                            initial='')
    matches = forms.CharField(max_length=10000,
                              required=True,
                              label=_('Matches'),
                              initial='')

    def __init__(self, is_adm, request=None):
        if request is not None:
            super(AddMatchesForm, self).__init__(request.POST)
            self.close_after = 'commit_close' in request.POST
            self.eobj = etn(lambda: request.POST['eventobj'])
        else:
            super(AddMatchesForm,
                  self).__init__(initial={'date': date.today()})
            self.close_after = False

        self.requested_close_after = self.close_after

        self.label_suffix = ''
        self.is_adm = is_adm

        self.fields['eventobj'] = forms.ChoiceField(
            choices=[(e['id'], e['fullname']) for e in Event.objects.filter(
                closed=False, type__in=(TYPE_ROUND, TYPE_EVENT)).annotate(
                    num_downlinks=Count('downlink')).filter(
                        num_downlinks=1).order_by('idx').values(
                            'id', 'fullname')],
            required=False,
            label=_('Event'),
        )

    # Validation
    def clean_eventtext(self):
        if self.is_adm:
            return self.cleaned_data['eventtext']
        if self.cleaned_data['eventtext'] in [None, '']:
            raise ValidationError(_('This field is required.'))
        return self.cleaned_data['eventtext']

    def clean_source(self):
        if self.is_adm:
            return self.cleaned_data['source']
        if self.cleaned_data['source'] in [None, '']:
            raise ValidationError(_('This field is required.'))
        return self.cleaned_data['source']

    def clean(self):
        if self.is_adm:
            try:
                self.cleaned_data['eventobj'] = Event.objects.get(
                    id=int(self.eobj))
            except:
                raise ValidationError(_('Could not find this event object.'))
        return self.cleaned_data

    # Parse the matches
    def parse_matches(self, submitter):
        self.messages = []

        if not self.is_valid():
            self.messages.append(
                Message(_('Entered data was invalid, no changes made.'),
                        type=Message.ERROR))
            for field, errors in self.errors.items():
                for error in errors:
                    self.messages.append(
                        Message(error=error, field=self.fields[field].label))
            return []

        if not self.is_adm:
            self.prematchgroup = PreMatchGroup(
                date=self.cleaned_data['date'],
                event=self.cleaned_data['eventtext'],
                source=self.cleaned_data['source'],
                contact=self.cleaned_data['contact'],
                notes=self.cleaned_data['notes'],
                game=self.cleaned_data['game'],
                offline=self.cleaned_data['offline'],
            )
            self.prematchgroup.save()

        error_lines, matches = [], []
        for line in self.cleaned_data['matches'].splitlines():
            if line.strip() == '':
                continue

            try:
                parse_results = parse_match(line.strip(), allow_archon=False)
                pla_query = parse_results['pla']
                plb_query = parse_results['plb']
                sca = parse_results['sca']
                scb = parse_results['scb']

                make_flag = 'MAKE' in parse_results['flags']
                dup_flag = 'DUP' in parse_results['flags']
            except pyparsing.ParseException as e:
                self.messages.append(
                    Message(_("Could not parse '%(line)s' (%(error)s).") % {
                        'line': line,
                        'error': str(e)
                    },
                            type=Message.ERROR))
                self.close_after = False
                error_lines.append(line)
                continue

            pla_race_override = find_race_override(pla_query)
            plb_race_override = find_race_override(plb_query)

            try:
                match = self.make_match(
                    pla_query,
                    plb_query,
                    pla_race_override,
                    plb_race_override,
                    sca,
                    scb,
                    make_flag,
                    dup_flag,
                )
                if match is None:
                    error_lines.append(line)
                    continue
            except Exception as e:
                self.messages.append(
                    Message(_("Error creating match '%(line)s' (%(error)s).") %
                            {
                                'line': line,
                                'error': str(e)
                            },
                            type=Message.ERROR))
                self.close_after = False
                error_lines.append(line)
                continue

            if self.is_adm:
                match.submitter = submitter
            matches.append(match)

        for m in matches:
            m.save()
        if len(matches) > 0:
            self.messages.append(
                Message(ungettext_lazy('Successfully added %i match.',
                                       'Successfully added %i matches.',
                                       len(matches)) % len(matches),
                        type=Message.SUCCESS))

        if self.close_after:
            self.cleaned_data['eventobj'].close()
            self.messages.append(
                Message(_("Closed '%s'.") %
                        self.cleaned_data['eventobj'].fullname,
                        type=Message.SUCCESS))
        elif self.requested_close_after:
            self.messages.append(
                Message(_("Did not close '%s'.") %
                        self.cleaned_data['eventobj'].fullname,
                        type=Message.INFO))

        self.data = self.data.copy()
        self.data['matches'] = '\n'.join(error_lines)

        return matches

    # Auxiliary function for searching for players
    def get_player(self, query, make_flag):
        players = find_player(lst=query, make=make_flag, soft=False)
        printable = ' '.join(str(x) for x in query)
        if players.count() != 1:
            if self.is_adm:
                if players.count() == 0:
                    self.messages.append(
                        Message(_("Could not find player: '%s'.") % printable,
                                type=Message.ERROR))
                    self.close_after = False
                elif players.count() > 1:
                    self.messages.append(
                        Message(_("Ambiguous player: '%s'.") % printable,
                                type=Message.ERROR))
                    self.close_after = False
            return None

        return players.first()

    # Make matches (called from parse_matches). DOES NOT SAVE THEM.
    def make_match(self, pla_query, plb_query, pla_race_or, plb_race_or, sca,
                   scb, make_flag, dup_flag):
        pla = self.get_player(pla_query, make_flag)
        plb = self.get_player(plb_query, make_flag)

        if (pla is None or plb is None) and self.is_adm:
            return None

        if not self.is_adm:
            match = PreMatch(
                group=self.prematchgroup,
                pla=pla,
                plb=plb,
                pla_string=' '.join(pla_query),
                plb_string=' '.join(plb_query),
                sca=sca,
                scb=scb,
                date=self.cleaned_data['date'],
                rca=pla_race_or,
                rcb=plb_race_or,
            )
            return match
        else:
            match = Match(
                pla=pla,
                plb=plb,
                sca=sca,
                scb=scb,
                rca=pla_race_or or (pla.race if pla.race != 'S' else 'R'),
                rcb=plb_race_or or (plb.race if plb.race != 'S' else 'R'),
                date=self.cleaned_data['date'],
                treated=False,
                eventobj=self.cleaned_data['eventobj'],
                game=self.cleaned_data['game'],
                offline=self.cleaned_data['offline'],
            )
            if check_duplicates(match, dup_flag):
                self.messages.append(
                    Message(
                        _("Could not make match %(pla)s vs %(plb)s: possible duplicate found."
                          ) % {
                              'pla': pla.tag,
                              'plb': plb.tag
                          },
                        type=Message.ERROR,
                    ))
                self.close_after = False
                return None
            if 'R' in [match.rca, match.rcb]:
                self.messages.append(
                    Message(
                        _("Unknown race in %(pla)s vs %(plb)s: set to random.")
                        % {
                            'pla': pla.tag,
                            'plb': plb.tag
                        },
                        type=Message.WARNING,
                    ))
            match.set_period()
            match.set_ratings()
            return match
Ejemplo n.º 8
0
class PlayerModForm(forms.Form):
    tag = StrippedCharField(max_length=30, required=True, label=_('Tag'))
    race = forms.ChoiceField(choices=RACES, required=True, label=_('Race'))
    name = StrippedCharField(max_length=100, required=False, label=_('Name'))
    romanized_name = StrippedCharField(max_length=100,
                                       required=False,
                                       label=_('Romanized Name'))
    akas = forms.CharField(max_length=200, required=False, label=_('AKAs'))
    birthday = forms.DateField(required=False, label=_('Birthday'))

    tlpd_id = forms.IntegerField(required=False, label=_('TLPD ID'))
    tlpd_db = forms.MultipleChoiceField(required=False,
                                        choices=TLPD_DBS,
                                        label=_('TLPD DB'),
                                        widget=forms.CheckboxSelectMultiple)
    lp_name = StrippedCharField(max_length=200,
                                required=False,
                                label=_('Liquipedia title'))
    sc2e_id = forms.IntegerField(required=False, label=_('SC2Earnings.com ID'))

    country = forms.ChoiceField(choices=data.countries,
                                required=False,
                                label=_('Country'))

    # {{{ Constructor
    def __init__(self, request=None, player=None):
        if request is not None:
            super(PlayerModForm, self).__init__(request.POST)
        else:
            super(PlayerModForm, self).__init__(
                initial={
                    'tag':
                    player.tag,
                    'race':
                    player.race,
                    'country':
                    player.country,
                    'name':
                    player.name,
                    'romanized_name':
                    player.romanized_name,
                    'akas':
                    ', '.join(player.get_aliases()),
                    'birthday':
                    player.birthday,
                    'sc2e_id':
                    player.sc2e_id,
                    'lp_name':
                    player.lp_name,
                    'tlpd_id':
                    player.tlpd_id,
                    'tlpd_db':
                    filter_flags(player.tlpd_db if player.tlpd_db else 0),
                })

        self.label_suffix = ''

    # }}}

    # {{{ update_player: Pushes updates to player, responds with messages
    def update_player(self, player):
        ret = []

        if not self.is_valid():
            ret.append(
                Message(_('Entered data was invalid, no changes made.'),
                        type=Message.ERROR))
            for field, errors in self.errors.items():
                for error in errors:
                    ret.append(
                        Message(error=error, field=self.fields[field].label))
            return ret

        def update(value, attr, setter, label):
            if value != getattr(player, attr):
                getattr(player, setter)(value)
                # Translators: Changed something (a noun).
                ret.append(
                    Message(_('Changed %s.') % label, type=Message.SUCCESS))

        update(self.cleaned_data['tag'], 'tag', 'set_tag', _('tag'))
        update(self.cleaned_data['race'], 'race', 'set_race', _('race'))
        update(self.cleaned_data['country'], 'country', 'set_country',
               _('country'))
        update(self.cleaned_data['name'], 'name', 'set_name', _('name'))
        update(self.cleaned_data['romanized_name'], 'romanized_name',
               'set_romanized_name', _('romanized name'))
        update(self.cleaned_data['birthday'], 'birthday', 'set_birthday',
               _('birthday'))
        update(self.cleaned_data['tlpd_id'], 'tlpd_id', 'set_tlpd_id',
               _('TLPD ID'))
        update(self.cleaned_data['lp_name'], 'lp_name', 'set_lp_name',
               _('Liquipedia title'))
        update(self.cleaned_data['sc2e_id'], 'sc2e_id', 'set_sc2e_id',
               _('SC2Earnings.com ID'))
        update(sum([int(a) for a in self.cleaned_data['tlpd_db']]), 'tlpd_db',
               'set_tlpd_db', _('TLPD DBs'))

        if player.set_aliases([
                x for x in self.cleaned_data['akas'].split(',')
                if x.strip() != ''
        ]):
            ret.append(Message(_('Changed aliases.'), type=Message.SUCCESS))

        return ret
Ejemplo n.º 9
0
class TeamModForm(forms.Form):
    name = StrippedCharField(max_length=100, required=True, label=_('Name'))
    akas = forms.CharField(max_length=200, required=False, label=_('AKAs'))
    shortname = StrippedCharField(max_length=100,
                                  required=False,
                                  label=_('Name'))
    homepage = StrippedCharField(max_length=200,
                                 required=False,
                                 label=_('Homepage'))
    lp_name = StrippedCharField(max_length=200,
                                required=False,
                                label=_('Liquipedia title'))

    # {{{ Constructor
    def __init__(self, request=None, team=None):
        if request is not None:
            super(TeamModForm, self).__init__(request.POST)
        else:
            super(TeamModForm, self).__init__(
                initial={
                    'name': team.name,
                    'akas': ', '.join(team.get_aliases()),
                    'shortname': team.shortname,
                    'homepage': team.homepage,
                    'lp_name': team.lp_name,
                })

        self.label_suffix = ''

    # }}}

    # {{{ update_player: Pushes updates to player, responds with messages
    def update_team(self, team):
        ret = []

        if not self.is_valid():
            ret.append(
                Message(_('Entered data was invalid, no changes made.'),
                        type=Message.ERROR))
            for field, errors in self.errors.items():
                for error in errors:
                    ret.append(
                        Message(error=error, field=self.fields[field].label))
            return ret

        def update(value, attr, setter, label):
            if value != getattr(team, attr):
                getattr(team, setter)(value)
                ret.append(
                    Message(_('Changed %s.') % label, type=Message.SUCCESS))

        update(self.cleaned_data['name'], 'name', 'set_name', _('name'))
        update(self.cleaned_data['lp_name'], 'lp_name', 'set_lp_name',
               _('Liquipedia title'))
        update(self.cleaned_data['shortname'], 'shortname', 'set_shortname',
               _('short name'))
        update(self.cleaned_data['homepage'], 'homepage', 'set_homepage',
               _('homepage'))

        if team.set_aliases(self.cleaned_data['akas'].split(',')):
            ret.append(Message(_('Changed aliases.'), type=Message.SUCCESS))

        return ret
Ejemplo n.º 10
0
class EventModForm(forms.Form):
    name = StrippedCharField(max_length=100, required=True, label='Name')
    date = forms.DateField(required=False, label='Date')
    game = forms.ChoiceField(choices=[('nochange', _('No change'))] + GAMES,
                             required=True,
                             label=_('Game version'))
    offline = forms.ChoiceField(choices=[('nochange', _('No change')),
                                         ('online', _('Online')),
                                         ('offline', _('Offline'))],
                                required=True,
                                label=_('On/offline'))
    type = forms.ChoiceField(
        choices=[('nochange', _('No change'))] + EVENT_TYPES,
        # Translators: Type as in event type
        required=True,
        label=_('Type'))
    # Translators: Apply (changes) to…
    same_level = forms.BooleanField(
        required=False, label=_('Apply to all events on the same level'))
    homepage = StrippedCharField(max_length=200,
                                 required=False,
                                 label=_('Homepage'))
    tlpd_id = forms.IntegerField(required=False, label=_('TLPD ID'))
    tlpd_db = forms.MultipleChoiceField(required=False,
                                        choices=TLPD_DBS,
                                        label=_('TLPD DB'),
                                        widget=forms.CheckboxSelectMultiple)
    tl_thread = forms.IntegerField(required=False, label=_('TL thread'))
    lp_name = StrippedCharField(max_length=200,
                                required=False,
                                label=_('Liquipedia title'))

    # {{{ Constructor
    def __init__(self, request=None, event=None):
        if request is not None:
            super(EventModForm, self).__init__(request.POST)
        else:
            super(EventModForm, self).__init__(
                initial={
                    'name': event.name,
                    'date': None,
                    'game': 'nochange',
                    'offline': 'nochange',
                    'type': event.type,
                    'same_level': False,
                    'homepage': event.homepage,
                    'tlpd_id': event.tlpd_id,
                    'tlpd_db': filter_flags(
                        event.tlpd_db if event.tlpd_db else 0),
                    'tl_thread': event.tl_thread,
                    'lp_name': event.lp_name,
                })

        self.label_suffix = ''

    # }}}

    # {{{ update_event: Pushes updates to event, responds with messages
    def update_event(self, event):
        ret = []

        if not self.is_valid():
            ret.append(
                Message(_('Entered data was invalid, no changes made.'),
                        type=Message.ERROR))
            for field, errors in self.errors.items():
                for error in errors:
                    ret.append(
                        Message(error=error, field=self.fields[field].label))
            return ret

        if self.cleaned_data['name'] != event.name:
            event.update_name(self.cleaned_data['name'])
            for e in event.get_children(id=False):
                e.update_name()
            ret.append(Message(_('Changed event name.'), type=Message.SUCCESS))

        if self.cleaned_data['date'] is not None:
            nchanged = event.get_matchset().update(
                date=self.cleaned_data['date'])
            ret.append(
                Message(
                    ungettext_lazy('Changed date for %i match.',
                                   'Changed date for %i matches.', nchanged) %
                    nchanged,
                    type=Message.SUCCESS))

        if self.cleaned_data['game'] != 'nochange':
            nchanged = event.get_matchset().update(
                game=self.cleaned_data['game'])
            ret.append(
                Message(ungettext_lazy('Changed game version for %i match.',
                                       'Changed game version for %i matches.',
                                       nchanged) % nchanged,
                        type=Message.SUCCESS))

        if self.cleaned_data['offline'] != 'nochange':
            nchanged = event.get_matchset().update(
                offline=(self.cleaned_data['offline'] == 'offline'))
            ret.append(
                Message(ungettext_lazy('Changed on/offline for %i match.',
                                       'Changed on/offline for %i matches.',
                                       nchanged) % nchanged,
                        type=Message.SUCCESS))

        events = [event] if not self.cleaned_data[
            'same_level'] else event.parent.get_immediate_children()
        nchanged = 0
        for e in events:
            if e.type != self.cleaned_data['type']:
                e.change_type(self.cleaned_data['type'])
            nchanged += 1
        if nchanged > 0:
            ret.append(
                Message(
                    ungettext_lazy('Changed type for %i event.',
                                   'Changed type for %i events.', nchanged) %
                    nchanged,
                    type=Message.SUCCESS))

        def update(value, attr, setter, label):
            if value != getattr(event, attr):
                getattr(event, setter)(value)
                ret.append(
                    Message(_('Changed %s.') % label, type=Message.SUCCESS))

        update(self.cleaned_data['homepage'], 'homepage', 'set_homepage',
               _('homepage'))
        update(self.cleaned_data['tlpd_id'], 'tlpd_id', 'set_tlpd_id',
               _('TLPD ID'))
        update(self.cleaned_data['lp_name'], 'lp_name', 'set_lp_name',
               _('Liquipedia title'))
        update(self.cleaned_data['tl_thread'], 'tl_thread', 'set_tl_thread',
               _('TL thread'))
        update(sum([int(a) for a in self.cleaned_data['tlpd_db']]), 'tlpd_db',
               'set_tlpd_db', _('TLPD DBs'))

        return ret
Ejemplo n.º 11
0
class SearchForm(forms.Form):
    after = forms.DateField(required=False, label=_('After'), initial=None)
    before = forms.DateField(required=False, label=_('Before'), initial=None)
    players = forms.CharField(max_length=10000,
                              required=False,
                              label=_('Involving players'),
                              initial='')
    event = StrippedCharField(max_length=200,
                              required=False,
                              label=_('Event'),
                              initial='')
    # Translators: Unassigned as in not assigned to an event.
    unassigned = forms.BooleanField(required=False,
                                    label=_('Only show unassigned matches'))
    bestof = forms.ChoiceField(choices=[
        ('all', _('All')),
        ('3', _('Best of 3+')),
        ('5', _('Best of 5+')),
    ],
                               required=False,
                               label=_('Match format'),
                               initial='all')
    offline = forms.ChoiceField(
        choices=[
            ('both', _('Both')),
            ('offline', _('Offline')),
            ('online', _('Online')),
        ],
        required=False,
        label=_('On/offline'),
        initial='both',
    )
    game = forms.ChoiceField(choices=[('all', _('All'))] + GAMES,
                             required=False,
                             label=_('Game version'),
                             initial='all')

    # {{{ Constructor
    def __init__(self, request=None):
        if request is not None:
            super(SearchForm, self).__init__(request.GET)
        else:
            super(SearchForm, self).__init__()

        self.label_suffix = ''

    # }}}

    # {{{ search: Performs a search, returns a dict with results to be added to the rendering context
    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
Ejemplo n.º 12
0
class PredictForm(forms.Form):
    format = forms.ChoiceField(
        choices=[(i, f['name']) for i, f in enumerate(FORMATS)],
        required=True,
        label=_('Format'),
        initial=0,
    )
    bestof = StrippedCharField(max_length=100,
                               required=True,
                               label=_('Best of'),
                               initial='1')
    players = forms.CharField(max_length=10000,
                              required=True,
                              label=_('Players'),
                              initial='')

    # {{{ Constructor
    def __init__(self, request=None):
        self.messages = []

        if request is not None:
            super(PredictForm, self).__init__(request.GET)
        else:
            super(PredictForm, self).__init__()

        self.label_suffix = ''

    # }}}

    # {{{ Custom validation of bestof and players
    def clean_bestof(self):
        try:
            ret = []
            for a in map(int, self.cleaned_data['bestof'].split(',')):
                ret.append(a)
                assert (a > 0 and a % 2 == 1)
            return ret
        except:
            raise ValidationError(
                _("Must be a comma-separated list of positive odd integers (1,3,5,…)."
                  ))

    def clean_players(self):
        lines = self.cleaned_data['players'].splitlines()
        lineno, ok, players = -1, True, []
        self.messages = []

        for line in lines:
            lineno += 1
            if line.strip() == '':
                continue

            if line.strip() == '-' or line.strip().lower() == 'bye':
                players.append(None)
                continue

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

        if not ok:
            raise ValidationError(
                _('One or more errors found in player list.'))

        return players

    # }}}

    # {{{ Combined validation of format, bestof and players
    def clean(self):
        self.cleaned_data['format'] = min(
            max(int(self.cleaned_data['format']), 0), len(FORMATS))
        fmt = FORMATS[self.cleaned_data['format']]

        if 'players' in self.cleaned_data and not fmt['np-check'](len(
                self.cleaned_data['players'])):
            raise ValidationError(fmt['np-errmsg'])
        if 'bestof' in self.cleaned_data and not fmt['bo-check'](len(
                self.cleaned_data['bestof'])):
            raise ValidationError(fmt['bo-errmsg'])

        return self.cleaned_data

    # }}}

    # {{{ get_messages: Returns a list of messages after validation
    def get_messages(self):
        if not self.is_valid():
            ret = []
            for field, errors in self.errors.items():
                for error in errors:
                    if field == '__all__':
                        ret.append(Message(error, type=Message.ERROR))
                    else:
                        ret.append(
                            Message(error=error,
                                    field=self.fields[field].label))
            return self.messages + ret

        return self.messages

    # }}}

    # {{{ generate_url: Returns an URL to continue to (assumes validation has passed)
    def generate_url(self):
        return '/inference/%s/?bo=%s&ps=%s' % (
            FORMATS[self.cleaned_data['format']]['url'],
            '%2C'.join([str(b) for b in self.cleaned_data['bestof']]),
            '%2C'.join([
                str(p.id) if p is not None else '0'
                for p in self.cleaned_data['players']
            ]),
        )