Exemple #1
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)

    submissions = Submission.objects.filter(
        challenge_phase=challenge_phase, challenge_phase__challenge=challenge)
    submission_count = submissions.count()
    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)
Exemple #2
0
def get_last_submission_datetime_analysis(request, challenge_pk,
                                          challenge_phase_pk):
    """
    API to fetch
    1. To get the last submission time in a challenge phase.
    2. To get the last submission time in a challenge.
    """

    challenge = get_challenge_model(challenge_pk)

    challenge_phase = get_challenge_phase_model(challenge_phase_pk)

    submissions = Submission.objects.filter(
        challenge_phase__challenge=challenge)

    last_submission_timestamp_in_challenge = submissions.order_by(
        '-submitted_at')[0].created_at

    last_submission_timestamp_in_challenge_phase = submissions.filter(
        challenge_phase=challenge_phase).order_by(
            '-submitted_at')[0].created_at

    last_submission_timestamp = LastSubmissionTimestamp(
        last_submission_timestamp_in_challenge,
        last_submission_timestamp_in_challenge_phase, challenge_phase.pk)

    try:
        serializer = LastSubmissionTimestampSerializer(
            last_submission_timestamp)
        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)
Exemple #3
0
def get_submissions_for_challenge(request, challenge_pk):

    challenge = get_challenge_model(challenge_pk)

    if not is_user_a_host_of_challenge(request.user, challenge.id):
        response_data = {
            "error": "Sorry, you are not authorized to make this request!"
        }
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

    submission_status = request.query_params.get("status", None)

    valid_submission_status = [
        Submission.SUBMITTED,
        Submission.RUNNING,
        Submission.FAILED,
        Submission.CANCELLED,
        Submission.FINISHED,
        Submission.SUBMITTING,
    ]

    if submission_status not in valid_submission_status:
        response_data = {
            "error": "Invalid submission status {}".format(submission_status)
        }
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

    submissions_done_in_challenge = Submission.objects.filter(
        challenge_phase__challenge=challenge.id, status=submission_status)

    serializer = SubmissionSerializer(submissions_done_in_challenge,
                                      many=True,
                                      context={"request": request})

    return Response(serializer.data, status=status.HTTP_200_OK)
