Exemplo n.º 1
0
def get_challenge_phase_submission_count_by_team(request, challenge_pk,
                                                 challenge_phase_pk):
    """
    Returns number of submissions done by a participant team in a challenge phase
    """
    challenge = get_challenge_model(challenge_pk)

    challenge_phase = get_challenge_phase_model(challenge_phase_pk)

    participant_team = get_participant_team_id_of_user_for_a_challenge(
        request.user, challenge.pk)

    submissions = Submission.objects.filter(
        challenge_phase=challenge_phase,
        challenge_phase__challenge=challenge,
        participant_team=participant_team)
    participant_team_submissions = submissions.count()

    challenge_phase_submission_count = ChallengePhaseSubmissionCount(
        participant_team_submissions, challenge_phase.pk)
    try:
        serializer = ChallengePhaseSubmissionCountSerializer(
            challenge_phase_submission_count)
        response_data = serializer.data
        return Response(response_data, status=status.HTTP_200_OK)
    except:
        response_data = {'error': "Bad request. Please try again later!"}
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)
Exemplo n.º 2
0
def change_submission_visibility(request, challenge_id, challenge_phase_id, submission_id):
    """API Endpoint for making a submission to a challenge"""

    # check if the challenge exists or not
    try:
        challenge = Challenge.objects.get(pk=challenge_id)
    except Challenge.DoesNotExist:
        response_data = {'error': 'Challenge does not exist'}
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

    # check if the challenge phase exists or not
    try:
        challenge_phase = ChallengePhase.objects.get(
            pk=challenge_phase_id, challenge=challenge)
    except ChallengePhase.DoesNotExist:
        response_data = {'error': 'Challenge Phase does not exist'}
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

    if not challenge.is_active:
        response_data = {'error': 'Challenge is not active'}
        return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE)

    # check if challenge phase is public and accepting solutions
    if not challenge_phase.is_public:
        response_data = {
            'error': 'Sorry, cannot accept submissions since challenge phase is not public'}
        return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE)

    participant_team_id = get_participant_team_id_of_user_for_a_challenge(
        request.user, challenge_id)

    try:
        participant_team = ParticipantTeam.objects.get(pk=participant_team_id)
    except ParticipantTeam.DoesNotExist:
        response_data = {'error': 'You haven\'t participated in the challenge'}
        return Response(response_data, status=status.HTTP_403_FORBIDDEN)

    try:
        submission = Submission.objects.get(participant_team=participant_team,
                                            challenge_phase=challenge_phase, id=submission_id)
    except Submission.DoesNotExist:
        response_data = {'error': 'Submission does not exist'}
        return Response(response_data, status=status.HTTP_403_FORBIDDEN)

    print request.data
    serializer = SubmissionSerializer(submission,
                                      data=request.data,
                                      context={
                                               'participant_team': participant_team,
                                               'challenge_phase': challenge_phase,
                                               'request': request
                                      },
                                      partial=True)

    if serializer.is_valid():
        serializer.save()
        response_data = serializer.data
        return Response(response_data, status=status.HTTP_200_OK)
    else:
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Exemplo n.º 3
0
def get_challenge_phase_submission_analysis(request, challenge_pk, challenge_phase_pk):
    """
    API to fetch
    1. The submissions count for challenge phase.
    2. The participated team count for challenge phase.
    """
    challenge = get_challenge_model(challenge_pk)

    challenge_phase = get_challenge_phase_model(challenge_phase_pk)

    participant_team = get_participant_team_id_of_user_for_a_challenge(request.user, challenge.pk)

    submissions = Submission.objects.filter(
        challenge_phase=challenge_phase, challenge_phase__challenge=challenge, participant_team=participant_team)
    submission_count = submissions.count()
    submissions = Submission.objects.filter(
        challenge_phase=challenge_phase, challenge_phase__challenge=challenge)
    participant_team_count = submissions.values_list(
        'participant_team', flat=True).distinct().count()

    challenge_phase_submission_count = ChallengePhaseSubmissionCount(
        submission_count, participant_team_count, challenge_phase.pk)
    try:
        serializer = ChallengePhaseSubmissionCountSerializer(challenge_phase_submission_count)
        response_data = serializer.data
        return Response(response_data, status=status.HTTP_200_OK)
    except:
        response_data = {'error': "Bad request. Please try again later!"}
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)
Exemplo n.º 4
0
def download_file_and_publish_submission_message(request_data, user_pk,
                                                 request_method,
                                                 challenge_phase_id):
    """
    Download submission file from url and send it for the evaluation
    """
    user = User.objects.get(pk=user_pk)
    challenge_phase = ChallengePhase.objects.get(pk=challenge_phase_id)
    participant_team_id = get_participant_team_id_of_user_for_a_challenge(
        user, challenge_phase.challenge.pk)
    participant_team = ParticipantTeam.objects.get(pk=participant_team_id)
    request = HttpRequest()
    request.method = request_method
    request.user = user
    try:
        downloaded_file = get_file_from_url(request_data["file_url"])
        file_path = os.path.join(downloaded_file["temp_dir_path"],
                                 downloaded_file["name"])

        with open(file_path, 'rb') as f:
            input_file = SimpleUploadedFile(downloaded_file["name"],
                                            f.read(),
                                            content_type="multipart/form-data")
        data = {
            "input_file": input_file,
            "method_name": request_data["method_name"],
            "method_description": request_data["method_description"],
            "project_url": request_data["project_url"],
            "publication_url": request_data["publication_url"],
            "status": Submission.SUBMITTED
        }
        serializer = SubmissionSerializer(data=data,
                                          context={
                                              'participant_team':
                                              participant_team,
                                              'challenge_phase':
                                              challenge_phase,
                                              'request': request
                                          })
        if serializer.is_valid():
            serializer.save()
            submission = serializer.instance

            # publish messages in the submission worker queue
            publish_submission_message({
                "challenge_pk":
                challenge_phase.challenge.pk,
                "phase_pk":
                challenge_phase.pk,
                "submission_pk":
                submission.pk
            })
            logger.info("Message published to submission worker successfully!")
            shutil.rmtree(downloaded_file['temp_dir_path'])
    except Exception as e:
        logger.exception(
            "Exception while downloading and sending submission for evaluation {}"
            .format(e))
