def __merge_with_cursor(cursor, to_merge_id, sovereign_state_id): assert isinstance(to_merge_id, int) assert isinstance(sovereign_state_id, int) to_merge = StateCRUD.get(cursor, to_merge_id) sovereign = StateCRUD.get(cursor, sovereign_state_id) if to_merge.validity_start < sovereign.validity_start or to_merge.validity_end > sovereign.validity_end: raise MergeStateConflictException( f'The state to merge period {(to_merge.validity_start, to_merge.validity_end)} overflows the period of the sovereign state {(sovereign.validity_start, sovereign.validity_end)}', [ t.territory_id for t in TerritoryCRUD.get_by_state(cursor, to_merge_id) ]) territories_to_change = TerritoryCRUD.get_by_state(cursor, to_merge_id) for territory in territories_to_change: # Color integrity check its_color = territory.color if not its_color: candidate_colors = [ r.color for r in to_merge.representations if r.period_intersects( territory.validity_start, territory.validity_end) ] # All representation matching with the territory have similar color => territory color can be determined (else too complex nothing is done) if all( colours_roughly_equal(candidate_colors[0], c) for c in candidate_colors[1:]): its_color = candidate_colors[0] if its_color: sovereign_color = [ r.color for r in sovereign.representations if r.period_intersects( territory.validity_start, territory.validity_end) ] if all( colours_roughly_equal(c, its_color) for c in sovereign_color): territory.color = None # Destination color is different => set the territory color to preserve it else: territory.color = its_color TerritoryCRUD.edit(cursor, territory, change_color=True) territory.state_id = sovereign_state_id TerritoryCRUD.edit(cursor, territory, change_state_id=True) StateCRUD.delete(cursor, to_merge_id) return sovereign_state_id
def _assign_to_state(cursor, territory, target_state_id): assert isinstance(territory, Territory) assert isinstance(target_state_id, int) created_territories_ids = [] target_state = StateCRUD.get(cursor, target_state_id) if target_state.validity_end <= territory.validity_start or target_state.validity_start >= territory.validity_end: raise BadRequest( f'The territory goes from {territory.validity_start} to {territory.validity_end} and has no time in common with state from {target_state.validity_start} to {target_state.validity_end}' ) if target_state.validity_end < territory.validity_end: to_add_at_end = Territory(None, territory.representations, territory.state_id, territory.bounding_box, target_state.validity_end, territory.validity_end, territory.color, territory.name) created_territories_ids.append( TerritoryCRUD.add(cursor, to_add_at_end)) territory.validity_end = target_state.validity_end TerritoryCRUD.edit(cursor, territory, change_end=True) if target_state.validity_start > territory.validity_start: to_add_at_start = Territory(None, territory.representations, territory.state_id, territory.bounding_box, territory.validity_start, target_state.validity_start, territory.color, territory.name) created_territories_ids.append( TerritoryCRUD.add(cursor, to_add_at_start)) territory.validity_start = target_state.validity_start TerritoryCRUD.edit(cursor, territory, change_start=True) new_color = TerritoryTag._get_color_for_territory( territory, StateCRUD.get(cursor, territory.state_id), target_state) if new_color != territory.color: territory.color = new_color TerritoryCRUD.edit(cursor, territory, change_color=True) territory.state_id = target_state.state_id TerritoryCRUD.edit(cursor, territory, change_state_id=True) return created_territories_ids
def delete(territory_id): with get_cursor() as cursor: territory = TerritoryCRUD.get(cursor, territory_id) state = StateCRUD.get(cursor, territory.state_id) if len(state.representations ) == 1 and not state.representations[0].name: its_territories = TerritoryCRUD.get_by_state( cursor, territory.state_id) if len(its_territories) == 1: StateCRUD.delete(cursor, state.state_id) return { "deleted_state": state.state_id, "deleted_territory": territory_id } TerritoryCRUD.delete(cursor, territory_id) return {"deleted_state": None, "deleted_territory": territory_id}
def post(territory): assert isinstance(territory, Territory) with get_cursor() as cursor: state = StateCRUD.get(cursor, territory.state_id) if territory.validity_start < state.validity_start or territory.validity_end > state.validity_end: raise Conflict( f"Cannot add territory ({territory.validity_start} , {territory.validity_end}) to state ({state.validity_start}, {state.validity_end}) : period overflows" ) potentially_intersecting = TerritoryCRUD.get_within_bbox_in_period( cursor, territory.bounding_box, territory.validity_start, territory.validity_end, 0) t_conflict_ids = [ other.territory_id for other in potentially_intersecting if territories_conflict(territory, other) ] if len(t_conflict_ids): raise Conflict( f"Cannot add the territory : it conflicts with territories {t_conflict_ids}" ) compressed_territory = compress_territory(territory) return TerritoryCRUD.add(cursor, compressed_territory)
def get(state_id): assert isinstance(state_id, int) with get_cursor() as cursor: return StateCRUD.get(cursor, state_id)