From 84f27db16e828d20b1511de9f0a44ff613eae8de Mon Sep 17 00:00:00 2001 From: tamara Date: Tue, 27 Feb 2024 15:44:07 +0100 Subject: [PATCH] DataCropfieldCharacteristics as an array containing cropyield and possibly strawyield. If no strawyield is filled in then straw remains in field. --- FarmmapsKPI/KPIApplication.cs | 22 ++- FarmmapsKPI/KPIInput.json | 258 ++++++++++++++++++++++++++------- FarmmapsKPI/Models/KPIInput.cs | 2 +- 3 files changed, 218 insertions(+), 64 deletions(-) diff --git a/FarmmapsKPI/KPIApplication.cs b/FarmmapsKPI/KPIApplication.cs index 312c002..e76b07f 100644 --- a/FarmmapsKPI/KPIApplication.cs +++ b/FarmmapsKPI/KPIApplication.cs @@ -88,7 +88,7 @@ namespace FarmmapsKPI TimeSpan tsTotalEstimated; for (int i = 0; i < fieldsInputs.Count; i++) - //for (int i = 3; i < 4; i++) + //for (int i = 10; i < 12; i++) { watch.Restart(); input = fieldsInputs[i]; @@ -182,21 +182,27 @@ namespace FarmmapsKPI SaveSettings(settingsfile); } - // The cropfieldCharacteristicItem is used to enter crop yields + // The cropfieldCharacteristicItem is used to enter crop yields and/or straw yields Item cropfieldCharacteristicItem; + string dataCropfieldCharacteristic; //1 useExistingCropfieldWithChildren = false -> create new //2 useExistingCropfieldWithChildren = true && input.CropfieldCharacteristicItemCode = "" or absent -> read from settings json //3 useExistingCropfieldWithChildren = true && input.CropfieldCharacteristicItemCode like "deb48a74c5b54299bb852f17288010e9" in KPIinput -> use this one if (useExistingCropfieldWithChildren == false) { - _logger.LogInformation("CreateCropfieldCharacteristicItemAsync ..."); - cropfieldCharacteristicItem = await _generalService.CreateCropfieldCharacteristicItemAsync(cropfieldItem.Code, cropYear, fieldGeom, input.DataCropfieldCharacteristic.ToString(Formatting.None)); - _settings.CropfieldCharacteristicItemCode = cropfieldCharacteristicItem.Code; - SaveSettings(settingsfile); + for (int i = 0; i < input.DataCropfieldCharacteristics.Length; i++) + { + dataCropfieldCharacteristic = input.DataCropfieldCharacteristics[i].ToString(Formatting.None); + dynamic data = JObject.Parse(dataCropfieldCharacteristic); + _logger.LogInformation($"CreateCropfieldCharacteristicItemAsync ... for cropfieldCharacteristic {i}: '{data.label}', value '{data.value}'"); + cropfieldCharacteristicItem = await _generalService.CreateCropfieldCharacteristicItemAsync(cropfieldItem.Code, cropYear, fieldGeom, dataCropfieldCharacteristic); + _settings.CropfieldCharacteristicItemCode = cropfieldCharacteristicItem.Code; + SaveSettings(settingsfile); + } } else if (string.IsNullOrEmpty(input.CropfieldItemCode)) { - _logger.LogInformation("reading OperationItemCode from settings file"); + _logger.LogInformation("reading CropfieldCharacteristicItemCode from settings file"); cropfieldCharacteristicItem = await _farmmapsApiService.GetItemAsync(_settings.CropfieldCharacteristicItemCode); } else @@ -362,7 +368,7 @@ namespace FarmmapsKPI //additional criterion for while loop: check if it really contains the E1 mbp elements. //while (trycnt == 0 || ((KPIItems.Count < targetKPIitemsCount || boolAquaticLife == false) & trycnt < maxtries)) //normal while loop - targetKPIitemsCount = 7; //if we know we should be getting 7 KPI items (A1,B1,B2,C1,D1,F1,F2) //8 if also E1 + targetKPIitemsCount = 8; //if we know we should be getting 8 KPI items (A1,B1,B2,C1,D1,E1,F1,F2) while (trycnt == 0 || (KPIItems.Count < targetKPIitemsCount & trycnt < maxtries)) { _logger.LogInformation($"Call nr {trycnt + 1}"); diff --git a/FarmmapsKPI/KPIInput.json b/FarmmapsKPI/KPIInput.json index a891c5a..c43fc1e 100644 --- a/FarmmapsKPI/KPIInput.json +++ b/FarmmapsKPI/KPIInput.json @@ -24,12 +24,14 @@ "OperationItemCodes": [], // could contain for example this: ["4d1a6f28ea3f414180663baa4b08c60f"] or ["4d1a6f28ea3f414180663baa4b08c60f","21e08386f0454ad79acfebf78649d59b"] if these are the operations of the provided CropRecordingItemCode. And then if useExistingCropfieldWithChildren = true, these would be used "dataOperations": [], //leaving the operations empty means no fertilizer is applied "CropfieldCharacteristicItemCode": "", - "DataCropfieldCharacteristic": { - //PO20231029: not different yields from different parts of fields? - "code": "860619", //PO20231004: so what does this code mean? Can we see the code list somewhere? - "label": "cropyield", - "value": "48.01" - }, + "DataCropfieldCharacteristics": [ + { + //PO20231029: not different yields from different parts of fields? + "code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha + "label": "cropyield", + "value": "48.01" + } + ], //"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\Downloads\ "CropYear": 2022, //geometryJson = polygon of location of the cropfield, coordinates in LON,LAT (LON: decimal degrees East, LAT: decimal degrees North) @@ -86,12 +88,14 @@ "OperationItemCodes": [], // could contain for example this: ["4d1a6f28ea3f414180663baa4b08c60f"] or ["4d1a6f28ea3f414180663baa4b08c60f","21e08386f0454ad79acfebf78649d59b"] if these are the operations of the provided CropRecordingItemCode. And then if useExistingCropfieldWithChildren = true, these would be used "dataOperations": [], //leaving the operations empty means no fertilizer is applied "CropfieldCharacteristicItemCode": "", - "DataCropfieldCharacteristic": { - //PO20231029: not different yields from different parts of fields? - "code": "860619", //PO20231004: so what does this code mean? Can we see the code list somewhere? - "label": "cropyield", - "value": "48.01" - }, + "DataCropfieldCharacteristics": [ + { + //PO20231029: not different yields from different parts of fields? + "code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha + "label": "cropyield", + "value": "48.01" + } + ], //"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\Downloads\ "CropYear": 2022, //geometryJson = polygon of location of the cropfield, coordinates in LON,LAT (LON: decimal degrees East, LAT: decimal degrees North) @@ -148,12 +152,14 @@ "OperationItemCodes": [], // could contain for example this: ["4d1a6f28ea3f414180663baa4b08c60f"] or ["4d1a6f28ea3f414180663baa4b08c60f","21e08386f0454ad79acfebf78649d59b"] if these are the operations of the provided CropRecordingItemCode. And then if useExistingCropfieldWithChildren = true, these would be used "dataOperations": [], //leaving the operations empty means no fertilizer is applied "CropfieldCharacteristicItemCode": "", - "DataCropfieldCharacteristic": { - //PO20231029: not different yields from different parts of fields? - "code": "860619", //PO20231004: so what does this code mean? Can we see the code list somewhere? - "label": "cropyield", - "value": "48.01" - }, + "DataCropfieldCharacteristics": [ + { + //PO20231029: not different yields from different parts of fields? + "code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha + "label": "cropyield", + "value": "48.01" + } + ], //"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\Downloads\ "CropYear": 2022, //geometryJson = polygon of location of the cropfield, coordinates in LON,LAT (LON: decimal degrees East, LAT: decimal degrees North) @@ -241,11 +247,13 @@ } ], "CropfieldCharacteristicItemCode": "", - "DataCropfieldCharacteristic": { - "code": "860619", //PO20231004: so what does this code mean? Can we see the code list somewhere? - "label": "cropyield", - "value": "48.01" - }, + "DataCropfieldCharacteristics": [ + { + "code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha + "label": "cropyield", + "value": "48.01" + } + ], //"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_WURtest\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Downloads\ "CropYear": 2022, "geometryJson": { @@ -314,11 +322,13 @@ } ], "CropfieldCharacteristicItemCode": "", - "DataCropfieldCharacteristic": { - "code": "860619", //PO20231004: so what does this code mean? Can we see the code list somewhere? - "label": "cropyield", - "value": "48.01" - }, + "DataCropfieldCharacteristics": [ + { + "code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha + "label": "cropyield", + "value": "48.01" + } + ], //"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_WURtest\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Downloads\ "CropYear": 2022, "geometryJson": { @@ -387,11 +397,13 @@ } ], "CropfieldCharacteristicItemCode": "", - "DataCropfieldCharacteristic": { - "code": "860619", //PO20231004: so what does this code mean? Can we see the code list somewhere? - "label": "cropyield", - "value": "48.01" - }, + "DataCropfieldCharacteristics": [ + { + "code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha + "label": "cropyield", + "value": "48.01" + } + ], //"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_WURtest\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Downloads\ "CropYear": 2022, "geometryJson": { @@ -460,11 +472,13 @@ } ], "CropfieldCharacteristicItemCode": "", - "DataCropfieldCharacteristic": { - "code": "860619", //PO20231004: so what does this code mean? Can we see the code list somewhere? - "label": "cropyield", - "value": "48.01" - }, + "DataCropfieldCharacteristics": [ + { + "code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha + "label": "cropyield", + "value": "48.01" + } + ], //"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_WURtest\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Downloads\ "CropYear": 2022, "geometryJson": { @@ -528,11 +542,13 @@ } ], "CropfieldCharacteristicItemCode": "", - "DataCropfieldCharacteristic": { - "code": "860619", - "label": "cropyield", - "value": "48.01" - }, + "DataCropfieldCharacteristics": [ + { + "code": "860619", + "label": "cropyield", + "value": "48.01" + } + ], //"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\Downloads\ "CropYear": 2022, //geometryJson = polygon of location of the cropfield, coordinates in LON,LAT (LON: decimal degrees East, LAT: decimal degrees North) @@ -578,11 +594,13 @@ "OperationItemCodes": [], "dataOperations": [], "CropfieldCharacteristicItemCode": "", - "DataCropfieldCharacteristic": { - "code": "860619", //PO20231004: so what does this code mean? Can we see the code list somewhere? - "label": "cropyield", - "value": "9.58" //CBS: https://www.cbs.nl/nl-nl/cijfers/detail/37738, 2022: 40.4 Mkg / 4216 ha = 40400 / 4216 - }, + "DataCropfieldCharacteristics": [ + { + "code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha + "label": "cropyield", + "value": "9.58" //CBS: https://www.cbs.nl/nl-nl/cijfers/detail/37738, 2022: 40.4 Mkg / 4216 ha = 40400 / 4216 + } + ], //"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_WURtest\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Downloads\ "CropYear": 2022, //"StartDate": "2022-04-15", //PO20231108: StartDate & EndDate important for legumes, where Nitrogen fixation depends on number of days from start to end. More days = more N fixation @@ -629,15 +647,145 @@ "OperationItemCodes": [], "dataOperations": [], "CropfieldCharacteristicItemCode": "", - "DataCropfieldCharacteristic": { - "code": "860619", //PO20231004: so what does this code mean? Can we see the code list somewhere? - "label": "cropyield", - "value": "9.58" //CBS: https://www.cbs.nl/nl-nl/cijfers/detail/37738, 2022: 40.4 Mkg / 4216 ha = 40400 / 4216 - }, + "DataCropfieldCharacteristics": [ + { + "code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha + "label": "cropyield", + "value": "9.58" //CBS: https://www.cbs.nl/nl-nl/cijfers/detail/37738, 2022: 40.4 Mkg / 4216 ha = 40400 / 4216 + } + ], //"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_WURtest\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Downloads\ "CropYear": 2022, - "StartDate": "2022-04-15", //PO20231108: StartDate & EndDate important for legumes, where Nitrogen fixation depends on number of days from start to end. More days = more N fixation - "EndDate": "2022-07-30", // if StartDate & EndDate left empty then whole year from cropYear + "StartDate": "2022-04-15", //PO20231108: StartDate & EndDate important for legumes, where Nitrogen fixation depends on number of days from start to end. More days = more N fixation + "EndDate": "2022-07-30", // if StartDate & EndDate left empty then whole year from cropYear + "geometryJson": { + "type": "Polygon", + "coordinates": [ + [ + [ + 5.5945257993548765, + 52.57080744107003 + ], + [ + 5.598645994070678, + 52.571540800206236 + ], + [ + 5.599381743127071, + 52.57012773140724 + ], + [ + 5.595408698222548, + 52.56968054825188 + ], + [ + 5.5945257993548765, + 52.57080744107003 + ] + ] + ] + } + }, + { + "useExistingCropfieldWithChildren": false, + "deleteNewlyCreatedAfterCalc": true, + "fieldName": "test_WinterWheat_DefaultStrawRemainsInField", + //Note when you run the FarmmapsKPI project, somewhere to your C:\git\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\ directory, files named like this are written: + //'Settings_aardappelveld_test_Potato_ZeroFertilizer.json', where 'aardappelveld_test_Potato_ZeroFertilizer.json' is your fieldName (see below) + //1 useExistingCropfieldWithChildren = false -> create new + //2 useExistingCropfieldWithChildren = true && CropfieldItemCode = "" or absent -> read fieldName (see below) -> read all codes from settings json file + //3 useExistingCropfieldWithChildren = true && CropfieldItemCode like "deb48a74c5b54299bb852f17288010e9" in KPIinput -> if you have in your account already an existing cropfield then use that + "CropfieldItemCode": "", // could contain for example this: "abae97f89f3c4ac08953b1b8bea9f076" if this is an exisiting CropfieldItemCode in your account. + //And then if useExistingCropfieldWithChildren = true, this would be used. + "dataCropfield": { + //"area": 4.22, //Leave empty, KPI app will calculate it from geometry + "final": true, //always true + "soilCode": "1", //From codelist CL405. Can be omitted if unknown + "soilName": "Sand", //From codelist CL405 + "cropTypeCode": "1020101", //From codelist CL263 + "cropTypeName": "Winter wheat" //From codelist CL263 + }, + "CropRecordingItemCode": "", // could contain for example this: "314aa1b6480b493ba28a5f55039a01d4" if this is the CropRecordingItemCode of the provided CropfieldItemCode. And then if useExistingCropfieldWithChildren = true, this would be used + "OperationItemCodes": [], // could contain for example this: ["4d1a6f28ea3f414180663baa4b08c60f"] or ["4d1a6f28ea3f414180663baa4b08c60f","21e08386f0454ad79acfebf78649d59b"] if these are the operations of the provided CropRecordingItemCode. And then if useExistingCropfieldWithChildren = true, these would be used + "dataOperations": [], //leaving the operations empty means no fertilizer is applied + "CropfieldCharacteristicItemCode": "", + "DataCropfieldCharacteristics": [ + { + //PO20231029: not different yields from different parts of fields? + "code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha + "label": "cropyield", + "value": "10.0" + } + ], + //"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\Downloads\ + "CropYear": 2022, + //geometryJson = polygon of location of the cropfield, coordinates in LON,LAT (LON: decimal degrees East, LAT: decimal degrees North) + "geometryJson": { + "type": "Polygon", + "coordinates": [ + [ + [ + 5.5945257993548765, + 52.57080744107003 + ], + [ + 5.598645994070678, + 52.571540800206236 + ], + [ + 5.599381743127071, + 52.57012773140724 + ], + [ + 5.595408698222548, + 52.56968054825188 + ], + [ + 5.5945257993548765, + 52.57080744107003 + ] + ] + ] + } + }, + { + "useExistingCropfieldWithChildren": false, + "deleteNewlyCreatedAfterCalc": true, + "fieldName": "test_WinterWheat_StrawRemovedFromField", + //Note when you run the FarmmapsKPI project, somewhere to your C:\git\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\ directory, files named like this are written: + //'Settings_aardappelveld_test_Potato_ZeroFertilizer.json', where 'aardappelveld_test_Potato_ZeroFertilizer.json' is your fieldName (see below) + //1 useExistingCropfieldWithChildren = false -> create new + //2 useExistingCropfieldWithChildren = true && CropfieldItemCode = "" or absent -> read fieldName (see below) -> read all codes from settings json file + //3 useExistingCropfieldWithChildren = true && CropfieldItemCode like "deb48a74c5b54299bb852f17288010e9" in KPIinput -> if you have in your account already an existing cropfield then use that + "CropfieldItemCode": "", // could contain for example this: "abae97f89f3c4ac08953b1b8bea9f076" if this is an exisiting CropfieldItemCode in your account. + //And then if useExistingCropfieldWithChildren = true, this would be used. + "dataCropfield": { + //"area": 4.22, //Leave empty, KPI app will calculate it from geometry + "final": true, //always true + "soilCode": "1", //From codelist CL405. Can be omitted if unknown + "soilName": "Sand", //From codelist CL405 + "cropTypeCode": "1020101", //From codelist CL263 + "cropTypeName": "Winter wheat" //From codelist CL263 + }, + "CropRecordingItemCode": "", // could contain for example this: "314aa1b6480b493ba28a5f55039a01d4" if this is the CropRecordingItemCode of the provided CropfieldItemCode. And then if useExistingCropfieldWithChildren = true, this would be used + "OperationItemCodes": [], // could contain for example this: ["4d1a6f28ea3f414180663baa4b08c60f"] or ["4d1a6f28ea3f414180663baa4b08c60f","21e08386f0454ad79acfebf78649d59b"] if these are the operations of the provided CropRecordingItemCode. And then if useExistingCropfieldWithChildren = true, these would be used + "dataOperations": [], //leaving the operations empty means no fertilizer is applied + "CropfieldCharacteristicItemCode": "", + "DataCropfieldCharacteristics": [ + { + //PO20231029: not different yields from different parts of fields? + "code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha + "label": "cropyield", + "value": "10.0" + }, + { + "code": "fm009", //TODO: which codelist? + "label": "strawyield", + "value": "5.9" + } + ], + "CropYear": 2022, + //geometryJson = polygon of location of the cropfield, coordinates in LON,LAT (LON: decimal degrees East, LAT: decimal degrees North) "geometryJson": { "type": "Polygon", "coordinates": [ diff --git a/FarmmapsKPI/Models/KPIInput.cs b/FarmmapsKPI/Models/KPIInput.cs index 8d2df12..1a89084 100644 --- a/FarmmapsKPI/Models/KPIInput.cs +++ b/FarmmapsKPI/Models/KPIInput.cs @@ -15,7 +15,7 @@ namespace FarmmapsKPI.Models public string[] OperationItemCodes { get; set; } public JObject[] DataOperations { get; set; } public string CropfieldCharacteristicItemCode { get; set; } - public JObject DataCropfieldCharacteristic { get; set; } + public JObject[] DataCropfieldCharacteristics { get; set; } public string DownloadFolder { get; set; } public int CropYear { get; set; } public DateTime StartDate { get; set; }