Compare commits

...

2 Commits

Author SHA1 Message Date
3c072d177a weighted-shortest-job-first-fibonacci as decimal 2025-08-01 19:12:32 -07:00
74461c147d Added ts file for bun testing
Added http to text area box

Moved CoD column to match query

Alignment
2025-07-18 14:29:21 -07:00
26 changed files with 1124 additions and 197 deletions

3
.gitignore vendored
View File

@ -339,6 +339,9 @@ ASALocalRun/
!**/.vscode/tasks.json !**/.vscode/tasks.json
!**/.vscode/mklink.md !**/.vscode/mklink.md
!**/.vscode/*.http !**/.vscode/*.http
**/.vscode/2025-*.http
**/.vscode/2026-*.http
*.lnk *.lnk

View File

@ -109,7 +109,7 @@ dotnet_diagnostic.CA2254.severity = none # CA2254: The logging message template
dotnet_diagnostic.IDE0001.severity = warning # IDE0001: Simplify name dotnet_diagnostic.IDE0001.severity = warning # IDE0001: Simplify name
dotnet_diagnostic.IDE0002.severity = warning # Simplify (member access) - System.Version.Equals("1", "2"); Version.Equals("1", "2"); dotnet_diagnostic.IDE0002.severity = warning # Simplify (member access) - System.Version.Equals("1", "2"); Version.Equals("1", "2");
dotnet_diagnostic.IDE0004.severity = warning # IDE0004: Cast is redundant. dotnet_diagnostic.IDE0004.severity = warning # IDE0004: Cast is redundant.
dotnet_diagnostic.IDE0005.severity = warning # Using directive is unnecessary dotnet_diagnostic.IDE0005.severity = none # Using directive is unnecessary
dotnet_diagnostic.IDE0028.severity = none # IDE0028: Collection initialization can be simplified dotnet_diagnostic.IDE0028.severity = none # IDE0028: Collection initialization can be simplified
dotnet_diagnostic.IDE0031.severity = warning # Use null propagation (IDE0031) dotnet_diagnostic.IDE0031.severity = warning # Use null propagation (IDE0031)
dotnet_diagnostic.IDE0047.severity = warning # IDE0047: Parentheses can be removed dotnet_diagnostic.IDE0047.severity = warning # IDE0047: Parentheses can be removed
@ -121,6 +121,7 @@ dotnet_diagnostic.IDE0290.severity = none # Use primary constructor [Distance]cs
dotnet_diagnostic.IDE0300.severity = none # IDE0300: Collection initialization can be simplified dotnet_diagnostic.IDE0300.severity = none # IDE0300: Collection initialization can be simplified
dotnet_diagnostic.IDE0301.severity = none #IDE0301: Collection initialization can be simplified dotnet_diagnostic.IDE0301.severity = none #IDE0301: Collection initialization can be simplified
dotnet_diagnostic.IDE0305.severity = none # IDE0305: Collection initialization can be simplified dotnet_diagnostic.IDE0305.severity = none # IDE0305: Collection initialization can be simplified
dotnet_diagnostic.MSTEST0015.severity = none # MSTEST0015: Test method {method} should not be ignored
dotnet_diagnostic.MSTEST0037.severity = error # MSTEST0037: Use proper 'Assert' methods dotnet_diagnostic.MSTEST0037.severity = error # MSTEST0037: Use proper 'Assert' methods
dotnet_diagnostic.SYSLIB1045.severity = none # SYSLIB1045: diagnostics for regex source generation dotnet_diagnostic.SYSLIB1045.severity = none # SYSLIB1045: diagnostics for regex source generation
dotnet_naming_rule.abstract_method_should_be_pascal_case.severity = warning dotnet_naming_rule.abstract_method_should_be_pascal_case.severity = warning

View File

@ -1,21 +0,0 @@
@host = https://tfs.intra.infineon.com
@pat = asdf
@ids = 126018, 224543
GET {{host}}/tfs/FactoryIntegration/_apis/wit/workitems?ids={{ids}}&$expand=Relations
Accept: application/json
Authorization: Basic {{pat}}
###
GET {{host}}/tfs/FactoryIntegration/_apis/wit/workitems/{{ids}}/updates
Accept: application/json
Authorization: Basic {{pat}}
### Iterations
GET {{host}}/tfs/FactoryIntegration/ART%20SPS/cea9f426-6fb1-4d65-93d5-dbf471056212/_apis/work/teamsettings/iterations?
Accept: application/json
Authorization: Basic {{pat}}
###

View File

@ -4,13 +4,7 @@
"name": ".NET Core Attach", "name": ".NET Core Attach",
"type": "coreclr", "type": "coreclr",
"request": "attach", "request": "attach",
"processId": 22868 "processId": 20292
},
{
"type": "node",
"request": "launch",
"name": "node Launch Current Opened File",
"program": "${file}"
} }
] ]
} }

View File

@ -22,9 +22,12 @@
"Rcpe", "Rcpe",
"RESIMAPCDE", "RESIMAPCDE",
"Rsens", "Rsens",
"signalr",
"Smpl", "Smpl",
"Villach", "Villach",
"Vrng" "Vrng",
"Weightest",
"WSJF"
], ],
"coverage-gutters.coverageBaseDir": "../../../../MESAFIBACKLOG/05_TestResults/TestResults/**", "coverage-gutters.coverageBaseDir": "../../../../MESAFIBACKLOG/05_TestResults/TestResults/**",
"workbench.colorCustomizations": { "workbench.colorCustomizations": {

View File

@ -1,19 +1,134 @@
{ {
"version": "2.0.0", "version": "2.0.0",
"inputs": [
{
"default": "Development",
"description": "Which ASP Net Core Environment?",
"id": "ASPNETCORE_ENVIRONMENT",
"options": [
"Development",
"Production"
],
"type": "pickString"
},
{
"default": "{AssemblyTitle}",
"description": "What Assembly Title?",
"id": "AssemblyTitle",
"type": "promptString"
},
{
"default": "{Build.BuildId}",
"description": "Which Build BuildId?",
"id": "Build.BuildId",
"type": "promptString"
},
{
"default": "{Build.Reason}",
"description": "Which Build Reason?",
"id": "Build.Reason",
"type": "promptString"
},
{
"default": "{Build.Repository.Id}",
"description": "Which Build Repository Id?",
"id": "Build.Repository.Id",
"type": "promptString"
},
{
"default": "{Build.Repository.Name}",
"description": "Which Build Repository Name?",
"id": "Build.Repository.Name",
"type": "promptString"
},
{
"default": "{Build.SourceVersion}",
"description": "Which Build Source Version?",
"id": "Build.SourceVersion",
"type": "promptString"
},
{
"default": "Debug",
"description": "Which Configuration?",
"id": "Configuration",
"options": [
"Debug",
"Release"
],
"type": "pickString"
},
{
"default": "net8.0",
"description": "Which Core Version?",
"id": "CoreVersion",
"options": [
"net8.0"
],
"type": "pickString"
},
{
"default": "C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/MSBuild/Current/Bin/MSBuild.exe",
"description": "Which MS Build?",
"id": "MSBuild",
"type": "promptString"
},
{
"default": "https://artifactory.intra.infineon.com/artifactory/api/nuget/ngt-fi-package-main-vir/",
"description": "Which Nuget Source?",
"id": "NugetSource",
"type": "promptString"
},
{
"default": "win-x64",
"description": "Which Runtime?",
"id": "Runtime",
"options": [
"win-x64",
"win-x32",
"linux-x64",
"linux-x32"
],
"type": "pickString"
},
{
"default": "L:/",
"description": "Which System DefaultWorkingDirectory?",
"id": "System.DefaultWorkingDirectory",
"options": [
"L:/",
"D:/",
"C:/"
],
"type": "pickString"
},
{
"default": "v4.8",
"description": "Which Core Target Framework Version?",
"id": "TargetFrameworkVersion",
"options": [
"v4.8"
],
"type": "pickString"
},
{
"default": "{UserSecretsId}",
"description": "Which Core User Secrets Id?",
"id": "UserSecretsId",
"type": "promptString"
}
],
"tasks": [ "tasks": [
{ {
"label": "Build", "label": "Build",
"command": "dotnet", "command": "dotnet",
"type": "process", "type": "process",
"args": [ "args": [
"build", "build"
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
], ],
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Test-Debug", "label": "Test Debug",
"command": "dotnet", "command": "dotnet",
"type": "process", "type": "process",
"args": [ "args": [
@ -24,7 +139,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Test-Release", "label": "Test Release",
"command": "dotnet", "command": "dotnet",
"type": "process", "type": "process",
"args": [ "args": [
@ -50,7 +165,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Format-Whitespaces", "label": "Format Whitespaces",
"command": "dotnet", "command": "dotnet",
"type": "process", "type": "process",
"args": [ "args": [
@ -87,13 +202,13 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Project", "label": "Code Project",
"type": "shell", "type": "shell",
"command": "code ../MESAFIBACKLOG.csproj", "command": "code ../MESAFIBACKLOG.csproj",
"problemMatcher": [] "problemMatcher": []
}, },
{ {
"label": "Readme", "label": "Code Read Me",
"type": "shell", "type": "shell",
"command": "code ../README.md", "command": "code ../README.md",
"problemMatcher": [] "problemMatcher": []
@ -113,7 +228,7 @@
"problemMatcher": [] "problemMatcher": []
}, },
{ {
"label": "Git Config", "label": "Code Git Config",
"type": "shell", "type": "shell",
"command": "code ../.git/config", "command": "code ../.git/config",
"problemMatcher": [] "problemMatcher": []

160
Adaptation/.vscode/tfs.http vendored Normal file
View File

@ -0,0 +1,160 @@
@Manufacturing-IT = https://tfs.intra.infineon.com/tfs/ManufacturingIT
@Factory-Integration = https://tfs.intra.infineon.com/tfs/FactoryIntegration
@userId = phares
@ids = 126018, 224543
@Unauthorized-Chase = asdf
@Factory-Integration-Phares-1CB1AEFED90C2A4A9A96F9ED9140A95E = asdf
### Work Items Expand Relations
GET {{Factory-Integration}}/_apis/wit/workitems?ids={{ids}}&$expand=Relations
Accept: application/json
Authorization: Basic {{Factory-Integration-Phares-1CB1AEFED90C2A4A9A96F9ED9140A95E}}
### Work Items Updates
GET {{Factory-Integration}}/_apis/wit/workitems/{{ids}}/updates
Accept: application/json
Authorization: Basic {{Factory-Integration-Phares-1CB1AEFED90C2A4A9A96F9ED9140A95E}}
### Iterations
GET {{Factory-Integration}}/ART%20SPS/cea9f426-6fb1-4d65-93d5-dbf471056212/_apis/work/teamsettings/iterations?
Accept: application/json
Authorization: Basic {{Factory-Integration-Phares-1CB1AEFED90C2A4A9A96F9ED9140A95E}}
### User Entitlements
GET {{Factory-Integration}}/_apis/userEntitlements/{{userId}}?api-version=6.0-preview.3
Authorization: Basic {{Factory-Integration-Phares-1CB1AEFED90C2A4A9A96F9ED9140A95E}}
Accept: application/json
### User Entitlements
GET {{Factory-Integration}}/_apis/userEntitlements?api-version=5.1-preview.2
Authorization: Basic {{Factory-Integration-Phares-1CB1AEFED90C2A4A9A96F9ED9140A95E}}
Accept: application/json
### Work Item Patch
patch {{Manufacturing-IT}}/Mesa_FI/_apis/wit/workitems/382290?api-version=7.0
Authorization: Basic {{Factory-Integration-Phares-1CB1AEFED90C2A4A9A96F9ED9140A95E}}
Content-Type: application/json-patch+json
[
{
"op": "test",
"path": "/rev",
"value": 1
},
{
"op": "test",
"path": "/fields/System.CreatedDate",
"value": "2023-10-07T18:51:52.783Z"
},
{
"op": "replace",
"path": "/fields/System.CreatedDate",
"value": "2023-10-07T18:41:52.783Z"
}
]
### Post Comment
POST {{Manufacturing-IT}}/Mesa_FI/_apis/wit/workitems/382005/comments?api-version=5.1-preview.3
Authorization: Basic {{Unauthorized-Chase}}
Content-Type: application/json
{
"text": "Force updated by"
}
### Delete Comment
DELETE {{Manufacturing-IT}}/Mesa_FI/_apis/wit/workitems/382005/comments?api-version=5.1-preview.3
Authorization: Basic {{Unauthorized-Chase}}
Content-Type: application/json
### Work Item Patch WSJF
patch {{Factory-Integration}}/_apis/wit/workitems/292309?api-version=7.0
Authorization: Basic {{Factory-Integration-Phares-1CB1AEFED90C2A4A9A96F9ED9140A95E}}
Content-Type: application/json-patch+json
[
{
"op": "replace",
"path": "/fields/Custom.WSJF",
"value": "5"
}
]
### Work Item Patch WSJF-B 100+300+400=800 800/200=4
patch {{Factory-Integration}}/_apis/wit/workitems/292309?api-version=7.0
Authorization: Basic {{Factory-Integration-Phares-1CB1AEFED90C2A4A9A96F9ED9140A95E}}
Content-Type: application/json-patch+json
[
{
"op": "replace",
"path": "/fields/Microsoft.VSTS.Common.BusinessValue",
"value": "100"
},
{
"op": "replace",
"path": "/fields/Microsoft.VSTS.Scheduling.Effort",
"value": "200"
},
{
"op": "replace",
"path": "/fields/Custom.RRminusOE",
"value": "300"
},
{
"op": "replace",
"path": "/fields/Microsoft.VSTS.Common.TimeCriticality",
"value": "400"
},
{
"op": "replace",
"path": "/fields/Custom.WSJF",
"value": "4"
}
]
### Work Item Patch WSJF-B 400+400+400=1200 1200/200=6
patch {{Factory-Integration}}/_apis/wit/workitems/110781?api-version=7.0
Authorization: Basic {{Factory-Integration-Phares-1CB1AEFED90C2A4A9A96F9ED9140A95E}}
Content-Type: application/json-patch+json
[
{
"op": "replace",
"path": "/fields/Microsoft.VSTS.Common.BusinessValue",
"value": "400"
},
{
"op": "replace",
"path": "/fields/Microsoft.VSTS.Scheduling.Effort",
"value": "200"
},
{
"op": "replace",
"path": "/fields/Custom.RRminusOE",
"value": "400"
},
{
"op": "replace",
"path": "/fields/Microsoft.VSTS.Common.TimeCriticality",
"value": "400"
},
{
"op": "replace",
"path": "/fields/Custom.WSJF",
"value": "6"
}
]
###

View File

@ -128,7 +128,7 @@ public class FileRead : Shared.FileRead, IFileRead
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray(); Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0) if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
FileCopy(reportFullPath, dateTime, descriptions); FileCopy(reportFullPath, dateTime, descriptions);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>()); results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics), tests, jsonElements, new List<FileInfo>());
return results; return results;
} }

View File

@ -153,7 +153,7 @@ public class FileRead : Shared.FileRead, IFileRead
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray(); Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0) if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
MoveArchive(reportFullPath, dateTime); MoveArchive(reportFullPath, dateTime);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>()); results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics), tests, jsonElements, new List<FileInfo>());
return results; return results;
} }

View File

@ -127,7 +127,7 @@ public class FileRead : Shared.FileRead, IFileRead
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray(); Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0) if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
FileCopy(reportFullPath, dateTime, descriptions); FileCopy(reportFullPath, dateTime, descriptions);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>()); results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics), tests, jsonElements, new List<FileInfo>());
return results; return results;
} }