Exemple #4
0
def get_challenge_phase_submission_analysis(request, challenge_pk,
                                            challenge_phase_pk):
    """
    Returns
    1. Total number of submissions in a challenge phase
    2. Number of teams which made submissions in a challenge phase
    3. Number of submissions with status a)Submitting, b)Submitted, c)Running, d)Failed, e)Cancelled, f)Finished status
    4. Number of flagged & public submissions in challenge phase
    """

    challenge = get_challenge_model(challenge_pk)
    challenge_phase = get_challenge_phase_model(challenge_phase_pk)
    # Get the total submissions in a challenge phase
    submissions = Submission.objects.filter(
        challenge_phase=challenge_phase, challenge_phase__challenge=challenge)
    total_submissions = submissions.count()
    # Get the total participant teams in a challenge phase
    participant_team_count = submissions.values(
        'participant_team').distinct().count()
    # Get flagged submission count
    flagged_submissions_count = submissions.filter(is_flagged=True).count()
    # Get public submission count
    public_submissions_count = submissions.filter(is_public=True).count()
    challenge_phase_submission_count = ChallengePhaseSubmissionAnalytics(
        total_submissions, participant_team_count, flagged_submissions_count,
        public_submissions_count, challenge_phase.pk)
    try:
        serializer = ChallengePhaseSubmissionAnalyticsSerializer(
            challenge_phase_submission_count)
        response_data = serializer.data
        return Response(response_data, status=status.HTTP_200_OK)
    except ValueError:
        response_data = {'error': 'Bad request. Please try again later!'}
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)
Exemple #5
0
def download_all_participants(request, challenge_pk):
    """
        Returns the List of Participant Teams and its details in csv format
    """
    if is_user_a_host_of_challenge(user=request.user,
                                   challenge_pk=challenge_pk):
        challenge = get_challenge_model(challenge_pk)
        participant_teams = challenge.participant_teams.all().order_by(
            "-team_name")
        teams = ChallengeParticipantSerializer(participant_teams,
                                               many=True,
                                               context={"request": request})
        response = HttpResponse(content_type="text/csv")
        response[
            "Content-Disposition"] = "attachment; filename=participant_teams_{0}.csv".format(
                challenge_pk)
        writer = csv.writer(response)
        writer.writerow([
            "Team Name",
            "Team Members",
            "Email Id",
        ])
        for team in teams.data:
            writer.writerow([
                team["team_name"],
                ",".join(team["team_members"]),
                ",".join(team["team_members_email_ids"]),
            ])
        return response
    else:
        response_data = {
            "error": "Sorry, you are not authorized to make this request"
        }
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)
Exemple #6
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)
Exemple #7
0
def challenge_list(request, challenge_host_team_pk):
    try:
        challenge_host_team = ChallengeHostTeam.objects.get(pk=challenge_host_team_pk)
    except ChallengeHostTeam.DoesNotExist:
        response_data = {'error': 'ChallengeHostTeam does not exist'}
        return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE)

    if request.method == 'GET':
        challenge = Challenge.objects.filter(creator=challenge_host_team)
        paginator, result_page = paginated_queryset(challenge, request)
        serializer = ChallengeSerializer(result_page, many=True, context={'request': request})
        response_data = serializer.data
        return paginator.get_paginated_response(response_data)

    elif request.method == 'POST':
        if not ChallengeHost.objects.filter(user=request.user, team_name_id=challenge_host_team_pk).exists():
            response_data = {
                'error': 'Sorry, you do not belong to this Host Team!'}
            return Response(response_data, status=status.HTTP_401_UNAUTHORIZED)

        serializer = ZipChallengeSerializer(data=request.data,
                                            context={'challenge_host_team': challenge_host_team,
                                                     'request': request})
        if serializer.is_valid():
            serializer.save()
            challenge = get_challenge_model(serializer.instance.pk)
            serializer = ChallengeSerializer(challenge)
            response_data = serializer.data
            return Response(response_data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Exemple #8
0
def get_submission_count(request, challenge_pk, duration):
    """
        Returns submission count for a challenge according to the duration
        Valid values for duration are all, daily, weekly and monthly.
    """
    # make sure that a valid url is requested.
    if duration.lower() not in ('all', 'daily', 'weekly', 'monthly'):
        response_data = {'error': 'Wrong URL pattern!'}
        return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE)

    challenge = get_challenge_model(challenge_pk)

    challenge_phase_ids = challenge.challengephase_set.all().values_list(
        'id', flat=True)

    q_params = {'challenge_phase__id__in': challenge_phase_ids}
    since_date = None
    if duration.lower() == 'daily':
        since_date = timezone.now().date()

    elif duration.lower() == 'weekly':
        since_date = (timezone.now() - timedelta(days=7)).date()

    elif duration.lower() == 'monthly':
        since_date = (timezone.now() - timedelta(days=30)).date()
    # for `all` we dont need any condition in `q_params`
    if since_date:
        q_params['submitted_at__gte'] = since_date

    submission_count = Submission.objects.filter(**q_params).count()
    submission_count = SubmissionCount(submission_count)
    serializer = SubmissionCountSerializer(submission_count)
    return Response(serializer.data, status=status.HTTP_200_OK)
Exemple #9
0
def get_last_submission_time(
    request, challenge_pk, challenge_phase_pk, submission_by
):
    """
        Returns the last submission time for a particular challenge phase
    """
    challenge = get_challenge_model(challenge_pk)

    challenge_phase = get_challenge_phase_model(challenge_phase_pk)

    # To get the last submission time by a user in a challenge phase.
    if submission_by == "user":
        last_submitted_at = Submission.objects.filter(
            created_by=request.user.pk,
            challenge_phase=challenge_phase,
            challenge_phase__challenge=challenge,
        )
        last_submitted_at = last_submitted_at.order_by("-submitted_at")[
            0
        ].created_at
        last_submitted_at = LastSubmissionDateTime(last_submitted_at)
        serializer = LastSubmissionDateTimeSerializer(last_submitted_at)
        return Response(serializer.data, status=status.HTTP_200_OK)

    else:
        response_data = {"error": "Page not found!"}
        return Response(response_data, status=status.HTTP_404_NOT_FOUND)