Exemplo n.º 5
0
def get_all_submissions_of_challenge(request, challenge_pk, challenge_phase_pk):
    """
    Returns all the submissions for a particular challenge
    """
    # To check for the corresponding challenge from challenge_pk.
    challenge = get_challenge_model(challenge_pk)

    # To check for the corresponding challenge phase from the challenge_phase_pk and challenge.
    try:
        challenge_phase = ChallengePhase.objects.get(pk=challenge_phase_pk, challenge=challenge)
    except ChallengePhase.DoesNotExist:
        response_data = {'error': 'Challenge Phase {} does not exist'.format(challenge_phase_pk)}
        return Response(response_data, status=status.HTTP_404_NOT_FOUND)

    # To check for the user as a host of the challenge from the request and challenge_pk.
    if is_user_a_host_of_challenge(user=request.user, challenge_pk=challenge_pk):

        # Filter submissions on the basis of challenge for host for now. Later on, the support for query
        # parameters like challenge phase, date is to be added.

        submissions = Submission.objects.filter(challenge_phase__challenge=challenge).order_by('-submitted_at')
        paginator, result_page = paginated_queryset(submissions, request)
        try:
            serializer = ChallengeSubmissionManagementSerializer(result_page, many=True, context={'request': request})
            response_data = serializer.data
            return paginator.get_paginated_response(response_data)
        except:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    # To check for the user as a participant of the challenge from the request and challenge_pk.
    elif has_user_participated_in_challenge(user=request.user, challenge_id=challenge_pk):

        # get participant team object for the user for a particular challenge.
        participant_team_pk = get_participant_team_id_of_user_for_a_challenge(
                request.user, challenge_pk)

        # Filter submissions on the basis of challenge phase for a participant.
        submissions = Submission.objects.filter(participant_team=participant_team_pk,
                                                challenge_phase=challenge_phase).order_by('-submitted_at')
        paginator, result_page = paginated_queryset(submissions, request)
        try:
            serializer = SubmissionSerializer(result_page, many=True, context={'request': request})
            response_data = serializer.data
            return paginator.get_paginated_response(response_data)
        except:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    # when user is neither host not participant of the challenge.
    else:
        response_data = {'error': 'You are neither host nor participant of the challenge!'}
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)
Exemplo n.º 6
0
def challenge_submission(request, challenge_id, challenge_phase_id):
    """API Endpoint for making a submission to a challenge"""

    # check if the challenge exists or not
    try:
        challenge = Challenge.objects.get(pk=challenge_id)
    except Challenge.DoesNotExist:
        response_data = {'error': 'Challenge does not exist'}
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

    # check if the challenge phase exists or not
    try:
        challenge_phase = ChallengePhase.objects.get(
            pk=challenge_phase_id, challenge=challenge)
    except ChallengePhase.DoesNotExist:
        response_data = {'error': 'Challenge Phase does not exist'}
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

    if request.method == 'GET':
        # getting participant team object for the user for a particular challenge.
        participant_team_id = get_participant_team_id_of_user_for_a_challenge(
            request.user, challenge_id)

        # check if participant team exists or not.
        try:
            ParticipantTeam.objects.get(pk=participant_team_id)
        except ParticipantTeam.DoesNotExist:
            response_data = {'error': 'You haven\'t participated in the challenge'}
            return Response(response_data, status=status.HTTP_403_FORBIDDEN)

        submission = Submission.objects.filter(participant_team=participant_team_id,
                                               challenge_phase=challenge_phase).order_by('-submitted_at')
        paginator, result_page = paginated_queryset(submission, request)
        try:
            serializer = SubmissionSerializer(result_page, many=True, context={'request': request})
            response_data = serializer.data
            return paginator.get_paginated_response(response_data)
        except:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'POST':

        # check if the challenge is active or not
        if not challenge.is_active:
            response_data = {'error': 'Challenge is not active'}
            return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE)

        # check if challenge phase is active
        if not challenge_phase.is_active:
            response_data = {
                'error': 'Sorry, cannot accept submissions since challenge phase is not active'}
            return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE)

        # check if user is a challenge host or a participant
        if not is_user_a_host_of_challenge(request.user, challenge_id):
            # check if challenge phase is public and accepting solutions
            if not challenge_phase.is_public:
                response_data = {
                    'error': 'Sorry, cannot accept submissions since challenge phase is not public'}
                return Response(response_data, status=status.HTTP_403_FORBIDDEN)

        participant_team_id = get_participant_team_id_of_user_for_a_challenge(
            request.user, challenge_id)
        try:
            participant_team = ParticipantTeam.objects.get(pk=participant_team_id)
        except ParticipantTeam.DoesNotExist:
            response_data = {'error': 'You haven\'t participated in the challenge'}
            return Response(response_data, status=status.HTTP_403_FORBIDDEN)

        # Fetch the number of submissions under progress.
        submissions_in_progress_status = [Submission.SUBMITTED, Submission.SUBMITTING, Submission.RUNNING]
        submissions_in_progress = Submission.objects.filter(
                                                participant_team=participant_team_id,
                                                challenge_phase=challenge_phase,
                                                status__in=submissions_in_progress_status).count()

        if submissions_in_progress >= challenge_phase.max_concurrent_submissions_allowed:
            message = 'You have {} submissions that are being processed. \
                       Please wait for them to finish and then try again.'
            response_data = {'error': message.format(submissions_in_progress)}
            return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE)

        serializer = SubmissionSerializer(data=request.data,
                                          context={'participant_team': participant_team,
                                                   'challenge_phase': challenge_phase,
                                                   'request': request
                                                   })
        if serializer.is_valid():
            serializer.save()
            response_data = serializer.data
            submission = serializer.instance
            # publish message in the queue
            publish_submission_message(challenge_id, challenge_phase_id, submission.id)
            return Response(response_data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_406_NOT_ACCEPTABLE)
