11import json
22import logging
3+ import math
34import typing
45from typing import Any , TypedDict
56
2728class ValidFeature (Feature [Polygon | MultiPolygon , dict [str , Any ]]): ...
2829
2930
30- class ValidateRawGroupItem (TypedDict ):
31+ class StreetRawGroupItem (TypedDict ):
3132 feature_ids : list [int ]
3233 features : list [ValidFeature ]
3334
3435
35- def group_input_geometries (features : list [ValidFeature ], group_size : int , tutorial : bool = False ):
36- groups : dict [str , ValidateRawGroupItem ] = {}
37-
38- # we will simply start with min group id = 100
39- group_id = 100
40- group_id_string = f"g{ group_id } "
41- for feature_count , feature in enumerate (features ):
42- feature_id = feature_count + 1
43- if feature_id % (group_size + 1 ) == 0 :
44- group_id += 1
45- group_id_string = f"g{ group_id } "
46-
47- try :
48- groups [group_id_string ]
49- except KeyError :
50- new_feature_group : ValidateRawGroupItem = {"feature_ids" : [], "features" : []}
51- groups [group_id_string ] = new_feature_group
52-
53- # we use a new id here based on the count
54- # since we are not sure that GetFID returns unique values
55- if not tutorial :
56- groups [group_id_string ]["feature_ids" ].append (feature_id )
57- # In the tutorial the feature id is defined by the "screen" attribute.
58- # We do this so that we can sort by the feature id later and
59- # get the screens displayed in the right order on the app.
60- elif feature .properties is not None :
61- groups [group_id_string ]["feature_ids" ].append (
62- feature .properties ["screen" ],
63- )
64- groups [group_id_string ]["features" ].append (feature )
65-
66- return groups
67-
68-
6936class StreetMappilaryImageFilters (BaseModel ):
7037 is_pano : bool | None = Field (
7138 default = None ,
@@ -97,7 +64,7 @@ class StreetMappilaryImageFilters(BaseModel):
9764 )
9865
9966
100- class StreetProperty (base_project .BaseProjectProperty ):
67+ class StreetProjectProperty (base_project .BaseProjectProperty ):
10168 aoi_geometry : custom_fields .PydanticId
10269 custom_options : list [CustomOption ] | None = None
10370 mappilary_image_filters : StreetMappilaryImageFilters
@@ -114,14 +81,14 @@ class StreetTaskProperty(base_project.BaseProjectTaskProperty):
11481
11582class StreetProject (
11683 base_project .BaseProject [
117- StreetProperty ,
84+ StreetProjectProperty ,
11885 StreetTaskGroupProperty ,
11986 StreetTaskProperty ,
120- list [ ValidFeature ] ,
121- ValidateRawGroupItem ,
87+ StreetRawGroupItem ,
88+ list [ tuple [ int , ValidFeature ]] ,
12289 ],
12390):
124- project_property_class = StreetProperty
91+ project_property_class = StreetProjectProperty
12592 project_task_group_property_class = StreetTaskGroupProperty
12693 project_task_property_class = StreetTaskProperty
12794
@@ -131,7 +98,7 @@ def __init__(self, project: Project):
13198 assert project .project_type == ProjectTypeEnum .STREET , f"{ type (self )} is defined for STREET"
13299
133100 @typing .override
134- def validate (self ) -> list [ ValidFeature ] :
101+ def validate (self ) -> StreetRawGroupItem :
135102 """Validate project before creating groups"""
136103 self .project .update_processing_status (Project .ProcessingStatus .VALIDATING_GEOMETRY , True )
137104
@@ -147,7 +114,7 @@ def validate(self) -> list[ValidFeature]:
147114
148115 mappilary_image_filters = self .project_type_specifics .mappilary_image_filters
149116
150- image_ids , geometries = get_image_metadata (
117+ image_metadata_data = get_image_metadata (
151118 aoi_geojson = aoi_geojson ,
152119 is_pano = mappilary_image_filters .is_pano ,
153120 creator_id = mappilary_image_filters .creator_id ,
@@ -157,19 +124,24 @@ def validate(self) -> list[ValidFeature]:
157124 randomize_order = mappilary_image_filters .randomize_order ,
158125 sampling_threshold = mappilary_image_filters .sampling_threshold ,
159126 )
127+ return StreetRawGroupItem (
128+ feature_ids = image_metadata_data ["ids" ],
129+ features = image_metadata_data ["geometries" ],
130+ )
160131
161132 @typing .override
162- def create_tasks (self , group : ProjectTaskGroup , raw_group : ValidateRawGroupItem ) -> int :
133+ def create_tasks (
134+ self ,
135+ / ,
136+ group : ProjectTaskGroup ,
137+ raw_group : list [tuple [int , ValidFeature ]],
138+ previous_tasks_count : int ,
139+ ) -> int :
163140 """Create tasks for a group."""
164141 bulk_mgr = BulkCreateManager (chunk_size = 1000 )
142+ tasks_count = previous_tasks_count
165143
166- tasks_count = 0
167- features = raw_group ["features" ]
168- f_ids = raw_group ["feature_ids" ]
169-
170- for i , f_id in enumerate (f_ids ):
171- feature = features [i ]
172-
144+ for f_id , feature in raw_group :
173145 if feature .geometry is not None :
174146 geom = ogr .CreateGeometryFromJson (
175147 feature .geometry .model_dump_json (),
@@ -198,13 +170,21 @@ def create_tasks(self, group: ProjectTaskGroup, raw_group: ValidateRawGroupItem)
198170 return tasks_count
199171
200172 @typing .override
201- def create_groups (self , resp : list [ ValidFeature ] ):
173+ def create_groups (self , resp : StreetRawGroupItem ):
202174 self .project .update_processing_status (Project .ProcessingStatus .GENERATING_GROUPS_AND_TASKS , True )
203- raw_groups = group_input_geometries (resp , self .project .group_size )
175+ number_of_groups = math .ceil (len (resp ["feature_ids" ]) / self .project .group_size )
176+
177+ total_tasks_accumulated : int = 0
178+
179+ for group_id in range (number_of_groups ):
180+ start_index = group_id * self .project .group_size
181+ end_index = start_index + self .project .group_size
204182
205- for group_key , raw_group in raw_groups .items ():
183+ group_features = resp ["features" ][start_index :end_index ]
184+ group_feature_ids = resp ["feature_ids" ][start_index :end_index ]
185+ raw_group = list (zip (group_feature_ids , group_features , strict = True ))
206186 new_group = ProjectTaskGroup .objects .create (
207- firebase_id = group_key ,
187+ firebase_id = f"g { group_id } " ,
208188 project_id = self .project .pk ,
209189 number_of_tasks = 0 ,
210190 progress = 0 ,
@@ -214,8 +194,9 @@ def create_groups(self, resp: list[ValidFeature]):
214194 )
215195
216196 # Create new tasks for this group
217- total_tasks = self .create_tasks (new_group , raw_group )
197+ total_tasks = self .create_tasks (new_group , raw_group , total_tasks_accumulated )
218198 logger .info ("Created %s tasks for group: %s" , total_tasks , new_group .pk )
199+ total_tasks_accumulated += total_tasks
219200
220201 @typing .override
221202 def post_create_groups (self ):
0 commit comments