using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using FarmmapsApi; using FarmmapsApi.Models; using FarmmapsApi.Services; using FarmmapsPoten.Models; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using static FarmmapsApiSamples.Constants; namespace FarmmapsVRApoten { public class PotenApplication : IApplication { private const string DownloadFolder = "Downloads"; private readonly ILogger _logger; private readonly FarmmapsApiService _farmmapsApiService; private readonly PotenService _potenService; private readonly GeneralService _generalService; public PotenApplication(ILogger logger, FarmmapsApiService farmmapsApiService, GeneralService generalService, PotenService potenService) { _logger = logger; _farmmapsApiService = farmmapsApiService; _generalService = generalService; _potenService = potenService; } public async Task RunAsync() { // read field data from separate json file var VRAPotenInputJson = File.ReadAllText("PotenInput.json"); List potenInputs = JsonConvert.DeserializeObject>(VRAPotenInputJson); if (!Directory.Exists(DownloadFolder)) Directory.CreateDirectory(DownloadFolder); // !! this call is needed the first time an api is called with a fresh clientid and secret !! await _farmmapsApiService.GetCurrentUserCodeAsync(); var roots = await _farmmapsApiService.GetCurrentUserRootsAsync(); foreach (var input in potenInputs) { try { await Process(roots, input); } catch (Exception ex) { _logger.LogError(ex.Message); } } } private async Task Process(List roots, PotenInput input) { var meanDensity = input.MeanDensity; var variation = input.Variation; var fieldName = input.FieldName; bool useShadow = input.UseShadow; var myDrive = roots.SingleOrDefault(r => r.Name == "My drive"); if (myDrive == null) { _logger.LogError("Could not find a needed root item"); return; } var uploadedRoot = roots.SingleOrDefault(r => r.Name == "Uploaded"); if (uploadedRoot == null) { _logger.LogError("Could not find a needed root item"); return; } _logger.LogInformation("Creating cropfield"); var cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDrive.Code, $"VRA Poten cropfield {input.OutputFileName}", input.PlantingYear, input.GeometryJson.ToString(Formatting.None)); //Calculating shadow map if (useShadow) { _logger.LogInformation("Calculate shadow map for field"); var shadowItem = await _generalService.RunShadowTask(cropfieldItem); if (shadowItem == null) { _logger.LogError("Something went wrong while obtaining the shadow map"); return; } _logger.LogInformation("Downloading shadow map"); await _farmmapsApiService.DownloadItemAsync(shadowItem.Code, Path.Combine(DownloadFolder, $"{input.OutputFileName}.shadow.zip")); } _logger.LogInformation("Looking for local data to use"); var localDataAvailable = input.File; var geotiffItem = (Item) null; if (String.IsNullOrEmpty(localDataAvailable)) { _logger.LogInformation("Could not find item for uploaded data, using BOFEK"); //Retreiving BOFEK _logger.LogInformation("Get BOFEK for field"); var bofekItem = await _generalService.RunBofekTask(cropfieldItem); if (bofekItem == null) { _logger.LogError("Something went wrong while obtaining the BOFEK data"); return; } _logger.LogInformation("Downloading Bofek map"); await _farmmapsApiService.DownloadItemAsync(bofekItem.Code, Path.Combine(DownloadFolder, $"{input.OutputFileName}.BOFEK.zip")); } else if (input.File.Contains(".tif") || input.File.Contains(".geotiff")) { _logger.LogInformation("input = tiff data"); var dataPath = Path.Combine("Data", input.File); geotiffItem = await _generalService.UploadDataAsync(uploadedRoot, GEOTIFF_PROCESSED_ITEMTYPE, dataPath, Path.GetFileNameWithoutExtension(input.File)); if (geotiffItem == null) { _logger.LogError("Could not find item for uploaded data"); return; } } else { var isGeoJson = input.File.Contains("json"); var dataPath = Path.Combine("Data", input.File); var shapeItem = isGeoJson ? await _generalService.UploadDataAsync(uploadedRoot, SHAPE_PROCESSED_ITEMTYPE, dataPath, Path.GetFileNameWithoutExtension(input.File)) : await _generalService.UploadZipWithShapeAsync(uploadedRoot, dataPath, Path.GetFileNameWithoutExtension(input.File)); if (shapeItem == null) { _logger.LogError("Something went wrong while searching for the shape file"); return; } // transform shape to geotiff as VRA poten only supports tiff input item _logger.LogInformation($"Converting shape to geotiff"); geotiffItem = await _generalService.ShapeToGeotiff(shapeItem); if (geotiffItem == null) { _logger.LogError("Something went wrong with shape to geotiff transformation"); return; } _logger.LogInformation("Downloading geotiff file"); await _farmmapsApiService.DownloadItemAsync(geotiffItem.Code, Path.Combine(DownloadFolder, $"VRApoten_inputGeotiff_{input.OutputFileName}.zip")); } // create appliance map _logger.LogInformation("Calculating application map"); // INPUT IS NEEDED as GEOTIFF var applianceMapItem = await _potenService.CalculateApplicationMapAsync(cropfieldItem, geotiffItem, meanDensity, variation); if (applianceMapItem == null) { return; } _logger.LogInformation("Downloading application map"); await _farmmapsApiService.DownloadItemAsync(applianceMapItem.Code, Path.Combine(DownloadFolder, $"VRApoten_appliancemap_{input.OutputFileName}.zip")); string finalOutput = Path.Combine(DownloadFolder, $"VRApoten_appliancemap_{input.OutputFileName}.zip"); _logger.LogInformation(File.Exists(finalOutput) ? "Download application map completed." : "Something went wrong while downloading."); _logger.LogInformation($"Converting geotiff to shape"); var taskmap = await _generalService.GeotiffToShape(applianceMapItem); if (taskmap == null) { _logger.LogError("Something went wrong with geotiff to shape transformation"); return; } _logger.LogInformation("Downloading taskmap"); await _farmmapsApiService.DownloadItemAsync(taskmap.Code, Path.Combine(DownloadFolder, $"VRApoten_taskmap_{input.OutputFileName}.zip")); } } }