Exemplo n.º 1
0
def delete_process(request, process_id):
    """Deletes an existing physical process.

    :param request: the current HTTP Request object
    :param process_id: the process's ID

    :type request: HttpRequest
    :type process_id: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    process = get_object_or_404(Process,
                                pk=int_or_zero(process_id)).actual_instance
    affected_objects = permissions.assert_can_delete_physical_process(
        request.user, process)
    for instance in affected_objects:
        if isinstance(instance, models.Sample):
            utils.Reporter(request.user).report_deleted_sample(instance)
        elif isinstance(instance, models.Process):
            utils.Reporter(request.user).report_deleted_process(instance)
    success_message = _(
        "Process {process} was successfully deleted in the database.").format(
            process=process)
    process.delete()
    return utils.successful_response(request, success_message)
Exemplo n.º 2
0
def delete_process_confirmation(request, process_id):
    """View for confirming that you really want to delete the given process.
    Typically, it is visited by clicking on an icon.

    :param request: the current HTTP Request object
    :param process_id: the ID of the process

    :type request: HttpRequest
    :type process_id: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    process = get_object_or_404(Process,
                                pk=int_or_zero(process_id)).actual_instance
    affected_objects = permissions.assert_can_delete_physical_process(
        request.user, process)
    digested_affected_objects = {}
    for instance in affected_objects:
        try:
            class_name = instance.__class__._meta.verbose_name_plural.title()
        except AttributeError:
            class_name = capfirst(_("miscellaneous"))
        digested_affected_objects.setdefault(class_name, set()).add(instance)
    return render(
        request, "samples/delete_process_confirmation.html", {
            "title": _("Delete process “{process}”").format(process=process),
            "process": process,
            "affected_objects": digested_affected_objects
        })
Exemplo n.º 3
0
def fold_main_menu_element(request):
    """Fold a single topic or sample series from the main menu.

    :param request: The current HTTP Request object.  It must contain the topic
        ID or sample series name.

    :type request: HttpRequest

    :return:
      True if the topic or sample series is now folded else False

    :rtype: HttpResponse
    """
    def fold_element(element_id, folded_elements):
        folded_elements = json.loads(folded_elements)
        if element_id in folded_elements:
            folded_elements.remove(element_id)
            is_folded = False
        else:
            folded_elements.append(element_id)
            is_folded = True
        folded_elements = json.dumps(folded_elements)
        return is_folded, folded_elements

    element_id = int_or_zero(request.POST["element_id"])

    if not element_id:
        element_id = request.POST["element_id"]
        element_is_folded, request.user.samples_user_details.folded_series = \
            fold_element(element_id, request.user.samples_user_details.folded_series)
    else:
        element_is_folded, request.user.samples_user_details.folded_topics = \
            fold_element(element_id, request.user.samples_user_details.folded_topics)
    request.user.samples_user_details.save()
    return respond_in_json(element_is_folded)
Exemplo n.º 4
0
def fold_process(request, sample_id):
    """Fold a single process in one sample data sheet. The new behavior is also saved.

    :param request: The current HTTP Request object.  It must contain the process
        ID of the process which behavior should be changed.
    :param sample_id: The sample ID represent the data sheet where the process has to be changed.

    :type request: HttpRequest
    :type sample_id: unicode

    :return:
      True when the process is now folded else False.

    :rtype: HttpResponse
    """
    process_id = int_or_zero(request.POST["process_id"])
    folded_process_classes = ContentType.objects.filter(
        dont_show_to_user=request.user.samples_user_details)
    folded_processes = json.loads(
        request.user.samples_user_details.folded_processes)
    exceptional_processes = folded_processes.setdefault(sample_id, [])
    is_folded = _is_folded(process_id,
                           folded_process_classes,
                           exceptional_processes,
                           switch=True)
    request.user.samples_user_details.folded_processes = json.dumps(
        folded_processes)
    request.user.samples_user_details.save()
    return respond_in_json(is_folded)
Exemplo n.º 5
0
def cancel_match(request, id_):
    match = get_object_or_404(models.Match, pk=int_or_zero(id_)) if id_ else None
    if match and match.reporter != request.user:
        raise JSONRequestException(3005, _("You must be the original reporter of this match."))
    if match.finished:
        raise JSONRequestException(3003, _("A finished match can't be canceled."))
    match.delete()
    return respond_in_json(True)
