Beispiel #1
0
def add_stage(request, comp):
    """add a stage to a competition incrementing other stages numbers

    :param request: expecting POST parameters:\n
        :param int number: number of the stage to add a stage after
        :param str stage_type: type of stage to add
    :param Competition comp: competition to delete stage from
    :return:
    """
    number = int(request.POST['number'])
    stage_type = request.POST['stage_type']
    if stage_type not in map(lambda x: x[0], Stage.stage_types):
        return api_failure('bad_type', _('Failed to add stage: unrecognised stage type'))
    if comp.stage_set.exists():
        stage = get_object_or_404(Stage, competition=comp, number=number)
        if stage.appendable_to():
            stages = comp.stage_set.filter(number__gt=number).order_by('-number').all()
            for stage in stages:
                stage.number += 1
                stage.save()
            if comp.stage_set.create(number=number + 1, type=request.POST['stage_type'], state=Stage.NOT_STARTED):
                out = {'success': True}
                return JsonResponse(out)
            else:
                return api_failure('error_adding_stage', _('Failed to add stage'))
        else:
            out = {'success': False,
                   'reason': 'stage_unappendable_to',
                   'verbose_reason': _('Stage cannot be appended to')}
            return JsonResponse(out)
    else:
        if comp.stage_set.create(type=stage_type, number=0):
            return api_success()
        else:
            return api_failure('error_adding_stage', _('Failed to add stage'))
Beispiel #2
0
def set_cull_level(request, stage: Stage):
    """set what level a cull should happen from

    :param request: expecting POST parameters:\n
        cull_number: value to set CullStage.number at
    :param stage: Stage of type cull to set
    :return: JSONResponse with either success or an error message
    """
    cull_stage = stage.cullstage_set.first()
    if stage.state == Stage.NOT_STARTED:
        try:
            input_size = len(stage.input())
        except Stage.NotCompleteError:
            return api_failure("previous stage incomplete")
        number = int(request.POST['cull_number'])
        if 2 < number < input_size:
            cull_stage.number = number
            stage.state = Stage.READY
            cull_stage.save()
            stage.save()
            return api_success()
        else:
            return api_failure(
                "invalid cull number",
                "cull number must be > 2 and < size of stages input ")

    else:
        return api_failure("incorrect state", "stage not in ready state")
Beispiel #3
0
def add_entries(request, stage: Stage):
    """add entries and set stage as ready
    entries will be ordered according to their seed

    :param request: expecting POST parameters:\n
        :param list of int ids: list of entry ids to add
    :param stage: Stage of type add
    :return: JSONResponse with either success or an error message
    """
    add_stage = stage.addstage_set.first()
    if stage.state != Stage.NOT_STARTED:
        return api_failure("incorrect state",
                           _("Stage not in NOT_STARTED state"))
    ids = request.POST.getlist('ids')
    entries = stage.competition.entry_set.filter(pk__in=ids)
    if len(entries) != len(ids) or not set(entries.all()).issubset(
            add_stage.possible_additions()):
        return api_failure(
            'bad_entry',
            _('one of these entries has already been added or is not in this competition'
              ))

    additions = []
    for y, equal_fencers in groupby(entries.order_by('seed'),
                                    lambda x: x.seed):
        additions.append(list(equal_fencers))
    add_stage.add_entries(additions)
    stage.state = Stage.READY
    stage.save()
    return api_success()
