From 276665bd4c4a71a4e1eee3359892cf4670c55153 Mon Sep 17 00:00:00 2001 From: Sushil Tiwari Date: Thu, 4 Sep 2025 14:55:42 +0545 Subject: [PATCH 1/2] feat(street): Street tutorial task generation --- .../graphql/types/project_types/street.py | 7 ----- apps/tutorial/graphql/types/types.py | 8 +---- firebase | 2 +- project_types/street/tutorial.py | 30 ++++++++++--------- schema.graphql | 8 ++--- 5 files changed, 20 insertions(+), 35 deletions(-) delete mode 100644 apps/tutorial/graphql/types/project_types/street.py diff --git a/apps/tutorial/graphql/types/project_types/street.py b/apps/tutorial/graphql/types/project_types/street.py deleted file mode 100644 index 0ac3ebaf..00000000 --- a/apps/tutorial/graphql/types/project_types/street.py +++ /dev/null @@ -1,7 +0,0 @@ -import strawberry - -from project_types.street import tutorial as street_tutorial - - -@strawberry.experimental.pydantic.type(model=street_tutorial.StreetTutorialTaskProperty, all_fields=True) -class StreetTutorialTaskPropertyType: ... diff --git a/apps/tutorial/graphql/types/types.py b/apps/tutorial/graphql/types/types.py index a0ad4615..5a92bc3c 100644 --- a/apps/tutorial/graphql/types/types.py +++ b/apps/tutorial/graphql/types/types.py @@ -17,7 +17,6 @@ import apps.project.graphql.types.asset_types # noqa: F401 # isort: skip # type: ignore[reportUnusedImport] -from project_types.street import tutorial as street_tutorial from project_types.tile_map_service.compare import tutorial as compare_tutorial from project_types.tile_map_service.completeness import tutorial as completeness_tutorial from project_types.tile_map_service.find import tutorial as find_tutorial @@ -27,7 +26,6 @@ from .project_types.compare import CompareTutorialTaskPropertyType from .project_types.completeness import CompletenessTutorialTaskPropertyType from .project_types.find import FindTutorialTaskPropertyType -from .project_types.street import StreetTutorialTaskPropertyType from .project_types.validate import ValidateTutorialTaskPropertyType from .project_types.validate_image import ValidateImageTutorialTaskPropertyType @@ -64,7 +62,6 @@ async def project_type_specifics( | ValidateTutorialTaskPropertyType | ValidateImageTutorialTaskPropertyType | CompletenessTutorialTaskPropertyType - | StreetTutorialTaskPropertyType | None ): data = task.project_type_specifics @@ -95,10 +92,7 @@ async def project_type_specifics( completeness_tutorial.CompletenessTutorialTaskProperty.model_validate(data), ) if project_type_enum == Project.Type.STREET: - return typing.cast( - "StreetTutorialTaskPropertyType", - street_tutorial.StreetTutorialTaskProperty.model_validate(data), - ) + return None typing.assert_never(project_type_enum) diff --git a/firebase b/firebase index c2f3bc74..baf3833c 160000 --- a/firebase +++ b/firebase @@ -1 +1 @@ -Subproject commit c2f3bc74c5d5387c51c50e7ac569e378f2fc3e87 +Subproject commit baf3833ca3645c3e0371bcc2f700c8af5411a133 diff --git a/project_types/street/tutorial.py b/project_types/street/tutorial.py index b5816dfb..4b396eeb 100644 --- a/project_types/street/tutorial.py +++ b/project_types/street/tutorial.py @@ -1,5 +1,7 @@ import typing +from osgeo import ogr +from pyfirebase_mapswipe import extended_models as firebase_ext_models from pyfirebase_mapswipe import models as firebase_models from apps.project.models import ProjectTypeEnum @@ -9,12 +11,9 @@ from utils.geo.transform import convert_json_str_to_wkt -class StreetTutorialTaskProperty(base_tutorial.BaseTutorialTaskProperty): - # FIXME(tnagorra): Use geometry from TutorialTask - object_geometry: str +class StreetTutorialTaskProperty(base_tutorial.BaseTutorialTaskProperty): ... -# TODO(susilnem): This is not finalized class StreetTutorial( base_tutorial.BaseTutorial[ StreetProjectProperty, @@ -28,20 +27,24 @@ def __init__(self, tutorial: Tutorial): super().__init__(tutorial) @typing.override - def get_task_specifics_for_firebase(self, task: TutorialTask, index: int): - task_specifics = self.tutorial_task_property_class( - **task.project_type_specifics, - ) - - geometry_wkt = convert_json_str_to_wkt(task_specifics.object_geometry) + def compress_tasks_on_firebase(self) -> bool: + return True + @typing.override + def get_task_specifics_for_firebase(self, task: TutorialTask, index: int): return firebase_models.FbStreetTutorialTask( - taskId=f"t{index}", - geometry=geometry_wkt, - screen=task.scenario.scenario_page_number, + projectId=self.tutorial.firebase_id, + groupId=self.get_tutorial_group_key(), + taskId=f"{index}", + geometry="", referenceAnswer=task.reference, + screen=task.scenario.scenario_page_number, ) + @typing.override + def get_group_specifics_for_firebase(self): + return firebase_ext_models.FbEmptyModel() + @typing.override def get_tutorial_specifics_for_firebase(self): custom_opts = self.project_type_specifics.custom_options @@ -50,7 +53,6 @@ def get_tutorial_specifics_for_firebase(self): assert projectType == 7, "Project Street should be 7" return firebase_models.FbStreetTutorial( - zoomLevel=14, projectType=projectType, customOptions=[ firebase_models.FbObjCustomOption( diff --git a/schema.graphql b/schema.graphql index ca858d87..24d2fb4a 100644 --- a/schema.graphql +++ b/schema.graphql @@ -326,7 +326,7 @@ type CompareTutorialTaskPropertyType { tileZ: Int! } -union CompareTutorialTaskPropertyTypeFindTutorialTaskPropertyTypeValidateTutorialTaskPropertyTypeValidateImageTutorialTaskPropertyTypeCompletenessTutorialTaskPropertyTypeStreetTutorialTaskPropertyType = CompareTutorialTaskPropertyType | CompletenessTutorialTaskPropertyType | FindTutorialTaskPropertyType | StreetTutorialTaskPropertyType | ValidateImageTutorialTaskPropertyType | ValidateTutorialTaskPropertyType +union CompareTutorialTaskPropertyTypeFindTutorialTaskPropertyTypeValidateTutorialTaskPropertyTypeValidateImageTutorialTaskPropertyTypeCompletenessTutorialTaskPropertyType = CompareTutorialTaskPropertyType | CompletenessTutorialTaskPropertyType | FindTutorialTaskPropertyType | ValidateImageTutorialTaskPropertyType | ValidateTutorialTaskPropertyType input CompletenessProjectPropertyInput { """Numeric value as string""" @@ -2152,10 +2152,6 @@ type StreetProjectPropertyType { mapillaryImageFilters: StreetMapillaryImageFilters! } -type StreetTutorialTaskPropertyType { - objectGeometry: String! -} - """Model representing assets for a tutorial.""" input TutorialAssetCreateInput { clientId: String! @@ -2505,7 +2501,7 @@ type TutorialTaskType implements UserResourceTypeMixin { id: ID! modifiedAt: DateTime! modifiedBy: UserType! - projectTypeSpecifics: CompareTutorialTaskPropertyTypeFindTutorialTaskPropertyTypeValidateTutorialTaskPropertyTypeValidateImageTutorialTaskPropertyTypeCompletenessTutorialTaskPropertyTypeStreetTutorialTaskPropertyType + projectTypeSpecifics: CompareTutorialTaskPropertyTypeFindTutorialTaskPropertyTypeValidateTutorialTaskPropertyTypeValidateImageTutorialTaskPropertyTypeCompletenessTutorialTaskPropertyType reference: Int! scenarioId: ID! } From b8062444acdcf755dd1e4fd481b76106e7acc68e Mon Sep 17 00:00:00 2001 From: Sushil Tiwari Date: Mon, 8 Sep 2025 14:07:58 +0545 Subject: [PATCH 2/2] feat(street): Add tutorial task property for the street project --- apps/tutorial/graphql/inputs/inputs.py | 2 ++ .../graphql/inputs/project_types/street.py | 7 +++++++ .../graphql/types/project_types/street.py | 7 +++++++ apps/tutorial/graphql/types/types.py | 8 +++++++- firebase | 2 +- project_types/street/tutorial.py | 11 +++++++---- schema.graphql | 15 +++++++++++++-- 7 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 apps/tutorial/graphql/inputs/project_types/street.py create mode 100644 apps/tutorial/graphql/types/project_types/street.py diff --git a/apps/tutorial/graphql/inputs/inputs.py b/apps/tutorial/graphql/inputs/inputs.py index 56943640..2d0c9b39 100644 --- a/apps/tutorial/graphql/inputs/inputs.py +++ b/apps/tutorial/graphql/inputs/inputs.py @@ -23,6 +23,7 @@ from .project_types.compare import CompareTutorialTaskPropertyInput from .project_types.completeness import CompletenessTutorialTaskPropertyInput from .project_types.find import FindTutorialTaskPropertyInput +from .project_types.street import StreetTutorialTaskPropertyInput from .project_types.validate import ValidateTutorialTaskPropertyInput from .project_types.validate_image import ValidateImageTutorialTaskPropertyInput @@ -34,6 +35,7 @@ class TutorialTaskProjectTypeSpecificInput: validate: ValidateTutorialTaskPropertyInput | None = strawberry.UNSET validate_image: ValidateImageTutorialTaskPropertyInput | None = strawberry.UNSET completeness: CompletenessTutorialTaskPropertyInput | None = strawberry.UNSET + street: StreetTutorialTaskPropertyInput | None = strawberry.UNSET @strawberry_django.input(TutorialTask) diff --git a/apps/tutorial/graphql/inputs/project_types/street.py b/apps/tutorial/graphql/inputs/project_types/street.py new file mode 100644 index 00000000..1d2c6ad1 --- /dev/null +++ b/apps/tutorial/graphql/inputs/project_types/street.py @@ -0,0 +1,7 @@ +import strawberry + +from project_types.street import tutorial as street_tutorial + + +@strawberry.experimental.pydantic.input(model=street_tutorial.StreetTutorialTaskProperty, all_fields=True) +class StreetTutorialTaskPropertyInput: ... diff --git a/apps/tutorial/graphql/types/project_types/street.py b/apps/tutorial/graphql/types/project_types/street.py new file mode 100644 index 00000000..0ac3ebaf --- /dev/null +++ b/apps/tutorial/graphql/types/project_types/street.py @@ -0,0 +1,7 @@ +import strawberry + +from project_types.street import tutorial as street_tutorial + + +@strawberry.experimental.pydantic.type(model=street_tutorial.StreetTutorialTaskProperty, all_fields=True) +class StreetTutorialTaskPropertyType: ... diff --git a/apps/tutorial/graphql/types/types.py b/apps/tutorial/graphql/types/types.py index 5a92bc3c..a0ad4615 100644 --- a/apps/tutorial/graphql/types/types.py +++ b/apps/tutorial/graphql/types/types.py @@ -17,6 +17,7 @@ import apps.project.graphql.types.asset_types # noqa: F401 # isort: skip # type: ignore[reportUnusedImport] +from project_types.street import tutorial as street_tutorial from project_types.tile_map_service.compare import tutorial as compare_tutorial from project_types.tile_map_service.completeness import tutorial as completeness_tutorial from project_types.tile_map_service.find import tutorial as find_tutorial @@ -26,6 +27,7 @@ from .project_types.compare import CompareTutorialTaskPropertyType from .project_types.completeness import CompletenessTutorialTaskPropertyType from .project_types.find import FindTutorialTaskPropertyType +from .project_types.street import StreetTutorialTaskPropertyType from .project_types.validate import ValidateTutorialTaskPropertyType from .project_types.validate_image import ValidateImageTutorialTaskPropertyType @@ -62,6 +64,7 @@ async def project_type_specifics( | ValidateTutorialTaskPropertyType | ValidateImageTutorialTaskPropertyType | CompletenessTutorialTaskPropertyType + | StreetTutorialTaskPropertyType | None ): data = task.project_type_specifics @@ -92,7 +95,10 @@ async def project_type_specifics( completeness_tutorial.CompletenessTutorialTaskProperty.model_validate(data), ) if project_type_enum == Project.Type.STREET: - return None + return typing.cast( + "StreetTutorialTaskPropertyType", + street_tutorial.StreetTutorialTaskProperty.model_validate(data), + ) typing.assert_never(project_type_enum) diff --git a/firebase b/firebase index baf3833c..23eadc93 160000 --- a/firebase +++ b/firebase @@ -1 +1 @@ -Subproject commit baf3833ca3645c3e0371bcc2f700c8af5411a133 +Subproject commit 23eadc9377d026ff7107c9b9fb0cc1624f4f9a6f diff --git a/project_types/street/tutorial.py b/project_types/street/tutorial.py index 4b396eeb..ff7d5ac6 100644 --- a/project_types/street/tutorial.py +++ b/project_types/street/tutorial.py @@ -1,6 +1,5 @@ import typing -from osgeo import ogr from pyfirebase_mapswipe import extended_models as firebase_ext_models from pyfirebase_mapswipe import models as firebase_models @@ -8,10 +7,13 @@ from apps.tutorial.models import Tutorial, TutorialTask from project_types.base import tutorial as base_tutorial from project_types.street.project import StreetProjectProperty -from utils.geo.transform import convert_json_str_to_wkt +from utils import fields as custom_fields -class StreetTutorialTaskProperty(base_tutorial.BaseTutorialTaskProperty): ... +class StreetTutorialTaskProperty(base_tutorial.BaseTutorialTaskProperty): + mapillary_image_id: custom_fields.PydanticLongText + # NOTE: geometry is not used but we are saving this for the records + geometry: str class StreetTutorial( @@ -32,10 +34,11 @@ def compress_tasks_on_firebase(self) -> bool: @typing.override def get_task_specifics_for_firebase(self, task: TutorialTask, index: int): + task_specifics = self.tutorial_task_property_class.model_validate(task.project_type_specifics) return firebase_models.FbStreetTutorialTask( projectId=self.tutorial.firebase_id, groupId=self.get_tutorial_group_key(), - taskId=f"{index}", + taskId=task_specifics.mapillary_image_id, geometry="", referenceAnswer=task.reference, screen=task.scenario.scenario_page_number, diff --git a/schema.graphql b/schema.graphql index 24d2fb4a..20efe53f 100644 --- a/schema.graphql +++ b/schema.graphql @@ -326,7 +326,7 @@ type CompareTutorialTaskPropertyType { tileZ: Int! } -union CompareTutorialTaskPropertyTypeFindTutorialTaskPropertyTypeValidateTutorialTaskPropertyTypeValidateImageTutorialTaskPropertyTypeCompletenessTutorialTaskPropertyType = CompareTutorialTaskPropertyType | CompletenessTutorialTaskPropertyType | FindTutorialTaskPropertyType | ValidateImageTutorialTaskPropertyType | ValidateTutorialTaskPropertyType +union CompareTutorialTaskPropertyTypeFindTutorialTaskPropertyTypeValidateTutorialTaskPropertyTypeValidateImageTutorialTaskPropertyTypeCompletenessTutorialTaskPropertyTypeStreetTutorialTaskPropertyType = CompareTutorialTaskPropertyType | CompletenessTutorialTaskPropertyType | FindTutorialTaskPropertyType | StreetTutorialTaskPropertyType | ValidateImageTutorialTaskPropertyType | ValidateTutorialTaskPropertyType input CompletenessProjectPropertyInput { """Numeric value as string""" @@ -2152,6 +2152,16 @@ type StreetProjectPropertyType { mapillaryImageFilters: StreetMapillaryImageFilters! } +input StreetTutorialTaskPropertyInput { + geometry: String! + mapillaryImageId: String! +} + +type StreetTutorialTaskPropertyType { + geometry: String! + mapillaryImageId: String! +} + """Model representing assets for a tutorial.""" input TutorialAssetCreateInput { clientId: String! @@ -2489,6 +2499,7 @@ input TutorialTaskProjectTypeSpecificInput @oneOf { compare: CompareTutorialTaskPropertyInput completeness: CompletenessTutorialTaskPropertyInput find: FindTutorialTaskPropertyInput + street: StreetTutorialTaskPropertyInput validate: ValidateTutorialTaskPropertyInput validateImage: ValidateImageTutorialTaskPropertyInput } @@ -2501,7 +2512,7 @@ type TutorialTaskType implements UserResourceTypeMixin { id: ID! modifiedAt: DateTime! modifiedBy: UserType! - projectTypeSpecifics: CompareTutorialTaskPropertyTypeFindTutorialTaskPropertyTypeValidateTutorialTaskPropertyTypeValidateImageTutorialTaskPropertyTypeCompletenessTutorialTaskPropertyType + projectTypeSpecifics: CompareTutorialTaskPropertyTypeFindTutorialTaskPropertyTypeValidateTutorialTaskPropertyTypeValidateImageTutorialTaskPropertyTypeCompletenessTutorialTaskPropertyTypeStreetTutorialTaskPropertyType reference: Int! scenarioId: ID! }