View File

@ -126,7 +126,7 @@ public class FileRead : Shared.FileRead, IFileRead
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray(); Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0) if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
SaveOpenInsightFile(reportFullPath, dateTime, descriptions, tests); SaveOpenInsightFile(reportFullPath, dateTime, descriptions, tests);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>()); results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics), tests, jsonElements, new List<FileInfo>());
return results; return results;
} }

View File

@ -137,7 +137,7 @@ public class FileRead : Shared.FileRead, IFileRead
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray(); Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0) if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
SendData(reportFullPath, dateTime, descriptions); SendData(reportFullPath, dateTime, descriptions);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>()); results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics), tests, jsonElements, new List<FileInfo>());
return results; return results;
} }

View File

@ -154,7 +154,7 @@ public class FileRead : Shared.FileRead, IFileRead
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray(); Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0) if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
PostOpenInsightMetrologyViewerAttachments(descriptions); PostOpenInsightMetrologyViewerAttachments(descriptions);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>()); results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics), tests, jsonElements, new List<FileInfo>());
return results; return results;
} }

View File

@ -173,7 +173,7 @@ public class FileRead : Shared.FileRead, IFileRead
JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat); JsonElement[] jsonElements = ProcessDataStandardFormat.GetArray(processDataStandardFormat);
List<Description> descriptions = json.ProcessData.GetDescriptions(jsonElements); List<Description> descriptions = json.ProcessData.GetDescriptions(jsonElements);
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray(); Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>()); results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics), tests, jsonElements, new List<FileInfo>());
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0) if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
DirectoryMove(reportFullPath, dateTime, descriptions); DirectoryMove(reportFullPath, dateTime, descriptions);
else if (!_IsEAFHosted) else if (!_IsEAFHosted)

View File

@ -125,7 +125,7 @@ public class FileRead : Shared.FileRead, IFileRead
Test[] tests = (from l in descriptions select (Test)l.Test).ToArray(); Test[] tests = (from l in descriptions select (Test)l.Test).ToArray();
if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0) if (_IsEAFHosted && _FileConnectorConfiguration.FileScanningIntervalInSeconds > 0)
FileCopy(reportFullPath, dateTime, descriptions); FileCopy(reportFullPath, dateTime, descriptions);
results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics[0]), tests, jsonElements, new List<FileInfo>()); results = new Tuple<string, Test[], JsonElement[], List<FileInfo>>(string.Join(Environment.NewLine, processDataStandardFormat.Logistics), tests, jsonElements, new List<FileInfo>());
return results; return results;
} }

View File

@ -189,7 +189,8 @@ public class FileRead : Shared.FileRead, IFileRead
timeCriticality: fields.MicrosoftVSTSCommonTimeCriticality is null or 0 ? null : (long)fields.MicrosoftVSTSCommonTimeCriticality, timeCriticality: fields.MicrosoftVSTSCommonTimeCriticality is null or 0 ? null : (long)fields.MicrosoftVSTSCommonTimeCriticality,
title: fields.SystemTitle.Trim(), title: fields.SystemTitle.Trim(),
violation: null, violation: null,
weightedShortestJobFirst: fields.CustomWSJF is null or 0 ? null : (long)fields.CustomWSJF, weightedShortestJobFirst: fields.CustomWSJF is null or 0 ? null : fields.CustomWSJF,
weightedShortestJobFirstFibonacci: fields.CustomWSJFFib is null or 0 ? null : fields.CustomWSJFFib,
workItemType: fields.SystemWorkItemType); workItemType: fields.SystemWorkItemType);
results.Add(workItem.Id, workItem); results.Add(workItem.Id, workItem);
} }

View File