Beispiel #4
0
def confirm_pools(request, stage):
    pool_stage = stage.poolstage_set.first()
    if stage.state != Stage.READY:
        return api_failure("incorrect state",
                           _("Stage not in ready state"))
    if 'pools' not in request.POST:
        stage.state = Stage.STARTED
        stage.save()
        return api_success()
    original_pools = pool_stage.pool_set.all()
    pools = json.loads(request.POST['pools'])
    if len(pools) != len(original_pools):
        return api_failure("pool count mismatch",
                           _("Number of pools submitted does not match number of pools in this round"))
    original_competitors_ids = set()
    [original_competitors_ids.update(x.poolentry_set.values_list('entry_id', flat=True)) for x in original_pools]
    competitors_ids = set()
    new_lengths = []
    for pool_num, entries in pools.items():
        competitors_ids.update(map(int, entries))
        new_lengths.append(len(entries))
    if competitors_ids != original_competitors_ids:
        return api_failure("pool entry mismatch",
                           _("Manipulation of entry ids detected"))
    if not (max(new_lengths) <= min(new_lengths) + 1):
        return api_failure("pool size difference",
                           _("Pools can differ in size by at most 1"))
    original_pools.delete()
    for index, pool in enumerate(pools.items()):
        new_pool = pool_stage.pool_set.create(number=index+1)
        for index, entry_id in enumerate(pool[1]):
            new_pool.poolentry_set.create(number=index+1, entry_id=int(entry_id))
    stage.state = Stage.STARTED
    stage.save()
    return api_success()
Beispiel #5
0
def add_result(request, table):
    """add a result to  a de table

    :param request: expecting POST parameters:\n
        :int entryA: detableentry id of the first entry the results pertain to
        :int entryB: detableentry id of the second entry the results pertain to
        :int scoreA: first entries score
        :int scoreB: second entries score
        :bool  victoryA: boolean indicating if first entry won. If false 2nd is assumed to have won
    :param DeTable table: table these results are from
    :return:
    """
    if table.de.stage.state != Stage.STARTED:
        return api_failure('incorrect state', 'stage not currently running')
    if table.children.exists():
        return api_failure(
            'child_exists',
            _('Cannot add results after next round of tables made'))
    if table.complete:
        return api_failure('table_complete',
                           _('This table has already been marked as complete'))
    e1_id = request.POST['entryA']
    e2_id = request.POST['entryB']
    e1 = table.detableentry_set.get(pk=e1_id)
    e2 = table.detableentry_set.get(pk=e2_id)
    e1_victory = bool(int(request.POST['victoryA']))
    e1_score = int(request.POST['scoreA'])
    e2_score = int(request.POST['scoreB'])
    return do_add_result(request, e1, e2, e1_score, e2_score, e1_victory)
Beispiel #6
0
def finish_stage(request, stage: Stage) -> JsonResponse:
    """mark a finished de_stage as finished is it is complete"""
    if stage.state != Stage.STARTED:
        return api_failure("invalid state", _("Stage not currently running"))
    de_stage = stage.destage_set.first()  # type: DeStage
    if de_stage.detable_set.filter(complete=False).exists():
        return api_failure('stage not finished', _('Stage not finished'))
    stage.state = Stage.FINISHED
    stage.save()
    return api_success()
Beispiel #7
0
def finish_stage(request, stage):
    pool_stage = stage.poolstage_set.first()
    if stage.state == Stage.STARTED:
        if all(map(lambda x: x.complete(), pool_stage.pool_set.all())):
            stage.state = Stage.FINISHED
            stage.save()
            return api_success()
        else:
            return api_failure('stage not finished')
    else:
        return api_failure("incorrect state",
                           "stage not currently running")
Beispiel #8
0
def start_stage(request, stage: Stage) -> JsonResponse:
    """start a not running de stage and generate its head table"""
    if stage.state != Stage.NOT_STARTED:
        return api_failure("invalid state", "Stage has already started")
    de_stage = stage.destage_set.first()  # type: DeStage
    try:
        de_stage.start()
    except Stage.NotCompleteError:
        return api_failure('previous stage incomplete',
                           'Previous stage not finished yet')
    stage.state = Stage.STARTED
    stage.save()
    return api_success()
