Skip to content

Commit

Permalink
Merge pull request #493 from eclipse-tractusx/chore/icc-irs-challenge…
Browse files Browse the repository at this point in the history
…-optimization

Add optimization for ai-assist 2 / 3
  • Loading branch information
ds-mwesener authored Dec 3, 2024
2 parents 40fc309 + 9e8ec86 commit 758d47f
Show file tree
Hide file tree
Showing 4 changed files with 689 additions and 318 deletions.
277 changes: 228 additions & 49 deletions icc-irs-challenges/ai-assistent-phase2.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,30 +36,236 @@ Our goal is to progressively enhance the frontend. In this second phase of the w
#### Input Phase 2

- **Goal**: Enhance the frontend from Phase 1 to:
- Read and visualize specific information from submodel data (e.g., `catenaXId`, `payload`, etc.).
- Visualize relationships between different data models using a graph.
- The `globalAssetId` and the `catenaXId` are the same, providing a direct link between these identifiers across
different components
- Child Relationships: - The children of a `SingleLevelBomAsBuilt` are represented as complete `SerialPart`
entities within the `submodels`. Each child is fully modeled to provide detailed information.
- Parent and Child Connections: In the payload of `SingleLevelBomAsBuilt`, the `catenaXId` refers to a`SerialPart`.
This `SerialPart` serves as the **parent part**, positioned above the `SingleLevelBomAsBuilt` in the graph
hierarchy.
- The `SingleLevelBomAsBuilt` acts as the **relationship node** connecting two `SerialParts`. It is positioned
**between** the parent `SerialPart` and its children.
- The children of the `SingleLevelBomAsBuilt` are positioned **below** the corresponding `SerialPart` in the
graph. This visualization clearly delineates parent-child relationships and highlights the intermediary role of
`SingleLevelBomAsBuilt`.
- By adhering to these rules, the graph accurately represents the hierarchical and relational structure of the data,
making it easier to interpret the connections between `SerialParts` and their relationships.
- Visualize a graph using mermaid.
- The graph should be placed above the json response of phase 1
- Below the buttons for Register Job or Get Job Response
- First parent node is the globalAssetId provided in the job.globalAssetId. Use this to search through shells[] shell.payload.globalAssetId and find the corresponding shell object.
- Take the shell object to find the corresponding submodeldescriptior parentShell.payload.submodelDescriptors object only for urn:samm:io.catenax.single_level_bom_as_built:3.0.0#SingleLevelBomAsBuilt
- Use the id of the submodeldescriptior and search for the submodel which corresponds to it submodels[?].identification === submodelDescriptor `semanticId.keys[0].value`
- The element will be a node in the graph.
- Do that as long as you find elements.
- The names of the nodes should be the catenaxid
- A Parent-Child relation should be oriented from top to bottom (TD)
- If a child of the first parent has other children it should act as parent to its children.
- If there are multiple children to one parent, then the children should be next to each other horizontally.
-
- Here is some additional information to let you understand the models:
- - The `globalAssetId` and the `catenaXId` are the same, providing a direct link between these identifiers across
different components
- Child Relationships: - The children of a `SingleLevelBomAsBuilt` are represented as complete `SerialPart`
entities within the `submodels`. Each child is fully modeled to provide detailed information.
- Parent and Child Connections: In the payload of `SingleLevelBomAsBuilt`, the `catenaXId` refers to a`SerialPart`.
This `SerialPart` serves as the **parent part**, positioned above the `SingleLevelBomAsBuilt` in the graph
hierarchy.
- The `SingleLevelBomAsBuilt` acts as the **relationship node** connecting two `SerialParts`. It is positioned
**between** the parent `SerialPart` and its children.
- The children of the `SingleLevelBomAsBuilt` are positioned **below** the corresponding `SerialPart` in the
graph. This visualization clearly delineates parent-child relationships and highlights the intermediary role of
`SingleLevelBomAsBuilt`.
-
- Under the graph there should be one box which acts as a display box to present detail information of a node
- The detail information will be shown if a node will be clicked.
- Use exactly this mermaid version: <script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
- Initialize mermaid like this:
- Initialize mermaid like this:
```js
mermaid.initialize({
startOnLoad: false,
theme: 'default'
});
```
- Use the provided html / js to achieve the expected behaviour
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IRS API Frontend with Graph and Details</title>
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
mermaid.initialize({
startOnLoad: false,
theme: 'default'
});
</script>
</head>
<body>
<h1>IRS API Job Registration</h1>