@ -0,0 +1,433 @@
var _b = {};
var _c = {};
var _e = {};
var _r = {};
var _t = {};
var _w = {};
var _page = '';
var _site = '';
var _apiUrl = '';
var _toggle = true;
var _username = '';
var _machineId = '';
var _sessionId = '';
var _windowLocationHRef = '';
function compareFunctionSortOrder(a: any, b: any) {
return a.SortOrder - b.SortOrder;
}
function compareFunctionParentId(a: any, b: any) {
return a.ParentId - b.ParentId || a.Id - b.Id;
}
function compareFunctionWeightedShortestJobFirst(a: any, b: any) {
if (b.WeightedShortestJobFirst === '&nbsp;') {
return -1;
}
return b.WeightedShortestJobFirst - a.WeightedShortestJobFirst;
}
function getState(state: any) {
let result;
if (state == undefined)
result = '9-Null';
else if (state === 'New')
result = `1-${state}`;
else if (state === 'Active')
result = `2-${state}`;
else if (state === 'Resolved')
result = `3-${state}`;
else if (state === 'Closed')
result = `4-${state}`;
else if (state === 'Removed')
result = `5-${state}`;
else
result = `8-${state}`;
return result;
}
function getPriority(workItemType: any, priority: any, sortPriorityGroup: any) {
let result;
if (workItemType === 'Bug')
result = '0-Bug {0}';
else if (priority == undefined || priority === 0)
result = '9-Null {0}';
else if (priority === 1)
result = `${priority}-High {${sortPriorityGroup}}`;
else if (priority === 2)
result = `${priority}-Med {${sortPriorityGroup}}`;
else if (priority === 3)
result = `${priority}-Low {${sortPriorityGroup}}`;
else if (priority === 4)
result = `${priority}-TBD {4}`;
else
result = '8-Not {0}';
return result;
}
function getNotifications(x: any, aggregation: any) {
let result: any;
if (aggregation == undefined || aggregation.Notifications == undefined || aggregation.Notifications.length === 0)
result = '&nbsp;';
else {
result = '';
aggregation.Notifications.forEach((element: any) => {
const username = element.username == null ? 'user' : element.username;
if (element.value === '1') {
result += 'Highest:' + username + ';|';
}
else if (element.value === '2') {
result += 'High:' + username + ';|';
}
else if (element.value === '3') {
result += 'Medium:' + username + ';|';
}
else if (element.value === '4') {
result += 'Low:' + username + ';|';
}
else if (element.value === '5') {
result += 'Lowest:' + username + ';|';
}
else {
result += element.value + ':' + username + ';|';
}
});
result = result.substring(0, result.length - 1);
result = result.replaceAll('|', '<br />');
}
return result;
}
function round(value: any, factor: number) {
return (Math.round((value + Number.EPSILON) * factor) / factor).toFixed(2);
}
function roundMultiply(value: any, factor: number, multiply: number) {
return (Math.round((value + Number.EPSILON) * factor) / factor) * multiply;
}
function sum(collection: any) {
let sum = 0;
if (collection != undefined) {
for (let i = 0; i < collection.length; i++) {
sum += collection[i];
}
}
return sum;
}
function updateRecordCoD(b: any, r: any, t: any, c: any, e: any, w: any, workItem: any, highestTotalStoryPoints: any, dataB: any, totalStoryPoints: any) {
if (workItem != undefined) {
let data = dataB == undefined ? undefined : dataB[workItem.Id];
if (data == undefined) {
workItem.api = '';
workItem.CumulativeStoryPoints = '&nbsp;';
workItem.TotalStoryPoints = '&nbsp;';
workItem.AbsoluteDelta = '&nbsp;';
workItem.Effort = '&nbsp;';
workItem.BusinessValue = '&nbsp;';
workItem.TimeCriticality = '&nbsp;';
workItem.RiskReductionMinusOpportunityEnablement = '&nbsp;';
workItem.CoD = '&nbsp;';
workItem.WeightedShortestJobFirst = '&nbsp;';
workItem.Priority = getPriority(workItem.WorkItemType, 4, 0);
workItem.EffortNotifications = '&nbsp;';
workItem.BusinessValueNotifications = '&nbsp;';
workItem.TimeCriticalityNotifications = '&nbsp;';
workItem.RiskReductionMinusOpportunityEnablementNotifications = '&nbsp;';
workItem.SortOrder = 0;
}
else {
let effort = workItem.Effort;
let businessValue = workItem.BusinessValue;
let timeCriticality = workItem.TimeCriticality;
let riskReductionMinusOpportunityEnablement = workItem.RiskReductionMinusOpportunityEnablement;
let weightedShortestJobFirst = workItem.WeightedShortestJobFirst == undefined ? null : workItem.WeightedShortestJobFirst.toFixed(2);
workItem.CumulativeStoryPoints = '&nbsp;';
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.Effort = data.Effort == undefined || data.Effort.FibonacciAverage == undefined ? '&nbsp;' : roundMultiply(data.Effort.FibonacciAverage, 100, 100);
workItem.BusinessValue = data.BusinessValue == undefined || data.BusinessValue.FibonacciAverage == undefined ? '&nbsp;' : roundMultiply(data.BusinessValue.FibonacciAverage, 100, 100);
workItem.TimeCriticality = data.TimeCriticality == undefined || data.TimeCriticality.FibonacciAverage == undefined ? '&nbsp;' : roundMultiply(data.TimeCriticality.FibonacciAverage, 100, 100);
workItem.RiskReductionMinusOpportunityEnablement = data.RiskReductionOpportunityEnablement == undefined || data.RiskReductionOpportunityEnablement.FibonacciAverage == undefined ? '&nbsp;' : roundMultiply(data.RiskReductionOpportunityEnablement.FibonacciAverage, 100, 100);
workItem.CoD = data.CostOfDelay == undefined ? '&nbsp;' : roundMultiply(data.CostOfDelay, 100, 100);
workItem.WeightedShortestJobFirst = data.WeightedShortestJobFirst == undefined ? '&nbsp;' : round(data.WeightedShortestJobFirst, 100);
workItem.Priority = data.SortPriority == undefined ? getPriority(workItem.WorkItemType, 4, 0) : getPriority(workItem.WorkItemType, data.SortPriority, data.SortPriorityGroup);
workItem.EffortNotifications = data.Effort == undefined ? '&nbsp;' : getNotifications(e, data.Effort);
workItem.BusinessValueNotifications = data.BusinessValue == undefined ? '&nbsp;' : getNotifications(b, data.BusinessValue);
workItem.TimeCriticalityNotifications = data.TimeCriticality == undefined ? '&nbsp;' : getNotifications(t, data.TimeCriticality);
workItem.RiskReductionMinusOpportunityEnablementNotifications = data.RiskReductionOpportunityEnablement == undefined ? '&nbsp;' : getNotifications(r, data.RiskReductionOpportunityEnablement);
workItem.SortOrder = data.SortOrder == undefined ? 0 : data.SortOrder;
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} ${weightedShortestJobFirst} != ${workItem.WeightedShortestJobFirst}
patch {{Factory-Integration}}/_apis/wit/workitems/${workItem.Id}?api-version=7.0
Authorization: Basic {{PAT}}
Content-Type: application/json-patch+json
[
{
"op": "replace",
"path": "/fields/Microsoft.VSTS.Common.BusinessValue",
"value": "${workItem.BusinessValue}"
},
{
"op": "replace",
"path": "/fields/Microsoft.VSTS.Scheduling.Effort",
"value": "${workItem.Effort}"
},
{
"op": "replace",
"path": "/fields/Custom.RRminusOE",
"value": "${workItem.RiskReductionMinusOpportunityEnablement}"
},
{
"op": "replace",
"path": "/fields/Microsoft.VSTS.Common.TimeCriticality",
"value": "${workItem.TimeCriticality}"
},
{
"op": "replace",
"path": "/fields/Custom.WSJF",
"value": "${workItem.WeightedShortestJobFirst}"
},
{
"op": "replace",
"path": "/fields/Custom.WSJFFib",
"value": "${workItem.WeightedShortestJobFirst}"
}
]`;
}
}
}
}
function updateRecordParent(parent: any, workItem: any) {
if (parent == undefined) {
workItem.ParentId = 9999999;
workItem.ParentTitle = null;
workItem.ParentState = null;
workItem.ParentCoD = 9999999;
}
else {
workItem.ParentId = parent.Id;
workItem.ParentCoD = parent.CoD;
workItem.ParentTitle = parent.Title;
workItem.ParentState = getState(parent.State);
}
}
function getRecords(b: any, r: any, t: any, c: any, e: any, w: any, data: any, dataB: any, workItems: any) {
let parent;
let workItem;
let storyPoints;
let records = [];
let totalStoryPoints;
let highestTotalStoryPoints = 0;
for (let i = 0; i < data.length; i++) {
workItem = data[i].WorkItem;
if (workItem.WorkItemType !== 'Feature')
continue;
if (workItem.State !== 'Active' && workItem.State !== 'New')
continue;
if (workItem.Tags != null && workItem.Tags.includes('Ignore'))
continue;
storyPoints = data[i].Tag?.StoryPoints == undefined ? null : JSON.parse(data[i].Tag.StoryPoints);
totalStoryPoints = sum(storyPoints);
if (totalStoryPoints > highestTotalStoryPoints)
highestTotalStoryPoints = totalStoryPoints;
}
for (let i = 0; i < data.length; i++) {
parent = data[i].Parent;
workItem = data[i].WorkItem;
if (workItem.WorkItemType !== 'Feature')
continue;
if (workItem.State !== 'Active' && workItem.State !== 'New')
continue;
if (workItem.Tags != null && workItem.Tags.includes('Ignore'))
continue;
storyPoints = data[i].Tag?.StoryPoints == undefined ? null : JSON.parse(data[i].Tag.StoryPoints);
totalStoryPoints = sum(storyPoints);
if ((_windowLocationHRef.indexOf('=LEO') > -1 && workItem.AreaPath !== 'ART SPS\\LEO') || (_windowLocationHRef.indexOf('=MES') > -1 && workItem.AreaPath !== 'ART SPS\\MES'))
continue;
updateRecordParent(parent, workItem);
updateRecordCoD(b, r, t, c, e, w, parent, highestTotalStoryPoints, null, null);
updateRecordCoD(b, r, t, c, e, w, workItem, highestTotalStoryPoints, dataB, totalStoryPoints);
workItem.State = getState(workItem.State);
records.push(workItem);
}
if (_windowLocationHRef.indexOf('=WSJF') > -1) {
records.sort(compareFunctionWeightedShortestJobFirst);
}
else if (_windowLocationHRef.indexOf('=LIVE') > -1) {
records.sort(compareFunctionSortOrder);
}
else {
records.sort(compareFunctionParentId);
}
return records;
}
function getHtmlTextAndHttp(fromHtml: any, b: any, r: any, t: any, c: any, e: any, w: any, records: any) {
let record;
let http = '';
let lineA = '';
let lineB = '';
let lineC = '';
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>';
for (let i = 0; i < records.length; i++) {
record = records[i];
if (record.api !== '') {
http += record.api + '\r\n';
}
text += record.Id + '\t' +
record.RiskReductionMinusOpportunityEnablement + '\t' +
record.TimeCriticality + '\t' +
record.BusinessValue + '\t' +
record.Effort + '\t' +
record.WeightedShortestJobFirst + '\t' +
record.CoD + '\t' +
record.TotalStoryPoints.split(' ')[0] + '\t' +
record.AbsoluteDelta + '\t' +
record.State.split('-')[0] + '\t' +
record.Requester + '\t' +
record.AssignedTo + '\t' +
record.IterationPath + '\t' +
record.Tags + '\t' +
record.Title + '\r\n';
lineA = '<tr id="tr' + record.Id + '"><td>' + '<a target="_blank" href="https://tfs.intra.infineon.com/tfs/FactoryIntegration/ART%20SPS/_workitems/edit/' + record.ParentId + '">' + record.ParentId + "</a>" +
'</td><td>' + record.ParentTitle +
'</td><td>' + '<a target="_blank" href="https://tfs.intra.infineon.com/tfs/FactoryIntegration/ART%20SPS/_workitems/edit/' + record.Id + '">' + record.Id + "</a>" +
'</td><td>' + record.Requester +
'</td><td>' + record.Title +
'</td><td>' + record.AssignedTo +
'</td><td>' + record.Tags +
'</td><td>' + record.State +
'</td><td>' + record.Priority +
'</td><td><span id=' + r.page + record.Id + '>' + record.RiskReductionMinusOpportunityEnablementNotifications + '</span><br />' +
'<select class="select" onchange="sendValue(' + fromHtml + ', this, \'' + r.page + '\', ' + record.Id + ')">' +
'<option value="9">Unknown</option>' +
'<option value="1">Highest (Most ' + r.description + ')</option>' +
'<option value="2">High</option>' +
'<option value="3">Medium</option>' +
'<option value="4">Low</option>' +
'<option value="5">Lowest</option>' +
'</select>' +
'</td><td><span id=' + t.page + record.Id + '>' + record.TimeCriticalityNotifications + '</span><br />' +
'<select class="select" onchange="sendValue(' + fromHtml + ', this, \'' + t.page + '\', ' + record.Id + ')">' +
'<option value="9">Unknown</option>' +
'<option value="1">Highest (Most ' + t.description + ')</option>' +
'<option value="2">High</option>' +
'<option value="3">Medium</option>' +
'<option value="4">Low</option>' +
'<option value="5">Lowest</option>' +
'</select>' +
'</td><td><span id=' + b.page + record.Id + '>' + record.BusinessValueNotifications + '</span><br />' +
'<select class="select" onchange="sendValue(' + fromHtml + ', this, \'' + b.page + '\', ' + record.Id + ')">' +
'<option value="9">Unknown</option>' +
'<option value="1">Highest (Most ' + b.description + ')</option>' +
'<option value="2">High</option>' +
'<option value="3">Medium</option>' +
'<option value="4">Low</option>' +
'<option value="5">Lowest</option>' +
'</select>' +
'</td><td><span id=' + c.page + record.Id + '>' + record.CoD + '</span>' +
'</td><td><span id=' + e.page + record.Id + '>' + record.EffortNotifications + '</span><br />';
if (!fromHtml || _windowLocationHRef.indexOf('=EFFORT') === -1) {
lineB = '';
}
else {
lineB = '<select class="select" onchange="sendValue(' + fromHtml + ', this, \'' + e.page + '\', ' + record.Id + ')">' +
'<option value="9">Unknown</option>' +
'<option value="1">Highest (Most ' + e.description + ')</option>' +
'<option value="2">High</option>' +
'<option value="3">Medium</option>' +
'<option value="4">Low</option>' +
'<option value="5">Lowest</option>' +
'</select><br />';
}
lineC = '<span>' + record.TotalStoryPoints + '</span></td>' +
'<td><span id=' + w.page + record.Id + '>' + record.WeightedShortestJobFirst + '<br /><span>' + record.CumulativeStoryPoints + '</span></span>' +
'</td></tr>';
if (!fromHtml)
console.log(text);
html += lineA + lineB + lineC;
}
return { html, text, http };
}
const username = '';
const machineId = '';
const fromHtml = false;
const baseUri = 'http://eaf-dev.mes.infineon.com:5054';
const apiUrl = baseUri + '/api/v1/ado/';
const windowLocationHRef = baseUri + '/html/cod.html?site=MES';
const signalRUrl = baseUri + '/signalr';
const workItems = {
a: baseUri + '/markdown/bugs-features-with-parents.json?v=2025-04-14-08-10',
b: baseUri + '/markdown/{}.json?v=2025-04-14-08-10',
timeout: 3000,
};
const b = {
page: 'business',
description: 'Value',
th: 'Business Value',
span: 'What is the relative value to the Customer or business?<br>• Do our users prefer this over that?<br>• What is the revenue impact on our business?<br>• Is there a potential penalty or other negative effects if we delay?'
};
const r = {
page: 'risk',
description: 'Risk',
th: 'Risk Reduction and/or Opportunity Enablement',
span: 'What else does this do for our business?<br>• Reduce the risk of this or future delivery?<br>• Is there value in the information we will receive?<br>• Enable new business opportunities?'
};
const t = {
page: 'time',
description: 'Critical',
th: 'Time Criticality',
span: 'How does user/business value decay over time?<br>• Is there a fixed deadline?<br>• Will they wait for us or move to another Solution?<br>• What is the current effect on Customer satisfaction?'
};
const c = {
page: 'cod',
description: 'CoD',
th: 'Cost of Delay (CoD)',
span: "Cost of Delay (CoD) is the money lost by delaying or not doing a job for a specific time. It's a measure of the economic value of a job over time."
};
const e = {
page: 'effort',
description: 'Effort',
th: 'Effort',
span: 'Effort'
};
const w = {
page: 'wsjf',
description: 'WSJF',
th: 'Weightest Shortest Job First calculation (WSJF)',
span: 'Weightest Shortest Job First calculation (see @SCALE formula)'
};
_windowLocationHRef = windowLocationHRef;
fetch(workItems.b)
.then((res) => res.text())
.then((textB) => {
fetch(workItems.a)
.then((res) => res.text())
.then((textA) => {
const dataA = JSON.parse(textA);
const dataB = JSON.parse(textB);
if (dataA.length > 0)
console.log(dataA[0]);
const records = getRecords(b, r, t, c, e, w, dataA, dataB, workItems);
let result = getHtmlTextAndHttp(fromHtml, b, r, t, c, e, w, records);
if (result == undefined) { }
})
.catch((e) => console.error(e));
})
.catch((e) => console.error(e));

View File

@ -31,16 +31,16 @@ function compareFunctionWeightedShortestJobFirst(a, b) {
function getState(state) { function getState(state) {
let result; let result;
if (state == undefined) if (state == undefined)
result = "9-Null"; result = '9-Null';
else if (state === "New") else if (state === 'New')
result = `1-${state}`; result = `1-${state}`;
else if (state === "Active") else if (state === 'Active')
result = `2-${state}`; result = `2-${state}`;
else if (state === "Resolved") else if (state === 'Resolved')
result = `3-${state}`; result = `3-${state}`;
else if (state === "Closed") else if (state === 'Closed')
result = `4-${state}`; result = `4-${state}`;
else if (state === "Removed") else if (state === 'Removed')
result = `5-${state}`; result = `5-${state}`;
else else
result = `8-${state}`; result = `8-${state}`;
@ -49,10 +49,10 @@ function getState(state) {
function getPriority(workItemType, priority, sortPriorityGroup) { function getPriority(workItemType, priority, sortPriorityGroup) {
let result; let result;
if (workItemType === "Bug") if (workItemType === 'Bug')
result = "0-Bug {0}"; result = '0-Bug {0}';
else if (priority == undefined || priority === 0) else if (priority == undefined || priority === 0)
result = "9-Null {0}"; result = '9-Null {0}';
else if (priority === 1) else if (priority === 1)
result = `${priority}-High {${sortPriorityGroup}}`; result = `${priority}-High {${sortPriorityGroup}}`;
else if (priority === 2) else if (priority === 2)
@ -62,31 +62,31 @@ function getPriority(workItemType, priority, sortPriorityGroup) {
else if (priority === 4) else if (priority === 4)
result = `${priority}-TBD {4}`; result = `${priority}-TBD {4}`;
else else
result = "8-Not {0}"; result = '8-Not {0}';
return result; return result;
} }
function getNotifications(x, aggregation) { function getNotifications(x, aggregation) {
let result; let result;
if (aggregation == undefined || aggregation.Notifications == undefined || aggregation.Notifications.length === 0) if (aggregation == undefined || aggregation.Notifications == undefined || aggregation.Notifications.length === 0)
result = "&nbsp;"; result = '&nbsp;';
else { else {
result = ''; result = '';
aggregation.Notifications.forEach(element => { aggregation.Notifications.forEach(element => {
const username = element.username == null ? 'user' : element.username; const username = element.username == null ? 'user' : element.username;
if (element.value === "1") { if (element.value === '1') {
result += 'Highest:' + username + ';|'; result += 'Highest:' + username + ';|';
} }
else if (element.value === "2") { else if (element.value === '2') {
result += 'High:' + username + ';|'; result += 'High:' + username + ';|';
} }
else if (element.value === "3") { else if (element.value === '3') {
result += 'Medium:' + username + ';|'; result += 'Medium:' + username + ';|';
} }
else if (element.value === "4") { else if (element.value === '4') {
result += 'Low:' + username + ';|'; result += 'Low:' + username + ';|';
} }
else if (element.value === "5") { else if (element.value === '5') {
result += 'Lowest:' + username + ';|'; result += 'Lowest:' + username + ';|';
} }
else { else {
@ -103,6 +103,10 @@ function round(value, factor) {
return (Math.round((value + Number.EPSILON) * factor) / factor).toFixed(2); return (Math.round((value + Number.EPSILON) * factor) / factor).toFixed(2);
} }
function roundMultiply(value, factor, multiply) {
return (Math.round((value + Number.EPSILON) * factor) / factor) * multiply;
}
function sum(collection) { function sum(collection) {
let sum = 0; let sum = 0;
if (collection != undefined) { if (collection != undefined) {
@ -117,38 +121,91 @@ function updateRecordCoD(b, r, t, c, e, w, workItem, highestTotalStoryPoints, da
if (workItem != undefined) { if (workItem != undefined) {
let data = dataB == undefined ? undefined : dataB[workItem.Id]; let data = dataB == undefined ? undefined : dataB[workItem.Id];
if (data == undefined) { if (data == undefined) {
workItem.CumulativeStoryPoints = "&nbsp;"; workItem.api = '';
workItem.TotalStoryPoints = "&nbsp;"; workItem.CumulativeStoryPoints = '&nbsp;';
workItem.AbsoluteDelta = "&nbsp;"; workItem.TotalStoryPoints = '&nbsp;';
workItem.Effort = "&nbsp;"; workItem.AbsoluteDelta = '&nbsp;';
workItem.BusinessValue = "&nbsp;"; workItem.Effort = '&nbsp;';
workItem.TimeCriticality = "&nbsp;"; workItem.BusinessValue = '&nbsp;';
workItem.RiskReductionMinusOpportunityEnablement = "&nbsp;"; workItem.TimeCriticality = '&nbsp;';
workItem.CoD = "&nbsp;"; workItem.RiskReductionMinusOpportunityEnablement = '&nbsp;';
workItem.WeightedShortestJobFirst = "&nbsp;"; workItem.CoD = '&nbsp;';
workItem.WeightedShortestJobFirst = '&nbsp;';
workItem.Priority = getPriority(workItem.WorkItemType, 4, 0); workItem.Priority = getPriority(workItem.WorkItemType, 4, 0);
workItem.EffortNotifications = "&nbsp;"; workItem.EffortNotifications = '&nbsp;';
workItem.BusinessValueNotifications = "&nbsp;"; workItem.BusinessValueNotifications = '&nbsp;';
workItem.TimeCriticalityNotifications = "&nbsp;"; workItem.TimeCriticalityNotifications = '&nbsp;';
workItem.RiskReductionMinusOpportunityEnablementNotifications = "&nbsp;"; workItem.RiskReductionMinusOpportunityEnablementNotifications = '&nbsp;';
workItem.SortOrder = 0; workItem.SortOrder = 0;
} }
else { else {
workItem.CumulativeStoryPoints = "&nbsp;"; let effort = workItem.Effort;
let businessValue = workItem.BusinessValue;
let timeCriticality = workItem.TimeCriticality;
let riskReductionMinusOpportunityEnablement = workItem.RiskReductionMinusOpportunityEnablement;
let weightedShortestJobFirst = workItem.WeightedShortestJobFirst == undefined ? null : workItem.WeightedShortestJobFirst.toFixed(2);
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);
workItem.Effort = data.Effort == undefined || data.Effort.FibonacciAverage == undefined ? "&nbsp;" : round(data.Effort.FibonacciAverage, 100); workItem.Effort = data.Effort == undefined || data.Effort.FibonacciAverage == undefined ? '&nbsp;' : roundMultiply(data.Effort.FibonacciAverage, 100, 100);
workItem.BusinessValue = data.BusinessValue == undefined || data.BusinessValue.FibonacciAverage == undefined ? "&nbsp;" : round(data.BusinessValue.FibonacciAverage, 100); workItem.BusinessValue = data.BusinessValue == undefined || data.BusinessValue.FibonacciAverage == undefined ? '&nbsp;' : roundMultiply(data.BusinessValue.FibonacciAverage, 100, 100);
workItem.TimeCriticality = data.TimeCriticality == undefined || data.TimeCriticality.FibonacciAverage == undefined ? "&nbsp;" : round(data.TimeCriticality.FibonacciAverage, 100); workItem.TimeCriticality = data.TimeCriticality == undefined || data.TimeCriticality.FibonacciAverage == undefined ? '&nbsp;' : roundMultiply(data.TimeCriticality.FibonacciAverage, 100, 100);
workItem.RiskReductionMinusOpportunityEnablement = data.RiskReductionOpportunityEnablement == undefined || data.RiskReductionOpportunityEnablement.FibonacciAverage == undefined ? "&nbsp;" : round(data.RiskReductionOpportunityEnablement.FibonacciAverage, 100); workItem.RiskReductionMinusOpportunityEnablement = data.RiskReductionOpportunityEnablement == undefined || data.RiskReductionOpportunityEnablement.FibonacciAverage == undefined ? '&nbsp;' : roundMultiply(data.RiskReductionOpportunityEnablement.FibonacciAverage, 100, 100);
workItem.CoD = data.CostOfDelay == undefined ? "&nbsp;" : round(data.CostOfDelay, 100); workItem.CoD = data.CostOfDelay == undefined ? '&nbsp;' : roundMultiply(data.CostOfDelay, 100, 100);
workItem.WeightedShortestJobFirst = data.WeightedShortestJobFirst == undefined ? "&nbsp;" : round(data.WeightedShortestJobFirst, 100); workItem.WeightedShortestJobFirst = data.WeightedShortestJobFirst == undefined ? '&nbsp;' : round(data.WeightedShortestJobFirst, 100);
workItem.Priority = data.SortPriority == undefined ? getPriority(workItem.WorkItemType, 4, 0) : getPriority(workItem.WorkItemType, data.SortPriority, data.SortPriorityGroup); workItem.Priority = data.SortPriority == undefined ? getPriority(workItem.WorkItemType, 4, 0) : getPriority(workItem.WorkItemType, data.SortPriority, data.SortPriorityGroup);
workItem.EffortNotifications = data.Effort == undefined ? "&nbsp;" : getNotifications(e, data.Effort); workItem.EffortNotifications = data.Effort == undefined ? '&nbsp;' : getNotifications(e, data.Effort);
workItem.BusinessValueNotifications = data.BusinessValue == undefined ? "&nbsp;" : getNotifications(b, data.BusinessValue); workItem.BusinessValueNotifications = data.BusinessValue == undefined ? '&nbsp;' : getNotifications(b, data.BusinessValue);
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
&& 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} ${weightedShortestJobFirst} != ${workItem.WeightedShortestJobFirst}
patch {{Factory-Integration}}/_apis/wit/workitems/${workItem.Id}?api-version=7.0
Authorization: Basic {{PAT}}
Content-Type: application/json-patch+json
[
{
"op": "replace",
"path": "/fields/Microsoft.VSTS.Common.BusinessValue",
"value": "${workItem.BusinessValue}"
},
{
"op": "replace",
"path": "/fields/Microsoft.VSTS.Scheduling.Effort",
"value": "${workItem.Effort}"
},
{
"op": "replace",
"path": "/fields/Custom.RRminusOE",
"value": "${workItem.RiskReductionMinusOpportunityEnablement}"
},
{
"op": "replace",
"path": "/fields/Microsoft.VSTS.Common.TimeCriticality",
"value": "${workItem.TimeCriticality}"
},
{
"op": "replace",
"path": "/fields/Custom.WSJF",
"value": "${workItem.WeightedShortestJobFirst}"
},
{
"op": "replace",
"path": "/fields/Custom.WSJFFib",
"value": "${workItem.WeightedShortestJobFirst}"
}
]`;
}
} }
} }
} }
@ -181,7 +238,7 @@ function getRecords(b, r, t, c, e, w, data, dataB, workItems) {
continue; continue;
if (workItem.State !== 'Active' && workItem.State !== 'New') if (workItem.State !== 'Active' && workItem.State !== 'New')
continue; continue;
if (workItem.Tags != null && workItem.Tags.includes("Ignore")) if (workItem.Tags != null && workItem.Tags.includes('Ignore'))
continue; continue;
storyPoints = data[i].Tag?.StoryPoints == undefined ? null : JSON.parse(data[i].Tag.StoryPoints); storyPoints = data[i].Tag?.StoryPoints == undefined ? null : JSON.parse(data[i].Tag.StoryPoints);
totalStoryPoints = sum(storyPoints); totalStoryPoints = sum(storyPoints);
@ -195,7 +252,7 @@ function getRecords(b, r, t, c, e, w, data, dataB, workItems) {
continue; continue;
if (workItem.State !== 'Active' && workItem.State !== 'New') if (workItem.State !== 'Active' && workItem.State !== 'New')
continue; continue;
if (workItem.Tags != null && workItem.Tags.includes("Ignore")) if (workItem.Tags != null && workItem.Tags.includes('Ignore'))
continue; continue;
storyPoints = data[i].Tag?.StoryPoints == undefined ? null : JSON.parse(data[i].Tag.StoryPoints); storyPoints = data[i].Tag?.StoryPoints == undefined ? null : JSON.parse(data[i].Tag.StoryPoints);
totalStoryPoints = sum(storyPoints); totalStoryPoints = sum(storyPoints);
@ -236,12 +293,12 @@ function sendValue(fromHtml, element, page, id) {
username: _username, username: _username,
value: element.value, value: element.value,
}; };
if (fromHtml && notification.value !== "9") { if (fromHtml && notification.value !== '9') {
$("#AllTextarea").hide(); $('#AllTextarea').hide();
document.getElementById('AllTextarea').value = ''; document.getElementById('AllTextarea').value = '';
$.post(_apiUrl, notification) $.post(_apiUrl, notification)
.done(function (msg) { .done(function (msg) {
console.log("Posted value of " + notification.value + " for " + id + " on page " + page + " " + msg); console.log('Posted value of ' + notification.value + ' for ' + id + ' on page ' + page + ' ' + msg);
}) })
.fail(function (_, textStatus, _) { .fail(function (_, textStatus, _) {
warn(textStatus); warn(textStatus);
@ -249,22 +306,26 @@ function sendValue(fromHtml, element, page, id) {
} }
} }
function setRecords(fromHtml, b, r, t, c, e, w, records) { function getHtmlTextAndHttp(fromHtml, b, r, t, c, e, w, records) {
let record; let record;
let lineA = ""; let http = '';
let lineB = ""; let lineA = '';
let lineC = ""; let lineB = '';
let text = 'Id\tRisk Reduction and/or Opportunity Enablement\tTime Criticality\tBusiness Value\tCoD\tEffort\tWSJF\tFeature Total Story Points\tAbsolute Delta\tState\tRequester\tAssigned To\tIteration Path\tSystem\tTitle\r\n'; let lineC = '';
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++) {
record = records[i]; record = records[i];
if (record.api !== '') {
http += record.api + '\r\n';
}
text += record.Id + '\t' + text += record.Id + '\t' +
record.RiskReductionMinusOpportunityEnablement + '\t' + record.RiskReductionMinusOpportunityEnablement + '\t' +
record.TimeCriticality + '\t' + record.TimeCriticality + '\t' +
record.BusinessValue + '\t' + record.BusinessValue + '\t' +
record.CoD + '\t' +
record.Effort + '\t' + record.Effort + '\t' +
record.WeightedShortestJobFirst + '\t' + record.WeightedShortestJobFirst + '\t' +
record.CoD + '\t' +
record.TotalStoryPoints.split(' ')[0] + '\t' + record.TotalStoryPoints.split(' ')[0] + '\t' +
record.AbsoluteDelta + '\t' + record.AbsoluteDelta + '\t' +
record.State.split('-')[0] + '\t' + record.State.split('-')[0] + '\t' +
@ -331,17 +392,7 @@ function setRecords(fromHtml, b, r, t, c, e, w, records) {
console.log(text); console.log(text);
html += lineA + lineB + lineC; html += lineA + lineB + lineC;
} }
if (fromHtml) { return { html, text, http };
document.getElementById('HeaderGrid').innerHTML = html.replaceAll('>null<', '>&nbsp;<');
if (_windowLocationHRef.indexOf('=WSJF') === -1) {
document.getElementById('AllTextarea').value = text.replaceAll('null', '').replaceAll('&nbsp;', '');
}
else {
_toggle = !_toggle;
$(".select").hide();
$("#AllTextarea").hide();
}
}
} }
function updateSite(c, w) { function updateSite(c, w) {
@ -379,25 +430,36 @@ function setDocument(fromHtml, b, r, t, c, e, w, dataA, dataB, workItems) {
console.log(dataA.length); console.log(dataA.length);
if (dataA.length > 0) if (dataA.length > 0)
console.log(dataA[0]); console.log(dataA[0]);
setRecords(fromHtml, b, r, t, c, e, w, records); let result = getHtmlTextAndHttp(fromHtml, b, r, t, c, e, w, records);
$("#toggle").click(function () { if (fromHtml) {
document.getElementById('HeaderGrid').innerHTML = result.html.replaceAll('>null<', '>&nbsp;<');
if (_windowLocationHRef.indexOf('=WSJF') === -1) {
document.getElementById('AllTextarea').value = result.text.replaceAll('null', '').replaceAll('&nbsp;', '') + result.http;
}
else {
_toggle = !_toggle;
$('.select').hide();
$('#AllTextarea').hide();
}
}
$('#toggle').click(function () {
if (_toggle) if (_toggle)
$(".select").hide(); $('.select').hide();
else else
$(".select").show(); $('.select').show();
_toggle = !_toggle; _toggle = !_toggle;
}); });
} }
function highlight(el, i) { function highlight(el, i) {
el.before("<tr/>") el.before('<tr/>')
el.prev() el.prev()
.width(el.width()) .width(el.width())
.height(el.height()) .height(el.height())
.css({ .css({
"position": "absolute", 'position': 'absolute',
"background-color": "#ffff99", 'background-color': '#ffff99',
"opacity": ".9" 'opacity': '.9'
}) })
.fadeOut(1000 * i); .fadeOut(1000 * i);
} }
@ -423,9 +485,9 @@ function updateWorkItem(b, r, t, c, e, w, page, workItem) {
aggregation = workItem.Effort; aggregation = workItem.Effort;
} }
if (x == undefined) if (x == undefined)
warn("Error with page!"); warn('Error with page!');
else if (aggregation.FibonacciAverage == undefined) else if (aggregation.FibonacciAverage == undefined)
warn("FibonacciAverage not set!"); warn('FibonacciAverage not set!');
else { else {
$('#' + x.page + workItem.Id).text('!' + round(aggregation.FibonacciAverage, 100)); $('#' + x.page + workItem.Id).text('!' + round(aggregation.FibonacciAverage, 100));
if (workItem.WeightedShortestJobFirst != undefined) { if (workItem.WeightedShortestJobFirst != undefined) {
@ -437,7 +499,7 @@ function updateWorkItem(b, r, t, c, e, w, page, workItem) {
if (_windowLocationHRef.indexOf('=LIVE') > -1) { if (_windowLocationHRef.indexOf('=LIVE') > -1) {
if (workItem.SortBeforeId != undefined) { if (workItem.SortBeforeId != undefined) {
let found = 0; let found = 0;
let row = element.parents("tr:first"); let row = element.parents('tr:first');
let next = row; let next = row;
for (let i = 0; i < 150; i++) { for (let i = 0; i < 150; i++) {
next = next.next(); next = next.next();
@ -445,7 +507,7 @@ function updateWorkItem(b, r, t, c, e, w, page, workItem) {
break; break;
if (next.attr('id') != 'tr' + workItem.SortBeforeId) if (next.attr('id') != 'tr' + workItem.SortBeforeId)
continue; continue;
console.log("Moved " + i + " down"); console.log('Moved ' + i + ' down');
row.insertAfter(next); row.insertAfter(next);
found = i; found = i;
break; break;
@ -458,7 +520,7 @@ function updateWorkItem(b, r, t, c, e, w, page, workItem) {
break; break;
if (prev.attr('id') != 'tr' + workItem.SortBeforeId) if (prev.attr('id') != 'tr' + workItem.SortBeforeId)
continue; continue;
console.log("Moved " + i + " up"); console.log('Moved ' + i + ' up');
row.insertAfter(prev); row.insertAfter(prev);
found = i; found = i;
break; break;
@ -468,7 +530,7 @@ function updateWorkItem(b, r, t, c, e, w, page, workItem) {
highlight(row, found); highlight(row, found);
} }
else { else {
console.log("Not found!"); console.log('Not found!');
} }
} }
} }
@ -519,7 +581,7 @@ function initIndex(fromHtml, username, machineId, windowLocationHRef, workItems,
console.log(r); console.log(r);
console.log(t); console.log(t);
console.log(c); console.log(c);
console.log("Done :)"); console.log('Done :)');
} }
else { else {
updateSite(c, w); updateSite(c, w);
@ -550,40 +612,40 @@ if (typeof document == 'undefined') {
timeout: 3000, timeout: 3000,
}; };
const b = { const b = {
page: "business", page: 'business',
description: "Value", description: 'Value',
th: "Business Value", th: 'Business Value',
span: "What is the relative value to the Customer or business?<br>• Do our users prefer this over that?<br>• What is the revenue impact on our business?<br>• Is there a potential penalty or other negative effects if we delay?" span: 'What is the relative value to the Customer or business?<br>• Do our users prefer this over that?<br>• What is the revenue impact on our business?<br>• Is there a potential penalty or other negative effects if we delay?'
}; };
const r = { const r = {
page: "risk", page: 'risk',
description: "Risk", description: 'Risk',
th: "Risk Reduction and/or Opportunity Enablement", th: 'Risk Reduction and/or Opportunity Enablement',
span: "What else does this do for our business?<br>• Reduce the risk of this or future delivery?<br>• Is there value in the information we will receive?<br>• Enable new business opportunities?" span: 'What else does this do for our business?<br>• Reduce the risk of this or future delivery?<br>• Is there value in the information we will receive?<br>• Enable new business opportunities?'
}; };
const t = { const t = {
page: "time", page: 'time',
description: "Critical", description: 'Critical',
th: "Time Criticality", th: 'Time Criticality',
span: "How does user/business value decay over time?<br>• Is there a fixed deadline?<br>• Will they wait for us or move to another Solution?<br>• What is the current effect on Customer satisfaction?" span: 'How does user/business value decay over time?<br>• Is there a fixed deadline?<br>• Will they wait for us or move to another Solution?<br>• What is the current effect on Customer satisfaction?'
}; };
const c = { const c = {
page: "cod", page: 'cod',
description: "CoD", description: 'CoD',
th: "Cost of Delay (CoD)", th: 'Cost of Delay (CoD)',
span: "Cost of Delay (CoD) is the money lost by delaying or not doing a job for a specific time. It's a measure of the economic value of a job over time." span: "Cost of Delay (CoD) is the money lost by delaying or not doing a job for a specific time. It's a measure of the economic value of a job over time."
}; };
const e = { const e = {
page: "effort", page: 'effort',
description: "Effort", description: 'Effort',
th: "Effort", th: 'Effort',
span: "Effort" span: 'Effort'
}; };
const w = { const w = {
page: "wsjf", page: 'wsjf',
description: "WSJF", description: 'WSJF',
th: "Weightest Shortest Job First calculation (WSJF)", th: 'Weightest Shortest Job First calculation (WSJF)',
span: "Weightest Shortest Job First calculation (see @SCALE formula)" span: 'Weightest Shortest Job First calculation (see @SCALE formula)'
}; };
_windowLocationHRef = windowLocationHRef; _windowLocationHRef = windowLocationHRef;
fetch(workItems.b, { _: new Date().getTime() }) fetch(workItems.b, { _: new Date().getTime() })
@ -597,7 +659,8 @@ if (typeof document == 'undefined') {
if (dataA.length > 0) if (dataA.length > 0)
console.log(dataA[0]); console.log(dataA[0]);
const records = getRecords(b, r, t, c, e, w, dataA, dataB, workItems); const records = getRecords(b, r, t, c, e, w, dataA, dataB, workItems);
setRecords(fromHtml, b, r, t, c, e, w, records); let result = getHtmlTextAndHttp(fromHtml, b, r, t, c, e, w, records);
if (result == undefined) { }
initIndex(fromHtml, username, machineId, windowLocationHRef, workItems, b, r, t, c, e, w, apiUrl, signalRUrl); initIndex(fromHtml, username, machineId, windowLocationHRef, workItems, b, r, t, c, e, w, apiUrl, signalRUrl);
}) })
.catch((e) => console.error(e)); .catch((e) => console.error(e));

View File

@ -9,20 +9,21 @@ internal class Fields
#nullable enable #nullable enable
[JsonConstructor] [JsonConstructor]
public Fields(float? customRRminusOE, public Fields(decimal? customRRminusOE,
CustomRequester? customRequester, CustomRequester? customRequester,
float? customWSJF, decimal? customWSJF,
decimal? customWSJFFib,
DateTime microsoftVSTSCommonActivatedDate, DateTime microsoftVSTSCommonActivatedDate,
float? microsoftVSTSCommonBusinessValue, decimal? microsoftVSTSCommonBusinessValue,
DateTime microsoftVSTSCommonClosedDate, DateTime microsoftVSTSCommonClosedDate,
int microsoftVSTSCommonPriority, int microsoftVSTSCommonPriority,
DateTime microsoftVSTSCommonResolvedDate, DateTime microsoftVSTSCommonResolvedDate,
DateTime microsoftVSTSCommonStateChangeDate, DateTime microsoftVSTSCommonStateChangeDate,
float? microsoftVSTSCommonTimeCriticality, decimal? microsoftVSTSCommonTimeCriticality,
float? microsoftVSTSSchedulingEffort, decimal? microsoftVSTSSchedulingEffort,
float? microsoftVSTSSchedulingRemainingWork, decimal? microsoftVSTSSchedulingRemainingWork,
DateTime microsoftVSTSSchedulingStartDate, DateTime microsoftVSTSSchedulingStartDate,
float? microsoftVSTSSchedulingStoryPoints, decimal? microsoftVSTSSchedulingStoryPoints,
DateTime microsoftVSTSSchedulingTargetDate, DateTime microsoftVSTSSchedulingTargetDate,
string systemAreaPath, string systemAreaPath,
SystemAssignedTo systemAssignedTo, SystemAssignedTo systemAssignedTo,
@ -45,6 +46,7 @@ internal class Fields
CustomRRminusOE = customRRminusOE; CustomRRminusOE = customRRminusOE;
CustomRequester = customRequester; CustomRequester = customRequester;
CustomWSJF = customWSJF; CustomWSJF = customWSJF;
CustomWSJFFib = customWSJFFib;
MicrosoftVSTSCommonActivatedDate = microsoftVSTSCommonActivatedDate; MicrosoftVSTSCommonActivatedDate = microsoftVSTSCommonActivatedDate;
MicrosoftVSTSCommonBusinessValue = microsoftVSTSCommonBusinessValue; MicrosoftVSTSCommonBusinessValue = microsoftVSTSCommonBusinessValue;
MicrosoftVSTSCommonClosedDate = microsoftVSTSCommonClosedDate; MicrosoftVSTSCommonClosedDate = microsoftVSTSCommonClosedDate;
@ -76,20 +78,21 @@ internal class Fields
SystemWorkItemType = systemWorkItemType; SystemWorkItemType = systemWorkItemType;
} }
[JsonPropertyName("Custom.RRminusOE")] public float? CustomRRminusOE { get; } [JsonPropertyName("Custom.RRminusOE")] public decimal? CustomRRminusOE { get; }
[JsonPropertyName("Custom.Requester")] public CustomRequester? CustomRequester { get; } [JsonPropertyName("Custom.Requester")] public CustomRequester? CustomRequester { get; }
[JsonPropertyName("Custom.WSJF")] public float? CustomWSJF { get; } [JsonPropertyName("Custom.WSJF")] public decimal? CustomWSJF { get; }
[JsonPropertyName("Custom.WSJFFib")] public decimal? CustomWSJFFib { get; }
[JsonPropertyName("Microsoft.VSTS.Common.ActivatedDate")] public DateTime MicrosoftVSTSCommonActivatedDate { get; } [JsonPropertyName("Microsoft.VSTS.Common.ActivatedDate")] public DateTime MicrosoftVSTSCommonActivatedDate { get; }
[JsonPropertyName("Microsoft.VSTS.Common.BusinessValue")] public float? MicrosoftVSTSCommonBusinessValue { get; } [JsonPropertyName("Microsoft.VSTS.Common.BusinessValue")] public decimal? MicrosoftVSTSCommonBusinessValue { get; }
[JsonPropertyName("Microsoft.VSTS.Common.ClosedDate")] public DateTime MicrosoftVSTSCommonClosedDate { get; } [JsonPropertyName("Microsoft.VSTS.Common.ClosedDate")] public DateTime MicrosoftVSTSCommonClosedDate { get; }
[JsonPropertyName("Microsoft.VSTS.Common.Priority")] public int MicrosoftVSTSCommonPriority { get; } [JsonPropertyName("Microsoft.VSTS.Common.Priority")] public int MicrosoftVSTSCommonPriority { get; }
[JsonPropertyName("Microsoft.VSTS.Common.ResolvedDate")] public DateTime MicrosoftVSTSCommonResolvedDate { get; } [JsonPropertyName("Microsoft.VSTS.Common.ResolvedDate")] public DateTime MicrosoftVSTSCommonResolvedDate { get; }
[JsonPropertyName("Microsoft.VSTS.Common.StateChangeDate")] public DateTime MicrosoftVSTSCommonStateChangeDate { get; } [JsonPropertyName("Microsoft.VSTS.Common.StateChangeDate")] public DateTime MicrosoftVSTSCommonStateChangeDate { get; }
[JsonPropertyName("Microsoft.VSTS.Common.TimeCriticality")] public float? MicrosoftVSTSCommonTimeCriticality { get; } [JsonPropertyName("Microsoft.VSTS.Common.TimeCriticality")] public decimal? MicrosoftVSTSCommonTimeCriticality { get; }
[JsonPropertyName("Microsoft.VSTS.Scheduling.Effort")] public float? MicrosoftVSTSSchedulingEffort { get; } [JsonPropertyName("Microsoft.VSTS.Scheduling.Effort")] public decimal? MicrosoftVSTSSchedulingEffort { get; }
[JsonPropertyName("Microsoft.VSTS.Scheduling.RemainingWork")] public float? MicrosoftVSTSSchedulingRemainingWork { get; } [JsonPropertyName("Microsoft.VSTS.Scheduling.RemainingWork")] public decimal? MicrosoftVSTSSchedulingRemainingWork { get; }
[JsonPropertyName("Microsoft.VSTS.Scheduling.StartDate")] public DateTime MicrosoftVSTSSchedulingStartDate { get; } [JsonPropertyName("Microsoft.VSTS.Scheduling.StartDate")] public DateTime MicrosoftVSTSSchedulingStartDate { get; }
[JsonPropertyName("Microsoft.VSTS.Scheduling.StoryPoints")] public float? MicrosoftVSTSSchedulingStoryPoints { get; } [JsonPropertyName("Microsoft.VSTS.Scheduling.StoryPoints")] public decimal? MicrosoftVSTSSchedulingStoryPoints { get; }
[JsonPropertyName("Microsoft.VSTS.Scheduling.TargetDate")] public DateTime MicrosoftVSTSSchedulingTargetDate { get; } [JsonPropertyName("Microsoft.VSTS.Scheduling.TargetDate")] public DateTime MicrosoftVSTSSchedulingTargetDate { get; }
[JsonPropertyName("System.AreaPath")] public string SystemAreaPath { get; } [JsonPropertyName("System.AreaPath")] public string SystemAreaPath { get; }
[JsonPropertyName("System.AssignedTo")] public SystemAssignedTo? SystemAssignedTo { get; } [JsonPropertyName("System.AssignedTo")] public SystemAssignedTo? SystemAssignedTo { get; }

View File

@ -62,6 +62,7 @@ internal class Record
title: record.WorkItem.Title, title: record.WorkItem.Title,
violation: record.WorkItem.Violation is null ? violation : record.WorkItem.Violation, violation: record.WorkItem.Violation is null ? violation : record.WorkItem.Violation,
weightedShortestJobFirst: record.WorkItem.WeightedShortestJobFirst, weightedShortestJobFirst: record.WorkItem.WeightedShortestJobFirst,
weightedShortestJobFirstFibonacci: record.WorkItem.WeightedShortestJobFirstFibonacci,
workItemType: record.WorkItem.WorkItemType); workItemType: record.WorkItem.WorkItemType);
result = new(workItem, record.Parent, Array.Empty<Record>(), Array.Empty<Record>(), Array.Empty<Record>(), record.Tag); result = new(workItem, record.Parent, Array.Empty<Record>(), Array.Empty<Record>(), Array.Empty<Record>(), record.Tag);
return result; return result;

View File

@ -37,7 +37,8 @@ internal class WorkItem
long? timeCriticality, long? timeCriticality,
string title, string title,
string? violation, string? violation,
long? weightedShortestJobFirst, decimal? weightedShortestJobFirst,
decimal? weightedShortestJobFirstFibonacci,
string workItemType) string workItemType)
{ {
ActivatedDate = activatedDate; ActivatedDate = activatedDate;
@ -69,6 +70,7 @@ internal class WorkItem
Title = title; Title = title;
Violation = violation; Violation = violation;
WeightedShortestJobFirst = weightedShortestJobFirst; WeightedShortestJobFirst = weightedShortestJobFirst;
WeightedShortestJobFirstFibonacci = weightedShortestJobFirstFibonacci;
WorkItemType = workItemType; WorkItemType = workItemType;
} }
@ -105,6 +107,7 @@ internal class WorkItem
title: workItem.Title, title: workItem.Title,
violation: workItem.Violation, violation: workItem.Violation,
weightedShortestJobFirst: workItem.WeightedShortestJobFirst, weightedShortestJobFirst: workItem.WeightedShortestJobFirst,
weightedShortestJobFirstFibonacci: workItem.WeightedShortestJobFirstFibonacci,
workItemType: workItem.WorkItemType); workItemType: workItem.WorkItemType);
return result; return result;
} }
@ -140,6 +143,7 @@ internal class WorkItem
title: workItem.Title, title: workItem.Title,
violation: workItem.Violation, violation: workItem.Violation,
weightedShortestJobFirst: workItem.WeightedShortestJobFirst, weightedShortestJobFirst: workItem.WeightedShortestJobFirst,
weightedShortestJobFirstFibonacci: workItem.WeightedShortestJobFirstFibonacci,
workItemType: workItem.WorkItemType); workItemType: workItem.WorkItemType);
return result; return result;
} }
@ -172,7 +176,8 @@ internal class WorkItem
[JsonPropertyName("TimeCriticality")] public long? TimeCriticality { get; } [JsonPropertyName("TimeCriticality")] public long? TimeCriticality { get; }
[JsonPropertyName("Title")] public string Title { get; } [JsonPropertyName("Title")] public string Title { get; }
[JsonPropertyName("Violation")] public string? Violation { get; } [JsonPropertyName("Violation")] public string? Violation { get; }
[JsonPropertyName("WeightedShortestJobFirst")] public long? WeightedShortestJobFirst { get; } [JsonPropertyName("WeightedShortestJobFirst")] public decimal? WeightedShortestJobFirst { get; }
[JsonPropertyName("WeightedShortestJobFirstFibonacci")] public decimal? WeightedShortestJobFirstFibonacci { get; }
[JsonPropertyName("WorkItemType")] public string WorkItemType { get; } [JsonPropertyName("WorkItemType")] public string WorkItemType { get; }
} }