Exemplo n.º 6
0
def edit(request, id):
    """View for changing the members of a particular topic, and to set the
    restriction status.  This is only allowed to heads of institute groups and
    topic managers.

    :param request: the current HTTP Request object
    :param id: the id of the topic

    :type request: HttpRequest
    :type name: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    topic = get_object_or_404(Topic, id=int_or_zero(id), parent_topic=None)
    permissions.assert_can_edit_topic(request.user, topic)
    if request.method == "POST":
        edit_topic_form = EditTopicForm(request.user, topic, request.POST)
        added_members = []
        removed_members = []
        if edit_topic_form.is_valid():
            old_manager = topic.manager
            new_manager = edit_topic_form.cleaned_data["topic_manager"]
            topic.manager = new_manager
            old_members = list(topic.members.all())
            new_members = edit_topic_form.cleaned_data["members"] + [new_manager]
            topic.members = new_members
            topic.confidential = edit_topic_form.cleaned_data["confidential"]
            topic.save()
            if old_manager != new_manager:
                if not old_manager.managed_topics.all():
                    old_manager.user_permissions.remove(PermissionsModels.topic_manager_permission)
                if not permissions.has_permission_to_edit_users_topics(new_manager):
                    new_manager.user_permissions.add(PermissionsModels.topic_manager_permission)
            for user in new_members:
                if user not in old_members:
                    added_members.append(user)
                    topic.auto_adders.add(user.samples_user_details)
            for user in old_members:
                if user not in new_members:
                    removed_members.append(user)
                    topic.auto_adders.remove(user.samples_user_details)
            if added_members:
                utils.Reporter(request.user).report_changed_topic_membership(added_members, topic, "added")
            if removed_members:
                utils.Reporter(request.user).report_changed_topic_membership(removed_members, topic, "removed")
            return utils.successful_response(
                request, _("Members of topic “{name}” were successfully updated.").format(name=topic.name))
    else:
        edit_topic_form = \
            EditTopicForm(request.user, topic, initial={"members": topic.members.values_list("pk", flat=True),
                                                        "topic_manager": topic.manager.pk})
    return render(request, "samples/edit_topic.html", {"title": _("Change topic memberships of “{0}”").format(topic.name),
                                                       "edit_topic": edit_topic_form})
Exemplo n.º 7
0
def edit(request, id):
    """View for changing the members of a particular topic, and to set the
    restriction status.  This is only allowed to heads of institute groups and
    topic managers.

    :param request: the current HTTP Request object
    :param id: the id of the topic

    :type request: HttpRequest
    :type name: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    topic = get_object_or_404(Topic, id=int_or_zero(id), parent_topic=None)
    permissions.assert_can_edit_topic(request.user, topic)
    if request.method == "POST":
        edit_topic_form = EditTopicForm(request.user, topic, request.POST)
        added_members = []
        removed_members = []
        if edit_topic_form.is_valid():
            old_manager = topic.manager
            new_manager = edit_topic_form.cleaned_data["topic_manager"]
            topic.manager = new_manager
            old_members = list(topic.members.all())
            new_members = edit_topic_form.cleaned_data["members"] + [new_manager]
            topic.members = new_members
            topic.confidential = edit_topic_form.cleaned_data["confidential"]
            topic.save()
            if old_manager != new_manager:
                if not old_manager.managed_topics.all():
                    old_manager.user_permissions.remove(PermissionsModels.topic_manager_permission)
                if not permissions.has_permission_to_edit_users_topics(new_manager):
                    new_manager.user_permissions.add(PermissionsModels.topic_manager_permission)
            for user in new_members:
                if user not in old_members:
                    added_members.append(user)
                    topic.auto_adders.add(user.samples_user_details)
            for user in old_members:
                if user not in new_members:
                    removed_members.append(user)
                    topic.auto_adders.remove(user.samples_user_details)
            if added_members:
                utils.Reporter(request.user).report_changed_topic_membership(added_members, topic, "added")
            if removed_members:
                utils.Reporter(request.user).report_changed_topic_membership(removed_members, topic, "removed")
            return utils.successful_response(
                request, _("Members of topic “{name}” were successfully updated.").format(name=topic.name))
    else:
        edit_topic_form = \
            EditTopicForm(request.user, topic, initial={"members": topic.members.values_list("pk", flat=True),
                                                        "topic_manager": topic.manager.pk})
    return render(request, "samples/edit_topic.html", {"title": _("Change topic memberships of “{0}”").format(topic.name),
                                                       "edit_topic": edit_topic_form})
Exemplo n.º 8
0
def cancel_match(request, id_):
    match = get_object_or_404(models.Match,
                              pk=int_or_zero(id_)) if id_ else None
    if match and match.reporter != request.user:
        raise JSONRequestException(
            3005, "You must be the original reporter of this match.")
    if match.finished:
        raise JSONRequestException(3003, "A finished match can't be canceled.")
    match.delete()
    return respond_in_json(True)