Exemplo n.º 7
0
def get_remaining_submissions(request, challenge_phase_pk, challenge_pk):

    '''
    Returns the number of remaining submissions that a participant can
    do per day and in total to a particular challenge phase of a
    challenge.
    '''

    # significance of get_challenge_model() here to check
    # if the challenge exists or not
    get_challenge_model(challenge_pk)

    challenge_phase = get_challenge_phase_model(challenge_phase_pk)

    participant_team_pk = get_participant_team_id_of_user_for_a_challenge(
        request.user, challenge_pk)

    # Conditional check for the existence of participant team of the user.
    if not participant_team_pk:
        response_data = {'error': 'You haven\'t participated in the challenge'}
        return Response(response_data, status=status.HTTP_403_FORBIDDEN)

    max_submissions_per_day_count = challenge_phase.max_submissions_per_day

    max_submissions_count = challenge_phase.max_submissions

    submissions_done = Submission.objects.filter(
        challenge_phase__challenge=challenge_pk,
        challenge_phase=challenge_phase_pk,
        participant_team=participant_team_pk)

    failed_submissions = submissions_done.filter(
        status=Submission.FAILED)

    submissions_done_today = submissions_done.filter(
        submitted_at__gte=timezone.now().date())

    failed_submissions_done_today = submissions_done_today.filter(
        status=Submission.FAILED)

    submissions_done_count = submissions_done.count()
    failed_submissions_count = failed_submissions.count()
    submissions_done_today_count = submissions_done_today.count()
    failed_submissions_done_today_count = failed_submissions_done_today.count()

    # Checks if #today's successful submission is greater than or equal to max submission per day
    if ((submissions_done_today_count - failed_submissions_done_today_count) >= max_submissions_per_day_count
            or (max_submissions_per_day_count == 0)):
        # Get the UTC time of the instant when the above condition is true.
        date_time_now = timezone.now()
        # Calculate the next day's date.
        date_time_tomorrow = date_time_now.date() + datetime.timedelta(1)
        utc = timezone.utc
        # Get the midnight time of the day i.e. 12:00 AM of next day.
        midnight = utc.localize(datetime.datetime.combine(
            date_time_tomorrow, datetime.time()))
        # Subtract the current time from the midnight time to get the remaining time for the next day's submissions.
        remaining_time = midnight - date_time_now
        # Return the remaining time with a message.
        response_data = {'message': 'You have exhausted today\'s submission limit',
                         'remaining_time': remaining_time
                         }
        return Response(response_data, status=status.HTTP_200_OK)
    else:
        # Calculate the remaining submissions for today.
        remaining_submissions_today_count = (max_submissions_per_day_count -
                                             (submissions_done_today_count -
                                              failed_submissions_done_today_count)
                                             )

        # calculate the remaining submissions from total submissions.
        remaining_submission_count = max_submissions_count - \
            (submissions_done_count - failed_submissions_count)

        if remaining_submissions_today_count > remaining_submission_count:
            remaining_submissions_today_count = remaining_submission_count

        # Return the above calculated data.
        response_data = {'remaining_submissions_today_count': remaining_submissions_today_count,
                         'remaining_submissions': remaining_submission_count
                         }
        return Response(response_data, status=status.HTTP_200_OK)