View File

@ -41,6 +41,24 @@ stages:
displayName: "Nuget Clear" displayName: "Nuget Clear"
enabled: false enabled: false
- task: CopyFiles@2
displayName: 'Copy GhostPCL Files to: D:\EAF-Mesa-Integration\copy'
inputs:
Contents: "*"
SourceFolder: '\\mesfs.infineon.com\EC_EAFRepository\Staging\DeploymentStorage\GhostPCL'
TargetFolder: 'D:\EAF-Mesa-Integration\copy\GhostPCL'
OverWrite: true
enabled: true
- task: CopyFiles@2
displayName: 'Copy LincPDFC Files to: D:\EAF-Mesa-Integration\copy'
inputs:
Contents: "*"
SourceFolder: '\\mesfs.infineon.com\EC_EAFRepository\Staging\DeploymentStorage\LincPDFC'
TargetFolder: 'D:\EAF-Mesa-Integration\copy\LincPDFC'
OverWrite: true
enabled: true
- script: | - script: |
"C:\program files\dotnet\dotnet.exe" user-secrets init "C:\program files\dotnet\dotnet.exe" user-secrets init
"C:\program files\dotnet\dotnet.exe" user-secrets set "BuildNumber" "$(Build.BuildId)" "C:\program files\dotnet\dotnet.exe" user-secrets set "BuildNumber" "$(Build.BuildId)"
@ -184,6 +202,24 @@ stages:
displayName: "Nuget Clear" displayName: "Nuget Clear"
enabled: false enabled: false
- task: CopyFiles@2
displayName: 'Copy GhostPCL Files to: D:\EAF-Mesa-Integration\copy'
inputs:
Contents: "*"
SourceFolder: '\\mestsa003.infineon.com\EC_EAFRepository\Staging\DeploymentStorage\GhostPCL'
TargetFolder: 'D:\EAF-Mesa-Integration\copy\GhostPCL'
OverWrite: true
enabled: true
- task: CopyFiles@2
displayName: 'Copy LincPDFC Files to: D:\EAF-Mesa-Integration\copy'
inputs:
Contents: "*"
SourceFolder: '\\mestsa003.infineon.com\EC_EAFRepository\Staging\DeploymentStorage\LincPDFC'
TargetFolder: 'D:\EAF-Mesa-Integration\copy\LincPDFC'
OverWrite: true
enabled: true
- script: | - script: |
"C:\program files\dotnet\dotnet.exe" user-secrets init "C:\program files\dotnet\dotnet.exe" user-secrets init
"C:\program files\dotnet\dotnet.exe" user-secrets set "BuildNumber" "$(Build.BuildId)" "C:\program files\dotnet\dotnet.exe" user-secrets set "BuildNumber" "$(Build.BuildId)"

