Skip to content

Commit

Permalink
[Backend] Add or delete challenge phases and splits (#4157)
Browse files Browse the repository at this point in the history
* Ability to remove and add challenge phase and phase split

* Remove changes to data split

* Added check for submission existence

* Added function to Zip function too

* Added check to delete the challenge phase split

* Added fix for challenge phase split removal

* Remove not used error messages and add split deletion to zip method

---------

Co-authored-by: Gunjan Chhablani <[email protected]>
  • Loading branch information
Suryansh5545 and gchhablani authored Sep 6, 2023
1 parent 7e3485f commit 13e4bfc
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 47 deletions.
49 changes: 3 additions & 46 deletions apps/challenges/challenge_config_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,19 +258,15 @@ 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",
"no_test_annotation_file_found": "ERROR: No test annotation file found in the zip file for challenge phase {}",
"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 {}: {}",
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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"
Expand Down
86 changes: 85 additions & 1 deletion apps/challenges/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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 = (
Expand Down Expand Up @@ -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"]
):
Expand All @@ -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,
Expand Down Expand Up @@ -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 = (
Expand Down

0 comments on commit 13e4bfc

Please sign in to comment.