Exemple #10
0
def get_remaining_submissions(request, challenge_pk):
    '''
    API to get the number of remaining submission for all phases.
    Below is the sample response returned by the API

    {
        "participant_team": "Sample_Participant_Team",
        "participant_team_id": 2,
        "phases": [
            {
                "id": 1,
                "name": "Megan Phase",
                "start_date": "2018-10-28T14:22:53.022639Z",
                "end_date": "2020-06-19T14:22:53.022660Z",
                "limits": {
                    "remaining_submissions_this_month_count": 9,
                    "remaining_submissions_today_count": 5,
                    "remaining_submissions_count": 29
                }
            },
            {
                "id": 2,
                "name": "Molly Phase",
                "start_date": "2018-10-28T14:22:53Z",
                "end_date": "2020-06-19T14:22:53Z",
                "limits": {
                    "message": "You have exhausted this month's submission limit!",
                    "remaining_time": "1481076.929224"  // remaining_time is in seconds
                }
            }
        ]
    }
    '''
    phases_data = {}
    challenge = get_challenge_model(challenge_pk)
    challenge_phases = ChallengePhase.objects.filter(
        challenge=challenge).order_by('pk')
    if not is_user_a_host_of_challenge(request.user, challenge_pk):
        challenge_phases = challenge_phases.filter(
            challenge=challenge, is_public=True).order_by('pk')
    phase_data_list = list()
    for phase in challenge_phases:
        remaining_submission_message, response_status = get_remaining_submission_for_a_phase(
            request.user, phase.id, challenge_pk)
        if response_status != status.HTTP_200_OK:
            return Response(remaining_submission_message,
                            status=response_status)
        phase_data_list.append(
            RemainingSubmissionDataSerializer(phase,
                                              context={
                                                  'limits':
                                                  remaining_submission_message
                                              }).data)
    phases_data["phases"] = phase_data_list
    participant_team = get_participant_team_of_user_for_a_challenge(
        request.user, challenge_pk)
    phases_data['participant_team'] = participant_team.team_name
    phases_data['participant_team_id'] = participant_team.id
    return Response(phases_data, status=status.HTTP_200_OK)
Exemple #11
0
def get_participant_count(request, challenge_pk):
    challenge = get_challenge_model(challenge_pk)
    participant_teams = challenge.participant_teams.all()
    participant_count = Participant.objects.filter(
        team__in=participant_teams).count()
    participant_count = ParticipantCount(participant_count)
    serializer = ParticipantCountSerializer(participant_count)
    return Response(serializer.data, status=status.HTTP_200_OK)
Exemple #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_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_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)

    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)
Exemple #13
0
def get_participant_team_count(request, challenge_pk):
    """
        Returns the number of participant teams in a challenge
    """
    challenge = get_challenge_model(challenge_pk)
    participant_team_count = challenge.participant_teams.count()
    participant_team_count = ParticipantTeamCount(participant_team_count)
    serializer = ParticipantTeamCountSerializer(participant_team_count)
    return Response(serializer.data, status=status.HTTP_200_OK)