View File

@ -478,27 +478,14 @@ public class FileRead : Properties.IFileRead
} }
} }
protected void WritePDSF(IFileRead fileRead, JsonElement[] jsonElements) protected static void WritePDSF(IFileRead fileRead, JsonElement[] jsonElements)
{ {
string directory; #pragma warning disable CA1510
string day = $"{_Logistics.DateTimeFromSequence:yyyy-MM-dd}"; if (fileRead is null)
string weekOfYear = _Calendar.GetWeekOfYear(_Logistics.DateTimeFromSequence, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00"); throw new ArgumentNullException(nameof(fileRead));
string weekDirectory = $"{_Logistics.DateTimeFromSequence:yyyy}_Week_{weekOfYear}"; if (jsonElements is null)
if (!_CellInstanceConnectionName.StartsWith(_CellInstanceName) && _CellInstanceConnectionNameBase == _EquipmentType) throw new ArgumentNullException(nameof(jsonElements));
directory = Path.Combine(_TracePath, _EquipmentType, "Target", weekDirectory, day, _CellInstanceName, _CellInstanceConnectionName); #pragma warning restore CA1510
else
directory = Path.Combine(_TracePath, _EquipmentType, "Source", weekDirectory, day, _CellInstanceName, _CellInstanceConnectionName);
if (!Directory.Exists(directory))
_ = Directory.CreateDirectory(directory);
string file = Path.Combine(directory, string.Concat(_Logistics.MesEntity, "_", _Logistics.Sequence, ".ipdsf"));
string lines = ProcessDataStandardFormat.GetPDSFText(fileRead, _Logistics, jsonElements, logisticsText: string.Empty);
File.WriteAllText(file, lines);
if (_Logistics.TotalSecondsSinceLastWriteTimeFromSequence > 600)
{
try
{ File.SetLastWriteTime(file, _Logistics.DateTimeFromSequence); }
catch (Exception) { }
}
} }
protected void WaitForThread(Thread thread, List<Exception> threadExceptions) protected void WaitForThread(Thread thread, List<Exception> threadExceptions)

View File

@ -136,6 +136,7 @@ internal class ProcessDataStandardFormat
internal static ProcessDataStandardFormat GetProcessDataStandardFormat(string reportFullPath, string[]? lines = null, int columnsLine = 6) internal static ProcessDataStandardFormat GetProcessDataStandardFormat(string reportFullPath, string[]? lines = null, int columnsLine = 6)
{ {
ProcessDataStandardFormat result; ProcessDataStandardFormat result;
long? sequence;
string segment; string segment;
string[] segments; string[] segments;
bool addToFooter = false; bool addToFooter = false;
@ -186,13 +187,25 @@ internal class ProcessDataStandardFormat
} }
string? linesOne = lines.Length > 0 && body.Count == 0 && columns.Count == 0 ? lines[1] : null; string? linesOne = lines.Length > 0 && body.Count == 0 && columns.Count == 0 ? lines[1] : null;
logistics = GetLogistics(footer, linesOne: linesOne); logistics = GetLogistics(footer, linesOne: linesOne);
if (logistics.Count == 0)
sequence = null;
else
{
segments = logistics[0].Split(new string[] { "SEQUENCE=" }, StringSplitOptions.None);
sequence = segments.Length < 2 || !long.TryParse(segments[1].Split(';')[0], out long s) ? null : s;
}
if (sequence is null && !string.IsNullOrEmpty(reportFullPath))
{
FileInfo fileInfo = new(reportFullPath);
sequence = fileInfo.LastWriteTime.Ticks;
}
result = new(body: body.AsReadOnly(), result = new(body: body.AsReadOnly(),
columns: columns.AsReadOnly(), columns: columns.AsReadOnly(),
footer: footer.AsReadOnly(), footer: footer.AsReadOnly(),
header: header.AsReadOnly(), header: header.AsReadOnly(),
inputPDSF: null, inputPDSF: null,
logistics: logistics, logistics: logistics,
sequence: null); sequence: sequence);
return result; return result;
} }
@ -236,7 +249,7 @@ internal class ProcessDataStandardFormat
private static ProcessDataStandardFormat GetProcessDataStandardFormat(DateTime lastWriteTime, int columnsLine, string path, string[]? lines) private static ProcessDataStandardFormat GetProcessDataStandardFormat(DateTime lastWriteTime, int columnsLine, string path, string[]? lines)
{ {
ProcessDataStandardFormat result; ProcessDataStandardFormat result;
long sequence; long? sequence;
string[] segments; string[] segments;
bool addToFooter = false; bool addToFooter = false;
List<string> body = new(); List<string> body = new();
@ -268,12 +281,13 @@ internal class ProcessDataStandardFormat
} }
logistics = GetLogistics(footer, linesOne: null); logistics = GetLogistics(footer, linesOne: null);
if (logistics.Count == 0) if (logistics.Count == 0)
sequence = lastWriteTime.Ticks; sequence = null;
else else
{ {
segments = logistics[0].Split(new string[] { "SEQUENCE=" }, StringSplitOptions.None); segments = logistics[0].Split(new string[] { "SEQUENCE=" }, StringSplitOptions.None);
sequence = segments.Length < 2 || !long.TryParse(segments[1].Split(';')[0], out long s) ? lastWriteTime.Ticks : s; sequence = segments.Length < 2 || !long.TryParse(segments[1].Split(';')[0], out long s) ? null : s;
} }
sequence ??= lastWriteTime.Ticks;
result = new(body: body.AsReadOnly(), result = new(body: body.AsReadOnly(),
columns: new(columns), columns: new(columns),
footer: footer.AsReadOnly(), footer: footer.AsReadOnly(),
@ -302,7 +316,7 @@ internal class ProcessDataStandardFormat
segments = bodyLine.Split('\t').ToList(); segments = bodyLine.Split('\t').ToList();
for (int c = 0; c < segments.Count; c++) for (int c = 0; c < segments.Count; c++)
{ {
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\"); value = segments[c].Replace("\\", "\\\\").Replace("\"", "\\\"");
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":\"").Append(value).Append("\","); _ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":\"").Append(value).Append("\",");
} }
_ = stringBuilder.Remove(stringBuilder.Length - 1, 1); _ = stringBuilder.Remove(stringBuilder.Length - 1, 1);
@ -378,19 +392,27 @@ internal class ProcessDataStandardFormat
break; break;
for (int c = 0; c < segments.Length; c++) for (int c = 0; c < segments.Length; c++)
{ {
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\"); value = segments[c].Replace("\\", "\\\\").Replace("\"", "\\\"");
line += string.Concat('"', processDataStandardFormat.InputPDSF.Columns[c].Trim('"'), '"', ':', '"', value, '"', ','); line += string.Concat('"', processDataStandardFormat.InputPDSF.Columns[c].Trim('"'), '"', ':', '"', value, '"', ',');
} }
line = string.Concat(line.Substring(0, line.Length - 1), '}'); line = string.Concat(line.Substring(0, line.Length - 1), '}');
lines.Add(line); lines.Add(line);
} }
string? json = null;
if (processDataStandardFormat.Footer is not null && processDataStandardFormat.Footer.Count > 0)
{
Dictionary<string, string> footerKeyValuePairs = GetFooterKeyValuePairs(processDataStandardFormat.Footer);
Dictionary<string, Dictionary<string, string>> logisticKeyValuePairs = GetLogisticKeyValuePairs(processDataStandardFormat.Footer, footerKeyValuePairs);
json = JsonSerializer.Serialize(logisticKeyValuePairs, DictionaryStringDictionaryStringStringSourceGenerationContext.Default.DictionaryStringDictionaryStringString);
}
string footerText = string.IsNullOrEmpty(json) || json == "{}" ? string.Empty : $",{Environment.NewLine}\"PDSF\":{Environment.NewLine}{json}";
result = string.Concat( result = string.Concat(
'{', '{',
Environment.NewLine, Environment.NewLine,
'"', '"',
"Count", "Count",
'"', '"',
": ", ": ",
processDataStandardFormat.Body.Count, processDataStandardFormat.Body.Count,
',', ',',
Environment.NewLine, Environment.NewLine,
@ -409,12 +431,88 @@ internal class ProcessDataStandardFormat
'"', '"',
"Sequence", "Sequence",
'"', '"',
": ", ": ",
processDataStandardFormat.Sequence, processDataStandardFormat.Sequence,
Environment.NewLine, Environment.NewLine,
footerText,
Environment.NewLine,
'}'); '}');
return result; return result;
#pragma warning restore CA1845, IDE0057 }
private static Dictionary<string, string> GetFooterKeyValuePairs(ReadOnlyCollection<string> footerLines)
{
Dictionary<string, string> results = new();
string[] segments;
foreach (string footerLine in footerLines)
{
segments = footerLine.Split('\t');
if (segments.Length != 2 || string.IsNullOrEmpty(segments[1].Trim()))
{
continue;
}
if (segments[1].Contains(';'))
{
continue;
}
else
{
if (results.ContainsKey(segments[0]))
{
continue;
}
results.Add(segments[0], segments[1]);
}
}
return results;
}
private static Dictionary<string, Dictionary<string, string>> GetLogisticKeyValuePairs(ReadOnlyCollection<string> footerLines, Dictionary<string, string> footerKeyValuePairs)
{
Dictionary<string, Dictionary<string, string>> results = new();
string[] segments;
string[] subSegments;
string[] subSubSegments;
Dictionary<string, string>? keyValue;
results.Add("Footer", footerKeyValuePairs);
foreach (string footerLine in footerLines)
{
segments = footerLine.Split('\t');
if (segments.Length != 2 || string.IsNullOrEmpty(segments[1].Trim()))
{
continue;
}
if (!segments[1].Contains(';') || !segments[1].Contains('='))
{
continue;
}
else
{
subSegments = segments[1].Split(';');
if (subSegments.Length < 1)
{
continue;
}
if (!results.TryGetValue(segments[0], out keyValue))
{
results.Add(segments[0], new());
if (!results.TryGetValue(segments[0], out keyValue))
{
throw new Exception();
}
}
foreach (string segment in subSegments)
{
subSubSegments = segment.Split('=');
if (subSubSegments.Length != 2)
{
continue;
}
keyValue.Add(subSubSegments[0], subSubSegments[1]);
}
}
}
return results;
} }
internal static void Write(string path, ProcessDataStandardFormat processDataStandardFormat, List<Metrology.WS.Results>? wsResults) internal static void Write(string path, ProcessDataStandardFormat processDataStandardFormat, List<Metrology.WS.Results>? wsResults)
@ -518,7 +616,7 @@ internal class ProcessDataStandardFormat
{ {
for (int c = 1; c < segments.Length; c++) for (int c = 1; c < segments.Length; c++)
{ {
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\"); value = segments[c].Replace("\\", "\\\\").Replace("\"", "\\\"");
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":\"").Append(value).Append("\","); _ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":\"").Append(value).Append("\",");
} }
} }
@ -526,7 +624,7 @@ internal class ProcessDataStandardFormat
{ {
for (int c = 1; c < segments.Length; c++) for (int c = 1; c < segments.Length; c++)
{ {
value = segments[c].Replace("\"", "\\\"").Replace("\\", "\\\\"); value = segments[c].Replace("\\", "\\\\").Replace("\"", "\\\"");
if (string.IsNullOrEmpty(value)) if (string.IsNullOrEmpty(value))
_ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":").Append(value).Append("null,"); _ = stringBuilder.Append('"').Append(processDataStandardFormat.Columns[c]).Append("\":").Append(value).Append("null,");
else if (value.All(char.IsDigit)) else if (value.All(char.IsDigit))
@ -763,4 +861,10 @@ internal class ProcessDataStandardFormat
[JsonSerializable(typeof(JsonElement[]))] [JsonSerializable(typeof(JsonElement[]))]
internal partial class JsonElementCollectionSourceGenerationContext : JsonSerializerContext internal partial class JsonElementCollectionSourceGenerationContext : JsonSerializerContext
{ {
}
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(Dictionary<string, Dictionary<string, string>>))]
internal partial class DictionaryStringDictionaryStringStringSourceGenerationContext : JsonSerializerContext
{
} }

View File

@ -1,4 +1,14 @@
{ {
"name": "adaptation",
"module": "index.ts",
"type": "module",
"private": true,
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5"
},
"scripts": { "scripts": {
"AA-CreateSelfDescription.Staging.v2_43_0-BACKLOG_EQPT": "dotnet test --runtime win-x64 --no-build --filter \"FullyQualifiedName~Adaptation._Tests.CreateSelfDescription.Staging.v2_43_0 & ClassName~BACKLOG_EQPT\" -- TestRunParameters.Parameter(name=\\\"WaitFor\\\", value=\\\"Debugger.IsAttached\\\")", "AA-CreateSelfDescription.Staging.v2_43_0-BACKLOG_EQPT": "dotnet test --runtime win-x64 --no-build --filter \"FullyQualifiedName~Adaptation._Tests.CreateSelfDescription.Staging.v2_43_0 & ClassName~BACKLOG_EQPT\" -- TestRunParameters.Parameter(name=\\\"WaitFor\\\", value=\\\"Debugger.IsAttached\\\")",
"BA-CreateSelfDescription.Staging.v2_43_0-BACKLOG": "dotnet test --runtime win-x64 --no-build --filter \"FullyQualifiedName~Adaptation._Tests.CreateSelfDescription.Staging.v2_43_0 & ClassName~BACKLOG\" -- TestRunParameters.Parameter(name=\\\"WaitFor\\\", value=\\\"Debugger.IsAttached\\\")", "BA-CreateSelfDescription.Staging.v2_43_0-BACKLOG": "dotnet test --runtime win-x64 --no-build --filter \"FullyQualifiedName~Adaptation._Tests.CreateSelfDescription.Staging.v2_43_0 & ClassName~BACKLOG\" -- TestRunParameters.Parameter(name=\\\"WaitFor\\\", value=\\\"Debugger.IsAttached\\\")",

29
Adaptation/tsconfig.json Normal file
View File

@ -0,0 +1,29 @@
{
"compilerOptions": {
// Environment setup & latest features
"lib": ["ESNext"],
"target": "ESNext",
"module": "Preserve",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}