diff --git a/.gitignore b/.gitignore index 9bc3e23b..5146d95f 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,8 @@ client/Boundaries/Boundaries/bin client/Boundaries/Boundaries/obj client/Boundaries/TestBoundaries/obj client/Boundaries/TestBoundaries/bin +client/Boundaries/Backend/bin +client/Boundaries/Backend/obj output.svg local chex.egg-info @@ -36,4 +38,4 @@ __pycache__ /SymbolLibrary/SymolLibrary.Tests/obj/ /SymbolLibrary/SymolLibrary.Tests/bin/ /SymbolLibrary/SymbolLibrary.sln.DotSettings.user -/SymbolLibrary/src/Data/Symbols.xlsm +/SymbolLibrary/src/Data/Symbols.xlsm \ No newline at end of file diff --git a/SymbolLibrary/src/Properties/launchSettings.json b/SymbolLibrary/src/Properties/launchSettings.json new file mode 100644 index 00000000..036455c4 --- /dev/null +++ b/SymbolLibrary/src/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "SymbolLibrary": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:54024;http://localhost:54025" + } + } +} \ No newline at end of file diff --git a/client/Boundaries/Backend/Backend.csproj b/client/Boundaries/Backend/Backend.csproj new file mode 100644 index 00000000..1f280f0b --- /dev/null +++ b/client/Boundaries/Backend/Backend.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + + + + + + + + diff --git a/client/Boundaries/Backend/Backend.csproj.user b/client/Boundaries/Backend/Backend.csproj.user new file mode 100644 index 00000000..9ff5820a --- /dev/null +++ b/client/Boundaries/Backend/Backend.csproj.user @@ -0,0 +1,6 @@ + + + + https + + \ No newline at end of file diff --git a/client/Boundaries/Backend/Model/CommissioningPackage.cs b/client/Boundaries/Backend/Model/CommissioningPackage.cs new file mode 100644 index 00000000..d8d644b1 --- /dev/null +++ b/client/Boundaries/Backend/Model/CommissioningPackage.cs @@ -0,0 +1,12 @@ +namespace Backend.Model; + +public class CommissioningPackage +{ + public required string Id { get; set; } + public required string Name { get; set; } + public required string Colour { get; set; } + public List? CalculatedInternal { get; set; } + public List? SelectedInternal { get; set; } + public List? Boundary { get; set; } + +} diff --git a/client/Boundaries/Backend/Model/Node.cs b/client/Boundaries/Backend/Model/Node.cs new file mode 100644 index 00000000..8477f713 --- /dev/null +++ b/client/Boundaries/Backend/Model/Node.cs @@ -0,0 +1,7 @@ +namespace Backend.Model; + + +public class Node +{ + public required string Id { get; set; } +} diff --git a/client/Boundaries/Backend/Program.cs b/client/Boundaries/Backend/Program.cs new file mode 100644 index 00000000..cdc8148b --- /dev/null +++ b/client/Boundaries/Backend/Program.cs @@ -0,0 +1,74 @@ +using Backend.Model; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + + +//Add node as boundary +app.MapPost("/commissioning-package/{packageId}/boundary/{nodeId}", (string packageId, string nodeId) => +{ + throw new NotImplementedException("TODO: Not implemented..."); +}); + +//Add node as internal +app.MapPost("/commissioning-package/{packageId}/internal/{nodeId}", (string packageId, string nodeId) => +{ + throw new NotImplementedException("TODO: Not implemented..."); +}); + +//Remove node as boundary +app.MapDelete("/commissioning-package/{packageId}/boundary/{nodeId}", (string packageId, string nodeId) => +{ + throw new NotImplementedException("TODO: Not implemented..."); +}); + +//Remove node as internal +app.MapDelete("/commissioning-package/{packageId}/internal/{nodeId}", (string packageId, string nodeId) => +{ + throw new NotImplementedException("TODO: Not implemented..."); +}); + +//Get adjacent nodes +app.MapGet("/nodes/{nodeId}/adjacent", (string nodeId) => +{ + throw new NotImplementedException("TODO: Not implemented..."); +}); + +//Add commissioning package +app.MapPost("/commissioning-package", (CommissioningPackage commissioningPackage) => +{ + throw new NotImplementedException("TODO: Not implemented..."); +}); + +//Update commissioning package - updating information like name, color and id while persisting the calculated internal nodes, and boundaries. +app.MapPut("/commissioning-package", (CommissioningPackage commissioningPackage) => +{ + throw new NotImplementedException("TODO: Not implemented..."); +}); + +//Delete commissioning package +app.MapDelete("/commissioning-package/{commissioningPackageId}", (string commissioningPackageId) => +{ + throw new NotImplementedException("TODO: Not implemented..."); +}); + +//Get commissioning package +app.MapGet("/commissioning-package/{commissioningPackageId}", (string commissioningPackageId) => +{ + throw new NotImplementedException("TODO: Not implemented..."); +}); + + +app.Run(); diff --git a/client/Boundaries/Backend/Properties/launchSettings.json b/client/Boundaries/Backend/Properties/launchSettings.json new file mode 100644 index 00000000..bcd54ee3 --- /dev/null +++ b/client/Boundaries/Backend/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:4141", + "sslPort": 44387 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5184", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7046;http://localhost:5184", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/client/Boundaries/Boundaries.sln b/client/Boundaries/Boundaries.sln index a33557e5..7c682a34 100644 --- a/client/Boundaries/Boundaries.sln +++ b/client/Boundaries/Boundaries.sln @@ -1,10 +1,15 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Boundaries", "Boundaries\Boundaries.csproj", "{B7723633-9BCD-44C6-BC90-1E3F5C6C8101}" +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35431.28 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Boundaries", "Boundaries\Boundaries.csproj", "{B7723633-9BCD-44C6-BC90-1E3F5C6C8101}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestBoundaries", "TestBoundaries\TestBoundaries.csproj", "{6389698E-C0E2-4262-AE30-FD2A01654FA5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestBoundaries", "TestBoundaries\TestBoundaries.csproj", "{6389698E-C0E2-4262-AE30-FD2A01654FA5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dexpi2Svg", "Dexpi2Svg\Dexpi2Svg.csproj", "{18B982C7-6B76-46E5-A662-4F6C56A3744E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dexpi2Svg", "Dexpi2Svg\Dexpi2Svg.csproj", "{18B982C7-6B76-46E5-A662-4F6C56A3744E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Backend", "Backend\Backend.csproj", "{49E561FC-F64F-4877-8F24-B8D593568DA9}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -24,5 +29,15 @@ Global {18B982C7-6B76-46E5-A662-4F6C56A3744E}.Debug|Any CPU.Build.0 = Debug|Any CPU {18B982C7-6B76-46E5-A662-4F6C56A3744E}.Release|Any CPU.ActiveCfg = Release|Any CPU {18B982C7-6B76-46E5-A662-4F6C56A3744E}.Release|Any CPU.Build.0 = Release|Any CPU + {49E561FC-F64F-4877-8F24-B8D593568DA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {49E561FC-F64F-4877-8F24-B8D593568DA9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {49E561FC-F64F-4877-8F24-B8D593568DA9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {49E561FC-F64F-4877-8F24-B8D593568DA9}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {86B458A0-804E-48CF-9B47-8E0DBDF1F23D} EndGlobalSection EndGlobal diff --git a/client/Boundaries/Boundaries/DatalogCreator.cs b/client/Boundaries/Boundaries/DatalogCreator.cs index 59d63b29..227911d6 100644 --- a/client/Boundaries/Boundaries/DatalogCreator.cs +++ b/client/Boundaries/Boundaries/DatalogCreator.cs @@ -5,12 +5,12 @@ namespace Boundaries; public class DatalogCreator { public IriReference BoundaryGraph = new IriReference($"https://data.equinor.com/boundaries/{Guid.NewGuid()}"); - + public string CreateCommissioningSparqlQuery() { return $"select ?s(GROUP_CONCAT(?label; SEPARATOR=',') AS ?labels) where {{?s a <{BoundaryGraph}>; rdfs:label ?label. OPTIONAL{{?s ?tag.}} }} GROUP BY (?s)"; } - + public string CreateBoundaryDatalogRule(string internalComponentLabel, IriReference[] borderComponentIris) { var filters = borderComponentIris @@ -29,8 +29,8 @@ public string CreateBoundaryDatalogRule(string internalComponentLabel, IriRefere dexpi:PipingOrEquipment [?node]. """; } - - + + public string CreateConnectedSparqlQuery() { return $"select * where {{?s a <{BoundaryGraph}>; rdfs:label ?tag.}}"; diff --git a/client/Boundaries/Boundaries/DexpiApi.cs b/client/Boundaries/Boundaries/DexpiApi.cs index 38a28f09..23467756 100644 --- a/client/Boundaries/Boundaries/DexpiApi.cs +++ b/client/Boundaries/Boundaries/DexpiApi.cs @@ -2,39 +2,40 @@ namespace Boundaries; -public static class DexpiApi{ +public static class DexpiApi +{ public static async Task GetCommissioningPackage(string internalComponentLabel, IriReference[] borderComponentIris, string dexpiFilePath) { var datalogCreator = new DatalogCreator(); var datalog = datalogCreator.CreateBoundaryDatalogRule(internalComponentLabel, borderComponentIris); var conn = RdfoxApi.GetDefaultConnectionSettings(); await RdfoxApi.LoadDatalog(conn, datalog); - + var data = File.ReadAllText(dexpiFilePath); await RdfoxApi.LoadData(conn, data); var queryString = datalogCreator.CreateCommissioningSparqlQuery(); var result = await RdfoxApi.QuerySparql(conn, queryString); - + await RdfoxApi.DeleteData(conn, data); await RdfoxApi.DeleteDatalog(conn, datalog); return result; } - - + + public static async Task GetConnectedEquipment(string internalComponentLabel, string dexpiFilePath) { var datalogCreator = new DatalogCreator(); var datalog = datalogCreator.CreateConnectedDatalogRule(internalComponentLabel); var conn = RdfoxApi.GetDefaultConnectionSettings(); await RdfoxApi.LoadDatalog(conn, datalog); - + var data = File.ReadAllText(dexpiFilePath); await RdfoxApi.LoadData(conn, data); var queryString = datalogCreator.CreateConnectedSparqlQuery(); var result = await RdfoxApi.QuerySparql(conn, queryString); - + await RdfoxApi.DeleteData(conn, data); await RdfoxApi.DeleteDatalog(conn, datalog); return result; diff --git a/client/Boundaries/Boundaries/RdfoxApi.cs b/client/Boundaries/Boundaries/RdfoxApi.cs index dd277962..e5f2f4b0 100644 --- a/client/Boundaries/Boundaries/RdfoxApi.cs +++ b/client/Boundaries/Boundaries/RdfoxApi.cs @@ -13,9 +13,9 @@ public struct ConnectionSettings public string Username { get; set; } public string Password { get; set; } public string Datastore { get; set; } - + } - + public static ConnectionSettings GetDefaultConnectionSettings() { return new ConnectionSettings @@ -27,8 +27,8 @@ public static ConnectionSettings GetDefaultConnectionSettings() Datastore = "boundaries" }; } - - + + /// /// curl -i -X POST localhost:12110/datastores/boundaries/content?operation=delete-content -H "Content-Type: application/x.datalog" -T boundaries.dlog /// @@ -45,12 +45,12 @@ public static async Task DeleteDatalog(ConnectionSettings conn, string datalog) { Content = content }; - + var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); - } + } } - + /// /// curl -i -X POST localhost:12110/datastores/boundaries/content -H "Content-Type: application/x.datalog" -T boundaries.dlog /// @@ -68,12 +68,12 @@ public static async Task LoadDatalog(ConnectionSettings conn, string datalog) Content = content }; - + var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); - } + } } - + /// /// curl -i -X PATCH localhost:12110/datastores/boundaries/content?operation=delete-content -H "Content-Type: application/trig" -T boundaries.dlog /// @@ -91,12 +91,12 @@ public static async Task DeleteData(ConnectionSettings conn, string data) Content = content }; - + var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); - } + } } - + /// /// curl -i -X POST localhost:12110/datastores/boundaries/content -H "Content-Type: application/trig" -T boundaries.dlog /// @@ -114,12 +114,12 @@ public static async Task LoadData(ConnectionSettings conn, string data) Content = content }; - + var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); - } + } } - + /// /// curl -i -X POST localhost:12110/datastores/boundaries/sparql -H "Accept: application/x.sparql-results+turtle-abbrev" -d "query=SELECT ?S ?P ?O WHERE { ?S ?P ?O }" /// @@ -137,12 +137,12 @@ public static async Task QuerySparql(ConnectionSettings conn, string que { Content = content }; - + var response = await client.SendAsync(request); - if(!response.IsSuccessStatusCode) + if (!response.IsSuccessStatusCode) throw new Exception(await response.Content.ReadAsStringAsync()); return await response.Content.ReadAsStringAsync(); - } + } } - + } \ No newline at end of file diff --git a/client/Boundaries/Dexpi2Svg/MathExtensions.cs b/client/Boundaries/Dexpi2Svg/MathExtensions.cs index 85d492ff..daf3237e 100644 --- a/client/Boundaries/Dexpi2Svg/MathExtensions.cs +++ b/client/Boundaries/Dexpi2Svg/MathExtensions.cs @@ -12,68 +12,68 @@ public double Sin(double angle) { return Math.Sin(angle); } - public double Sqrt(double value) - { - return Math.Sqrt(value); - } - - public double Pow(double x, double y) - { - return Math.Pow(x, y); - } - - public double Acos(double value) + public double Sqrt(double value) + { + return Math.Sqrt(value); + } + + public double Pow(double x, double y) + { + return Math.Pow(x, y); + } + + public double Acos(double value) + { + return Math.Acos(value); + } + + public double pi() + { + return Math.PI; + } + /// + /// See page 14 of Proteus P&Id file specification 3.3.3 + /// + /// + /// + /// + /// + /// + /// + /// + /// + public double CalculateAngle(double axisX, double axisY, double axisZ, double refX, double refY, double refZ) + { + var axisLength = Math.Sqrt(axisX * axisX + axisY * axisY + axisZ * axisZ); + if (axisLength == 0) { - return Math.Acos(value); + throw new NotImplementedException("axisX, axisY and axisZ must not be all zero"); } - - public double pi() + + var rotDirection = Math.Sign(axisZ); + double refAxisLength = Math.Sqrt(refX * refX + refY * refY + refZ * refZ); + if (refAxisLength == 0) { - return Math.PI; + throw new NotImplementedException("refX, refY and refZ must not be all zero"); } - /// - /// See page 14 of Proteus P&Id file specification 3.3.3 - /// - /// - /// - /// - /// - /// - /// - /// - /// - public double CalculateAngle(double axisX, double axisY, double axisZ, double refX, double refY, double refZ) - { - var axisLength = Math.Sqrt(axisX*axisX+axisY*axisY+axisZ*axisZ); - if (axisLength == 0) - { - throw new NotImplementedException("axisX, axisY and axisZ must not be all zero"); - } - var rotDirection = Math.Sign(axisZ); - double refAxisLength = Math.Sqrt(refX*refX+refY*refY+refZ*refZ); - if (refAxisLength == 0) + var cosTheta = refX / refAxisLength; + var sinTheta = refY / refAxisLength; + var thetaFromCos = Math.Acos(cosTheta); + var thetaFromSin = Math.Asin(sinTheta); + var theta = thetaFromCos; + if (sinTheta < 0) + { + if (cosTheta < 0) { - throw new NotImplementedException("refX, refY and refZ must not be all zero"); + theta = -thetaFromCos; } - - var cosTheta = refX / refAxisLength; - var sinTheta = refY / refAxisLength; - var thetaFromCos = Math.Acos(cosTheta); - var thetaFromSin = Math.Asin(sinTheta); - var theta = thetaFromCos; - if (sinTheta < 0) + else { - if(cosTheta < 0) - { - theta = -thetaFromCos; - } - else - { - theta = thetaFromSin; - } + theta = thetaFromSin; } - return - rotDirection * theta * 180 / Math.PI; - } + return -rotDirection * theta * 180 / Math.PI; + + } } \ No newline at end of file diff --git a/client/Boundaries/Dexpi2Svg/Program.cs b/client/Boundaries/Dexpi2Svg/Program.cs index fcc5dc11..d0e4c91d 100644 --- a/client/Boundaries/Dexpi2Svg/Program.cs +++ b/client/Boundaries/Dexpi2Svg/Program.cs @@ -32,14 +32,14 @@ static void Main(string[] args) { xslt.Load(xr, xsltSettings, new XmlUrlResolver());//added } - + MathExtensions mathExtensions = new MathExtensions(); ColorExtensions colorExtensions = new ColorExtensions(); - + XsltArgumentList xsltArgs = new XsltArgumentList(); xsltArgs.AddExtensionObject("urn:math", mathExtensions); xsltArgs.AddExtensionObject("urn:color", colorExtensions); - + XmlWriterSettings settings = xslt.OutputSettings?.Clone() ?? throw new Exception("No xslt output settings found!"); settings.OmitXmlDeclaration = true; diff --git a/client/Boundaries/TestBoundaries/DatalogCreatorTests.cs b/client/Boundaries/TestBoundaries/DatalogCreatorTests.cs index f6488cac..ef3c6b6c 100644 --- a/client/Boundaries/TestBoundaries/DatalogCreatorTests.cs +++ b/client/Boundaries/TestBoundaries/DatalogCreatorTests.cs @@ -14,7 +14,7 @@ public void TestCreateDatalog() new IriTools.IriReference("https://assetid.equinor.com/plantx#PlateHeatExchanger-1"), new IriTools.IriReference("https://assetid.equinor.com/plantx#ReciprocatingPump-1") }); - Assert.Equal( $$""" + Assert.Equal($$""" <{{graphIri}}> [?node] :- rdfs:label [?internal, "T4750"], @@ -29,6 +29,6 @@ NOT FILTER(?node1 = ), NOT FILTER(?node1 = ), NOT FILTER(?node1 = ), dexpi:PipingOrEquipment [?node]. - """ , datalog); + """, datalog); } } \ No newline at end of file