Exemplo n.º 9
0
def split_and_rename_after_deposition(request, deposition_number):
    """View for renaming and/or splitting samples immediately after they have
    been deposited in the same run.

    Optionally, you can give query string parameters of the form
    ``new-name-21=super`` where 21 is the sample ID and “super” is the
    suggested new name of this sample.

    :param request: the current HTTP Request object
    :param deposition_number: the number of the deposition after which samples
        should be split and/or renamed

    :type request: HttpRequest
    :type deposition_number: unicode

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    deposition = get_object_or_404(models.Deposition, number=deposition_number).actual_instance
    permissions.assert_can_edit_physical_process(request.user, deposition)
    if not deposition.finished:
        raise Http404("This deposition is not finished yet.")
    if deposition.split_done:
        raise Http404("You can use the split and rename function only once after a deposition.")
    remote_client = is_json_requested(request)
    if request.POST:
        original_data_forms, new_name_form_lists, global_new_data_form = \
            forms_from_post_data(request.user, request.POST, deposition, remote_client)
        all_valid = is_all_valid(original_data_forms, new_name_form_lists, global_new_data_form)
        structure_changed = change_structure(request.user, original_data_forms, new_name_form_lists)
        referentially_valid = is_referentially_valid(original_data_forms, new_name_form_lists, deposition)
        if all_valid and referentially_valid and not structure_changed:
            sample_splits = save_to_database(original_data_forms, new_name_form_lists, global_new_data_form, deposition)
            for sample_split in sample_splits:
                utils.Reporter(request.user).report_sample_split(sample_split, sample_completely_split=True)
            return utils.successful_response(request, _("Samples were successfully split and/or renamed."),
                                             json_response=True)
    else:
        new_names = dict((int_or_zero(key[len("new-name-"):]), new_name)
                         for key, new_name in request.GET.items() if key.startswith("new-name-"))
        new_names.pop(0, None)
        original_data_forms, new_name_form_lists, global_new_data_form = \
            forms_from_database(request.user, deposition, remote_client, new_names)
    return render(request, "samples/split_after_deposition.html",
                  {"title": _("Bulk sample rename for {deposition}").format(deposition=deposition),
                   "samples": list(zip(original_data_forms, new_name_form_lists)),
                   "new_sample_data": global_new_data_form})
Exemplo n.º 10
0
def search(request):
    """View for searching for samples.  The rule is: Everyone can see the
    *names* (not the data sheets) of all samples, unless they are in a
    confidential topic, unless the user is a member in that topic, its
    currently responsible person, or you have a clearance for the sample.

    A POST request on this URL will add samples to the “My Samples” list.
    *All* search parameters are in the query string, so if you just want to
    search, this is a GET requets.  Therefore, this view has two submit
    buttons.

    :param request: the current HTTP Request object

    :type request: HttpRequest

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    too_many_results = False
    base_query = utils.restricted_samples_query(request.user)
    search_samples_form = SearchSamplesForm(request.GET)
    found_samples = []
    if search_samples_form.is_valid():
        name_pattern = search_samples_form.cleaned_data["name_pattern"]
        if name_pattern:
            if search_samples_form.cleaned_data["aliases"]:
                found_samples = base_query.filter(Q(name__icontains=name_pattern) | Q(aliases__name__icontains=name_pattern))
            else:
                found_samples = base_query.filter(name__icontains=name_pattern)
            too_many_results = found_samples.count() > max_results
            found_samples = found_samples[:max_results] if too_many_results else found_samples
    my_samples = request.user.my_samples.all()
    if request.method == "POST":
        sample_ids = set(int_or_zero(key.partition("-")[0]) for key, value in request.POST.items()
                         if value == "on")
        samples = base_query.in_bulk(sample_ids).values()
        request.user.my_samples.add(*samples)
    add_to_my_samples_forms = [AddToMySamplesForm(prefix=str(sample.pk)) if sample not in my_samples else None
                               for sample in found_samples]
    return render(request, "samples/search_samples.html", {"title": _("Search for sample"),
                                                           "search_samples": search_samples_form,
                                                           "found_samples": list(zip(found_samples, add_to_my_samples_forms)),
                                                           "too_many_results": too_many_results,
                                                           "max_results": max_results})
