/// <summary> /// Generates the tiles for a zoom level /// </summary> /// <param name="map">Map</param> /// <param name="image">Image</param> /// <param name="zoomLevel">Zoom Level</param> private void GenerateTiles(KartaMap map, Image <Rgba32> image, int zoomLevel) { int maxImageSize = (int)Math.Pow(2, TilePowOfTwo + map.MaxZoom); int imageTargetSize = (int)Math.Pow(2, TilePowOfTwo + zoomLevel); int originalImageWidth = (int)(((float)map.Width / maxImageSize) * imageTargetSize); int originalImageHeight = (int)(((float)map.Height / maxImageSize) * imageTargetSize); int tileCount = (int)Math.Pow(2, zoomLevel); using (Image <Rgba32> resizedImage = image.Clone()) { resizedImage.Mutate(i => i.Resize(imageTargetSize, imageTargetSize)); for (int curX = 0; curX < tileCount; ++curX) { for (int curY = 0; curY < tileCount; ++curY) { if ((curX + 1) * TileSize - originalImageWidth > TileSize) { return; } if ((curY + 1) * TileSize - originalImageHeight > TileSize) { break; } SaveTileImage(map, resizedImage, zoomLevel, curX, curY); } } } }
/// <summary> /// Saves the raw image /// </summary> /// <param name="map">Map for which to process</param> /// <param name="file">Uploaded image file</param> /// <returns>Task for the async task</returns> private async Task SaveRawImage(KartaMap map, IFormFile file) { using (Stream saveStream = _imageAccess.CreateRawImage(map.Id, file.FileName)) { await file.CopyToAsync(saveStream); } }
public async Task <IActionResult> RenameMap(string id, string name) { // Update map KartaMap map = await _mapDbAccess.GetMapById(id); if (map == null) { return(StatusCode((int)HttpStatusCode.NotFound)); } bool hasNameChanged = map.Name != name; map.Name = name; await this.SetModifiedData(_userManager, map); await _mapDbAccess.RenameMap(map); if (hasNameChanged) { await this.SyncMapNameToMarkers(id, name); } await _timelineService.AddTimelineEntry(TimelineEvent.KartaMapUpdated, name, id); return(Ok(id)); }
/// <summary> /// Compares a marker /// </summary> /// <param name="mapId">Id of the map</param> /// <param name="markerId">Id of the marker</param> /// <param name="markerType">Type of the marker</param> /// <param name="currentMarker">Current marker, if null the marker will be loaded</param> /// <returns>Compare Result</returns> public async Task <CompareResult> CompareMarker(string mapId, string markerId, MarkerType markerType, IImplementationComparable currentMarker = null) { KartaMap loadingMap = null; if (currentMarker == null) { loadingMap = await _mapDbAccess.GetMapById(mapId); } IImplementationComparable oldMarker = null; if (markerType == MarkerType.Npc) { oldMarker = await _markerSnapshotDbAccess.GetNpcMarkerSnapshotById(markerId); if (loadingMap != null && loadingMap.NpcMarker != null) { currentMarker = loadingMap.NpcMarker.First(m => m.Id == markerId); } } else if (markerType == MarkerType.Item) { oldMarker = await _markerSnapshotDbAccess.GetItemMarkerSnapshotById(markerId); if (loadingMap != null && loadingMap.ItemMarker != null) { currentMarker = loadingMap.ItemMarker.First(m => m.Id == markerId); } } else if (markerType == MarkerType.MapChange) { oldMarker = await _markerSnapshotDbAccess.GetMapChangeMarkerSnapshotById(markerId); if (loadingMap != null && loadingMap.MapChangeMarker != null) { currentMarker = loadingMap.MapChangeMarker.First(m => m.Id == markerId); } } else if (markerType == MarkerType.Quest) { oldMarker = await _markerSnapshotDbAccess.GetQuestMarkerSnapshotById(markerId); if (loadingMap != null && loadingMap.QuestMarker != null) { currentMarker = loadingMap.QuestMarker.First(m => m.Id == markerId); } } else if (markerType == MarkerType.Note) { oldMarker = await _markerSnapshotDbAccess.GetNoteMarkerSnapshotById(markerId); if (loadingMap != null && loadingMap.NoteMarker != null) { currentMarker = loadingMap.NoteMarker.First(m => m.Id == markerId); } } return(CompareObjects(currentMarker, oldMarker)); }
public async Task <IActionResult> FlagMarkerAsImplemented(string mapId, string markerId, MarkerType markerType) { // Check Data KartaMap map = await _mapDbAccess.GetMapById(mapId); if (map == null) { return(StatusCode((int)HttpStatusCode.NotFound)); } // Flag Marker as implemented if (markerType == MarkerType.Npc && map.NpcMarker != null) { NpcMapMarker marker = map.NpcMarker.First(m => m.Id == markerId); marker.IsImplemented = true; await _markerSnapshotDbAccess.SaveNpcMarkerSnapshot(marker); await _mapDbAccess.UpdateMap(map); } else if (markerType == MarkerType.Item && map.ItemMarker != null) { ItemMapMarker marker = map.ItemMarker.First(m => m.Id == markerId); marker.IsImplemented = true; await _markerSnapshotDbAccess.SaveItemMarkerSnapshot(marker); await _mapDbAccess.UpdateMap(map); } else if (markerType == MarkerType.MapChange && map.MapChangeMarker != null) { MapChangeMapMarker marker = map.MapChangeMarker.First(m => m.Id == markerId); marker.IsImplemented = true; await _markerSnapshotDbAccess.SaveMapChangeMarkerSnapshot(marker); await _mapDbAccess.UpdateMap(map); } else if (markerType == MarkerType.Quest && map.MapChangeMarker != null) { QuestMapMarker marker = map.QuestMarker.First(m => m.Id == markerId); marker.IsImplemented = true; await _markerSnapshotDbAccess.SaveQuestMarkerSnapshot(marker); await _mapDbAccess.UpdateMap(map); } else if (markerType == MarkerType.Note && map.NoteMarker != null) { NoteMapMarker marker = map.NoteMarker.First(m => m.Id == markerId); marker.IsImplemented = true; await _markerSnapshotDbAccess.SaveNoteMarkerSnapshot(marker); await _mapDbAccess.UpdateMap(map); } // Add Timeline entry await _timelineService.AddTimelineEntry(TimelineEvent.ImplementedMarker, mapId, markerId, markerType.ToString(), map.Name); return(Ok()); }
public async Task <IActionResult> DeleteMapMarker(string id, string markerId, MarkerType markerType) { if ((!User.IsInRole(RoleNames.Kirja) && markerType == MarkerType.KirjaPage) || (!User.IsInRole(RoleNames.Kortisto) && markerType == MarkerType.Npc) || (!User.IsInRole(RoleNames.Styr) && markerType == MarkerType.Item) || (!User.IsInRole(RoleNames.Aika) && markerType == MarkerType.Quest)) { return(StatusCode((int)HttpStatusCode.Unauthorized)); } string deleteError = await CheckMarkerReferencesForDelete(markerId); if (!string.IsNullOrEmpty(deleteError)) { return(BadRequest(deleteError)); } KartaMap map = await _mapDbAccess.GetMapById(id); if (markerType == MarkerType.KirjaPage) { DeleteMarkerFromList(map.KirjaPageMarker, markerId); } else if (markerType == MarkerType.Npc) { DeleteMarkerFromList(map.NpcMarker, markerId); await _markerImplementationSnapshotDbAccess.DeleteNpcMarkerSnapshot(markerId); } else if (markerType == MarkerType.Item) { DeleteMarkerFromList(map.ItemMarker, markerId); await _markerImplementationSnapshotDbAccess.DeleteItemMarkerSnapshot(markerId); } else if (markerType == MarkerType.Quest) { DeleteMarkerFromList(map.QuestMarker, markerId); await _markerImplementationSnapshotDbAccess.DeleteQuestMarkerSnapshot(markerId); } else if (markerType == MarkerType.MapChange) { DeleteMarkerFromList(map.MapChangeMarker, markerId); await _markerImplementationSnapshotDbAccess.DeleteMapChangeMarkerSnapshot(markerId); } else if (markerType == MarkerType.Note) { DeleteMarkerFromList(map.NoteMarker, markerId); await _markerImplementationSnapshotDbAccess.DeleteNoteMarkerSnapshot(markerId); } await _mapDbAccess.UpdateMap(map); string localizedMarkerType = _localizer["MarkerType" + markerType.ToString()].Value; await _timelineService.AddTimelineEntry(TimelineEvent.KartaMapMarkerDeleted, map.Name, map.Id, localizedMarkerType); return(Ok(id)); }
public async Task <IActionResult> CreateMap(string name) { // Validate data if (string.IsNullOrEmpty(name)) { return(StatusCode((int)HttpStatusCode.BadRequest)); } string validateResult = this.ValidateImageUploadData(); if (validateResult != null) { return(StatusCode((int)HttpStatusCode.BadRequest, _localizer[validateResult])); } // Prepare Map KartaMap map = new KartaMap(); map.Id = Guid.NewGuid().ToString(); map.Name = name; await this.SetModifiedData(_userManager, map); GoNorthProject project = await _projectDbAccess.GetDefaultProject(); map.ProjectId = project.Id; // Process Map try { await _imageProcessor.ProcessMapImage(map, Request.Form.Files[0]); } catch (Exception ex) { _logger.LogError(ex, "Could not process map image."); _mapImageAccess.DeleteMapFolder(map.Id); return(StatusCode((int)HttpStatusCode.InternalServerError)); } // Save Map try { await _mapDbAccess.CreateMap(map); } catch (Exception ex) { _logger.LogError(ex, "Could not save map."); _mapImageAccess.DeleteMapFolder(map.Id); return(StatusCode((int)HttpStatusCode.InternalServerError)); } await _timelineService.AddTimelineEntry(TimelineEvent.KartaMapCreated, map.Name, map.Id); return(Ok(map.Id)); }
/// <summary> /// Saves a tile image /// </summary> /// <param name="map">Map</param> /// <param name="resizedImage">Resized image for the zoom level</param> /// <param name="zoomLevel">Zoom Level</param> /// <param name="x">X</param> /// <param name="y">Y</param> private void SaveTileImage(KartaMap map, Image <Rgba32> resizedImage, int zoomLevel, int x, int y) { using (Image <Rgba32> cropImage = resizedImage.Clone()) { cropImage.Mutate(i => i.Crop(new Rectangle(x * TileSize, y * TileSize, TileSize, TileSize))); using (Stream imageSaveStream = _imageAccess.CreateTileImage(map.Id, zoomLevel, x, y)) { cropImage.Save(imageSaveStream, new PngEncoder()); } } }
/// <summary> /// Ensures an image has a power of two size /// </summary> /// <param name="map">Map which is being processed</param> /// <param name="image">Image to format</param> private void EnsurePowerOfTwo(KartaMap map, Image <Rgba32> image) { int targetSize = (int)Math.Pow(2, TilePowOfTwo + map.MaxZoom); ResizeOptions fillOptions = new ResizeOptions(); fillOptions.Mode = ResizeMode.BoxPad; fillOptions.Position = AnchorPosition.TopLeft; fillOptions.Size = new SixLabors.Primitives.Size(targetSize, targetSize); image.Mutate(i => i.Resize(fillOptions)); }
/// <summary> /// Determines the map image values (MaxZoom, Size) /// </summary> /// <param name="map">Map to fill with values</param> /// <param name="image">Image to check</param> private void DetermineMapImageValues(KartaMap map, Image <Rgba32> image) { map.Width = image.Width; map.Height = image.Height; int zoomLevels = 0; int zoomLevelSize = Math.Max(map.Width, map.Height); while (zoomLevelSize > TileSize) { zoomLevelSize = zoomLevelSize / 2; ++zoomLevels; } map.MaxZoom = zoomLevels; }
/// <summary> /// Syncs the map name to markers after an update /// </summary> /// <param name="id">Id of the map</param> /// <param name="mapName">New map name</param> /// <returns>Task</returns> private async Task SyncMapNameToMarkers(string id, string mapName) { List<KartaMap> markerResult = await _mapDbAccess.GetAllMapsMapIsMarkedIn(id); foreach(KartaMap curMap in markerResult) { KartaMap map = await _mapDbAccess.GetMapById(curMap.Id); foreach(MapChangeMapMarker curMarker in map.MapChangeMarker) { if(curMarker.MapId == id) { curMarker.MapName = mapName; } } await _mapDbAccess.UpdateMap(map); } }
/// <summary> /// Proccesses an image for a karta map /// </summary> /// <param name="map">Map for which to process</param> /// <param name="file">Uploaded image file</param> /// <returns>Task for the async task</returns> public async Task ProcessMapImage(KartaMap map, IFormFile file) { _imageAccess.EnsureEmptyMapFolder(map.Id); await SaveRawImage(map, file); using (Image <Rgba32> image = OpenRawImage(file)) { DetermineMapImageValues(map, image); EnsurePowerOfTwo(map, image); for (int curZoomLevel = 0; curZoomLevel <= map.MaxZoom; ++curZoomLevel) { GenerateTiles(map, image, curZoomLevel); } } }
/// <summary> /// Syncs the page name to markers after an update /// </summary> /// <param name="id">Id of the page</param> /// <param name="pageName">New page name</param> /// <returns>Task</returns> private async Task SyncPageNameToMarkers(string id, string pageName) { List <KartaMapMarkerQueryResult> markerResult = await _kartaMapDbAccess.GetAllMapsKirjaPageIsMarkedIn(id); foreach (KartaMapMarkerQueryResult curMapQueryResult in markerResult) { KartaMap map = await _kartaMapDbAccess.GetMapById(curMapQueryResult.MapId); foreach (KirjaPageMapMarker curMarker in map.KirjaPageMarker) { if (curMarker.PageId == id) { curMarker.PageName = pageName; } } await _kartaMapDbAccess.UpdateMap(map); } }
/// <summary> /// Syncs the npc name to markers after an update /// </summary> /// <param name="id">Id of the npc</param> /// <param name="npcName">New npc name</param> /// <returns>Task</returns> private async Task SyncNpcNameToMarkers(string id, string npcName) { List <KartaMapMarkerQueryResult> markerResult = await _kartaMapDbAccess.GetAllMapsNpcIsMarkedIn(id); foreach (KartaMapMarkerQueryResult curMapQueryResult in markerResult) { KartaMap map = await _kartaMapDbAccess.GetMapById(curMapQueryResult.MapId); foreach (NpcMapMarker curMarker in map.NpcMarker) { if (curMarker.NpcId == id) { curMarker.NpcName = npcName; } } await _kartaMapDbAccess.UpdateMap(map); } }
/// <summary> /// Syncs kortisto marker label /// </summary> /// <param name="map">Map To sync</param> /// <returns>Task</returns> private async Task SyncKortistoMarkerLabels(KartaMap map) { if (map.NpcMarker == null) { return; } foreach (NpcMapMarker curMarker in map.NpcMarker) { KortistoNpc curNpc = await _kortistoNpcDbAccess.GetFlexFieldObjectById(curMarker.NpcId); if (curNpc == null) { continue; } curMarker.NpcName = curNpc.Name; } }
/// <summary> /// Syncs the karta map change marker labels /// </summary> /// <param name="map">Map To sync</param> /// <returns>Task</returns> private async Task SyncKartaMapChangeMarkerLabels(KartaMap map) { if (map.MapChangeMarker == null) { return; } foreach (MapChangeMapMarker curMarker in map.MapChangeMarker) { KartaMap curMap = await _kartaMapDbAccess.GetMapById(curMarker.MapId); if (curMap == null) { continue; } curMarker.MapName = curMap.Name; } }
/// <summary> /// Syncs kirja marker label /// </summary> /// <param name="map">Map To sync</param> /// <returns>Task</returns> private async Task SyncKirjaMarkerLabels(KartaMap map) { if (map.KirjaPageMarker == null) { return; } foreach (KirjaPageMapMarker curMarker in map.KirjaPageMarker) { KirjaPage curPage = await _kirjaPageDbAccess.GetPageById(curMarker.PageId); if (curPage == null) { continue; } curMarker.PageName = curPage.Name; } }
/// <summary> /// Syncs styr marker label /// </summary> /// <param name="map">Map To sync</param> /// <returns>Task</returns> private async Task SyncStyrMarkerLabels(KartaMap map) { if (map.ItemMarker == null) { return; } foreach (ItemMapMarker curMarker in map.ItemMarker) { StyrItem curItem = await _styrItemDbAccess.GetFlexFieldObjectById(curMarker.ItemId); if (curItem == null) { continue; } curMarker.ItemName = curItem.Name; } }
public async Task<IActionResult> DeleteMap(string id) { string error = await CheckMapReferencesForDeletion(id); if(!string.IsNullOrEmpty(error)) { return BadRequest(error); } await DeleteAdditionalMapReferences(id); KartaMap map = await _mapDbAccess.GetMapById(id); await _mapDbAccess.DeleteMap(map); _logger.LogInformation("Map was deleted."); _mapImageAccess.DeleteMapFolder(map.Id); _logger.LogInformation("Map image was deleted."); await _timelineService.AddTimelineEntry(map.ProjectId, TimelineEvent.KartaMapDeleted, map.Name); return Ok(id); }
public async Task<IActionResult> Map(string id) { KartaMap map = await _mapDbAccess.GetMapById(id); if(!User.IsInRole(RoleNames.Kirja)) { map.KirjaPageMarker = new List<KirjaPageMapMarker>(); } if(!User.IsInRole(RoleNames.Kortisto)) { map.NpcMarker = new List<NpcMapMarker>(); } if(!User.IsInRole(RoleNames.Styr)) { map.ItemMarker = new List<ItemMapMarker>(); } if(!User.IsInRole(RoleNames.Aika)) { map.QuestMarker = new List<QuestMapMarker>(); } return Ok(map); }
public async Task <IActionResult> DeleteMap(string id) { List <KartaMap> kartaMaps = await _mapDbAccess.GetAllMapsMapIsMarkedIn(id); if (kartaMaps.Count > 0) { string markedInMaps = string.Join(", ", kartaMaps.Select(p => p.Name)); return(StatusCode((int)HttpStatusCode.BadRequest, _localizer["CanNotDeleteMapMarkedInKartaMap", markedInMaps].Value)); } KartaMap map = await _mapDbAccess.GetMapById(id); await _mapDbAccess.DeleteMap(map); _logger.LogInformation("Map was deleted."); _mapImageAccess.DeleteMapFolder(map.Id); _logger.LogInformation("Map image was deleted."); await _timelineService.AddTimelineEntry(TimelineEvent.KartaMapDeleted, map.Name); return(Ok(id)); }
public async Task <IActionResult> SaveMapMarker(string id, [FromBody] SaveMarkerRequest markerRequest) { if ((!User.IsInRole(RoleNames.Kirja) && markerRequest.KirjaMarker != null) || (!User.IsInRole(RoleNames.Kortisto) && markerRequest.NpcMarker != null) || (!User.IsInRole(RoleNames.Styr) && markerRequest.ItemMarker != null) || (!User.IsInRole(RoleNames.Aika) && markerRequest.QuestMarker != null)) { return(StatusCode((int)HttpStatusCode.Unauthorized)); } string markerId = string.Empty; string markerType = string.Empty; KartaMap map = await _mapDbAccess.GetMapById(id); if (markerRequest.KirjaMarker != null) { if (map.KirjaPageMarker == null) { map.KirjaPageMarker = new List <KirjaPageMapMarker>(); } markerId = markerRequest.KirjaMarker.Id; markerType = MarkerType.KirjaPage.ToString(); KirjaPageMapMarker existingMarker = map.KirjaPageMarker.FirstOrDefault(m => m.Id == markerRequest.KirjaMarker.Id); if (existingMarker != null) { CopyBaseMarkerAttributes(existingMarker, markerRequest.KirjaMarker); existingMarker.IsImplemented = false; } else { map.KirjaPageMarker.Add(markerRequest.KirjaMarker); } } else if (markerRequest.NpcMarker != null) { if (map.NpcMarker == null) { map.NpcMarker = new List <NpcMapMarker>(); } markerId = markerRequest.NpcMarker.Id; markerType = MarkerType.Npc.ToString(); NpcMapMarker existingMarker = map.NpcMarker.FirstOrDefault(m => m.Id == markerRequest.NpcMarker.Id); if (existingMarker != null) { CopyBaseMarkerAttributes(existingMarker, markerRequest.NpcMarker); existingMarker.IsImplemented = false; } else { map.NpcMarker.Add(markerRequest.NpcMarker); } } else if (markerRequest.ItemMarker != null) { if (map.ItemMarker == null) { map.ItemMarker = new List <ItemMapMarker>(); } markerId = markerRequest.ItemMarker.Id; markerType = MarkerType.Item.ToString(); ItemMapMarker existingMarker = map.ItemMarker.FirstOrDefault(m => m.Id == markerRequest.ItemMarker.Id); if (existingMarker != null) { CopyBaseMarkerAttributes(existingMarker, markerRequest.ItemMarker); existingMarker.IsImplemented = false; } else { map.ItemMarker.Add(markerRequest.ItemMarker); } } else if (markerRequest.QuestMarker != null) { if (map.QuestMarker == null) { map.QuestMarker = new List <QuestMapMarker>(); } markerId = markerRequest.QuestMarker.Id; markerType = MarkerType.Quest.ToString(); QuestMapMarker existingMarker = map.QuestMarker.FirstOrDefault(m => m.Id == markerRequest.QuestMarker.Id); if (existingMarker != null) { CopyBaseMarkerAttributes(existingMarker, markerRequest.QuestMarker); existingMarker.Name = markerRequest.QuestMarker.Name; existingMarker.IsImplemented = false; } else { map.QuestMarker.Add(markerRequest.QuestMarker); } } else if (markerRequest.MapChangeMarker != null) { if (map.MapChangeMarker == null) { map.MapChangeMarker = new List <MapChangeMapMarker>(); } markerId = markerRequest.MapChangeMarker.Id; markerType = MarkerType.MapChange.ToString(); MapChangeMapMarker existingMarker = map.MapChangeMarker.FirstOrDefault(m => m.Id == markerRequest.MapChangeMarker.Id); if (existingMarker != null) { CopyBaseMarkerAttributes(existingMarker, markerRequest.MapChangeMarker); existingMarker.IsImplemented = false; } else { map.MapChangeMarker.Add(markerRequest.MapChangeMarker); } } else if (markerRequest.NoteMarker != null) { if (map.NoteMarker == null) { map.NoteMarker = new List <NoteMapMarker>(); } markerId = markerRequest.NoteMarker.Id; markerType = MarkerType.Note.ToString(); NoteMapMarker existingMarker = map.NoteMarker.FirstOrDefault(m => m.Id == markerRequest.NoteMarker.Id); if (existingMarker != null) { CopyBaseMarkerAttributes(existingMarker, markerRequest.NoteMarker); existingMarker.Name = markerRequest.NoteMarker.Name; existingMarker.Description = markerRequest.NoteMarker.Description; existingMarker.IsImplemented = false; } else { map.NoteMarker.Add(markerRequest.NoteMarker); } } await _mapDbAccess.UpdateMap(map); string localizedMarkerType = _localizer["MarkerType" + markerType].Value; await _timelineService.AddTimelineEntry(TimelineEvent.KartaMapMarkerUpdated, map.Name, map.Id, markerId, markerType, localizedMarkerType); return(Ok(id)); }
public async Task <IActionResult> UpdateMap(string id, string name) { // Validate data if (string.IsNullOrEmpty(name)) { return(StatusCode((int)HttpStatusCode.BadRequest)); } string validateResult = this.ValidateImageUploadData(); if (validateResult != null) { return(StatusCode((int)HttpStatusCode.BadRequest, _localizer[validateResult])); } // Get Old Data KartaMap map = await _mapDbAccess.GetMapById(id); int oldWidth = map.Width; int oldHeight = map.Height; // Rename map bool nameChanged = map.Name != name; map.Name = name; await this.SetModifiedData(_userManager, map); // Rebuild images try { _mapImageAccess.SaveMapImagesForRollback(map.Id); await _imageProcessor.ProcessMapImage(map, Request.Form.Files[0]); } catch (Exception ex) { _mapImageAccess.RollbackMapImages(map.Id); _logger.LogError(ex, "Could not process map image."); return(StatusCode((int)HttpStatusCode.InternalServerError)); } // Scale Map Markers float scaleX = (int)((float)map.Width / oldWidth); float scaleY = (int)((float)map.Height / oldHeight); foreach (MapMarker curMarker in map.NpcMarker) { ScaleMapMarker(curMarker, scaleX, scaleY); } foreach (MapMarker curMarker in map.ItemMarker) { ScaleMapMarker(curMarker, scaleX, scaleY); } foreach (MapMarker curMarker in map.KirjaPageMarker) { ScaleMapMarker(curMarker, scaleX, scaleY); } foreach (MapMarker curMarker in map.QuestMarker) { ScaleMapMarker(curMarker, scaleX, scaleY); } foreach (MapMarker curMarker in map.MapChangeMarker) { ScaleMapMarker(curMarker, scaleX, scaleY); } foreach (MapMarker curMarker in map.NoteMarker) { ScaleMapMarker(curMarker, scaleX, scaleY); } try { await _mapDbAccess.UpdateMap(map); } catch (Exception ex) { _mapImageAccess.RollbackMapImages(map.Id); _logger.LogError(ex, "Could not update map image."); return(StatusCode((int)HttpStatusCode.InternalServerError)); } if (nameChanged) { await SyncMapNameToMarkers(id, name); } // Clean rollback data _mapImageAccess.CleanRollbackMapImages(map.Id); await _timelineService.AddTimelineEntry(TimelineEvent.KartaMapUpdated, name, id); return(Ok(id)); }