Exemple #14
0
def get_last_submission_datetime_analysis(
    request, challenge_pk, challenge_phase_pk
):
    """
    API to fetch
    1. To get the last submission time in a challenge phase.
    2. To get the last submission time in a challenge.
    """

    challenge = get_challenge_model(challenge_pk)

    challenge_phase = get_challenge_phase_model(challenge_phase_pk)

    submissions = Submission.objects.filter(
        challenge_phase__challenge=challenge
    )

    if not submissions:
        response_data = {
            "message": "You dont have any submissions in this challenge!"
        }
        return Response(response_data, status.HTTP_200_OK)

    last_submission_timestamp_in_challenge = submissions.order_by(
        "-submitted_at"
    )[0].created_at

    submissions_in_a_phase = submissions.filter(
        challenge_phase=challenge_phase
    )

    if not submissions_in_a_phase:
        last_submission_timestamp_in_challenge_phase = (
            "You dont have any submissions in this challenge phase!"
        )
    else:
        last_submission_timestamp_in_challenge_phase = submissions_in_a_phase.order_by(
            "-submitted_at"
        )[
            0
        ].created_at

    last_submission_timestamp = LastSubmissionTimestamp(
        last_submission_timestamp_in_challenge,
        last_submission_timestamp_in_challenge_phase,
        challenge_phase.pk,
    )

    try:
        serializer = LastSubmissionTimestampSerializer(
            last_submission_timestamp
        )
        response_data = serializer.data
        return Response(response_data, status=status.HTTP_200_OK)
    except:  # noqa: E722
        response_data = {"error": "Bad request. Please try again later!"}
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)
Exemple #15
0
def download_all_submissions_file(request, challenge_pk, file_type):

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

    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')
            response = HttpResponse(content_type='text/csv')
            response[
                'Content-Disposition'] = 'attachment; filename=all_submissions.csv'
            writer = csv.writer(response)
            writer.writerow([
                'id',
                'Team Name',
                '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:
                writer.writerow([
                    submission.id,
                    submission.participant_team,
                    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
        else:
            response_data = {
                'error': 'Only Challenge Hosts can use the export feature!'
            }
            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)
Exemple #16
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)
Exemple #17
0
def challenge_detail(request, challenge_host_team_pk, challenge_pk):
    try:
        challenge_host_team = ChallengeHostTeam.objects.get(
            pk=challenge_host_team_pk)
    except ChallengeHostTeam.DoesNotExist:
        response_data = {'error': 'ChallengeHostTeam does not exist'}
        return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE)

    try:
        challenge = Challenge.objects.get(pk=challenge_pk)
    except Challenge.DoesNotExist:
        response_data = {'error': 'Challenge does not exist'}
        return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE)

    if request.method == 'GET':
        serializer = ChallengeSerializer(challenge,
                                         context={'request': request})
        response_data = serializer.data
        return Response(response_data, status=status.HTTP_200_OK)

    elif request.method in ['PUT', 'PATCH']:
        if request.method == 'PATCH':
            serializer = ZipChallengeSerializer(challenge,
                                                data=request.data,
                                                context={
                                                    'challenge_host_team':
                                                    challenge_host_team,
                                                    'request': request
                                                },
                                                partial=True)
        else:
            serializer = ZipChallengeSerializer(challenge,
                                                data=request.data,
                                                context={
                                                    'challenge_host_team':
                                                    challenge_host_team,
                                                    'request': request
                                                })
        if serializer.is_valid():
            serializer.save()
            challenge = get_challenge_model(serializer.instance.pk)
            serializer = ChallengeSerializer(challenge)
            response_data = serializer.data
            return Response(response_data, status=status.HTTP_200_OK)
        else:
            return Response(serializer.errors,
                            status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        challenge.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
Exemple #18
0
def star_challenge(request, challenge_pk):
    """
    API endpoint for starring and unstarring
    a challenge.
    """
    challenge = get_challenge_model(challenge_pk)

    if request.method == 'POST':
        try:
            starred_challenge = StarChallenge.objects.get(user=request.user,
                                                          challenge=challenge)
            starred_challenge.is_starred = not starred_challenge.is_starred
            starred_challenge.save()
            serializer = StarChallengeSerializer(starred_challenge)
            response_data = serializer.data
            return Response(response_data, status=status.HTTP_200_OK)
        except:
            serializer = StarChallengeSerializer(data=request.data,
                                                 context={
                                                     'request': request,
                                                     'challenge': challenge,
                                                     'is_starred': True
                                                 })
            if serializer.is_valid():
                serializer.save()
                response_data = serializer.data
                return Response(response_data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors,
                            status=status.HTTP_400_BAD_REQUEST)

    if request.method == 'GET':
        try:
            starred_challenge = StarChallenge.objects.get(user=request.user,
                                                          challenge=challenge)
            serializer = StarChallengeSerializer(starred_challenge)
            response_data = serializer.data
            return Response(response_data, status=status.HTTP_200_OK)
        except:
            starred_challenge = StarChallenge.objects.filter(
                challenge=challenge)
            if not starred_challenge:
                response_data = {'is_starred': False, 'count': 0}
                return Response(response_data, status=status.HTTP_200_OK)

            serializer = StarChallengeSerializer(starred_challenge, many=True)
            response_data = {
                'is_starred': False,
                'count': serializer.data[0]['count']
            }
            return Response(response_data, status=status.HTTP_200_OK)
Exemple #19
0
def remove_participant_team_from_challenge(
    request, challenge_pk, participant_team_pk
):
    """
    API to remove the participant team from a challenge

    Arguments:
        request {HttpRequest} -- The request object
        challenge_pk {[int]} -- Challenge primary key
        participant_team_pk {[int]} -- Participant team primary key

    Returns:
        Response Object -- An object containing api response
    """
    challenge = get_challenge_model(challenge_pk)

    participant_team = get_participant_model(participant_team_pk)

    if participant_team.created_by == request.user:
        if participant_team.challenge_set.filter(id=challenge_pk).exists():
            challenge_phases = ChallengePhase.objects.filter(
                challenge=challenge
            )
            for challenge_phase in challenge_phases:
                submissions = Submission.objects.filter(
                    participant_team=participant_team_pk,
                    challenge_phase=challenge_phase,
                )
                if submissions.count() > 0:
                    response_data = {
                        "error": "Unable to remove team as you have already made submission to the challenge"
                    }
                    return Response(
                        response_data, status=status.HTTP_400_BAD_REQUEST
                    )

            challenge.participant_teams.remove(participant_team)
            return Response(status=status.HTTP_200_OK)
        else:
            response_data = {
                "error": "Team has not participated in the challenge"
            }
            return Response(response_data, status=status.HTTP_400_BAD_REQUEST)
    else:
        response_data = {
            "error": "Sorry, you do not have permissions to remove this participant team"
        }
        return Response(response_data, status=status.HTTP_401_UNAUTHORIZED)
Exemple #20
0
def get_submissions_for_challenge(request, challenge_pk):

    challenge = get_challenge_model(challenge_pk)

    if not is_user_a_host_of_challenge(request.user, challenge.id):
        response_data = {
            "error": "Sorry, you are not authorized to make this request!"
        }
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

    submissions_done_in_challenge = SubmissionFilter(
        request.GET,
        queryset=Submission.objects.filter(
            challenge_phase__challenge=challenge.id))

    serializer = SubmissionSerializer(submissions_done_in_challenge.qs,
                                      many=True,
                                      context={'request': request})

    return Response(serializer.data, status=status.HTTP_200_OK)
Exemple #21
0
 def test_host_downloads_participant_team(self):
     expected = io.StringIO()
     expected_participant_teams = csv.writer(expected)
     expected_participant_teams.writerow(
         ["Team Name", "Team Members", "Email Id"])
     challenge = get_challenge_model(self.challenge.pk)
     participant_team = challenge.participant_teams.all().order_by(
         "-team_name")
     participant_teams = ChallengeParticipantSerializer(participant_team,
                                                        many=True)
     for team in participant_teams.data:
         expected_participant_teams.writerow([
             team["team_name"],
             ",".join(team["team_members"]),
             ",".join(team["team_members_email_ids"]),
         ])
     self.client.force_authenticate(user=self.user)
     response = self.client.get(self.url, {})
     self.assertEqual(response.content.decode("utf-8"), expected.getvalue())
     self.assertEqual(response.status_code, status.HTTP_200_OK)
Exemple #22
0
def get_submission_count(request, challenge_pk, duration):
    """
        Returns submission count for a challenge according to the duration
        Valid values for duration are all, daily, weekly and monthly.
    """
    # make sure that a valid url is requested.
    if duration.lower() not in ("all", "daily", "weekly", "monthly"):
        response_data = {"error": "Wrong URL pattern!"}
        return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE)

    challenge = get_challenge_model(challenge_pk)

    challenge_phase_ids = challenge.challengephase_set.all().values_list(
        "id", flat=True
    )

    q_params = {"challenge_phase__id__in": challenge_phase_ids}
    since_date = None
    if duration.lower() == "daily":
        # Get the midnight time of the day
        since_date = timezone.now().replace(
            hour=0, minute=0, second=0, microsecond=0
        )

    elif duration.lower() == "weekly":
        since_date = (timezone.now() - timedelta(days=7)).replace(
            hour=0, minute=0, second=0, microsecond=0
        )

    elif duration.lower() == "monthly":
        since_date = (timezone.now() - timedelta(days=30)).replace(
            hour=0, minute=0, second=0, microsecond=0
        )
    # for `all` we dont need any condition in `q_params`
    if since_date:
        q_params["submitted_at__gte"] = since_date

    submission_count = Submission.objects.filter(**q_params).count()
    submission_count = SubmissionCount(submission_count)
    serializer = SubmissionCountSerializer(submission_count)
    return Response(serializer.data, status=status.HTTP_200_OK)