Beispiel #9
0
def mark_table_complete(request, table):
    if table.complete:
        return api_failure('already_complete',
                           _("This table is already marked as complete"))
    if table.detableentry_set.count() == 2:
        table.complete = True
        table.save()
        return api_success()
    try:
        table.make_children()
        return api_success()
    except UnfinishedTableException:
        return api_failure('incomplete_bouts',
                           _('One or more bouts incomplete'))
Beispiel #10
0
def confirm_cull(request, stage: Stage):
    """confirm a cull

    :param request: no additional parameters
    :param stage: Stage of type cull to set
    :return: JSONResponse with either success or an error message
    """
    cull_stage = stage.cullstage_set.first()
    if stage.state == Stage.NOT_STARTED:
        return api_failure('number not set')
    elif stage.state == Stage.READY:
        stage.state = Stage.FINISHED
        stage.save()
        return api_success()
    else:
        return api_failure("stage already complete")
Beispiel #11
0
def add_entry(request, comp):
    """ Manually add a single entry to a competition

        :param request: expecting POST parameters:\n
            :param str name: name of competitor to add
            :param str license_number: license number of the competitor to add
            :param str club_name: name of the club to enter competitor under
            :param int seed: seed of entry being added
            :param optional bool check_in: if true checks in entry at same time
        :param Competition comp: Competition to enter competitor into
        :return:
    """
    if 'seed' in request.POST:
        try:
            seed = int(request.POST['seed'])
        except ValueError:
            return api_failure('seed_parse_error',
                               _('one of the seeds could not be interpreted as a number'))
    else:
        seed = 999
    entry = comp.add_entry(request.POST['license_number'], request.POST['name'], request.POST['club_name'], seed)
    if 'check_in' in request.POST and int(request.POST['check_in']):
        entry.state = Entry.CHECKED_IN
        entry.save()
    return api_success()
Beispiel #12
0
def manage_cull_stage_post(request, stage):
    r_type = request.POST['type']
    if r_type == 'set_cull_level':
        return set_cull_level(request, stage)
    elif r_type == 'confirm_cull':
        return confirm_cull(request, stage)
    else:
        return api_failure('unrecognised request')
Beispiel #13
0
def manage_add_stage_post(request, stage):
    r_type = request.POST['type']
    if r_type == 'add_entries':
        return add_entries(request, stage)
    elif r_type == "confirm_add":
        return confirm_add(stage)
    else:
        return api_failure('unrecognised request')
Beispiel #14
0
def manage_de_stage_post(request, stage):
    r_type = request.POST['type']
    if r_type == 'start_stage':
        return start_stage(request, stage)
    elif r_type == 'finish_stage':
        return finish_stage(request, stage)
    else:
        return api_failure('unrecognised request')
Beispiel #15
0
def do_add_result(request, e1, e2, e1_score, e2_score, e1_victory):
    if e1.against() != e2:
        return api_failure(
            'bad entry pair',
            "these entries aren't fighting each other this round")
    if (e1.entry is None and e1_victory) or (e2.entry is None
                                             and not e1_victory):
        return api_failure('bye_victory', _('Byes cannot win a match'))
    if (e1_victory and e2_score > e1_score) or (not e1_victory
                                                and e2_score < e1_score):
        return api_failure('score victory mismatch')
    e1.victory = e1_victory
    e1.score = e1_score
    e2.victory = not e1_victory
    e2.score = e2_score
    e1.save()
    e2.save()
    return api_success()
Beispiel #16
0
def generate_pools(request, stage):
    pool_stage = stage.poolstage_set.first()
    previous = Stage.objects.get(competition=stage.competition, number=stage.number - 1)
    if stage.state != stage.NOT_STARTED:
        return api_failure("incorrect state",
                           _('this stage has already generated pools'))
    if previous.state not in [Stage.FINISHED, Stage.LOCKED]:
        return api_failure('previous stage not completed yet')
    number = int(request.POST['number_of_pools'])
    entry_count = len(previous.ordered_competitors())
    if entry_count / number >= 3.0 and ceil(entry_count / number) <= MAX_POOL_SIZE:
        pool_stage.start(number)
        stage.state = Stage.READY
        stage.save()
        return api_success()
    else:
        return api_failure("invalid pool size",
                           _('produces pools with less than 3 or more than %(max_pool_size)i fencers') %
                           {'max_pool_size': MAX_POOL_SIZE})
