Enhance JSON deserialization and file associations; refactor ProcessData classes for improved clarity and performance

This commit is contained in:
2025-10-16 23:29:26 -07:00
parent 68c3a8b5f3
commit d9cf8d2aae
11 changed files with 149 additions and 44 deletions

View File

@ -1,4 +1,11 @@
{ {
"files.associations": {
"*.ffs_gui": "xml",
"*.hurl": "http",
"*.org": "ini",
"*.net": "ini",
"default": "ini"
},
"[markdown]": { "[markdown]": {
"editor.wordWrap": "off" "editor.wordWrap": "off"
}, },

View File

@ -7,6 +7,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Linq;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@ -44,12 +45,11 @@ public class ProcessData : IProcessData
{ {
List<Description> results = new(); List<Description> results = new();
Description? description; Description? description;
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
foreach (JsonElement jsonElement in jsonElements) foreach (JsonElement jsonElement in jsonElements)
{ {
if (jsonElement.ValueKind != JsonValueKind.Object) if (jsonElement.ValueKind != JsonValueKind.Object)
throw new Exception(); throw new Exception();
description = JsonSerializer.Deserialize<Description>(jsonElement.ToString(), jsonSerializerOptions); description = JsonSerializer.Deserialize(jsonElement.ToString(), SharedDescriptionSourceGenerationContext.Default.Description);
if (description is null) if (description is null)
continue; continue;
results.Add(description); results.Add(description);

View File

@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@ -221,12 +222,11 @@ public class ProcessData : IProcessData
{ {
List<Description> results = new(); List<Description> results = new();
Description? description; Description? description;
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
foreach (JsonElement jsonElement in jsonElements) foreach (JsonElement jsonElement in jsonElements)
{ {
if (jsonElement.ValueKind != JsonValueKind.Object) if (jsonElement.ValueKind != JsonValueKind.Object)
throw new Exception(); throw new Exception();
description = JsonSerializer.Deserialize<Description>(jsonElement.ToString(), jsonSerializerOptions); description = JsonSerializer.Deserialize(jsonElement.ToString(), SharedDescriptionSourceGenerationContext.Default.Description);
if (description is null) if (description is null)
continue; continue;
results.Add(description); results.Add(description);

View File

@ -399,12 +399,11 @@ public class ProcessData : IProcessData
{ {
List<Description> results = new(); List<Description> results = new();
Description? description; Description? description;
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
foreach (JsonElement jsonElement in jsonElements) foreach (JsonElement jsonElement in jsonElements)
{ {
if (jsonElement.ValueKind != JsonValueKind.Object) if (jsonElement.ValueKind != JsonValueKind.Object)
throw new Exception(); throw new Exception();
description = JsonSerializer.Deserialize<Description>(jsonElement.ToString(), jsonSerializerOptions); description = JsonSerializer.Deserialize(jsonElement.ToString(), SharedDescriptionSourceGenerationContext.Default.Description);
if (description is null) if (description is null)
continue; continue;
results.Add(description); results.Add(description);

View File

@ -615,12 +615,11 @@ public class ProcessData : IProcessData
{ {
List<Description> results = new(); List<Description> results = new();
Description? description; Description? description;
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
foreach (JsonElement jsonElement in jsonElements) foreach (JsonElement jsonElement in jsonElements)
{ {
if (jsonElement.ValueKind != JsonValueKind.Object) if (jsonElement.ValueKind != JsonValueKind.Object)
throw new Exception(); throw new Exception();
description = JsonSerializer.Deserialize<Description>(jsonElement.ToString(), jsonSerializerOptions); description = JsonSerializer.Deserialize(jsonElement.ToString(), SharedDescriptionSourceGenerationContext.Default.Description);
if (description is null) if (description is null)
continue; continue;
results.Add(description); results.Add(description);

View File

@ -150,6 +150,11 @@ function updateRecordCoD(b: any, r: any, t: any, c: any, e: any, w: any, workIte
} }
} }
if (workItem.Id === 330178) {
if (weightedShortestJobFirst != weightedShortestJobFirstFibonacci) {
}
}
workItem.CumulativeStoryPoints = '&nbsp;'; workItem.CumulativeStoryPoints = '&nbsp;';
workItem.TotalStoryPoints = totalStoryPoints + ' User Story Point(s)'; workItem.TotalStoryPoints = totalStoryPoints + ' User Story Point(s)';
workItem.AbsoluteDelta = data.Effort == undefined || data.Effort.FibonacciAverage == undefined || totalStoryPoints == undefined || totalStoryPoints === 0 ? '&nbsp;' : round(Math.abs(data.Effort.FibonacciAverage - ((totalStoryPoints / highestTotalStoryPoints) * 5)), 1); workItem.AbsoluteDelta = data.Effort == undefined || data.Effort.FibonacciAverage == undefined || totalStoryPoints == undefined || totalStoryPoints === 0 ? '&nbsp;' : round(Math.abs(data.Effort.FibonacciAverage - ((totalStoryPoints / highestTotalStoryPoints) * 5)), 1);
@ -165,17 +170,30 @@ function updateRecordCoD(b: any, r: any, t: any, c: any, e: any, w: any, workIte
workItem.TimeCriticalityNotifications = data.TimeCriticality == undefined ? '&nbsp;' : getNotifications(t, data.TimeCriticality); workItem.TimeCriticalityNotifications = data.TimeCriticality == undefined ? '&nbsp;' : getNotifications(t, data.TimeCriticality);
workItem.RiskReductionMinusOpportunityEnablementNotifications = data.RiskReductionOpportunityEnablement == undefined ? '&nbsp;' : getNotifications(r, data.RiskReductionOpportunityEnablement); workItem.RiskReductionMinusOpportunityEnablementNotifications = data.RiskReductionOpportunityEnablement == undefined ? '&nbsp;' : getNotifications(r, data.RiskReductionOpportunityEnablement);
workItem.SortOrder = data.SortOrder == undefined ? 0 : data.SortOrder; workItem.SortOrder = data.SortOrder == undefined ? 0 : data.SortOrder;
let check = effort == workItem.Effort if (workItem.Effort == undefined ||
&& businessValue === workItem.BusinessValue workItem.BusinessValue == undefined ||
&& timeCriticality === workItem.TimeCriticality workItem.TimeCriticality == undefined ||
&& riskReductionMinusOpportunityEnablement === workItem.RiskReductionMinusOpportunityEnablement; workItem.RiskReductionMinusOpportunityEnablement == undefined ||
if (check && weightedShortestJobFirst == workItem.WeightedShortestJobFirst) { workItem.WeightedShortestJobFirst == undefined ||
workItem.Effort == '&nbsp;' ||
workItem.BusinessValue == '&nbsp;' ||
workItem.TimeCriticality == '&nbsp;' ||
workItem.RiskReductionMinusOpportunityEnablement == '&nbsp;' ||
workItem.WeightedShortestJobFirst == '&nbsp;') {
workItem.api = ''; workItem.api = '';
} else { }
workItem.api = ` else {
### Work Item Patch ${check} WSJF ${workItem.Id} ${weightedShortestJobFirst} != ${workItem.WeightedShortestJobFirst} let check = effort === workItem.Effort
&& businessValue === workItem.BusinessValue
&& timeCriticality === workItem.TimeCriticality
&& riskReductionMinusOpportunityEnablement === workItem.RiskReductionMinusOpportunityEnablement;
if (check && weightedShortestJobFirst == workItem.WeightedShortestJobFirst) {
workItem.api = '';
} else {
workItem.api = `
### Work Item Patch ${check} WSJF ${workItem.Id} ${effort}:${workItem.Effort}; ${businessValue}:${workItem.BusinessValue}; ${timeCriticality}:${workItem.TimeCriticality}; ${riskReductionMinusOpportunityEnablement}:${workItem.RiskReductionMinusOpportunityEnablement}; ${weightedShortestJobFirst}:${workItem.WeightedShortestJobFirst};
patch {{Factory-Integration}}/_apis/wit/workitems/${workItem.Id}?api-version=7.0 PATCH https://tfs.intra.infineon.com/tfs/FactoryIntegration/_apis/wit/workitems/${workItem.Id}?api-version=7.0
Authorization: Basic {{PAT}} Authorization: Basic {{PAT}}
Content-Type: application/json-patch+json Content-Type: application/json-patch+json
@ -222,6 +240,7 @@ jsonpath "$.fields['Custom.RRminusOE']" == ${workItem.RiskReductionMinusOpportun
jsonpath "$.fields['Microsoft.VSTS.Common.TimeCriticality']" == ${workItem.TimeCriticality} jsonpath "$.fields['Microsoft.VSTS.Common.TimeCriticality']" == ${workItem.TimeCriticality}
jsonpath "$.fields['Custom.WSJF']" == ${workItem.WeightedShortestJobFirst} jsonpath "$.fields['Custom.WSJF']" == ${workItem.WeightedShortestJobFirst}
jsonpath "$.fields['Custom.WSJFFib']" == ${workItem.WeightedShortestJobFirst}`; jsonpath "$.fields['Custom.WSJFFib']" == ${workItem.WeightedShortestJobFirst}`;
}
} }
} }
} }
@ -295,10 +314,19 @@ function getRecords(b: any, r: any, t: any, c: any, e: any, w: any, data: any, d
function getHtmlTextAndApi(fromHtml: any, b: any, r: any, t: any, c: any, e: any, w: any, records: any) { function getHtmlTextAndApi(fromHtml: any, b: any, r: any, t: any, c: any, e: any, w: any, records: any) {
let record; let record;
let api = '';
let lineA = ''; let lineA = '';
let lineB = ''; let lineB = '';
let lineC = ''; let lineC = '';
let api = `
### FactoryIntegration (hurl.exe)
GET https://tfs.intra.infineon.com/tfs/FactoryIntegration
HTTP 401
[Asserts]
duration < 12345
`;
let text = 'Id\tRisk Reduction and/or Opportunity Enablement\tTime Criticality\tBusiness Value\tEffort\tWSJF\tCoD\tFeature Total Story Points\tAbsolute Delta\tState\tRequester\tAssigned To\tIteration Path\tSystem\tTitle-123\r\n'; let text = 'Id\tRisk Reduction and/or Opportunity Enablement\tTime Criticality\tBusiness Value\tEffort\tWSJF\tCoD\tFeature Total Story Points\tAbsolute Delta\tState\tRequester\tAssigned To\tIteration Path\tSystem\tTitle-123\r\n';
let html = '<tr><th>Parent Id</th><th>Parent Title</th><th>Id</th><th>Requester</th><th>Title</th><th>Assigned To</th><th>System(s)</th><th>State</th><th>Priority</th><th>Risk Reduction and/or Opportunity Enablement</th><th>Time Criticality</th><th>Business Value</th><th>Cost of Delay (CoD)</th><th>Effort</th><th>WSJF</th></tr>'; let html = '<tr><th>Parent Id</th><th>Parent Title</th><th>Id</th><th>Requester</th><th>Title</th><th>Assigned To</th><th>System(s)</th><th>State</th><th>Priority</th><th>Risk Reduction and/or Opportunity Enablement</th><th>Time Criticality</th><th>Business Value</th><th>Cost of Delay (CoD)</th><th>Effort</th><th>WSJF</th></tr>';
for (let i = 0; i < records.length; i++) { for (let i = 0; i < records.length; i++) {
@ -379,7 +407,7 @@ function getHtmlTextAndApi(fromHtml: any, b: any, r: any, t: any, c: any, e: any
console.log(text); console.log(text);
html += lineA + lineB + lineC; html += lineA + lineB + lineC;
} }
return { html, text, http: api }; return { html, text, api };
} }
const username = ''; const username = '';

View File

@ -143,7 +143,7 @@ function updateRecordCoD(b, r, t, c, e, w, workItem, highestTotalStoryPoints, da
let businessValue = workItem.BusinessValue; let businessValue = workItem.BusinessValue;
let timeCriticality = workItem.TimeCriticality; let timeCriticality = workItem.TimeCriticality;
let riskReductionMinusOpportunityEnablement = workItem.RiskReductionMinusOpportunityEnablement; let riskReductionMinusOpportunityEnablement = workItem.RiskReductionMinusOpportunityEnablement;
let weightedShortestJobFirst = workItem.WeightedShortestJobFirst == undefined ? null : workItem.WeightedShortestJobFirst.toFixed(2); let weightedShortestJobFirst = workItem.WeightedShortestJobFirst == undefined ? '&nbsp;' : workItem.WeightedShortestJobFirst.toFixed(2);
workItem.CumulativeStoryPoints = '&nbsp;'; workItem.CumulativeStoryPoints = '&nbsp;';
workItem.TotalStoryPoints = totalStoryPoints + ' User Story Point(s)'; workItem.TotalStoryPoints = totalStoryPoints + ' User Story Point(s)';
workItem.AbsoluteDelta = data.Effort == undefined || data.Effort.FibonacciAverage == undefined || totalStoryPoints == undefined || totalStoryPoints === 0 ? '&nbsp;' : round(Math.abs(data.Effort.FibonacciAverage - ((totalStoryPoints / highestTotalStoryPoints) * 5)), 1); workItem.AbsoluteDelta = data.Effort == undefined || data.Effort.FibonacciAverage == undefined || totalStoryPoints == undefined || totalStoryPoints === 0 ? '&nbsp;' : round(Math.abs(data.Effort.FibonacciAverage - ((totalStoryPoints / highestTotalStoryPoints) * 5)), 1);
@ -159,17 +159,30 @@ function updateRecordCoD(b, r, t, c, e, w, workItem, highestTotalStoryPoints, da
workItem.TimeCriticalityNotifications = data.TimeCriticality == undefined ? '&nbsp;' : getNotifications(t, data.TimeCriticality); workItem.TimeCriticalityNotifications = data.TimeCriticality == undefined ? '&nbsp;' : getNotifications(t, data.TimeCriticality);
workItem.RiskReductionMinusOpportunityEnablementNotifications = data.RiskReductionOpportunityEnablement == undefined ? '&nbsp;' : getNotifications(r, data.RiskReductionOpportunityEnablement); workItem.RiskReductionMinusOpportunityEnablementNotifications = data.RiskReductionOpportunityEnablement == undefined ? '&nbsp;' : getNotifications(r, data.RiskReductionOpportunityEnablement);
workItem.SortOrder = data.SortOrder == undefined ? 0 : data.SortOrder; workItem.SortOrder = data.SortOrder == undefined ? 0 : data.SortOrder;
let check = effort == workItem.Effort if (workItem.Effort == undefined ||
&& businessValue === workItem.BusinessValue workItem.BusinessValue == undefined ||
&& timeCriticality === workItem.TimeCriticality workItem.TimeCriticality == undefined ||
&& riskReductionMinusOpportunityEnablement === workItem.RiskReductionMinusOpportunityEnablement; workItem.RiskReductionMinusOpportunityEnablement == undefined ||
if (check && weightedShortestJobFirst == workItem.WeightedShortestJobFirst) { workItem.WeightedShortestJobFirst == undefined ||
workItem.Effort == '&nbsp;' ||
workItem.BusinessValue == '&nbsp;' ||
workItem.TimeCriticality == '&nbsp;' ||
workItem.RiskReductionMinusOpportunityEnablement == '&nbsp;' ||
workItem.WeightedShortestJobFirst == '&nbsp;') {
workItem.api = ''; workItem.api = '';
} else { }
workItem.api = ` else {
### Work Item Patch ${check} WSJF ${workItem.Id} ${weightedShortestJobFirst} != ${workItem.WeightedShortestJobFirst} let check = effort === workItem.Effort
&& businessValue === workItem.BusinessValue
&& timeCriticality === workItem.TimeCriticality
&& riskReductionMinusOpportunityEnablement === workItem.RiskReductionMinusOpportunityEnablement;
if (check && weightedShortestJobFirst == workItem.WeightedShortestJobFirst) {
workItem.api = '';
} else {
workItem.api = `
### Work Item Patch ${check} WSJF ${workItem.Id} ${effort}:${workItem.Effort}; ${businessValue}:${workItem.BusinessValue}; ${timeCriticality}:${workItem.TimeCriticality}; ${riskReductionMinusOpportunityEnablement}:${workItem.RiskReductionMinusOpportunityEnablement}; ${weightedShortestJobFirst}:${workItem.WeightedShortestJobFirst};
patch {{Factory-Integration}}/_apis/wit/workitems/${workItem.Id}?api-version=7.0 PATCH https://tfs.intra.infineon.com/tfs/FactoryIntegration/_apis/wit/workitems/${workItem.Id}?api-version=7.0
Authorization: Basic {{PAT}} Authorization: Basic {{PAT}}
Content-Type: application/json-patch+json Content-Type: application/json-patch+json
@ -216,6 +229,7 @@ jsonpath "$.fields['Custom.RRminusOE']" == ${workItem.RiskReductionMinusOpportun
jsonpath "$.fields['Microsoft.VSTS.Common.TimeCriticality']" == ${workItem.TimeCriticality} jsonpath "$.fields['Microsoft.VSTS.Common.TimeCriticality']" == ${workItem.TimeCriticality}
jsonpath "$.fields['Custom.WSJF']" == ${workItem.WeightedShortestJobFirst} jsonpath "$.fields['Custom.WSJF']" == ${workItem.WeightedShortestJobFirst}
jsonpath "$.fields['Custom.WSJFFib']" == ${workItem.WeightedShortestJobFirst}`; jsonpath "$.fields['Custom.WSJFFib']" == ${workItem.WeightedShortestJobFirst}`;
}
} }
} }
} }
@ -319,10 +333,19 @@ function sendValue(fromHtml, element, page, id) {
function getHtmlTextAndApi(fromHtml, b, r, t, c, e, w, records) { function getHtmlTextAndApi(fromHtml, b, r, t, c, e, w, records) {
let record; let record;
let api = '';
let lineA = ''; let lineA = '';
let lineB = ''; let lineB = '';
let lineC = ''; let lineC = '';
let api = `
### FactoryIntegration (hurl.exe)
GET https://tfs.intra.infineon.com/tfs/FactoryIntegration
HTTP 401
[Asserts]
duration < 12345
`;
let text = 'Id\tRisk Reduction and/or Opportunity Enablement\tTime Criticality\tBusiness Value\tEffort\tWSJF\tCoD\tFeature Total Story Points\tAbsolute Delta\tState\tRequester\tAssigned To\tIteration Path\tSystem\tTitle-123\r\n'; let text = 'Id\tRisk Reduction and/or Opportunity Enablement\tTime Criticality\tBusiness Value\tEffort\tWSJF\tCoD\tFeature Total Story Points\tAbsolute Delta\tState\tRequester\tAssigned To\tIteration Path\tSystem\tTitle-123\r\n';
let html = '<tr><th>Parent Id</th><th>Parent Title</th><th>Id</th><th>Requester</th><th>Title</th><th>Assigned To</th><th>System(s)</th><th>State</th><th>Priority</th><th>Risk Reduction and/or Opportunity Enablement</th><th>Time Criticality</th><th>Business Value</th><th>Cost of Delay (CoD)</th><th>Effort</th><th>WSJF</th></tr>'; let html = '<tr><th>Parent Id</th><th>Parent Title</th><th>Id</th><th>Requester</th><th>Title</th><th>Assigned To</th><th>System(s)</th><th>State</th><th>Priority</th><th>Risk Reduction and/or Opportunity Enablement</th><th>Time Criticality</th><th>Business Value</th><th>Cost of Delay (CoD)</th><th>Effort</th><th>WSJF</th></tr>';
for (let i = 0; i < records.length; i++) { for (let i = 0; i < records.length; i++) {
@ -403,7 +426,7 @@ function getHtmlTextAndApi(fromHtml, b, r, t, c, e, w, records) {
console.log(text); console.log(text);
html += lineA + lineB + lineC; html += lineA + lineB + lineC;
} }
return { html, text, http: api }; return { html, text, api };
} }
function updateSite(c, w) { function updateSite(c, w) {
@ -445,7 +468,12 @@ function setDocument(fromHtml, b, r, t, c, e, w, dataA, dataB, workItems) {
if (fromHtml) { if (fromHtml) {
document.getElementById('HeaderGrid').innerHTML = result.html.replaceAll('>null<', '>&nbsp;<'); document.getElementById('HeaderGrid').innerHTML = result.html.replaceAll('>null<', '>&nbsp;<');
if (_windowLocationHRef.indexOf('=WSJF') === -1) { if (_windowLocationHRef.indexOf('=WSJF') === -1) {
document.getElementById('AllTextarea').value = result.text.replaceAll('null', '').replaceAll('&nbsp;', '') + result.http; if (_windowLocationHRef.indexOf('=EFFORT') > -1) {
document.getElementById('AllTextarea').value = result.api;
}
else {
document.getElementById('AllTextarea').value = result.text.replaceAll('null', '').replaceAll('&nbsp;', '');
}
} }
else { else {
_toggle = !_toggle; _toggle = !_toggle;

View File

@ -226,9 +226,9 @@ public class MonIn : IMonIn, IDisposable
{ {
StringBuilder stringBuilder = new(); StringBuilder stringBuilder = new();
if (string.IsNullOrEmpty(subresource)) if (string.IsNullOrEmpty(subresource))
_ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" {4} \n{5}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), stateName.Trim(), state.Trim(), description.Trim()); _ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" {4} \n{5}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : "now", resource.Trim(), stateName.Trim(), state.Trim(), description.Trim());
else else
_ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" \"{4}\" {5} \n{6}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), subresource.Trim(), stateName.Trim(), state.Trim(), description.Trim()); _ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" \"{4}\" {5} \n{6}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : "now", resource.Trim(), subresource.Trim(), stateName.Trim(), state.Trim(), description.Trim());
return stringBuilder.ToString(); return stringBuilder.ToString();
} }
@ -247,14 +247,14 @@ public class MonIn : IMonIn, IDisposable
if (string.IsNullOrEmpty(subresource)) if (string.IsNullOrEmpty(subresource))
{ {
if (unit.Equals(string.Empty) && !interval.HasValue) if (unit.Equals(string.Empty) && !interval.HasValue)
_ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" {4} \n{5}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), performanceName.Trim(), value, description.Trim()); _ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" {4} \n{5}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : "now", resource.Trim(), performanceName.Trim(), value, description.Trim());
else else
_ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" {4} {5} {{interval={6}, unit={7}}}\n", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), performanceName.Trim(), value, description.Trim(), interval.HasValue ? interval.Value.ToString() : (object)string.Empty, unit.Trim()); _ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" {4} {5} {{interval={6}, unit={7}}}\n", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : "now", resource.Trim(), performanceName.Trim(), value, description.Trim(), interval.HasValue ? interval.Value.ToString() : string.Empty, unit.Trim());
} }
else if (unit.Equals(string.Empty) && !interval.HasValue) else if (unit.Equals(string.Empty) && !interval.HasValue)
_ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" \"{4}\" {5} \n{6}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), subresource.Trim(), performanceName.Trim(), value, description.Trim()); _ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" \"{4}\" {5} \n{6}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : "now", resource.Trim(), subresource.Trim(), performanceName.Trim(), value, description.Trim());
else else
_ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" \"{4}\" {5} {6} {{interval={7}, unit={8}}}\n", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), subresource.Trim(), performanceName.Trim(), value, description.Trim(), interval.HasValue ? interval.Value.ToString() : (object)string.Empty, unit.Trim()); _ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" \"{4}\" {5} {6} {{interval={7}, unit={8}}}\n", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : "now", resource.Trim(), subresource.Trim(), performanceName.Trim(), value, description.Trim(), interval.HasValue ? interval.Value.ToString() : string.Empty, unit.Trim());
return stringBuilder.ToString(); return stringBuilder.ToString();
} }

View File

@ -3,6 +3,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization;
namespace Adaptation.Shared.Duplicator; namespace Adaptation.Shared.Duplicator;
@ -142,4 +143,16 @@ public class Description : IDescription, Properties.IDescription
internal static string GetDateFormat() => "MM/dd/yyyy hh:mm:ss tt"; internal static string GetDateFormat() => "MM/dd/yyyy hh:mm:ss tt";
}
[JsonSourceGenerationOptions(WriteIndented = true, NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)]
[JsonSerializable(typeof(Description))]
internal partial class SharedDescriptionSourceGenerationContext : JsonSerializerContext
{
}
[JsonSourceGenerationOptions(WriteIndented = true, NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)]
[JsonSerializable(typeof(Description[]))]
internal partial class SharedDescriptionArraySourceGenerationContext : JsonSerializerContext
{
} }

View File

@ -9,7 +9,6 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading; using System.Threading;
namespace Adaptation.Shared; namespace Adaptation.Shared;
@ -447,12 +446,13 @@ public class FileRead : Properties.IFileRead
{ {
List<Properties.IDescription> results = new(); List<Properties.IDescription> results = new();
Duplicator.Description description; Duplicator.Description description;
JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
foreach (JsonElement jsonElement in jsonElements) foreach (JsonElement jsonElement in jsonElements)
{ {
if (jsonElement.ValueKind != JsonValueKind.Object) if (jsonElement.ValueKind != JsonValueKind.Object)
throw new Exception(); throw new Exception();
description = JsonSerializer.Deserialize<Duplicator.Description>(jsonElement.ToString(), jsonSerializerOptions); description = JsonSerializer.Deserialize(jsonElement.ToString(), Duplicator.SharedDescriptionSourceGenerationContext.Default.Description);
if (description is null)
continue;
results.Add(description); results.Add(description);
} }
return results; return results;

View File

@ -187,7 +187,7 @@ internal class ProcessDataStandardFormat
break; break;
} }
} }
string? linesOne = lines.Length > 0 && body.Count == 0 && columns.Count == 0 ? lines[1] : null; string? linesOne = lines.Length > 1 && body.Count == 0 && columns.Count == 0 ? lines[1] : null;
logistics = GetLogistics(footer, linesOne: linesOne); logistics = GetLogistics(footer, linesOne: linesOne);
if (logistics.Count == 0) if (logistics.Count == 0)
sequence = null; sequence = null;
@ -235,7 +235,7 @@ internal class ProcessDataStandardFormat
const int columnsLine = 6; const int columnsLine = 6;
FileInfo fileInfo = new(reportFullPath); FileInfo fileInfo = new(reportFullPath);
ProcessDataStandardFormat processDataStandardFormat = GetProcessDataStandardFormat(fileInfo.LastWriteTime, columnsLine, fileInfo.FullName, lines: null); ProcessDataStandardFormat processDataStandardFormat = GetProcessDataStandardFormat(fileInfo.LastWriteTime, columnsLine, fileInfo.FullName, lines: null);
JsonElement[]? jsonElements = processDataStandardFormatMapping.OldColumnNames.Count != processDataStandardFormatMapping.ColumnIndices.Count ? null : GetFullArray(processDataStandardFormat); JsonElement[]? jsonElements = processDataStandardFormatMapping.OldColumnNames.Count == 0 ? null : GetFullArray(processDataStandardFormat);
JsonProperty[]? jsonProperties = jsonElements is null || jsonElements.Length == 0 ? null : jsonElements[0].EnumerateObject().ToArray(); JsonProperty[]? jsonProperties = jsonElements is null || jsonElements.Length == 0 ? null : jsonElements[0].EnumerateObject().ToArray();
if (jsonElements is null || jsonProperties is null || jsonProperties.Length != processDataStandardFormatMapping.NewColumnNames.Count) if (jsonElements is null || jsonProperties is null || jsonProperties.Length != processDataStandardFormatMapping.NewColumnNames.Count)
result = processDataStandardFormat; result = processDataStandardFormat;
@ -654,6 +654,17 @@ internal class ProcessDataStandardFormat
return results; return results;
} }
internal static JsonElement[] GetArray(string reportFullPath, string[] lines, ProcessDataStandardFormat processDataStandardFormat)
{
JsonElement[] results;
string? json = GetRecordsJson(reportFullPath, lines);
if (string.IsNullOrEmpty(json))
results = GetArray(processDataStandardFormat);
else
results = JsonSerializer.Deserialize(json, JsonElementCollectionSourceGenerationContext.Default.JsonElementArray) ?? throw new Exception();
return results;
}
internal static string GetPDSFText(IFileRead fileRead, Logistics logistics, JsonElement[] jsonElements, string logisticsText) internal static string GetPDSFText(IFileRead fileRead, Logistics logistics, JsonElement[] jsonElements, string logisticsText)
{ {
string result; string result;
@ -903,7 +914,7 @@ internal class ProcessDataStandardFormat
} }
foreach (KeyValuePair<string, List<string>> keyValuePair in results) foreach (KeyValuePair<string, List<string>> keyValuePair in results)
{ {
if (body.Count < 3) if (body.Count < 2)
break; break;
if (keyValuePair.Value.Count != body.Count) if (keyValuePair.Value.Count != body.Count)
continue; continue;
@ -956,6 +967,26 @@ internal class ProcessDataStandardFormat
return result; return result;
} }
private static string? GetRecordsJson(string reportFullPath, string[] lines)
{
string? result;
bool foundRecords = false;
List<string> results = new();
lines ??= File.ReadAllLines(reportFullPath);
foreach (string line in lines)
{
if (line.StartsWith("\"Records\""))
foundRecords = true;
if (!foundRecords)
continue;
if (line == "],")
break;
results.Add(line);
}
result = results.Count == 0 ? null : $"{string.Join(Environment.NewLine, results.Skip(1))}{Environment.NewLine}]";
return result;
}
} }
[JsonSourceGenerationOptions(WriteIndented = true)] [JsonSourceGenerationOptions(WriteIndented = true)]