Exemple #23
0
def get_last_submission_time(request, challenge_pk, challenge_phase_pk,
                             submission_by):
    challenge = get_challenge_model(challenge_pk)

    challenge_phase = get_challenge_phase_model(challenge_phase_pk)

    # To get the last submission time by a user in a challenge phase.
    if submission_by == 'user':
        last_submitted_at = Submission.objects.filter(
            created_by=request.user.pk,
            challenge_phase=challenge_phase,
            challenge_phase__challenge=challenge)
        last_submitted_at = last_submitted_at.order_by(
            '-submitted_at')[0].created_at
        last_submitted_at = LastSubmissionDateTime(last_submitted_at)
        serializer = LastSubmissionDateTimeSerializer(last_submitted_at)
        return Response(serializer.data, status=status.HTTP_200_OK)

    else:
        response_data = {'error': 'Page not found!'}
        return Response(response_data, status=status.HTTP_404_NOT_FOUND)
Exemple #24
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)

    submissions = Submission.objects.filter(
        challenge_phase__challenge=challenge, challenge_phase=challenge_phase)
    try:
        serializer = ChallengePhaseSubmissionAnalysisSerializer(submissions,
                                                                many=True)
        if serializer.data:
            response_data = serializer.data[0]
            return Response(response_data, status=status.HTTP_200_OK)
        return Response(serializer.data, status=status.HTTP_200_OK)
    except:
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Exemple #25
0
def get_last_submission_datetime_analysis(request, challenge_pk,
                                          challenge_phase_pk):
    """
    API to fetch
    1. To get the last submission time in a challenge phase.
    2. To get the last submission time in a challenge.
    """

    challenge = get_challenge_model(challenge_pk)

    challenge_phase = get_challenge_phase_model(challenge_phase_pk)

    submissions = Submission.objects.filter(
        challenge_phase__challenge=challenge, challenge_phase=challenge_phase)
    try:
        serializer = LastSubmissionDateTimeAnalysisSerializer(submissions,
                                                              many=True)
        if serializer.data:
            response_data = serializer.data[0]
            return Response(response_data, status=status.HTTP_200_OK)
        return Response(serializer.data, status=status.HTTP_200_OK)
    except:
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Exemple #26
0
def get_participant_team_details_for_challenge(request, challenge_pk):
    """
    API to get the participant team detail

    Arguments:
        request {HttpRequest} -- The request object
        challenge_pk {[int]} -- Challenge primary key

    Returns:
        {dict} -- Participant team detail that has participated in the challenge
    """

    challenge = get_challenge_model(challenge_pk)
    if has_user_participated_in_challenge(request.user, challenge_pk):
        participant_team = get_participant_team_of_user_for_a_challenge(
            request.user, challenge_pk)
        serializer = ParticipantTeamSerializer(participant_team)
        return Response(serializer.data, status=status.HTTP_200_OK)
    else:
        response_data = {
            "error":
            f"The user {request.user.username} has not participanted in {challenge.title}"
        }
        return Response(response_data, status=status.HTTP_404_NOT_FOUND)
