added code for checking if multiple runs give same KPI output

(should be but is not, so where is it going wrong?)
This commit is contained in:
Pepijn van Oort 2024-05-15 15:45:53 +02:00
parent 6faa5104c8
commit e05bb5a8f7

View File

@ -5,6 +5,7 @@ using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Transactions;
using FarmmapsApi; using FarmmapsApi;
using FarmmapsApi.Models; using FarmmapsApi.Models;
using FarmmapsApi.Services; using FarmmapsApi.Services;
@ -46,7 +47,7 @@ namespace FarmmapsKPI
//fnKPIinput = Console.ReadLine(); //fnKPIinput = Console.ReadLine();
//if (string.IsNullOrEmpty(fnKPIinput)) //if (string.IsNullOrEmpty(fnKPIinput))
//{ //{
fnKPIinput = "KPIinput.json"; fnKPIinput = "KPIinput.json";
//} //}
var fieldsInputJson = File.ReadAllText(fnKPIinput); var fieldsInputJson = File.ReadAllText(fnKPIinput);
@ -71,7 +72,7 @@ namespace FarmmapsKPI
StreamWriter sw; StreamWriter sw;
string KPIItemCsv = Path.GetFileNameWithoutExtension(fnKPIinput) + "_Items.csv"; string KPIItemCsv = Path.GetFileNameWithoutExtension(fnKPIinput) + "_Items.csv";
string KPIItemPathCsv = Path.Combine(downloadFolder, KPIItemCsv); string KPIItemPathCsv = Path.Combine(downloadFolder, KPIItemCsv);
List<string> headerList = new List<string> { "parentName", "cropfieldcode", "area_ha", "cropTypeCode", "cropTypeName", "KPIid", "KPIvariable", "KPIvalue", "KPIunit", "KPItargetvalue", "KPIthresholdValue", List<string> headerList = new List<string> { "run","parentName", "cropfieldcode", "area_ha", "cropTypeCode", "cropTypeName", "KPIid", "KPIvariable", "KPIvalue", "KPIunit", "KPItargetvalue", "KPIthresholdValue",
"mbp_productCode","mbp_productName","mbp_quantity","mbp_unitCode","mbp_date","mbp_KPIvariable","mbp_KPIvalue"}; "mbp_productCode","mbp_productName","mbp_quantity","mbp_unitCode","mbp_date","mbp_KPIvariable","mbp_KPIvalue"};
//Create a new csv file. Means if existing then overwritten !!! //Create a new csv file. Means if existing then overwritten !!!
sw = new StreamWriter(KPIItemPathCsv); sw = new StreamWriter(KPIItemPathCsv);
@ -87,25 +88,29 @@ namespace FarmmapsKPI
TimeSpan tsRemaining; TimeSpan tsRemaining;
TimeSpan tsTotalEstimated; TimeSpan tsTotalEstimated;
for (int i = 0; i < fieldsInputs.Count; i++) //Per default just 1 run per field. For debugging check if when we run multiple times do we get (should be) always the same output?
//for (int i = 10; i < 12; i++) int nrun = 1;
{ for (int run = 1; run <= nrun; run++) {
watch.Restart(); //for (int i = 0; i < fieldsInputs.Count; i++)
input = fieldsInputs[i]; for (int i = 3; i < 4; i++) // for testing
_logger.LogInformation(string.Format($"// FarmmapsKPI: Downloading KPI's for field {i + 1} out of {fieldsInputs.Count} to single csv file {KPIItemPathCsv}"));
try
{ {
await Process(roots, input, sw); watch.Restart();
input = fieldsInputs[i];
_logger.LogInformation(string.Format($"// FarmmapsKPI: Run {run}: Downloading KPI's for field {i + 1} out of {fieldsInputs.Count} to single csv file {KPIItemPathCsv}"));
try
{
await Process(roots, input, sw, run);
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
watch.Stop();
tsSofar = tsSofar + watch.Elapsed;
tsTotalEstimated = tsSofar / (i + 1) * fieldsInputs.Count;
tsRemaining = tsTotalEstimated - tsSofar;
_logger.LogInformation(string.Format($"// Time (hh:mm:ss): this field: {strTime(watch.Elapsed)}. Sofar: {strTime(tsSofar)}. Estimated total: {strTime(tsTotalEstimated)}. Remaining: {strTime(tsRemaining)}"));
} }
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
watch.Stop();
tsSofar = tsSofar + watch.Elapsed;
tsTotalEstimated = tsSofar / (i + 1) * fieldsInputs.Count;
tsRemaining = tsTotalEstimated - tsSofar;
_logger.LogInformation(string.Format($"// Time (hh:mm:ss): this field: {strTime(watch.Elapsed)}. Sofar: {strTime(tsSofar)}. Estimated total: {strTime(tsTotalEstimated)}. Remaining: {strTime(tsRemaining)}"));
} }
//Close the csv file, write message to screen //Close the csv file, write message to screen
sw.Close(); sw.Close();
@ -113,7 +118,7 @@ namespace FarmmapsKPI
_logger.LogInformation($"Done! Written all KPI for all fields in '{fnKPIinput}' to output file '{KPIItemPathCsv}'"); _logger.LogInformation($"Done! Written all KPI for all fields in '{fnKPIinput}' to output file '{KPIItemPathCsv}'");
} }
private async Task Process(List<UserRoot> roots, KPIInput input, StreamWriter sw) private async Task Process(List<UserRoot> roots, KPIInput input, StreamWriter sw, int run)
{ {
List<Item> cropfieldChildren; List<Item> cropfieldChildren;
List<Item> crprecChildren; List<Item> crprecChildren;
@ -125,6 +130,8 @@ namespace FarmmapsKPI
int targetKPIitemsCount; //if we know we should be getting 8 KPI items (A1,B1,B2,C1,D1,E1,F1,F2) int targetKPIitemsCount; //if we know we should be getting 8 KPI items (A1,B1,B2,C1,D1,E1,F1,F2)
int maxtries = 5; // but don't keep on trying forever; there is a maximum number of tries int maxtries = 5; // but don't keep on trying forever; there is a maximum number of tries
int trycnt; int trycnt;
double totalNferiliserInput = 0;
double totalNferiliserCropfield = 0;
string downloadFolder = input.DownloadFolder; string downloadFolder = input.DownloadFolder;
if (string.IsNullOrEmpty(downloadFolder)) { if (string.IsNullOrEmpty(downloadFolder)) {
@ -317,6 +324,8 @@ namespace FarmmapsKPI
crpOperationItem = await _generalService.CreateOperationItemAsync(crprecItem.Code, cropYear, fieldGeom, dataOperation); crpOperationItem = await _generalService.CreateOperationItemAsync(crprecItem.Code, cropYear, fieldGeom, dataOperation);
crpOperationItems.Add(crpOperationItem); crpOperationItems.Add(crpOperationItem);
crpOperationItemCodes.Add(crpOperationItem.Code); crpOperationItemCodes.Add(crpOperationItem.Code);
//Keep track of totalNferiliserInput
totalNferiliserInput = totalNferiliserInput + (double)data.n;
} }
_settings.OperationItemCodes = crpOperationItemCodes.ToArray(); _settings.OperationItemCodes = crpOperationItemCodes.ToArray();
SaveSettings(settingsfile); SaveSettings(settingsfile);
@ -352,6 +361,22 @@ namespace FarmmapsKPI
cropfieldChildren = await _farmmapsApiService.GetItemChildrenAsync(cropfieldItem.Code); cropfieldChildren = await _farmmapsApiService.GetItemChildrenAsync(cropfieldItem.Code);
crprecChildren = await _farmmapsApiService.GetItemChildrenAsync(crprecItem.Code); crprecChildren = await _farmmapsApiService.GetItemChildrenAsync(crprecItem.Code);
//Check total operations
int nOperationsInput = input.DataOperations.Length;
int nOperationsCropfield = crprecChildren.Count;
if (nOperationsInput != nOperationsCropfield)
throw new Exception(String.Format($"run {run}: nOperationsInput != nOperationsCropfield?!"));
//Check totalNfertiliser input and Cropfield
for (int o = 0; o < crprecChildren.Count; o++)
{
dynamic data = JObject.Parse(crprecChildren[o].Data.ToString());
totalNferiliserCropfield = totalNferiliserCropfield + (double)data.n;
}
if (totalNferiliserInput != totalNferiliserCropfield)
throw new Exception(String.Format($"run {run}: totalNferiliserInput != totalNferiliserCropfield?!"));
//Now get the KPIs for this cropfield, mounted with operations & cropyield //Now get the KPIs for this cropfield, mounted with operations & cropyield
//Note sometimes the KPIItems.Count is already for some crazy reason greater than or equal to targetKPIitemsCount //Note sometimes the KPIItems.Count is already for some crazy reason greater than or equal to targetKPIitemsCount
//But that would have strange results, since that was from above before adding the crop recordings. We want to do at least one new call -> 'while (trycnt == 0 || ' //But that would have strange results, since that was from above before adding the crop recordings. We want to do at least one new call -> 'while (trycnt == 0 || '
@ -409,6 +434,7 @@ namespace FarmmapsKPI
//Fill the datalist with this kpi //Fill the datalist with this kpi
dataList = new List<string> dataList = new List<string>
{ {
run.ToString(),
kpio.parentName, kpio.parentName,
cropfieldItem.Code, cropfieldItem.Code,
kpio.data.area, kpio.data.area,
@ -430,6 +456,7 @@ namespace FarmmapsKPI
string elementValue = (string)kpio.data.GetType().GetProperty(elementName).GetValue(kpio.data, null); string elementValue = (string)kpio.data.GetType().GetProperty(elementName).GetValue(kpio.data, null);
dataList = new List<string> dataList = new List<string>
{ {
run.ToString(),
kpio.parentName, kpio.parentName,
cropfieldItem.Code, cropfieldItem.Code,
kpio.data.area, kpio.data.area,
@ -452,6 +479,7 @@ namespace FarmmapsKPI
//Fill the datalist with this kpi //Fill the datalist with this kpi
dataList = new List<string> dataList = new List<string>
{ {
run.ToString(),
kpio.parentName, kpio.parentName,
cropfieldItem.Code, cropfieldItem.Code,
kpio.data.area, kpio.data.area,
@ -473,6 +501,7 @@ namespace FarmmapsKPI
string elementValue = (string)kPIelementsOfBalance.GetType().GetProperty(elementName).GetValue(kPIelementsOfBalance, null); string elementValue = (string)kPIelementsOfBalance.GetType().GetProperty(elementName).GetValue(kPIelementsOfBalance, null);
dataList = new List<string> dataList = new List<string>
{ {
run.ToString(),
kpio.parentName, kpio.parentName,
cropfieldItem.Code, cropfieldItem.Code,
kpio.data.area, kpio.data.area,
@ -487,6 +516,12 @@ namespace FarmmapsKPI
}; };
//Write the datalist to a line to the streamwrieter sw for the output csv file //Write the datalist to a line to the streamwrieter sw for the output csv file
sw.WriteLine(string.Join(",", dataList)); sw.WriteLine(string.Join(",", dataList));
//Check if totalNferiliserInput is equal to what comes out of the KPI calculation
//PO20240515: Hier gaat het mis!!!
if (elementName == "nFertilizerNKgHa")
if (totalNferiliserInput != Convert.ToDouble(elementValue))
throw new Exception(String.Format($"run {run}: totalNferiliserInput != nFertilizerNKgHa?!"));
} }
} }
else if (kpio.id == "B2") else if (kpio.id == "B2")
@ -495,6 +530,7 @@ namespace FarmmapsKPI
dataList = new List<string> dataList = new List<string>
{ {
//Fill the datalist with this kpi //Fill the datalist with this kpi
run.ToString(),
kpio.parentName, kpio.parentName,
cropfieldItem.Code, cropfieldItem.Code,
kpio.data.area, kpio.data.area,
@ -516,6 +552,7 @@ namespace FarmmapsKPI
string elementValue = (string)kPIelementsOfBalance.GetType().GetProperty(elementName).GetValue(kPIelementsOfBalance, null); string elementValue = (string)kPIelementsOfBalance.GetType().GetProperty(elementName).GetValue(kPIelementsOfBalance, null);
dataList = new List<string> dataList = new List<string>
{ {
run.ToString(),
kpio.parentName, kpio.parentName,
cropfieldItem.Code, cropfieldItem.Code,
kpio.data.area, kpio.data.area,
@ -538,6 +575,7 @@ namespace FarmmapsKPI
//Make a new dataList = new line to be written //Make a new dataList = new line to be written
dataList = new List<string> dataList = new List<string>
{ {
run.ToString(),
kpio.parentName, kpio.parentName,
cropfieldItem.Code, cropfieldItem.Code,
kpio.data.area, kpio.data.area,
@ -559,6 +597,7 @@ namespace FarmmapsKPI
string elementValue = (string)kPIelementsOfBalance.GetType().GetProperty(elementName).GetValue(kPIelementsOfBalance, null); string elementValue = (string)kPIelementsOfBalance.GetType().GetProperty(elementName).GetValue(kPIelementsOfBalance, null);
dataList = new List<string> dataList = new List<string>
{ {
run.ToString(),
kpio.parentName, kpio.parentName,
cropfieldItem.Code, cropfieldItem.Code,
kpio.data.area, kpio.data.area,
@ -587,6 +626,7 @@ namespace FarmmapsKPI
//Make a new dataList = new line to be written //Make a new dataList = new line to be written
dataList = new List<string> dataList = new List<string>
{ {
run.ToString(),
kpio.parentName, kpio.parentName,
cropfieldItem.Code, cropfieldItem.Code,
kpio.data.area, kpio.data.area,
@ -616,6 +656,7 @@ namespace FarmmapsKPI
//Any other KPI, example A1 or D1, with just 1 record to write //Any other KPI, example A1 or D1, with just 1 record to write
dataList = new List<string> dataList = new List<string>
{ {
run.ToString(),
kpio.parentName, kpio.parentName,
cropfieldItem.Code, cropfieldItem.Code,
kpio.data.area, kpio.data.area,