Beispiel #17
0
def manage_pool_stage(request, stage):
    if request.method == "POST":
        r_type = request.POST['type']
        if r_type == 'generate_pools':
            return generate_pools(request, stage)
        elif r_type == "confirm_pools":
            return confirm_pools(request, stage)
        elif r_type == 'finish_stage':
            return finish_stage(request,stage)
        else:
            return api_failure('unrecognised request')
Beispiel #18
0
def confirm_add(stage: Stage):
    """advances a stage from READY -> FINISHED

    :param request: expects type: "confirm_add"
    :param stage: Stage of type add
    :return: JSONResponse with either success or an error message
    """
    if stage.state != Stage.READY:
        return api_failure("incorrect state", _("Stage not in READY state"))
    stage.state = Stage.FINISHED
    stage.save()
    return api_success()
Beispiel #19
0
def de_table(request, table_id):
    table = get_object_or_404(DeTable, pk=table_id)
    if request.method == "POST":
        rtype = request.POST['type']
        if rtype == 'add_result':
            return add_result(request, table)
        elif rtype == 'table_complete':
            return mark_table_complete(request, table)
        else:
            return api_failure('unrecognised request')
    else:
        return get_bouts(table)
Beispiel #20
0
def entry_csv(request, comp):
    """adds entries to a competition and create an add stage

    :param request: expecting POST parameters:\n
        :param File file: a csv file following the format:
            name, club name, license number, seed
    :param Competition comp: competition to add entries to
    :return:
    """
    expected_columns = 4
    file = request.FILES['file']
    data = [row for row in csv.reader(file.read().decode("utf-8").splitlines())]
    if not data or any(map(lambda x: len(x) != expected_columns, data)):
        return api_failure('row_column_error',
                           _('Unexpected number of rows/columns in uploaded file'))
    try:
        data = [(n, cn, ln, int(seed)) for (n, cn, ln, seed) in data]
    except ValueError:
        return api_failure('seed_parse_error',
                           _('one of the seeds could not be interpreted as a number'))
    fields = [Competitor._meta.get_field('name'),
              Club._meta.get_field('name'),
              Competitor._meta.get_field('license_number')]
    for index, field in enumerate(fields):
        if any(map(lambda x: len(x[index]) > field.max_length, data)):
            return api_failure('oversize_field_error',
                               _('a %(model_name)s %(field_name)s was longer than %(max_len)i') %
                               {'model_name': fields[index].model.__name__,
                                'field_name': fields[index].name,
                                'max_len': fields[index].max_length})
    if comp.stage_set.exists():
        number = comp.stage_set.latest().number + 1
    else:
        number = 0
    add_stage = comp.stage_set.create(type=Stage.ADD, number=number)
    for new_entry in data:
        comp.add_entry(new_entry[2], new_entry[0], new_entry[1], new_entry[3])
    out = {'success': True,
           'added_count': len(data)}
    return JsonResponse(out)
Beispiel #21
0
def delete_stage(request, comp):
    """delete a stage from the competition

    :param request: expecting POST parameters:\n
        :param int id: id of the stage to delete
    :param Competition comp: competition to delete stage from
    :return:
    """
    stage_id = request.POST['id']
    stage = get_object_or_404(Stage, competition=comp, pk=stage_id)
    if stage.deletable():
        number = stage.number
        if stage.delete():
            stages = comp.stage_set.filter(number__gt=number).order_by('number')
            for stage in stages:
                stage.number -= 1
                stage.save()
            return api_success()
        else:
            return api_failure('deletion_failure', _('Failed to delete stage'))
    else:
        return api_failure('stage_undeletable', 'Cannot delete this stage')