Exemplo n.º 8
0
def change_submission_data_and_visibility(request, challenge_pk, challenge_phase_pk, submission_pk):
    """
    API Endpoint for updating the submission meta data
    and changing submission visibility.
    """

    # check if the challenge exists or not
    challenge = get_challenge_model(challenge_pk)

    # check if the challenge phase exists or not
    challenge_phase = get_challenge_phase_model(challenge_phase_pk)

    if not challenge.is_active:
        response_data = {'error': 'Challenge is not active'}
        return Response(response_data, status=status.HTTP_403_FORBIDDEN)

    # check if challenge phase is public and accepting solutions
    if not is_user_a_host_of_challenge(request.user, challenge_pk):
        if not challenge_phase.is_public:
            response_data = {
                'error': 'Sorry, cannot accept submissions since challenge phase is not public'}
            return Response(response_data, status=status.HTTP_403_FORBIDDEN)

    participant_team_pk = get_participant_team_id_of_user_for_a_challenge(
        request.user, challenge_pk)

    try:
        participant_team = ParticipantTeam.objects.get(pk=participant_team_pk)
    except ParticipantTeam.DoesNotExist:
        response_data = {'error': 'You haven\'t participated in the challenge'}
        return Response(response_data, status=status.HTTP_403_FORBIDDEN)

    try:
        submission = Submission.objects.get(participant_team=participant_team,
                                            challenge_phase=challenge_phase,
                                            id=submission_pk)
    except Submission.DoesNotExist:
        response_data = {'error': 'Submission does not exist'}
        return Response(response_data, status=status.HTTP_403_FORBIDDEN)

    try:
        is_public = request.data['is_public']
        if is_public is True:
            when_made_public = datetime.datetime.now()
            request.data['when_made_public'] = when_made_public
    except KeyError:
        pass

    serializer = SubmissionSerializer(submission,
                                      data=request.data,
                                      context={
                                               'participant_team': participant_team,
                                               'challenge_phase': challenge_phase,
                                               'request': request
                                      },
                                      partial=True)

    if serializer.is_valid():
        serializer.save()
        response_data = serializer.data
        return Response(response_data, status=status.HTTP_200_OK)
    else:
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Exemplo n.º 9
0
def download_all_submissions(request, challenge_pk, challenge_phase_pk,
                             file_type):

    # To check for the corresponding challenge from challenge_pk.
    challenge = get_challenge_model(challenge_pk)

    # To check for the corresponding challenge phase from the challenge_phase_pk and challenge.
    try:
        challenge_phase = ChallengePhase.objects.get(pk=challenge_phase_pk,
                                                     challenge=challenge)
    except ChallengePhase.DoesNotExist:
        response_data = {
            'error':
            'Challenge Phase {} does not exist'.format(challenge_phase_pk)
        }
        return Response(response_data, status=status.HTTP_404_NOT_FOUND)

    if file_type == 'csv':
        if is_user_a_host_of_challenge(user=request.user,
                                       challenge_pk=challenge_pk):
            submissions = Submission.objects.filter(
                challenge_phase__challenge=challenge).order_by('-submitted_at')
            submissions = ChallengeSubmissionManagementSerializer(
                submissions, many=True, context={'request': request})
            response = HttpResponse(content_type='text/csv')
            response[
                'Content-Disposition'] = 'attachment; filename=all_submissions.csv'
            writer = csv.writer(response)
            writer.writerow([
                'id',
                'Team Name',
                'Team Members',
                'Team Members Email Id',
                'Challenge Phase',
                'Status',
                'Created By',
                'Execution Time(sec.)',
                'Submission Number',
                'Submitted File',
                'Stdout File',
                'Stderr File',
                'Submitted At',
                'Submission Result File',
                'Submission Metadata File',
            ])
            for submission in submissions.data:
                writer.writerow([
                    submission['id'],
                    submission['participant_team'],
                    ",".join(username['username'] for username in
                             submission['participant_team_members']),
                    ",".join(
                        email['email']
                        for email in submission['participant_team_members']),
                    submission['challenge_phase'],
                    submission['status'],
                    submission['created_by'],
                    submission['execution_time'],
                    submission['submission_number'],
                    submission['input_file'],
                    submission['stdout_file'],
                    submission['stderr_file'],
                    submission['created_at'],
                    submission['submission_result_file'],
                    submission['submission_metadata_file'],
                ])
            return response

        elif has_user_participated_in_challenge(user=request.user,
                                                challenge_id=challenge_pk):

            # get participant team object for the user for a particular challenge.
            participant_team_pk = get_participant_team_id_of_user_for_a_challenge(
                request.user, challenge_pk)

            # Filter submissions on the basis of challenge phase for a participant.
            submissions = Submission.objects.filter(
                participant_team=participant_team_pk,
                challenge_phase=challenge_phase).order_by('-submitted_at')
            submissions = ChallengeSubmissionManagementSerializer(
                submissions, many=True, context={'request': request})
            response = HttpResponse(content_type='text/csv')
            response[
                'Content-Disposition'] = 'attachment; filename=all_submissions.csv'
            writer = csv.writer(response)
            writer.writerow([
                'Team Name',
                'Method Name',
                'Status',
                'Execution Time(sec.)',
                'Submitted File',
                'Result File',
                'Stdout File',
                'Stderr File',
                'Submitted At',
            ])
            for submission in submissions.data:
                writer.writerow([
                    submission['participant_team'],
                    submission['method_name'],
                    submission['status'],
                    submission['execution_time'],
                    submission['input_file'],
                    submission['submission_result_file'],
                    submission['stdout_file'],
                    submission['stderr_file'],
                    submission['created_at'],
                ])
            return response
        else:
            response_data = {
                'error':
                'You are neither host nor participant of the challenge!'
            }
            return Response(response_data, status=status.HTTP_400_BAD_REQUEST)
    else:
        response_data = {'error': 'The file type requested is not valid!'}
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)
Exemplo n.º 10
0
def get_remaining_submission_for_a_phase(user, challenge_phase_pk,
                                         challenge_pk):
    """
    Returns the number of remaining submissions that a participant can
    do daily, monthly and in total to a particular challenge phase of a
    challenge.
    """

    get_challenge_model(challenge_pk)
    challenge_phase = get_challenge_phase_model(challenge_phase_pk)
    participant_team_pk = get_participant_team_id_of_user_for_a_challenge(
        user, challenge_pk)

    # Conditional check for the existence of participant team of the user.
    if not participant_team_pk:
        response_data = {"error": "You haven't participated in the challenge"}
        return response_data, status.HTTP_403_FORBIDDEN

    max_submissions_count = challenge_phase.max_submissions
    max_submissions_per_month_count = challenge_phase.max_submissions_per_month
    max_submissions_per_day_count = challenge_phase.max_submissions_per_day

    submissions_done = Submission.objects.filter(
        challenge_phase__challenge=challenge_pk,
        challenge_phase=challenge_phase_pk,
        participant_team=participant_team_pk,
    ).exclude(status__in=submission_status_to_exclude)

    submissions_done_this_month = submissions_done.filter(
        submitted_at__gte=timezone.now().replace(
            day=1, hour=0, minute=0, second=0, microsecond=0))

    # Get the submissions_done_today by midnight time of the day
    submissions_done_today = submissions_done.filter(
        submitted_at__gte=timezone.now().replace(
            hour=0, minute=0, second=0, microsecond=0))

    submissions_done_count = submissions_done.count()
    submissions_done_this_month_count = submissions_done_this_month.count()
    submissions_done_today_count = submissions_done_today.count()

    # Check for maximum submission limit
    if submissions_done_count >= max_submissions_count:
        response_data = {
            "message": "You have exhausted maximum submission limit!",
            "submission_limit_exceeded": True,
        }
        return response_data, status.HTTP_200_OK

    # Check for monthy submission limit
    elif submissions_done_this_month_count >= max_submissions_per_month_count:
        date_time_now = timezone.now()
        next_month_start_date_time = date_time_now + datetime.timedelta(
            days=+30)
        next_month_start_date_time = next_month_start_date_time.replace(
            day=1, hour=0, minute=0, second=0, microsecond=0)
        remaining_time = next_month_start_date_time - date_time_now

        if submissions_done_today_count >= max_submissions_per_day_count:
            response_data = {
                "message":
                "Both daily and monthly submission limits are exhausted!",
                "remaining_time": remaining_time,
            }
        else:
            response_data = {
                "message": "You have exhausted this month's submission limit!",
                "remaining_time": remaining_time,
            }
        return response_data, status.HTTP_200_OK

    # Checks if #today's successful submission is greater than or equal to max submission per day
    elif submissions_done_today_count >= max_submissions_per_day_count:
        date_time_now = timezone.now()
        date_time_tomorrow = date_time_now + datetime.timedelta(1)
        # Get the midnight time of the day i.e. 12:00 AM of next day.
        midnight = date_time_tomorrow.replace(hour=0, minute=0, second=0)
        remaining_time = midnight - date_time_now

        response_data = {
            "message": "You have exhausted today's submission limit!",
            "remaining_time": remaining_time,
        }
        return response_data, status.HTTP_200_OK

    else:
        # calculate the remaining submissions from total submissions.
        remaining_submission_count = (max_submissions_count -
                                      submissions_done_count)
        # Calculate the remaining submissions for current month.
        remaining_submissions_this_month_count = (
            max_submissions_per_month_count -
            submissions_done_this_month_count)
        # Calculate the remaining submissions for today.
        remaining_submissions_today_count = (max_submissions_per_day_count -
                                             submissions_done_today_count)

        remaining_submissions_this_month_count = min(
            remaining_submission_count, remaining_submissions_this_month_count)
        remaining_submissions_today_count = min(
            remaining_submissions_this_month_count,
            remaining_submissions_today_count,
        )

        response_data = {
            "remaining_submissions_this_month_count":
            remaining_submissions_this_month_count,
            "remaining_submissions_today_count":
            remaining_submissions_today_count,
            "remaining_submissions_count": remaining_submission_count,
        }
        return response_data, status.HTTP_200_OK