Exemplo n.º 11
0
def fold_process(request, sample_id):
    """Fold a single process in one sample data sheet. The new behavior is also saved.

    :param request: The current HTTP Request object.  It must contain the process
        ID of the process which behavior should be changed.
    :param sample_id: The sample ID represent the data sheet where the process has to be changed.

    :type request: HttpRequest
    :type sample_id: unicode

    :return:
      True when the process is now folded else False.

    :rtype: HttpResponse
    """
    process_id = int_or_zero(request.POST["process_id"])
    folded_process_classes = ContentType.objects.filter(dont_show_to_user=request.user.samples_user_details)
    folded_processes = json.loads(request.user.samples_user_details.folded_processes)
    exceptional_processes = folded_processes.setdefault(sample_id, [])
    is_folded = _is_folded(process_id, folded_process_classes, exceptional_processes, switch=True)
    request.user.samples_user_details.folded_processes = json.dumps(folded_processes)
    request.user.samples_user_details.save()
    return respond_in_json(is_folded)
Exemplo n.º 12
0
def fold_main_menu_element(request):
    """Fold a single topic or sample series from the main menu.

    :param request: The current HTTP Request object.  It must contain the the topic ID or
        sample series name.
    :param element_id: The id from the topic or sample series

    :type request: HttpRequest

    :return:
     True when the topic or sample series is now folded else False

    :rtype: HttpResponse
    """
    def fold_element(element_id, folded_elements):
        folded_elements = json.loads(folded_elements)
        if element_id in folded_elements:
            folded_elements.remove(element_id)
            is_folded = False
        else:
            folded_elements.append(element_id)
            is_folded = True
        folded_elements = json.dumps(folded_elements)
        return is_folded, folded_elements

    element_id = int_or_zero(request.POST["element_id"])

    if not element_id:
        element_id = request.POST["element_id"]
        element_is_folded, request.user.samples_user_details.folded_series = \
            fold_element(element_id, request.user.samples_user_details.folded_series)
    else:
        element_is_folded, request.user.samples_user_details.folded_topics = \
            fold_element(element_id, request.user.samples_user_details.folded_topics)
    request.user.samples_user_details.save()
    return respond_in_json(element_is_folded)
Exemplo n.º 13
0
def edit_match(request, id_=None):
    match = get_object_or_404(models.Match,
                              pk=int_or_zero(id_)) if id_ else None
    if match and match.reporter != request.user:
        raise JSONRequestException(
            3005, _("You must be the original reporter of this match."))
    try:
        if not match:
            player_a_1 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_a_1"])
            player_a_2 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_a_2"])
            player_b_1 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_b_1"])
            player_b_2 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_b_2"])
        goals_a = int(request.POST["goals_a"])
        goals_b = int(request.POST["goals_b"])
        seconds = float(request.POST["seconds"])
        finished = request.POST.get("finished") == "on"
        timestamp = django.utils.timezone.make_aware(
            datetime.datetime.strptime(request.POST["timestamp"],
                                       "%Y-%m-%d %H:%M:%S"))
    except KeyError as error:
        raise JSONRequestException(3, error.args[0])
    except ValueError as error:
        raise JSONRequestException(5, error.args[0])
    if not match:
        if player_a_1 == player_a_2 and player_b_1 != player_b_2 or player_a_1 != player_a_2 and player_b_1 == player_b_2:
            raise JSONRequestException(
                3000, _("Matches with three players can't be processed."))
        if player_a_1 == player_a_2 == player_b_1 == player_b_2:
            raise JSONRequestException(3001,
                                       _("All players are the same person."))
        models.Match.objects.filter(finished=False,
                                    reporter=request.user).delete()
    else:
        if match.finished:
            raise JSONRequestException(
                3003, _("A finished match can't be edited anymore."))
        player_a_1 = match.player_a_1
        player_a_2 = match.player_a_2
        player_b_1 = match.player_b_1
        player_b_2 = match.player_b_2
    try:
        if finished and models.KickerNumber.objects.latest(
        ).timestamp > timestamp:
            raise JSONRequestException(
                3002,
                _("This match is older than the most recent kicker numbers."))
    except models.KickerNumber.DoesNotExist:
        pass
    if match:
        match.player_a_1 = player_a_1
        match.player_a_2 = player_a_2
        match.player_b_1 = player_b_1
        match.player_b_2 = player_b_2
        match.goals_a = goals_a
        match.goals_b = goals_b
        match.timestamp = timestamp
        match.finished = finished
        match.seconds = seconds
        match.save()
    else:
        match = models.Match.objects.create(player_a_1=player_a_1,
                                            player_a_2=player_a_2,
                                            player_b_1=player_b_1,
                                            player_b_2=player_b_2,
                                            goals_a=goals_a,
                                            goals_b=goals_b,
                                            timestamp=timestamp,
                                            finished=finished,
                                            seconds=seconds,
                                            reporter=request.user)
    if match.finished:
        if seconds <= 0:
            raise JSONRequestException(5, _("Seconds must be positive."))
        match_result = MatchResult(match)
        match_result.add_kicker_numbers()
        match_result.add_stock_values()
    else:
        match.seconds = max(1, match.seconds)
        match_result = MatchResult(match)
    return respond_in_json((match.pk, match_result.expected_goal_difference,
                            match_result.estimated_win_team_1))
