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)
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) 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)
def leaderboard(request, challenge_phase_split_id): """Returns leaderboard for a corresponding Challenge Phase Split""" # check if the challenge exists or not try: challenge_phase_split = ChallengePhaseSplit.objects.get( pk=challenge_phase_split_id) except ChallengePhaseSplit.DoesNotExist: response_data = {'error': 'Challenge Phase Split does not exist'} return Response(response_data, status=status.HTTP_400_BAD_REQUEST) # Check if the Challenge Phase Split is publicly visible or not if challenge_phase_split.visibility != ChallengePhaseSplit.PUBLIC: response_data = { 'error': 'Sorry, leaderboard is not public yet for this Challenge Phase Split!' } return Response(response_data, status=status.HTTP_400_BAD_REQUEST) # Get the leaderboard associated with the Challenge Phase Split leaderboard = challenge_phase_split.leaderboard # Get the default order by key to rank the entries on the leaderboard try: default_order_by = leaderboard.schema['default_order_by'] except: response_data = { 'error': 'Sorry, Default filtering key not found in leaderboard schema!' } return Response(response_data, status=status.HTTP_400_BAD_REQUEST) # Get all the successful submissions related to the challenge phase split leaderboard_data = LeaderboardData.objects.filter( challenge_phase_split=challenge_phase_split, submission__is_public=True).order_by('created_at') leaderboard_data = leaderboard_data.annotate( filtering_score=RawSQL('result->>%s', (default_order_by, ), output_field=FloatField())).values( 'id', 'submission__participant_team__team_name', 'challenge_phase_split', 'result', 'filtering_score', 'leaderboard__schema') sorted_leaderboard_data = sorted(leaderboard_data, key=lambda k: float(k['filtering_score']), reverse=True) distinct_sorted_leaderboard_data = [] team_list = [] for data in sorted_leaderboard_data: if data['submission__participant_team__team_name'] in team_list: continue else: distinct_sorted_leaderboard_data.append(data) team_list.append(data['submission__participant_team__team_name']) leaderboard_labels = challenge_phase_split.leaderboard.schema['labels'] for item in distinct_sorted_leaderboard_data: item['result'] = [ item['result'][index.lower()] for index in leaderboard_labels ] paginator, result_page = paginated_queryset( distinct_sorted_leaderboard_data, request, pagination_class=StandardResultSetPagination()) response_data = result_page return paginator.get_paginated_response(response_data)
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_phase).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)
def leaderboard(request, challenge_phase_split_id): """Returns leaderboard for a corresponding Challenge Phase Split""" # check if the challenge exists or not try: challenge_phase_split = ChallengePhaseSplit.objects.get( pk=challenge_phase_split_id) except ChallengePhaseSplit.DoesNotExist: response_data = {"error": "Challenge Phase Split does not exist"} return Response(response_data, status=status.HTTP_400_BAD_REQUEST) # Get the leaderboard associated with the Challenge Phase Split leaderboard = challenge_phase_split.leaderboard # Get the default order by key to rank the entries on the leaderboard try: default_order_by = leaderboard.schema["default_order_by"] except KeyError: response_data = { "error": "Sorry, Default filtering key not found in leaderboard schema!" } return Response(response_data, status=status.HTTP_400_BAD_REQUEST) # Exclude the submissions done by members of the host team # while populating leaderboard challenge_obj = challenge_phase_split.challenge_phase.challenge challenge_hosts_emails = ( challenge_obj.creator.get_all_challenge_host_email()) is_challenge_phase_public = challenge_phase_split.challenge_phase.is_public # Exclude the submissions from challenge host team to be displayed on the leaderboard of public phases challenge_hosts_emails = ([] if not is_challenge_phase_public else challenge_hosts_emails) challenge_host_user = is_user_a_host_of_challenge(request.user, challenge_obj.pk) # Check if challenge phase leaderboard is public for participant user or not if (challenge_phase_split.visibility != ChallengePhaseSplit.PUBLIC and not challenge_host_user): response_data = {"error": "Sorry, the leaderboard is not public!"} return Response(response_data, status=status.HTTP_400_BAD_REQUEST) leaderboard_data = LeaderboardData.objects.exclude( submission__created_by__email__in=challenge_hosts_emails) # Get all the successful submissions related to the challenge phase split leaderboard_data = leaderboard_data.filter( challenge_phase_split=challenge_phase_split, submission__is_flagged=False, submission__status=Submission.FINISHED, ).order_by("created_at") leaderboard_data = leaderboard_data.annotate( filtering_score=RawSQL("result->>%s", (default_order_by, ), output_field=FloatField())).values( "id", "submission__participant_team__team_name", "challenge_phase_split", "result", "filtering_score", "leaderboard__schema", "submission__submitted_at", ) if challenge_phase_split.visibility == ChallengePhaseSplit.PUBLIC: leaderboard_data = leaderboard_data.filter(submission__is_public=True) sorted_leaderboard_data = sorted( leaderboard_data, key=lambda k: float(k["filtering_score"]), reverse=True, ) distinct_sorted_leaderboard_data = [] team_list = [] for data in sorted_leaderboard_data: if data["submission__participant_team__team_name"] in team_list: continue else: distinct_sorted_leaderboard_data.append(data) team_list.append(data["submission__participant_team__team_name"]) leaderboard_labels = challenge_phase_split.leaderboard.schema["labels"] for item in distinct_sorted_leaderboard_data: item["result"] = [ item["result"][index] for index in leaderboard_labels ] paginator, result_page = paginated_queryset( distinct_sorted_leaderboard_data, request, pagination_class=StandardResultSetPagination(), ) response_data = result_page return paginator.get_paginated_response(response_data)
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) # 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) # 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)
def leaderboard(request, challenge_phase_split_id): """Returns leaderboard for a corresponding Challenge Phase Split""" # check if the challenge exists or not try: challenge_phase_split = ChallengePhaseSplit.objects.get( pk=challenge_phase_split_id) except ChallengePhaseSplit.DoesNotExist: response_data = {'error': 'Challenge Phase Split does not exist'} return Response(response_data, status=status.HTTP_400_BAD_REQUEST) # Get the leaderboard associated with the Challenge Phase Split leaderboard = challenge_phase_split.leaderboard # Get the default order by key to rank the entries on the leaderboard try: default_order_by = leaderboard.schema['default_order_by'] except: response_data = { 'error': 'Sorry, Default filtering key not found in leaderboard schema!' } return Response(response_data, status=status.HTTP_400_BAD_REQUEST) # Exclude the submissions done by members of the host team # while populating leaderboard challenge_obj = challenge_phase_split.challenge_phase.challenge challenge_hosts_emails = challenge_obj.creator.get_all_challenge_host_email( ) is_challenge_phase_public = challenge_phase_split.challenge_phase.is_public # Exclude the submissions from challenge host team to be displayed on the leaderboard of public phases challenge_hosts_emails = [] if not is_challenge_phase_public else challenge_hosts_emails leaderboard_data = LeaderboardData.objects.exclude( submission__created_by__email__in=challenge_hosts_emails) # Get all the successful submissions related to the challenge phase split leaderboard_data = leaderboard_data.filter( challenge_phase_split=challenge_phase_split, submission__is_public=True, submission__is_flagged=False, submission__status=Submission.FINISHED).order_by('created_at') leaderboard_data = leaderboard_data.annotate( filtering_score=RawSQL('result->>%s', (default_order_by, ), output_field=FloatField())).values( 'id', 'submission__participant_team__team_name', 'challenge_phase_split', 'result', 'filtering_score', 'leaderboard__schema', 'submission__submitted_at') sorted_leaderboard_data = sorted(leaderboard_data, key=lambda k: float(k['filtering_score']), reverse=True) distinct_sorted_leaderboard_data = [] team_list = [] for data in sorted_leaderboard_data: if data['submission__participant_team__team_name'] in team_list: continue else: distinct_sorted_leaderboard_data.append(data) team_list.append(data['submission__participant_team__team_name']) leaderboard_labels = challenge_phase_split.leaderboard.schema['labels'] for item in distinct_sorted_leaderboard_data: item['result'] = [ item['result'][index] for index in leaderboard_labels ] paginator, result_page = paginated_queryset( distinct_sorted_leaderboard_data, request, pagination_class=StandardResultSetPagination()) challenge_host_user = is_user_a_host_of_challenge(request.user, challenge_obj.pk) # Show the Private leaderboard only if the user is a challenge host if challenge_host_user: response_data = result_page return paginator.get_paginated_response(response_data) # Check if challenge phase leaderboard is public for participant user or not elif challenge_phase_split.visibility != ChallengePhaseSplit.PUBLIC: response_data = {'error': 'Sorry, the leaderboard is not public!'} return Response(response_data, status=status.HTTP_400_BAD_REQUEST) else: response_data = result_page return paginator.get_paginated_response(response_data)