Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions app/grandchallenge/challenges/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,14 @@ class ChallengeRequestAdmin(ModelAdmin):
"creator",
"created",
"status",
"total_cost",
"total_price",
)
actions = ["create_challenge", "send_status_update_email"]
list_filter = ["status"]

@admin.display(description="Total cost")
def total_cost(self, obj):
return obj.total_challenge_cost
@admin.display(description="Total price")
def total_price(self, obj):
return obj.total_challenge_price

@admin.action(description="Create challenge for this request")
def create_challenge(self, request, queryset):
Expand Down
351 changes: 243 additions & 108 deletions app/grandchallenge/challenges/forms.py

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
# Generated by Django 4.2.24 on 2025-10-22 15:54

from django.db import migrations, models

import grandchallenge.core.validators


class Migration(migrations.Migration):

dependencies = [
(
"challenges",
"0061_alter_challenge_banner_alter_challenge_logo_and_more",
),
]

operations = [
migrations.AddField(
model_name="challengerequest",
name="algorithm_maximum_settable_memory_gb_for_tasks",
field=models.JSONField(
default=list,
help_text="Maximum amount of main memory (DRAM) that participants will be allowed to assign to algorithm inference jobs for submission.",
),
),
migrations.AddField(
model_name="challengerequest",
name="algorithm_selectable_gpu_type_choices_for_tasks",
field=models.JSONField(
default=list,
help_text='The GPU type choices that participants will be able to select for their algorithm inference jobs, for each task. Options are ["", "A100", "A10G", "V100", "K80", "T4"].',
validators=[
grandchallenge.core.validators.JSONValidator(
schema={
"$schema": "http://json-schema.org/draft-07/schema",
"items": {
"items": {
"enum": [
"",
"A100",
"A10G",
"V100",
"K80",
"T4",
],
"type": "string",
},
"type": "array",
"uniqueItems": True,
},
"title": "The Selectable GPU Types Schema",
"type": "array",
}
)
],
),
),
migrations.AddField(
model_name="challengerequest",
name="average_size_test_case_mb_for_tasks",
field=models.JSONField(
default=list,
help_text="Average size of a test image in MB, for each task.",
validators=[
grandchallenge.core.validators.JSONValidator(
schema={
"$schema": "http://json-schema.org/draft-07/schema",
"items": {
"maximum": 10000,
"minimum": 1,
"type": "integer",
},
"type": "array",
}
)
],
),
),
migrations.AddField(
model_name="challengerequest",
name="inference_time_average_minutes_for_tasks",
field=models.JSONField(
default=list,
help_text="Average run time per algorithm job in minutes, for each task.",
validators=[
grandchallenge.core.validators.JSONValidator(
schema={
"$schema": "http://json-schema.org/draft-07/schema",
"items": {
"maximum": 60,
"minimum": 5,
"type": "integer",
},
"type": "array",
}
)
],
),
),
migrations.AddField(
model_name="challengerequest",
name="number_of_submissions_per_team_for_phases",
field=models.JSONField(
default=list,
help_text="Number of submissions per team for each phase",
validators=[
grandchallenge.core.validators.JSONValidator(
schema={
"$schema": "http://json-schema.org/draft-07/schema",
"items": {"minimum": 1, "type": "integer"},
"type": "array",
}
)
],
),
),
migrations.AddField(
model_name="challengerequest",
name="number_of_teams_for_phases",
field=models.JSONField(
default=list,
help_text="Number of teams for each phase",
validators=[
grandchallenge.core.validators.JSONValidator(
schema={
"$schema": "http://json-schema.org/draft-07/schema",
"items": {"minimum": 1, "type": "integer"},
"type": "array",
}
)
],
),
),
migrations.AddField(
model_name="challengerequest",
name="number_of_test_cases_for_phases",
field=models.JSONField(
default=list,
help_text="Number of test images for each phase.",
validators=[
grandchallenge.core.validators.JSONValidator(
schema={
"$schema": "http://json-schema.org/draft-07/schema",
"items": {"minimum": 1, "type": "integer"},
"type": "array",
}
)
],
),
),
migrations.AddField(
model_name="challengerequest",
name="task_id_for_phases",
field=models.JSONField(
default=list,
help_text="Indicate which phase belongs to which task, e.g. [1, 1, 2, 2] means the first two phases below to task 1, the last two phases below to task 2.",
validators=[
grandchallenge.core.validators.JSONValidator(
schema={
"$schema": "http://json-schema.org/draft-07/schema",
"items": {"type": "integer"},
"type": "array",
}
)
],
),
),
migrations.AddField(
model_name="challengerequest",
name="task_ids",
field=models.JSONField(
default=list,
help_text="List the task id's, e.g. [1, 2, 3].",
validators=[
grandchallenge.core.validators.JSONValidator(
schema={
"$schema": "http://json-schema.org/draft-07/schema",
"items": {"type": "integer"},
"type": "array",
"uniqueItems": True,
}
)
],
),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Generated by Django 4.2.23 on 2025-08-20 14:20

from django.db import migrations


def copy_data_to_new_budget_fields(apps, schema_editor): # noqa: C901
ChallengeRequest = apps.get_model( # noqa: N806
"challenges", "ChallengeRequest"
)

for cr in ChallengeRequest.objects.all():
if not cr.algorithm_selectable_gpu_type_choices_for_tasks:
cr.algorithm_selectable_gpu_type_choices_for_tasks = [
cr.algorithm_selectable_gpu_type_choices
] * cr.number_of_tasks
if not cr.algorithm_maximum_settable_memory_gb_for_tasks:
cr.algorithm_maximum_settable_memory_gb_for_tasks = [
cr.algorithm_maximum_settable_memory_gb
] * cr.number_of_tasks
if not cr.average_size_test_case_mb_for_tasks:
cr.average_size_test_case_mb_for_tasks = [
cr.average_size_of_test_image_in_mb
] * cr.number_of_tasks
if not cr.inference_time_average_minutes_for_tasks:
cr.inference_time_average_minutes_for_tasks = [
cr.inference_time_limit_in_minutes
] * cr.number_of_tasks
if not cr.task_ids:
cr.task_ids = list(range(1, cr.number_of_tasks + 1))
if not cr.task_id_for_phases:
cr.task_id_for_phases = [
task_id for task_id in cr.task_ids for _ in range(2)
]
if not cr.number_of_teams_for_phases:
cr.number_of_teams_for_phases = (
[cr.expected_number_of_teams] * 2 * cr.number_of_tasks
)
if not cr.number_of_submissions_per_team_for_phases:
cr.number_of_submissions_per_team_for_phases = [
cr.phase_1_number_of_submissions_per_team,
cr.phase_2_number_of_submissions_per_team,
] * cr.number_of_tasks
if not cr.number_of_test_cases_for_phases:
cr.number_of_test_cases_for_phases = [
cr.phase_1_number_of_test_images,
cr.phase_2_number_of_test_images,
] * cr.number_of_tasks
cr.save()


class Migration(migrations.Migration):

dependencies = [
(
"challenges",
"0062_challengerequest_algorithm_maximum_settable_memory_gb_for_tasks_and_more",
),
]

operations = [
migrations.RunPython(copy_data_to_new_budget_fields, elidable=True)
]
Loading