Exemplo n.º 14
0
def add_samples_to_database(add_samples_form, user):
    """Create the new samples and add them to the database.  This routine consists
    of two parts: First, it tries to find a consecutive block of provisional
    sample names.  Then, in actuall creates the samples.

    :param add_samples_form: the form with the samples' common data, including
        the substrate
    :param user: the current user

    :type add_samples_form: `AddSamplesForm`
    :type user: django.contrib.auth.models.User

    :return:
      the names of the new samples

    :rtype: list of unicode
    """
    cleaned_data = add_samples_form.cleaned_data
    cleaning_number = cleaned_data.get("cleaning_number")
    substrate = institute_models.Substrate.objects.create(
        operator=user,
        timestamp=cleaned_data["timestamp"],
        material=cleaned_data["substrate"],
        comments=cleaned_data["substrate_comments"],
        external_operator=cleaned_data["substrate_originator"])
    inaccuracy = cleaned_data["timestamp_inaccuracy"]
    if inaccuracy:
        substrate.timestamp_inaccuracy = inaccuracy
        substrate.save()
    provisional_sample_names = \
        models.Sample.objects.filter(name__startswith="*").values_list("name", flat=True)
    occupied_provisional_numbers = [
        int(name[1:]) for name in provisional_sample_names
    ]
    occupied_provisional_numbers.sort()
    occupied_provisional_numbers.insert(0, 0)
    number_of_samples = cleaned_data["number_of_samples"]
    if add_samples_form.cleaned_data.get("rename") == "cleaning":
        subnumbers = [
            int_or_zero(name.rpartition("-")[2])
            for name in models.Sample.objects.filter(
                name__startswith=cleaning_number).values_list("name",
                                                              flat=True)
        ]
        starting_number = max(subnumbers) + 1 if subnumbers else 1
        names = [
            cleaning_number + "-{0:02}".format(i)
            for i in range(starting_number, starting_number +
                           number_of_samples)
        ]
    else:
        for i in range(len(occupied_provisional_numbers) - 1):
            if occupied_provisional_numbers[i +
                                            1] - occupied_provisional_numbers[
                                                i] - 1 >= number_of_samples:
                starting_number = occupied_provisional_numbers[i] + 1
                break
        else:
            starting_number = occupied_provisional_numbers[-1] + 1
        names = [
            "*{0:05}".format(i)
            for i in range(starting_number, starting_number +
                           number_of_samples)
        ]
    new_names = []
    samples = []
    current_location, purpose, tags, topic = cleaned_data["current_location"], cleaned_data["purpose"], \
        cleaned_data["tags"], cleaned_data["topic"]
    for new_name in names:
        sample = models.Sample.objects.create(
            name=new_name,
            current_location=current_location,
            currently_responsible_person=user,
            purpose=purpose,
            tags=tags,
            topic=topic)
        samples.append(sample)
        sample.processes.add(substrate)
        if cleaning_number:
            models.SampleAlias.objects.create(name=cleaning_number,
                                              sample=sample)
        sample.watchers.add(user)
        if topic:
            for watcher in (user_details.user
                            for user_details in topic.auto_adders.all()):
                watcher.my_samples.add(sample)
        new_names.append(six.text_type(sample))
    return new_names, samples
