Example #1
0
    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
Example #2
0
    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

            dashes = find_dashes(line)
            try:
                pla_query = shlex.split(line[:dashes[0]])
                middle = shlex.split(line[dashes[0]+1:dashes[1]])
                plb_query = middle[:-1]
                sca = int(middle[-1])
                end = shlex.split(line[dashes[1]+1:])
                scb = int(end[0])

                make_flag = '!MAKE' in end
                dup_flag = '!DUP' in end
            except Exception 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
Example #3
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
Example #4
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=HOTS)
    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)
                    .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

            dashes = find_dashes(line)
            try:
                pla_query = shlex.split(line[:dashes[0]])
                middle = shlex.split(line[dashes[0]+1:dashes[1]])
                plb_query = middle[:-1]
                sca = int(middle[-1])
                end = shlex.split(line[dashes[1]+1:])
                scb = int(end[0])

                make_flag = '!MAKE' in end
                dup_flag = '!DUP' in end
            except Exception 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)

        if players.count() != 1:
            if self.is_adm:
                if players.count() == 0:
                    self.messages.append(
                        Message(_("Could not find player: '%s'.") % ' '.join(query), type=Message.ERROR))
                    self.close_after = False
                elif players.count() > 1:
                    self.messages.append(
                        Message(_("Ambiguous player: '%s'.") % ' '.join(query), 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