Exemplo n.º 11
0
def challenge_submission(request, challenge_id, challenge_phase_id):
    """API Endpoint for making a submission to a challenge"""

    # check if the challenge exists or not
    try:
        challenge = Challenge.objects.get(pk=challenge_id)
    except Challenge.DoesNotExist:
        response_data = {'error': 'Challenge does not exist'}
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

    # check if the challenge phase exists or not
    try:
        challenge_phase = ChallengePhase.objects.get(pk=challenge_phase_id,
                                                     challenge=challenge)
    except ChallengePhase.DoesNotExist:
        response_data = {'error': 'Challenge Phase does not exist'}
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

    if request.method == 'GET':
        # getting participant team object for the user for a particular challenge.
        participant_team_id = get_participant_team_id_of_user_for_a_challenge(
            request.user, challenge_id)

        # check if participant team exists or not.
        try:
            ParticipantTeam.objects.get(pk=participant_team_id)
        except ParticipantTeam.DoesNotExist:
            response_data = {
                'error': 'You haven\'t participated in the challenge'
            }
            return Response(response_data, status=status.HTTP_403_FORBIDDEN)

        submission = Submission.objects.filter(
            participant_team=participant_team_id,
            challenge_phase=challenge_phase).order_by('-submitted_at')
        paginator, result_page = paginated_queryset(submission, request)
        try:
            serializer = SubmissionSerializer(result_page,
                                              many=True,
                                              context={'request': request})
            response_data = serializer.data
            return paginator.get_paginated_response(response_data)
        except:
            return Response(serializer.errors,
                            status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'POST':

        # check if the challenge is active or not
        if not challenge.is_active:
            response_data = {'error': 'Challenge is not active'}
            return Response(response_data,
                            status=status.HTTP_406_NOT_ACCEPTABLE)

        # check if challenge phase is active
        if not challenge_phase.is_active:
            response_data = {
                'error':
                'Sorry, cannot accept submissions since challenge phase is not active'
            }
            return Response(response_data,
                            status=status.HTTP_406_NOT_ACCEPTABLE)

        # check if challenge phase is public and accepting solutions
        if not challenge_phase.is_public:
            response_data = {
                'error':
                'Sorry, cannot accept submissions since challenge phase is not public'
            }
            return Response(response_data,
                            status=status.HTTP_406_NOT_ACCEPTABLE)

        participant_team_id = get_participant_team_id_of_user_for_a_challenge(
            request.user, challenge_id)
        try:
            participant_team = ParticipantTeam.objects.get(
                pk=participant_team_id)
        except ParticipantTeam.DoesNotExist:
            response_data = {
                'error': 'You haven\'t participated in the challenge'
            }
            return Response(response_data, status=status.HTTP_403_FORBIDDEN)

        serializer = SubmissionSerializer(data=request.data,
                                          context={
                                              'participant_team':
                                              participant_team,
                                              'challenge_phase':
                                              challenge_phase,
                                              'request': request
                                          })
        if serializer.is_valid():
            serializer.save()
            response_data = serializer.data
            submission = serializer.instance
            # publish message in the queue
            publish_submission_message(challenge_id, challenge_phase_id,
                                       submission.id)
            return Response(response_data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Exemplo n.º 12
0
def change_submission_data_and_visibility(request, challenge_pk,
                                          challenge_phase_pk, submission_pk):
    """
    API Endpoint for updating the submission meta data
    and changing submission visibility.
    """

    # check if the challenge exists or not
    challenge = get_challenge_model(challenge_pk)

    # check if the challenge phase exists or not
    challenge_phase = get_challenge_phase_model(challenge_phase_pk)

    if not challenge.is_active:
        response_data = {"error": "Challenge is not active"}
        return Response(response_data, status=status.HTTP_403_FORBIDDEN)

    # check if challenge phase is public and accepting solutions
    if not is_user_a_host_of_challenge(request.user, challenge_pk):
        if not challenge_phase.is_public:
            response_data = {
                "error":
                "Sorry, cannot accept submissions since challenge phase is not public"
            }
            return Response(response_data, status=status.HTTP_403_FORBIDDEN)
        elif request.data.get("is_baseline"):
            response_data = {
                "error": "Sorry, you are not authorized to make this request"
            }
            return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

    participant_team_pk = get_participant_team_id_of_user_for_a_challenge(
        request.user, challenge_pk)

    try:
        participant_team = ParticipantTeam.objects.get(pk=participant_team_pk)
    except ParticipantTeam.DoesNotExist:
        response_data = {"error": "You haven't participated in the challenge"}
        return Response(response_data, status=status.HTTP_403_FORBIDDEN)

    try:
        submission = Submission.objects.get(
            participant_team=participant_team,
            challenge_phase=challenge_phase,
            id=submission_pk,
        )
    except Submission.DoesNotExist:
        response_data = {"error": "Submission does not exist"}
        return Response(response_data, status=status.HTTP_403_FORBIDDEN)

    try:
        is_public = request.data["is_public"]
        if is_public is True:
            when_made_public = datetime.datetime.now()
            request.data["when_made_public"] = when_made_public
    except KeyError:
        pass

    serializer = SubmissionSerializer(
        submission,
        data=request.data,
        context={
            "participant_team": participant_team,
            "challenge_phase": challenge_phase,
            "request": request,
        },
        partial=True,
    )

    if serializer.is_valid():
        serializer.save()
        response_data = serializer.data
        return Response(response_data, status=status.HTTP_200_OK)
    else:
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Exemplo n.º 13
0
def get_remaining_submissions(request, challenge_phase_pk, challenge_pk):
    '''
    Returns the number of remaining submissions that a participant can
    do daily, monthly and in total to a particular challenge phase of a
    challenge.
    '''

    # significance of get_challenge_model() here to check
    # if the challenge exists or not
    get_challenge_model(challenge_pk)

    challenge_phase = get_challenge_phase_model(challenge_phase_pk)

    participant_team_pk = get_participant_team_id_of_user_for_a_challenge(
        request.user, challenge_pk)

    # Conditional check for the existence of participant team of the user.
    if not participant_team_pk:
        response_data = {'error': 'You haven\'t participated in the challenge'}
        return Response(response_data, status=status.HTTP_403_FORBIDDEN)

    max_submissions_count = challenge_phase.max_submissions
    max_submissions_per_month_count = challenge_phase.max_submissions_per_month
    max_submissions_per_day_count = challenge_phase.max_submissions_per_day

    submissions_done = Submission.objects.filter(
        challenge_phase__challenge=challenge_pk,
        challenge_phase=challenge_phase_pk,
        participant_team=participant_team_pk).exclude(status=Submission.FAILED)

    submissions_done_this_month = submissions_done.filter(
        submitted_at__gte=timezone.now().replace(
            day=1, hour=0, minute=0, second=0, microsecond=0))

    # Get the submissions_done_today by midnight time of the day
    submissions_done_today = submissions_done.filter(
        submitted_at__gte=timezone.now().replace(
            hour=0, minute=0, second=0, microsecond=0))

    submissions_done_count = submissions_done.count()
    submissions_done_this_month_count = submissions_done_this_month.count()
    submissions_done_today_count = submissions_done_today.count()

    # Check for maximum submission limit
    if submissions_done_count >= max_submissions_count:
        response_data = {
            'message': 'You have exhausted maximum submission limit!',
            'max_submission_exceeded': True
        }
        return Response(response_data, status=status.HTTP_200_OK)

    # Check for monthy submission limit
    elif submissions_done_this_month_count >= max_submissions_per_month_count:
        date_time_now = timezone.now()
        next_month_start_date_time = date_time_now + datetime.timedelta(
            days=+30)
        next_month_start_date_time = next_month_start_date_time.replace(
            day=1, hour=0, minute=0, second=0, microsecond=0)
        remaining_time = next_month_start_date_time - date_time_now

        if submissions_done_today_count >= max_submissions_per_day_count:
            response_data = {
                'message':
                'Both daily and monthly submission limits are exhausted!',
                'remaining_time': remaining_time
            }
        else:
            response_data = {
                'message':
                'You have exhausted this month\'s submission limit!',
                'remaining_time': remaining_time
            }
        return Response(response_data, status=status.HTTP_200_OK)

    # Checks if #today's successful submission is greater than or equal to max submission per day
    elif submissions_done_today_count >= max_submissions_per_day_count:
        date_time_now = timezone.now()
        date_time_tomorrow = date_time_now + datetime.timedelta(1)
        # Get the midnight time of the day i.e. 12:00 AM of next day.
        midnight = date_time_tomorrow.replace(hour=0, minute=0, second=0)
        remaining_time = midnight - date_time_now

        response_data = {
            'message': 'You have exhausted today\'s submission limit!',
            'remaining_time': remaining_time
        }
        return Response(response_data, status=status.HTTP_200_OK)

    else:
        # calculate the remaining submissions from total submissions.
        remaining_submission_count = max_submissions_count - submissions_done_count
        # Calculate the remaining submissions for current month.
        remaining_submissions_this_month_count = (
            max_submissions_per_month_count -
            submissions_done_this_month_count)
        # Calculate the remaining submissions for today.
        remaining_submissions_today_count = (max_submissions_per_day_count -
                                             submissions_done_today_count)

        remaining_submissions_this_month_count = min(
            remaining_submission_count, remaining_submissions_this_month_count)
        remaining_submissions_today_count = min(
            remaining_submissions_this_month_count,
            remaining_submissions_today_count)

        response_data = {
            'remaining_submissions_this_month_count':
            remaining_submissions_this_month_count,
            'remaining_submissions_today_count':
            remaining_submissions_today_count,
            'remaining_submissions': remaining_submission_count
        }
        return Response(response_data, status=status.HTTP_200_OK)
Exemplo n.º 14
0
def challenge_submission(request, challenge_id, challenge_phase_id):
    """API Endpoint for making a submission to a challenge"""

    # check if the challenge exists or not
    try:
        challenge = Challenge.objects.get(pk=challenge_id)
    except Challenge.DoesNotExist:
        response_data = {"error": "Challenge does not exist"}
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

    # check if the challenge phase exists or not
    try:
        challenge_phase = ChallengePhase.objects.get(pk=challenge_phase_id,
                                                     challenge=challenge)
    except ChallengePhase.DoesNotExist:
        response_data = {"error": "Challenge Phase does not exist"}
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

    if request.method == "GET":
        # getting participant team object for the user for a particular challenge.
        participant_team_id = get_participant_team_id_of_user_for_a_challenge(
            request.user, challenge_id)

        # check if participant team exists or not.
        try:
            ParticipantTeam.objects.get(pk=participant_team_id)
        except ParticipantTeam.DoesNotExist:
            response_data = {
                "error": "You haven't participated in the challenge"
            }
            return Response(response_data, status=status.HTTP_403_FORBIDDEN)

        submission = Submission.objects.filter(
            participant_team=participant_team_id,
            challenge_phase=challenge_phase,
        ).order_by("-submitted_at")
        filtered_submissions = SubmissionFilter(request.GET,
                                                queryset=submission)
        paginator, result_page = paginated_queryset(filtered_submissions.qs,
                                                    request)
        serializer = SubmissionSerializer(result_page,
                                          many=True,
                                          context={"request": request})
        response_data = serializer.data
        return paginator.get_paginated_response(response_data)

    elif request.method == "POST":

        # check if the challenge is active or not
        if not challenge.is_active:
            response_data = {"error": "Challenge is not active"}
            return Response(response_data,
                            status=status.HTTP_406_NOT_ACCEPTABLE)

        # check if challenge phase is active
        if not challenge_phase.is_active:
            response_data = {
                "error":
                "Sorry, cannot accept submissions since challenge phase is not active"
            }
            return Response(response_data,
                            status=status.HTTP_406_NOT_ACCEPTABLE)

        # check if user is a challenge host or a participant
        if not is_user_a_host_of_challenge(request.user, challenge_id):
            # check if challenge phase is public and accepting solutions
            if not challenge_phase.is_public:
                response_data = {
                    "error":
                    "Sorry, cannot accept submissions since challenge phase is not public"
                }
                return Response(response_data,
                                status=status.HTTP_403_FORBIDDEN)

            # if allowed email ids list exist, check if the user exist in that list or not
            if challenge_phase.allowed_email_ids:
                if request.user.email not in challenge_phase.allowed_email_ids:
                    response_data = {
                        "error":
                        "Sorry, you are not allowed to participate in this challenge phase"
                    }
                    return Response(response_data,
                                    status=status.HTTP_403_FORBIDDEN)

        participant_team_id = get_participant_team_id_of_user_for_a_challenge(
            request.user, challenge_id)
        try:
            participant_team = ParticipantTeam.objects.get(
                pk=participant_team_id)
        except ParticipantTeam.DoesNotExist:
            response_data = {
                "error": "You haven't participated in the challenge"
            }
            return Response(response_data, status=status.HTTP_403_FORBIDDEN)

        all_participants_email = participant_team.get_all_participants_email()
        for participant_email in all_participants_email:
            if participant_email in challenge.banned_email_ids:
                message = "You're a part of {} team and it has been banned from this challenge. \
                Please contact the challenge host.".format(
                    participant_team.team_name)
                response_data = {"error": message}
                return Response(response_data,
                                status=status.HTTP_403_FORBIDDEN)

        # Fetch the number of submissions under progress.
        submissions_in_progress_status = [
            Submission.SUBMITTED,
            Submission.SUBMITTING,
            Submission.RUNNING,
        ]
        submissions_in_progress = Submission.objects.filter(
            participant_team=participant_team_id,
            challenge_phase=challenge_phase,
            status__in=submissions_in_progress_status,
        ).count()

        if (submissions_in_progress >=
                challenge_phase.max_concurrent_submissions_allowed):
            message = "You have {} submissions that are being processed. \
                       Please wait for them to finish and then try again."

            response_data = {"error": message.format(submissions_in_progress)}
            return Response(response_data,
                            status=status.HTTP_406_NOT_ACCEPTABLE)

        if not request.FILES:
            if not is_url_valid(request.data['file_url']):
                response_data = {'error': 'The file URL does not exists!'}
                return Response(response_data,
                                status=status.HTTP_400_BAD_REQUEST)
            download_file_and_publish_submission_message.delay(
                request.data, request.user.id, request.method,
                challenge_phase_id)
            response_data = {
                'message': 'Please wait while your submission being evaluated!'
            }
            return Response(response_data, status=status.HTTP_200_OK)
        serializer = SubmissionSerializer(
            data=request.data,
            context={
                "participant_team": participant_team,
                "challenge_phase": challenge_phase,
                "request": request,
            },
        )
        if serializer.is_valid():
            serializer.save()
            response_data = serializer.data
            submission = serializer.instance
            # publish message in the queue
            publish_submission_message(challenge_id, challenge_phase_id,
                                       submission.id)
            return Response(response_data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors,
                        status=status.HTTP_406_NOT_ACCEPTABLE)