Exemplo n.º 15
0
def add_samples_to_database(add_samples_form, user):
    """Create the new samples and add them to the database.  This routine consists
    of two parts: First, it tries to find a consecutive block of provisional
    sample names.  Then, in actuall creates the samples.

    :param add_samples_form: the form with the samples' common data, including
        the substrate
    :param user: the current user

    :type add_samples_form: `AddSamplesForm`
    :type user: django.contrib.auth.models.User

    :return:
      the names of the new samples

    :rtype: list of unicode
    """
    cleaned_data = add_samples_form.cleaned_data
    cleaning_number = cleaned_data.get("cleaning_number")
    substrate = institute_models.Substrate.objects.create(operator=user, timestamp=cleaned_data["timestamp"],
                                                    material=cleaned_data["substrate"],
                                                    comments=cleaned_data["substrate_comments"],
                                                    external_operator=cleaned_data["substrate_originator"])
    inaccuracy = cleaned_data["timestamp_inaccuracy"]
    if inaccuracy:
        substrate.timestamp_inaccuracy = inaccuracy
        substrate.save()
    provisional_sample_names = \
        models.Sample.objects.filter(name__startswith="*").values_list("name", flat=True)
    occupied_provisional_numbers = [int(name[1:]) for name in provisional_sample_names]
    occupied_provisional_numbers.sort()
    occupied_provisional_numbers.insert(0, 0)
    number_of_samples = cleaned_data["number_of_samples"]
    if add_samples_form.cleaned_data.get("rename") == "cleaning":
        subnumbers = [int_or_zero(name.rpartition("-")[2]) for name in
                      models.Sample.objects.filter(name__startswith=cleaning_number).values_list("name", flat=True)]
        starting_number = max(subnumbers) + 1 if subnumbers else 1
        names = [cleaning_number + "-{0:02}".format(i) for i in range(starting_number, starting_number + number_of_samples)]
    else:
        for i in range(len(occupied_provisional_numbers) - 1):
            if occupied_provisional_numbers[i + 1] - occupied_provisional_numbers[i] - 1 >= number_of_samples:
                starting_number = occupied_provisional_numbers[i] + 1
                break
        else:
            starting_number = occupied_provisional_numbers[-1] + 1
        names = ["*{0:05}".format(i) for i in range(starting_number, starting_number + number_of_samples)]
    new_names = []
    samples = []
    current_location, purpose, tags, topic = cleaned_data["current_location"], cleaned_data["purpose"], \
        cleaned_data["tags"], cleaned_data["topic"]
    for new_name in names:
        sample = models.Sample.objects.create(name=new_name, current_location=current_location,
                                              currently_responsible_person=user, purpose=purpose, tags=tags, topic=topic)
        samples.append(sample)
        sample.processes.add(substrate)
        if cleaning_number:
            models.SampleAlias.objects.create(name=cleaning_number, sample=sample)
        sample.watchers.add(user)
        if topic:
            for watcher in (user_details.user for user_details in topic.auto_adders.all()):
                watcher.my_samples.add(sample)
        new_names.append(six.text_type(sample))
    return new_names, samples
Exemplo n.º 16
0
def edit_match(request, id_=None):
    match = get_object_or_404(models.Match,
                              pk=int_or_zero(id_)) if id_ else None
    if match and match.reporter != request.user:
        raise JSONRequestException(
            3005, "You must be the original reporter of this match.")
    try:
        if not match:
            player_a_1 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_a_1"])
            player_a_2 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_a_2"])
            player_b_1 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_b_1"])
            player_b_2 = get_object_or_404(django.contrib.auth.models.User,
                                           username=request.POST["player_b_2"])
        goals_a = int(request.POST["goals_a"])
        goals_b = int(request.POST["goals_b"])
        seconds = float(request.POST["seconds"])
        finished = request.POST.get("finished") == "on"
        timestamp = datetime.datetime.strptime(request.POST["timestamp"],
                                               "%Y-%m-%d %H:%M:%S")
    except KeyError as error:
        raise JSONRequestException(3, error.args[0])
    except ValueError as error:
        raise JSONRequestException(5, error.args[0])
    if not match:
        if player_a_1 == player_a_2 and player_b_1 != player_b_2 or player_a_1 != player_a_2 and player_b_1 == player_b_2:
            raise JSONRequestException(
                3000, "Games with three players can't be processed.")
        if player_a_1 == player_a_2 == player_b_1 == player_b_2:
            raise JSONRequestException(3001,
                                       "All players are the same person.")
        unfinished_matches = models.Match.objects.filter(finished=False)
        if unfinished_matches.exists():
            if unfinished_matches.exclude(reporter=request.user).exists():
                raise JSONRequestException(
                    3004,
                    "You can't add a match if another one of another reporter is not yet finished."
                )
            for match in unfinished_matches.all():
                match.delete()
    else:
        if match.finished:
            raise JSONRequestException(
                3003, "A finished match can't be edited anymore.")
        player_a_1 = match.player_a_1
        player_a_2 = match.player_a_2
        player_b_1 = match.player_b_1
        player_b_2 = match.player_b_2
    try:
        seconds_since_most_recent = (
            timestamp - models.Match.objects.latest("timestamp").timestamp
        ).total_seconds()
        if seconds_since_most_recent <= 0:
            if seconds_since_most_recent < -10:
                raise JSONRequestException(
                    3002, "This game is not the most recent one.")
            else:
                timestamp = models.Match.objects.latest(
                    "timestamp").timestamp + datetime.timedelta(seconds=1)
    except models.Match.DoesNotExist:
        pass
    if match:
        match.player_a_1 = player_a_1
        match.player_a_2 = player_a_2
        match.player_b_1 = player_b_1
        match.player_b_2 = player_b_2
        match.goals_a = goals_a
        match.goals_b = goals_b
        match.timestamp = timestamp
        match.finished = finished
        match.seconds = seconds
        match.save()
    else:
        match = models.Match.objects.create(player_a_1=player_a_1,
                                            player_a_2=player_a_2,
                                            player_b_1=player_b_1,
                                            player_b_2=player_b_2,
                                            goals_a=goals_a,
                                            goals_b=goals_b,
                                            timestamp=timestamp,
                                            finished=finished,
                                            seconds=seconds,
                                            reporter=request.user)
    if match.finished:
        if seconds <= 0:
            raise JSONRequestException(5, "Seconds must be positive.")
        match_result = MatchResult(match)
        match_result.add_kicker_numbers()
        match_result.add_stock_values()
    else:
        match.seconds = max(1, match.seconds)
        match_result = MatchResult(match)
    return respond_in_json((match.pk, match_result.expected_goal_difference,
                            match_result.estimated_win_team_1))