<!-- Input fields for BPN and Global Asset ID -->
<label for="bpn">BPN:</label>
<input type="text" id="bpn" placeholder="Enter BPN" required><br><br>

<label for="globalAssetId">Global Asset ID:</label>
<input type="text" id="globalAssetId" placeholder="Enter Global Asset ID" required><br><br>

<!-- Buttons to register job, get job details, and visualize graph -->
<button id="registerJobBtn">Register Job</button>
<button id="getJobResponseBtn" style="display:none;">Get Job Response</button>
<button id="visualizeGraphBtn" style="display:none;">Visualize Graph</button>

<h3>Graph Visualization:</h3>
<div id="graphContainer"></div>

<h3>Node Detail Information:</h3>
<div id="nodeDetails" style="border: 1px solid #ccc; padding: 10px; display: none;">
<h4>Shell Details for Node:</h4>
<p id="nodeName">Node (GlobalAssetId): </p>
<p id="manufacturerId">Manufacturer ID: </p>
<p id="manufacturerPartId">Manufacturer Part ID: </p>
<p id="digitalTwinType">Digital Twin Type: </p>
</div>

<h3>Response:</h3>
<pre id="responseDisplay"></pre>

<script>
document.getElementById('registerJobBtn').addEventListener('click', registerJob);
document.getElementById('getJobResponseBtn').addEventListener('click', getJobResponse);
document.getElementById('visualizeGraphBtn').addEventListener('click', visualizeGraph);
let jobId = ''; // To store the job ID for subsequent request
let irsResponse = null;
// Function to register a job
function registerJob() {
const bpn = document.getElementById('bpn').value;
const globalAssetId = document.getElementById('globalAssetId').value;
const data = {
aspects: [
"urn:samm:io.catenax.serial_part:3.0.0#SerialPart",
"urn:samm:io.catenax.just_in_sequence_part:3.0.0#JustInSequencePart",
"urn:samm:io.catenax.batch:3.0.0#Batch",
"urn:samm:io.catenax.single_level_bom_as_built:3.0.0#SingleLevelBomAsBuilt"
],
key: {
globalAssetId: globalAssetId,
bpn: bpn
},
collectAspects: true,
direction: "downward"
};
fetch('http://localhost:3000/api/irs/jobs', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
.then(response => response.json())
.then(data => {
jobId = data.id;
document.getElementById('getJobResponseBtn').style.display = 'inline';
displayResponse(data);
})
.catch(error => console.error('Error:', error));
}
function getJobResponse() {
fetch(`http://localhost:3000/api/irs/jobs/${jobId}`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
})
.then(response => response.json())
.then(data => {
irsResponse = data;
displayResponse(data);
document.getElementById('visualizeGraphBtn').style.display = 'inline';
})
.catch(error => console.error('Error:', error));
}
function displayResponse(data) {
document.getElementById('responseDisplay').textContent = JSON.stringify(data, null, 2);
}
function visualizeGraph() {
if (!irsResponse || !irsResponse.job.globalAssetId || !irsResponse.shells) {
alert('Invalid IRS Response.');
return;
}
const globalAssetId = irsResponse.job.globalAssetId;
const shells = irsResponse.shells;
const submodels = irsResponse.submodels;
let graphDefinition = "graph TD\n";
const visited = new Set();
function buildGraph(parentId) {
const parentShell = shells.find(shell => shell.payload.globalAssetId === parentId);
if (!parentShell) return;
const submodelDescriptor = parentShell.payload.submodelDescriptors.find(descriptor =>
descriptor.semanticId.keys[0].value === "urn:samm:io.catenax.single_level_bom_as_built:3.0.0#SingleLevelBomAsBuilt"
);
if (!submodelDescriptor) return;
const submodel = submodels.find(sub => sub.identification === submodelDescriptor.id);
if (!submodel || visited.has(parentId)) return;
visited.add(parentId);
graphDefinition += `${parentId}["${parentId}"]\n`;
if (submodel.aspectType === 'urn:samm:io.catenax.single_level_bom_as_built:3.0.0#SingleLevelBomAsBuilt') {
submodel.payload.childItems.forEach(child => {
graphDefinition += `${parentId} --> ${child.catenaXId}["${child.catenaXId}"]\n`;
buildGraph(child.catenaXId);
});
}
}
buildGraph(globalAssetId);
document.getElementById('graphContainer').innerHTML = `<div class="mermaid">${graphDefinition}</div>`;
mermaid.init();
// Add event listener to nodes for detail display
document.querySelectorAll('.mermaid').forEach((node) => {
node.addEventListener('click', (event) => {
const nodeId = event.target.textContent;
// Show the details for the clicked node
showNodeDetails(nodeId);
});
});
}
function showNodeDetails(nodeId) {
if (!irsResponse || !irsResponse.shells) return;
// Find the shell matching the nodeId (GlobalAssetId)
const shell = irsResponse.shells.find(s => s.payload.globalAssetId === nodeId);
if (!shell || !shell.payload.specificAssetIds) return;
// Get the list of specific asset IDs
const specificAssets = shell.payload.specificAssetIds;
// Clear previous node details
let detailsHtml = `<h4>Details for Node: ${nodeId}</h4>`;
// Loop through the specificAssetIds to dynamically build the details
specificAssets.forEach(asset => {
const assetName = asset.name;
const assetValue = asset.value || 'N/A'; // Use 'N/A' if value doesn't exist
// Add the name and value of the asset to the details HTML
detailsHtml += `<p><strong>${assetName}:</strong> ${assetValue}</p>`;
});
// Update the node detail section with the new information
document.getElementById('nodeDetails').innerHTML = detailsHtml;
// Display the details section
document.getElementById('nodeDetails').style.display = 'block';
}
</script>
</body>
</html>
```

- Present the result and gather feedback.

- **Acceptance Criteria**:
- All criteria from Phase 1 are met.
- Specific submodel data fields are extracted and visualized.
Expand All @@ -83,44 +289,17 @@ Our goal is to progressively enhance the frontend. In this second phase of the w
---

### Step 2: Request current code base
- Explain the user that you need the code for the previous phase to be able to support with phase 2.
- Explain the user that you need the code for the previous phase to be able to support with phase 2.
- Tell them that they also can copy multiple files at the same time in the chat
- Tell them that you only need the html, css and javascript not any libraries or something else.
- Tell them that you only need the html, css and javascript not any libraries or something else.
- Also make clear that they can copy the raw content of the full file (js / html / css)

### Step 3: Request more code
- Do the same as you did in step 2.
### Step 3: Request more code
- Do the same as you did in step 2.
- Request confirmation if all files have been provided, if not ask for the content.

### Step 4: Develop Solution for Phase 2
- Extend the frontend from Phase 1, which was provided in Step 2 by the user to:
- Extract fields (e.g., `job.globalAssetId`, `job.state`, `job.parameter.bpn`, `shells[?].payload.globalAssetId`,
`shells[?].payload.submodelDescriptors.semanticId.keys[0].value`, `shells[?].payload.submodelDescriptors.id`,
`submodels[?].identification`, `submodels[?].payload.catenaXId`, `submodels[?].payload.localIdentifiers`) from the
job detail response.
- Visualize these fields and relationships with a mermaid graph. Embed the graph in the html and visualize it with mermaid. Use Mermaid version 11
- The names of the nodes should be the catenaxid
- The requested globalAssetId (catenaXId) is the beginning node. This is found with `data.job.globalAssetId` from the response.
- A Parent-Child relation should be oriented from top to bottom (TD)
- If there are multiple children to one parent, then the children should be next to each other horizontally.
- If a child of the first parent has other children it should act as parent to its children.
- Find the shells[] array from `data.shells[]`
- From shells[] array
- Extract fields from shells (`payload.globalAssetId`, `payload.specificAssetIds[]`,
`payload.submodelDescriptors[]`)
- From array submodelDescriptors[] get the submodelDescriptor where `semanticId.keys[0].value` is equal to `urn:samm:io.catenax.single_level_bom_as_built:3.0.0#SingleLevelBomAsBuilt`
- Extract field from submodelDescriptor: `id`
- From array specificAssetIds[] get the name value pairs where `name` is one of `manufacturerId`,
`manufacturerPartId`, `digitalTwinType` if they are present.
- Attach fields from shells to shells graph node
- Find the submodels[] array from `data.submodels[]`
- From submodels[] array
- Get submodel with `identification` equal to the `id` from the submodelDescriptor
- Attach fields submodels graph edge (`submodels[?].payload.catenaXId`,
`submodels[?].payload.childItems[?].catenaXId`,`submodels[?].payload.childItems[?].businessPartner`)
- Ensure JSON data is now structured and visually accessible in HTML.
- Present the result and gather feedback.

- Extend the frontend from Phase 1, which was provided in Step 2 by the user to create a graph as described in the "Input Phase 2"
- **Next Step**: Inform participants they can enhance the graph and styling creatively. Encourage questions about
styling.

Expand Down
Loading

0 comments on commit 758d47f

Please sign in to comment.