Exemple #27
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)
Exemple #28
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)
Exemple #29
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
Exemple #30
0
def invite_participant_to_team(request, pk):
    try:
        participant_team = ParticipantTeam.objects.get(pk=pk)
    except ParticipantTeam.DoesNotExist:
        response_data = {"error": "Participant Team does not exist"}
        return Response(response_data, status=status.HTTP_404_NOT_FOUND)

    if not is_user_part_of_participant_team(request.user, participant_team):
        response_data = {"error": "You are not a member of this team!"}
        return Response(response_data, status=status.HTTP_400_BAD_REQUEST)

    email = request.data.get("email")
    try:
        user = User.objects.get(email=email)
    except User.DoesNotExist:
        response_data = {
            "error": "User does not exist with this email address!"
        }
        return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE)

    participant = Participant.objects.filter(team=participant_team, user=user)
    if participant.exists():
        response_data = {"error": "User is already part of the team!"}
        return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE)

    invited_user_participated_challenges = get_list_of_challenges_participated_by_a_user(
        user).values_list("id", flat=True)
    team_participated_challenges = get_list_of_challenges_for_participant_team(
        [participant_team]).values_list("id", flat=True)

    if set(invited_user_participated_challenges) & set(
            team_participated_challenges):
        """
        Check if the user has already participated in
        challenges where the inviting participant has participated.
        If this is the case, then the user cannot be invited since
        he cannot participate in a challenge via two teams.
        """
        response_data = {
            "error":
            "Sorry, the invited user has already participated"
            " in atleast one of the challenges which you are already a"
            " part of. Please try creating a new team and then invite."
        }
        return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE)

    if len(team_participated_challenges) > 0:
        for challenge_pk in team_participated_challenges:
            challenge = get_challenge_model(challenge_pk)

            if len(challenge.banned_email_ids) > 0:
                # Check if team participants emails are banned
                for (participant_email
                     ) in participant_team.get_all_participants_email():
                    if participant_email in challenge.banned_email_ids:
                        message = "You cannot invite as you're a part of {} team and it has been banned "
                        "from this challenge. Please contact the challenge host."
                        response_data = {
                            "error": message.format(participant_team.team_name)
                        }
                        return Response(
                            response_data,
                            status=status.HTTP_406_NOT_ACCEPTABLE,
                        )

                # Check if invited user is banned
                if email in challenge.banned_email_ids:
                    message = "You cannot invite as the invited user has been banned "
                    "from this challenge. Please contact the challenge host."
                    response_data = {"error": message}
                    return Response(response_data,
                                    status=status.HTTP_406_NOT_ACCEPTABLE)

            # Check if user is in allowed list.
            if len(challenge.allowed_email_domains) > 0:
                if not is_user_in_allowed_email_domains(email, challenge_pk):
                    message = "Sorry, users with {} email domain(s) are only allowed to participate in this challenge."
                    domains = ""
                    for domain in challenge.allowed_email_domains:
                        domains = "{}{}{}".format(domains, "/", domain)
                    domains = domains[1:]
                    response_data = {"error": message.format(domains)}
                    return Response(response_data,
                                    status=status.HTTP_406_NOT_ACCEPTABLE)

            # Check if user is in blocked list.
            if is_user_in_blocked_email_domains(email, challenge_pk):
                message = "Sorry, users with {} email domain(s) are not allowed to participate in this challenge."
                domains = ""
                for domain in challenge.blocked_email_domains:
                    domains = "{}{}{}".format(domains, "/", domain)
                domains = domains[1:]
                response_data = {"error": message.format(domains)}
                return Response(response_data,
                                status=status.HTTP_406_NOT_ACCEPTABLE)

    serializer = InviteParticipantToTeamSerializer(
        data=request.data,
        context={
            "participant_team": participant_team,
            "request": request
        },
    )

    if serializer.is_valid():
        serializer.save()
        response_data = {
            "message": "User has been successfully added to the team!"
        }
        return Response(response_data, status=status.HTTP_202_ACCEPTED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)