Exemplo n.º 17
0
 def clean_number_of_layers_to_add(self):
     return int_or_zero(self.cleaned_data["number_of_layers_to_add"])
Exemplo n.º 18
0
 def clean_number_of_layers_to_add(self):
     return int_or_zero(self.cleaned_data["number_of_layers_to_add"])
Exemplo n.º 19
0
def edit_match(request, id_=None):
    match = get_object_or_404(models.Match, pk=int_or_zero(id_)) if id_ else None
    if match and match.reporter != request.user:
        raise JSONRequestException(3005, _("You must be the original reporter of this match."))
    try:
        if not match:
            player_a_1 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_a_1"])
            player_a_2 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_a_2"])
            player_b_1 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_b_1"])
            player_b_2 = get_object_or_404(django.contrib.auth.models.User, username=request.POST["player_b_2"])
        goals_a = int(request.POST["goals_a"])
        goals_b = int(request.POST["goals_b"])
        seconds = float(request.POST["seconds"])
        finished = request.POST.get("finished") == "on"
        timestamp = datetime.datetime.strptime(request.POST["timestamp"], "%Y-%m-%d %H:%M:%S")
    except KeyError as error:
        raise JSONRequestException(3, error.args[0])
    except ValueError as error:
        raise JSONRequestException(5, error.args[0])
    if not match:
        if player_a_1 == player_a_2 and player_b_1 != player_b_2 or player_a_1 != player_a_2 and player_b_1 == player_b_2:
            raise JSONRequestException(3000, _("Matches with three players can't be processed."))
        if player_a_1 == player_a_2 == player_b_1 == player_b_2:
            raise JSONRequestException(3001, _("All players are the same person."))
        models.Match.objects.filter(finished=False, reporter=request.user).delete()
    else:
        if match.finished:
            raise JSONRequestException(3003, _("A finished match can't be edited anymore."))
        player_a_1 = match.player_a_1
        player_a_2 = match.player_a_2
        player_b_1 = match.player_b_1
        player_b_2 = match.player_b_2
    try:
        if finished and models.KickerNumber.objects.latest().timestamp > timestamp:
            raise JSONRequestException(3002, _("This match is older than the most recent kicker numbers."))
    except models.KickerNumber.DoesNotExist:
        pass
    if match:
        match.player_a_1 = player_a_1
        match.player_a_2 = player_a_2
        match.player_b_1 = player_b_1
        match.player_b_2 = player_b_2
        match.goals_a = goals_a
        match.goals_b = goals_b
        match.timestamp = timestamp
        match.finished = finished
        match.seconds = seconds
        match.save()
    else:
        match = models.Match.objects.create(
            player_a_1=player_a_1, player_a_2=player_a_2, player_b_1=player_b_1, player_b_2=player_b_2,
            goals_a=goals_a, goals_b=goals_b, timestamp=timestamp, finished=finished, seconds=seconds,
            reporter=request.user)
    if match.finished:
        if seconds <= 0:
            raise JSONRequestException(5, _("Seconds must be positive."))
        match_result = MatchResult(match)
        match_result.add_kicker_numbers()
        match_result.add_stock_values()
    else:
        match.seconds = max(1, match.seconds)
        match_result = MatchResult(match)
    return respond_in_json((match.pk, match_result.expected_goal_difference, match_result.estimated_win_team_1))