Beispiel #22
0
def check_in(request, comp):
    """ Check in a single entry

    :param request: expecting POST parameters:\n
        :param int id: id of the stage to delete
    :param comp: Competition to check in entry for
    :return:
    """
    entry = get_object_or_404(Entry, pk=request.POST['id'], competition=comp)
    if entry.state != Entry.NOT_CHECKED_IN:
        return api_failure('already_checked_in', _('That entry has already checked in'))
    entry.state = Entry.CHECKED_IN
    entry.save()
    return api_success()
Beispiel #23
0
def organisation(request, org_id):
    org = get_object_or_404(Organisation, pk=org_id)
    if request.method == "POST":
        r_type = request.POST['type']
        if r_type == "join_request":
            return join_organisation(request, org)
        elif r_type == "accept_application":
            return accept_application(request, org)
    elif request.method == "GET":
        r_type = request.GET['type']
        if r_type == "autocomplete_competitor":
            return auto_complete_competitor(request, org)

    return api_failure('unrecognised request', _('Unrecognised request'))
Beispiel #24
0
def handle_post(request, comp):
    r_type = request.POST['type']
    if r_type == "add_stage":
        return add_stage(request, comp)
    elif r_type == "delete_stage":
        return delete_stage(request, comp)
    elif r_type == "entry_csv":
        return entry_csv(request, comp)
    elif r_type == "check_in_all":
        return check_in_all(comp)
    elif r_type == "check_in":
        return check_in(request, comp)
    elif r_type == "add_entry":
        return add_entry(request, comp)
    else:
        out = {'success': False,
               'reason': 'post type not recognised'}
        return api_failure('unrecognised request', _('Unrecognised request'))
Beispiel #25
0
def accept_application(request, org):
    """Allows an organisation manager to accept applications to join an org

    :param request: expecting POST parameters:\n
        :param int user_id: id of the user who's application is being accepted
    :param Organisation org: organisation the application is for
    """
    user_id = request.POST['user_id']
    membership = get_object_or_404(OrganisationMembership,
                                   user_id=user_id,
                                   organisation=org)
    if membership.state == OrganisationMembership.APPLICANT:
        membership.state = OrganisationMembership.DT
        membership.save()
        return api_success()
    else:
        return api_failure("already_full_member",
                           _("User is already a full member"))
Beispiel #26
0
def update_pool(request, pool):
    """handles POST requests to update pools"""
    if pool.stage.stage.state != Stage.STARTED:
        return JsonResponse({'success': False, 'reason': 'stage not currently running'})
    else:
        r_type = request.POST['type']
        if r_type == 'bout_result':
            e1 = pool.poolentry_set.get(pk=request.POST['entry_1'])
            e2 = pool.poolentry_set.get(pk=request.POST['entry_2'])
            e1_victory = bool(int(request.POST['e1_victory']))
            e1_score = int(request.POST['e1_score'])
            e2_score = int(request.POST['e2_score'])
            if (e1_victory and e2_score > e1_score) or (not e1_victory and e2_score < e1_score):
                return api_failure('score victory mismatch')
            e1.fencerA_bout_set.update_or_create(fencerB=e2, defaults={'scoreA': e1_score,
                                                                       'victoryA': e1_victory})
            e2.fencerA_bout_set.update_or_create(fencerB=e1, defaults={'scoreA': e2_score,
                                                                       'victoryA': not e1_victory})
            return JsonResponse({'success': True, 'pool_complete': pool.complete()})
    return JsonResponse({'success': False, 'reason': 'unable to understand post'})
Beispiel #27
0
def competition(request, comp_id):
    comp = get_object_or_404(Competition, pk=comp_id)
    if request.method == "POST":
        return handle_post(request, comp)
    else:
        return api_failure('not implemented')