diff --git a/apps/challenges/challenge_config_utils.py b/apps/challenges/challenge_config_utils.py index 65040b0db4..4db564dfa2 100644 --- a/apps/challenges/challenge_config_utils.py +++ b/apps/challenges/challenge_config_utils.py @@ -258,10 +258,8 @@ def get_value_from_field(data, base_location, field_name): "dataset_split_schema_errors": "ERROR: Dataset split {} has the following schema errors:\n {}", "dataset_split_addition": "ERROR: Dataset split {} doesn't exist. Addition of a new dataset split after challenge creation is not allowed.", "missing_existing_dataset_split_id": "ERROR: Dataset split {} not found in config. Deletion of existing dataset split after challenge creation is not allowed.", - "challenge_phase_split_not_exist": "ERROR: Challenge phase split (leaderboard_id: {}, challenge_phase_id: {}, dataset_split_id: {}) doesn't exist. Addition of challenge phase split after challenge creation is not allowed.", "challenge_phase_split_schema_errors": "ERROR: Challenge phase split {} has the following schema errors:\n {}", "missing_keys_in_challenge_phase_splits": "ERROR: The following keys are missing in the challenge phase splits of YAML file (phase_split: {}): {}", - "challenge_phase_split_not_found": "ERROR: Challenge phase split (leaderboard_id: {}, challenge_phase_id: {}, dataset_split_id: {}) not found in config. Deletion of existing challenge phase split after challenge creation is not allowed.", "no_key_for_challenge_phase_splits": "ERROR: There is no key for challenge phase splits.", "no_codename_for_challenge_phase": "ERROR: No codename found for the challenge phase. Please add a codename and try again!", "duplicate_codename_for_phase": "ERROR: Duplicate codename {} for phase {}. Please ensure codenames are unique", @@ -269,8 +267,6 @@ def get_value_from_field(data, base_location, field_name): "submission_meta_attribute_option_missing": "ERROR: Please include at least one option in the attribute for challenge phase {}", "missing_submission_meta_attribute_fields": "ERROR: Please enter the following fields for the submission meta attribute in challenge phase {}: {}", "challenge_phase_schema_errors": "ERROR: Challenge phase {} has the following schema errors:\n {}", - "challenge_phase_addition": "ERROR: Challenge phase {} doesn't exist. Addition of a new challenge phase after challenge creation is not allowed.", - "challenge_phase_not_found": "ERROR: Challenge phase {} not found in config. Deletion of existing challenge phase after challenge creation is not allowed.", "is_submission_public_restricted": "ERROR: is_submission_public can't be 'True' for challenge phase '{}' with is_restricted_to_select_one_submission 'True'. Please change is_submission_public to 'False' and try again!", "missing_option_in_submission_meta_attribute": "ERROR: Please include at least one option in the attribute for challenge phase {}", "missing_fields_in_submission_meta_attribute": "ERROR: Please enter the following fields for the submission meta attribute in challenge phase {}: {}", @@ -782,23 +778,8 @@ def validate_challenge_phases(self, current_phase_config_ids): ].format(data["id"], serializer_error) self.error_messages.append(message) else: - if ( - current_phase_config_ids - and int(data["id"]) not in current_phase_config_ids - ): - message = self.error_messages_dict[ - "challenge_phase_addition" - ].format(data["id"]) - self.error_messages.append(message) self.phase_ids.append(data["id"]) - for current_challenge_phase_id in current_phase_config_ids: - if current_challenge_phase_id not in self.phase_ids: - message = self.error_messages_dict[ - "challenge_phase_not_found" - ].format(current_challenge_phase_id) - self.error_messages.append(message) - def validate_challenge_phase_splits(self, current_phase_split_ids): challenge_phase_splits = self.yaml_file_data.get( "challenge_phase_splits" @@ -849,31 +830,13 @@ def validate_challenge_phase_splits(self, current_phase_split_ids): "challenge_phase_id", } if expected_keys.issubset(data.keys()): - if ( - current_phase_split_ids - and ( - data["leaderboard_id"], - data["challenge_phase_id"], - data["dataset_split_id"], - ) - not in current_phase_split_ids - ): - message = self.error_messages_dict[ - "challenge_phase_split_not_exist" - ].format( + challenge_phase_split_uuids.append( + ( data["leaderboard_id"], data["challenge_phase_id"], data["dataset_split_id"], ) - self.error_messages.append(message) - else: - challenge_phase_split_uuids.append( - ( - data["leaderboard_id"], - data["challenge_phase_id"], - data["dataset_split_id"], - ) - ) + ) ( is_mapping_valid, @@ -904,12 +867,6 @@ def validate_challenge_phase_splits(self, current_phase_split_ids): "missing_keys_in_challenge_phase_splits" ].format(phase_split, missing_keys_string) self.error_messages.append(message) - for uuid in current_phase_split_ids: - if uuid not in challenge_phase_split_uuids: - message = self.error_messages_dict[ - "challenge_phase_split_not_found" - ].format(uuid[0], uuid[1], uuid[2]) - self.error_messages.append(message) else: message = self.error_messages_dict[ "no_key_for_challenge_phase_splits" diff --git a/apps/challenges/views.py b/apps/challenges/views.py index c0457843f5..75b24876e7 100644 --- a/apps/challenges/views.py +++ b/apps/challenges/views.py @@ -1596,6 +1596,23 @@ def create_challenge_using_zip_file(request, challenge_host_team_pk): # Create Challenge Phase challenge_phase_ids = {} + + # Delete the challenge phase if it is not present in the yaml file + existing_challenge_phases = ChallengePhase.objects.filter(challenge=challenge) + existing_challenge_phase_ids = [str(challenge_phase.config_id) for challenge_phase in existing_challenge_phases] + challenge_phases_data_ids = [str(challenge_phase_data["id"]) for challenge_phase_data in challenge_phases_data] + challenge_phase_ids_to_delete = list(set(existing_challenge_phase_ids) - set(challenge_phases_data_ids)) + for challenge_phase_id_to_delete in challenge_phase_ids_to_delete: + challenge_phase = ChallengePhase.objects.filter(challenge__pk=challenge.pk, config_id=challenge_phase_id_to_delete).first() + submission_exist = Submission.objects.filter(challenge_phase=challenge_phase).exists() + if submission_exist: + response_data = { + "error": "Sorry, you cannot delete a challenge phase with submissions." + } + return Response(response_data, status=status.HTTP_400_BAD_REQUEST) + else: + challenge_phase.delete() + for data in challenge_phases_data: # Check for challenge phase description file phase_description_file_path = join( @@ -1694,6 +1711,30 @@ def create_challenge_using_zip_file(request, challenge_host_team_pk): response_data = {"error": message} return Response(response_data, status.HTTP_406_NOT_ACCEPTABLE) + # Delete the challenge phase split if it is not present in the yaml file + existing_challenge_phase_splits = ChallengePhaseSplit.objects.filter(challenge_phase__challenge=challenge) + challenge_phase_splits_set = set() + for challenge_phase_split in existing_challenge_phase_splits: + challenge_phase = challenge_phase_split.challenge_phase + dataset_split = challenge_phase_split.dataset_split + leaderboard = challenge_phase_split.leaderboard + combination = (challenge_phase, dataset_split, leaderboard) + challenge_phase_splits_set.add(combination) + for data in challenge_phase_splits_data: + challenge_phase = challenge_phase_ids[str(data["challenge_phase_id"])] + dataset_split = dataset_split_ids[str(data["dataset_split_id"])] + leaderboard = leaderboard_ids[str(data["leaderboard_id"])] + combination = (challenge_phase, dataset_split, leaderboard) + if combination in challenge_phase_splits_set: + challenge_phase_splits_set.remove(combination) + for challenge_phase_split in challenge_phase_splits_set: + challenge_phase_split_qs = ChallengePhaseSplit.objects.filter( + challenge_phase=challenge_phase_split[0], + dataset_split=challenge_phase_split[1], + leaderboard=challenge_phase_split[2] + ) + challenge_phase_split_qs.delete() + for data in challenge_phase_splits_data: if challenge_phase_ids.get(str(data["challenge_phase_id"])) is None: message = ( @@ -4006,6 +4047,25 @@ def create_or_update_github_challenge(request, challenge_host_team_pk): # Updating ChallengePhase objects challenge_phase_ids = {} challenge_phases_data = yaml_file_data["challenge_phases"] + + # Delete the challenge phase if it is not present in the yaml file + existing_challenge_phases = ChallengePhase.objects.filter(challenge=challenge) + existing_challenge_phase_ids = [str(challenge_phase.config_id) for challenge_phase in existing_challenge_phases] + challenge_phases_data_ids = [str(challenge_phase_data["id"]) for challenge_phase_data in challenge_phases_data] + challenge_phase_ids_to_delete = list(set(existing_challenge_phase_ids) - set(challenge_phases_data_ids)) + for challenge_phase_id_to_delete in challenge_phase_ids_to_delete: + challenge_phase = ChallengePhase.objects.filter( + challenge__pk=challenge.pk, config_id=challenge_phase_id_to_delete + ).first() + submission_exist = Submission.objects.filter(challenge_phase=challenge_phase).exists() + if submission_exist: + response_data = { + "error": "Sorry, you cannot delete a challenge phase with submissions." + } + return Response(response_data, status=status.HTTP_400_BAD_REQUEST) + else: + challenge_phase.delete() + for data, challenge_test_annotation_file in zip( challenge_phases_data, files["challenge_test_annotation_files"] ): @@ -4025,7 +4085,6 @@ def create_or_update_github_challenge(request, challenge_host_team_pk): ).first() if ( challenge_test_annotation_file - and not challenge_phase.annotations_uploaded_using_cli ): serializer = ChallengePhaseCreateSerializer( challenge_phase, @@ -4099,6 +4158,31 @@ def create_or_update_github_challenge(request, challenge_host_team_pk): challenge_phase_splits_data = yaml_file_data[ "challenge_phase_splits" ] + + # Delete the challenge phase split if it is not present in the yaml file + existing_challenge_phase_splits = ChallengePhaseSplit.objects.filter(challenge_phase__challenge=challenge) + challenge_phase_splits_set = set() + for challenge_phase_split in existing_challenge_phase_splits: + challenge_phase = challenge_phase_split.challenge_phase + dataset_split = challenge_phase_split.dataset_split + leaderboard = challenge_phase_split.leaderboard + combination = (challenge_phase, dataset_split, leaderboard) + challenge_phase_splits_set.add(combination) + for data in challenge_phase_splits_data: + challenge_phase = challenge_phase_ids[str(data["challenge_phase_id"])] + dataset_split = dataset_split_ids[str(data["dataset_split_id"])] + leaderboard = leaderboard_ids[str(data["leaderboard_id"])] + combination = (challenge_phase, dataset_split, leaderboard) + if combination in challenge_phase_splits_set: + challenge_phase_splits_set.remove(combination) + for challenge_phase_split in challenge_phase_splits_set: + challenge_phase_split_qs = ChallengePhaseSplit.objects.filter( + challenge_phase=challenge_phase_split[0], + dataset_split=challenge_phase_split[1], + leaderboard=challenge_phase_split[2] + ) + challenge_phase_split_qs.delete() + for data in challenge_phase_splits_data: if challenge_phase_ids.get(str(data["challenge_phase_id"])) is None: message = (