Exemplo n.º 20
0
def advanced_search(request):
    """View for searching for samples, sample series, physical processes, and
    results.  The visibility rules of the search results are the same as for
    the sample search.  Additionally, you can only see sample series you are
    the currently responsible person of or that are in one of your topics.

    A POST request on this URL will add samples to the “My Samples” list.
    *All* search parameters are in the query string, so if you just want to
    search, this is a GET requets.  Therefore, this view has two submit
    buttons.

    :param request: the current HTTP Request object

    :type request: HttpRequest

    :return:
      the HTTP response object

    :rtype: HttpResponse
    """
    model_list = [model for model in jb_common.search.get_all_searchable_models() if hasattr(model, "get_absolute_url")]
    search_tree = None
    results, add_forms = [], []
    too_many_results = False
    root_form = jb_common.search.SearchModelForm(model_list, request.GET)
    search_performed = False
    no_permission_message = None
    _search_parameters_hash = hashlib.sha1(json.dumps(sorted(dict((key, value) for key, value in request.GET.items()
                                    if not "__" in key and key != "_search_parameters_hash").items())).encode("utf-8")).hexdigest()
    column_groups_form = columns_form = table = switch_row_forms = old_data_form = None
    if root_form.is_valid() and root_form.cleaned_data["_model"]:
        search_tree = get_all_models()[root_form.cleaned_data["_model"]].get_search_tree_node()
        parse_tree = root_form.cleaned_data["_model"] == root_form.cleaned_data["_old_model"]
        search_tree.parse_data(request.GET if parse_tree else None, "")
        if search_tree.is_valid():
            if search_tree.model_class == models.Sample:
                base_query = utils.restricted_samples_query(request.user)
            elif search_tree.model_class == models.SampleSeries:
                base_query = models.SampleSeries.objects.filter(
                    Q(topic__confidential=False) | Q(topic__members=request.user) |
                    Q(currently_responsible_person=request.user)).distinct()
            else:
                base_query = None
            results, too_many_results = jb_common.search.get_search_results(search_tree, max_results, base_query)
            if search_tree.model_class == models.Sample:
                if request.method == "POST":
                    sample_ids = set(int_or_zero(key[2:].partition("-")[0]) for key, value in request.POST.items() if value == "on")
                    samples = base_query.in_bulk(sample_ids).values()
                    request.user.my_samples.add(*samples)
                my_samples = request.user.my_samples.all()
                add_forms = [AddToMySamplesForm(prefix="0-" + str(sample.pk)) if sample not in my_samples else None
                             for sample in results]
            else:
                add_forms = len(results) * [None]
            if results and root_form.cleaned_data["_search_parameters_hash"] == _search_parameters_hash:
                data_node = data_tree.DataNode(_("search results"))
                for result in results:
                    insert = False
                    if isinstance(result, models.PhysicalProcess) \
                        and permissions.has_permission_to_view_physical_process(request.user, result):
                            insert = True
                    elif isinstance(result, models.Result) \
                        and permissions.has_permission_to_view_result_process(request.user, result):
                            insert = True
                    elif isinstance(result, models.Sample) \
                        and permissions.has_permission_to_fully_view_sample(request.user, result):
                            insert = True
                    elif isinstance(result, models.SampleSeries) \
                        and permissions.has_permission_to_view_sample_series(request.user, result):
                            insert = True
                    if insert:
                        data_node.children.append(result.get_data_for_table_export())
                if len(data_node.children) == 0:
                    no_permission_message = _("You don't have the permission to see any content of the search results.")
                else:
                    export_result = utils.table_export(request, data_node, "")
                    if isinstance(export_result, tuple):
                        column_groups_form, columns_form, table, switch_row_forms, old_data_form = export_result
                    elif isinstance(export_result, HttpResponse):
                        return export_result
            search_performed = True
        root_form = jb_common.search.SearchModelForm(
            model_list, initial={"_old_model": root_form.cleaned_data["_model"], "_model": root_form.cleaned_data["_model"],
                                 "_search_parameters_hash": _search_parameters_hash})
    else:
        root_form = jb_common.search.SearchModelForm(model_list)
    root_form.fields["_model"].label = ""
    content_dict = {"title": capfirst(_("advanced search")), "search_root": root_form, "search_tree": search_tree,
                    "results": list(zip(results, add_forms)), "search_performed": search_performed,
                    "something_to_add": any(add_forms), "too_many_results": too_many_results, "max_results": max_results,
                    "column_groups": column_groups_form, "columns": columns_form, "old_data": old_data_form,
                    "rows": list(zip(table, switch_row_forms)) if table else None,
                    "no_permission_message": no_permission_message}
    return render(request, "samples/advanced_search.html", content_dict)