analyzer added

This commit is contained in:
Bane Stojkovic
2025-04-24 21:38:04 +02:00
parent c914749413
commit f7cd33c80f
7 changed files with 230 additions and 19 deletions
@@ -43,6 +43,20 @@ public interface IChatbotAPI {
@ParamName("machineId") String machineId, @ParamName("project") String project, @ParamName("machineId") String machineId, @ParamName("project") String project,
@ParamName("netlist") File netlist, @ParamName("prompt") String prompt); @ParamName("netlist") File netlist, @ParamName("prompt") String prompt);
/**
* Analyzes the provided circuit
*
* @param username
* @param token
* @param machineId
* @param project
* @param netlist
* @return
*/
String analyzeCircuit(@ParamName("username") String username, @ParamName("token") String token,
@ParamName("machineId") String machineId, @ParamName("project") String project,
@ParamName("netlist") File netlist);
SubscriptionEntity getSubscriptionInfo(@ParamName("username") String username, @ParamName("token") String token, SubscriptionEntity getSubscriptionInfo(@ParamName("username") String username, @ParamName("token") String token,
@ParamName("machineId") String machineId); @ParamName("machineId") String machineId);
@@ -5,6 +5,7 @@ import java.awt.geom.Point2D;
import java.util.*; import java.util.*;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@@ -34,7 +35,8 @@ public class AiProjectBuilder {
sets.stream().map(s -> s.stream() sets.stream().map(s -> s.stream()
.map(AiProjectBuilder::mapTerminal) .map(AiProjectBuilder::mapTerminal)
.collect(Collectors.toSet())) .collect(Collectors.toSet()))
.collect(Collectors.toMap(x -> "N" + counter.incrementAndGet(), x -> x)); .collect(Collectors.toMap(x -> "N" + String.format("%03d", counter.incrementAndGet()),
Function.identity()));
List<AiSwitch> switches = List<AiSwitch> switches =
project.getComponents().stream() project.getComponents().stream()
@@ -123,9 +123,57 @@ public class ChatbotService {
String currentFile = plugInPort.getCurrentFileName(); String currentFile = plugInPort.getCurrentFileName();
String fileName = extractFileName(currentFile); String fileName = extractFileName(currentFile);
File aiProjectFile = null; File aiProjectFile = getAiProjectFile();
try { try {
return getService().promptChatbot(
plugInPort.getCloudService().getCurrentUsername(),
plugInPort.getCloudService().getCurrentToken(),
plugInPort.getCloudService().getMachineId(),
fileName,
aiProjectFile,
prompt);
} finally {
// Clean up the temp file immediately after use
if (aiProjectFile != null && aiProjectFile.exists()) {
aiProjectFile.delete();
}
}
}
public String analyzeCircuit() throws NotLoggedInException {
if (!plugInPort.getCloudService().isLoggedIn())
throw new NotLoggedInException();
LOG.info("Analyzing circuit...");
String currentFile = plugInPort.getCurrentFileName();
String fileName = extractFileName(currentFile);
File aiProjectFile = getAiProjectFile();
try {
String jsonResult = getService().analyzeCircuit(plugInPort.getCloudService().getCurrentUsername(),
plugInPort.getCloudService().getCurrentToken(),
plugInPort.getCloudService().getMachineId(), fileName, aiProjectFile);
return JsonToHtmlConverter.convertToHtml(jsonResult);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
// Clean up the temp file immediately after use
if (aiProjectFile != null && aiProjectFile.exists()) {
aiProjectFile.delete();
}
}
}
private File getAiProjectFile() {
File aiProjectFile = null;
AiProject aiProject = extractAiProject(); AiProject aiProject = extractAiProject();
if (aiProject == null) {
return null;
}
try {
String aiProjectStr = null; String aiProjectStr = null;
try { try {
aiProjectStr = MAPPER.writeValueAsString(aiProject); aiProjectStr = MAPPER.writeValueAsString(aiProject);
@@ -181,24 +229,13 @@ public class ChatbotService {
} catch (Exception e) { } catch (Exception e) {
LOG.error("Error extracting or saving netlist", e); LOG.error("Error extracting or saving netlist", e);
} }
return aiProjectFile;
try {
return getService().promptChatbot(
plugInPort.getCloudService().getCurrentUsername(),
plugInPort.getCloudService().getCurrentToken(),
plugInPort.getCloudService().getMachineId(),
fileName,
aiProjectFile,
prompt);
} finally {
// Clean up the temp file immediately after use
if (aiProjectFile != null && aiProjectFile.exists()) {
aiProjectFile.delete();
}
}
} }
private AiProject extractAiProject() throws NetlistException { private AiProject extractAiProject() {
if (plugInPort.getCurrentProject().getComponents().isEmpty()) {
return null;
}
List<ContinuityArea> continuityAreas = plugInPort.getDrawingManager().getContinuityAreas(); List<ContinuityArea> continuityAreas = plugInPort.getDrawingManager().getContinuityAreas();
return AiProjectBuilder.build(plugInPort.getCurrentProject(), continuityAreas); return AiProjectBuilder.build(plugInPort.getCurrentProject(), continuityAreas);
} }
@@ -0,0 +1,92 @@
package org.diylc.plugins.chatbot.service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class JsonToHtmlConverter {
private static final ObjectMapper MAPPER = new ObjectMapper();
/**
* Convert the given JSON string into HTML.
*
* @param json the input JSON
* @return an HTML document as a String
* @throws IOException if JSON parsing fails
*/
public static String convertToHtml(String json) throws IOException {
JsonNode root = MAPPER.readTree(json);
StringBuilder html = new StringBuilder();
html.append("<!DOCTYPE html>\n<html>\n<head>\n")
.append(" <meta charset=\"UTF-8\">\n")
.append(" <title>Validation Report</title>\n")
.append(" <style>\n")
.append(" body { font-family: Arial, sans-serif; }\n")
.append(" h2 { color: #444; }\n")
.append(" ul { list-style: disc; margin-left: 20px; }\n")
.append(" li { margin-bottom: 5px; }\n")
.append(" </style>\n")
.append("</head>\n<body>\n");
// Process each section
processSection(root, "critical", html, "#c00");
processSection(root, "warnings", html, "#e65c00");
processSection(root, "optimizations", html, "#0066c0");
html.append("</body>\n</html>");
return html.toString();
}
private static void processSection(JsonNode root, String field, StringBuilder html, String color) {
JsonNode array = root.path(field);
if (array.isArray() && array.size() > 0) {
html.append(String.format("<h2 style=\"color:%s;\">%s</h2>\n", color, capitalize(field)));
html.append("<ul>\n");
for (JsonNode item : array) {
String message = escapeHtml(item.path("message").asText(""));
if (item.hasNonNull("componentId") && !item.path("componentId").asText().isEmpty()) {
String id = escapeHtml(item.path("componentId").asText());
html.append(" <li><strong>")
.append(id)
.append("</strong>: ")
.append(message)
.append("</li>\n");
} else {
html.append(" <li>")
.append(message)
.append("</li>\n");
}
}
html.append("</ul>\n");
}
}
private static String capitalize(String text) {
if (text == null || text.isEmpty()) return text;
return Character.toUpperCase(text.charAt(0)) + text.substring(1);
}
/**
* Very basic HTML escapement; for more robust use Apache Commons StringEscapeUtils.escapeHtml4().
*/
private static String escapeHtml(String s) {
return s.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
.replace("\"", "&quot;");
}
// Example usage:
public static void main(String[] args) throws IOException {
String json = "{\n" +
" \"critical\": [{\"message\":\"Value too low\"}],\n" +
" \"warnings\": [{\"componentId\":\"C3\",\"message\":\"Consider higher tolerance\"}],\n" +
" \"optimizations\": [{\"componentId\":\"L2\",\"message\":\"Could use 0805 package\"}]\n" +
"}";
String html = convertToHtml(json);
System.out.println(html);
}
}
@@ -21,6 +21,7 @@ import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.ClipboardOwner;
import javax.swing.Icon; import javax.swing.Icon;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.diylc.swing.actions.analyze.AiAnalyzeAction;
import org.diylc.swing.actions.analyze.HighlightConnectedAreasAction; import org.diylc.swing.actions.analyze.HighlightConnectedAreasAction;
import org.diylc.swingframework.IDrawingProvider; import org.diylc.swingframework.IDrawingProvider;
@@ -275,6 +276,10 @@ public class ActionFactory {
return new GenerateNetlistAction(plugInPort, swingUI, includeSwitches); return new GenerateNetlistAction(plugInPort, swingUI, includeSwitches);
} }
public AiAnalyzeAction createAiAnalyzeAction(IPlugInPort plugInPort, ISwingUI swingUI) {
return new AiAnalyzeAction(plugInPort, swingUI);
}
public SummarizeNetlistAction createSummarizeNetlistAction(IPlugInPort plugInPort, public SummarizeNetlistAction createSummarizeNetlistAction(IPlugInPort plugInPort,
ISwingUI swingUI, INetlistAnalyzer summarizer, boolean includeSwitches) { ISwingUI swingUI, INetlistAnalyzer summarizer, boolean includeSwitches) {
return new SummarizeNetlistAction(plugInPort, swingUI, summarizer, includeSwitches); return new SummarizeNetlistAction(plugInPort, swingUI, summarizer, includeSwitches);
@@ -0,0 +1,60 @@
package org.diylc.swing.actions.analyze;
import org.diylc.common.INetlistAnalyzer;
import org.diylc.common.IPlugInPort;
import org.diylc.common.ITask;
import org.diylc.netlist.Netlist;
import org.diylc.netlist.Summary;
import org.diylc.swing.ISwingUI;
import org.diylc.swingframework.TextDialog;
import org.diylc.utils.IconLoader;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.List;
public class AiAnalyzeAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private IPlugInPort plugInPort;
private ISwingUI swingUI;
public AiAnalyzeAction(IPlugInPort plugInPort, ISwingUI swingUI) {
super();
this.plugInPort = plugInPort;
this.swingUI = swingUI;
putValue(AbstractAction.NAME, "AI Circuit Analyzer");
// putValue(AbstractAction.SMALL_ICON,
// Enum.valueOf(IconLoader.class, summarizer.getIconName()).getIcon());
}
@Override
public void actionPerformed(ActionEvent e) {
swingUI.executeBackgroundTask(new ITask<String>() {
@Override
public String doInBackground() throws Exception {
return plugInPort.getChatbotService().analyzeCircuit();
}
@Override
public void failed(Exception e) {
swingUI.showMessage(e.getMessage(), "AI Circuit Analyzer", ISwingUI.ERROR_MESSAGE);
}
@Override
public void complete(String res) {
if (res == null || res.isEmpty()) {
swingUI.showMessage("The generated analysis is empty, nothing to show.",
"AI Circuit Analyzer", ISwingUI.INFORMATION_MESSAGE);
return;
}
new TextDialog(swingUI.getOwnerFrame().getRootPane(), res, "AI Circuit Analyzer",
new Dimension(800, 600)).setVisible(true);
}
}, true);
}
}
@@ -66,6 +66,7 @@ public class AnalyzeMenuPlugin implements IPlugIn {
List<Action> menuActions = new ArrayList<>(); List<Action> menuActions = new ArrayList<>();
// Add all menu actions to the list // Add all menu actions to the list
menuActions.add(actionFactory.createAiAnalyzeAction(plugInPort, swingUI));
menuActions.add(actionFactory.createCheckProximityAction(plugInPort, swingUI)); menuActions.add(actionFactory.createCheckProximityAction(plugInPort, swingUI));
menuActions.add(actionFactory.createBomAction(plugInPort)); menuActions.add(actionFactory.createBomAction(plugInPort));
menuActions.add(actionFactory.createGenerateNetlistAction(plugInPort, swingUI, false)); menuActions.add(actionFactory.createGenerateNetlistAction(plugInPort, swingUI, false));