componentDescriptorMap = new HashMap<>();
+ componentDescriptorMap.put("name", c.getName());
+ componentDescriptorMap.put("type", componentType.getName());
+ componentDescriptorMap.put("category", componentType.getCategory());
+
+ properties.forEach(p -> {
+ if (PROPERTY_TYPES_TO_SKIP.contains(p.getType()))
+ return;
+
+ try {
+ p.readFrom(c);
+ if (p.getValue() == null)
+ return;
+
+ componentDescriptorMap.put(p.getName(), p.getValue().toString());
+ } catch (Exception e) {
+ LOG.warn("Error extracting properties", e);
+ }
+ });
+
+ componentDescriptors.add(componentDescriptorMap);
+ });
+
+ try {
+ String json = MAPPER.writeValueAsString(componentDescriptors);
+ sb.append(json).append("\n\n");
+ } catch (Exception e) {
+ LOG.error("Failed to serialize component descriptors to JSON", e);
+ }
+
+ for (Netlist netlist : netlists) {
+ sb.append("Switch configuration: ").append(netlist.getSwitchSetup()).append("\n\n")
+ .append("Connected node groups:\n\n");
+ for (Group v : netlist.getSortedGroups()) {
+ sb.append(v.getSortedNodes()).append("\n");
+ }
+ }
+ return sb.toString();
+ }
+
+ public String getInitialChatContents() {
+ Random r = new Random();
+
+ String chatHtml =
+ "Welcome to the DIYLC AI Assistant!
\n" +
+ "I'm here to help you design, build, and troubleshoot your electronics projects using DIY Layout Creator (DIYLC). You can ask me questions about:
\n" +
+ // "\n" +
+ "\n" +
+ "- Electronics theory or concepts: e.g., '" + electronicsQuestions[r.nextInt(
+ electronicsQuestions.length)] + "'
\n" +
+ "- DIYLC features and usage: e.g., '" + diylcQuestions[r.nextInt(diylcQuestions.length)] + "'
\n" +
+ "- Your current circuit project: e.g., '" + circuitQuestions[r.nextInt(circuitQuestions.length)] + "'
\n" +
+ // "
\n" +
+ "
\n" +
+ "Feel free to ask your own question or use one of these examples to get started!
\n";
+
+ if (!CloudPresenter.Instance.isLoggedIn()) {
+ chatHtml = chatHtml + "Please log into your DIYLC Cloud account in order to use the AI Assistant.
\n";
+ }
+
+ return chatHtml;
+ }
+
+ public static final String ASSISTANT = "assistant";
+ public static final String SYSTEM = "system";
+ public static final String USER = "user";
+ public static final String TEMPORARY = "temporary";
+
+ String[] electronicsQuestions = {
+ "What is Ohm's Law, and how do voltage, current, and resistance relate to each other?",
+ "Why are resistors important in circuits, and what happens if the resistor value is incorrect?",
+ "What is a capacitor, and how does it behave differently from a resistor?",
+ "How does an inductor work, and where might you find one in common DIY projects?",
+ "What's the difference between AC (Alternating Current) and DC (Direct Current), and where is each used?",
+ "How do diodes work, and why are they essential in electronics?",
+ "What's the difference between series and parallel circuits, and why does it matter?",
+ "How does a transistor function, and what role does it typically play in a circuit?",
+ "Why is grounding important in electronic circuits, and what exactly does it do?",
+ "What is impedance, and why is it important when connecting speakers or audio equipment?",
+ "What exactly is an operational amplifier (op amp), and what are its common uses in audio circuits?",
+ "How does a relay work, and when would you choose a relay over a transistor or MOSFET?",
+ "What's the purpose of using a fuse or circuit breaker in a DIY electronics project?",
+ "Why do certain electronic components need specific voltage ratings?",
+ "What is electromagnetic interference (EMI), and how can you minimize it in your projects?",
+ "What does polarity mean for components like electrolytic capacitors and diodes, and why is it important?",
+ "How does filtering work to remove unwanted noise from audio signals or power supplies?",
+ "What is signal clipping in audio circuits, and how can you prevent it?",
+ "Why do some circuits require a heatsink, and how do heatsinks help protect components?",
+ "What is frequency response, and why is it crucial for audio circuits like guitar pedals and amplifiers?",
+ "How do you calculate the correct resistor value for limiting current to an LED?",
+ "What is the role of a voltage regulator, and how does it keep voltage stable?",
+ "How can you measure and verify voltage and current safely using a multimeter?",
+ "What does it mean when a circuit is described as having a 'high input impedance' or 'low output impedance,' and why does it matter?",
+ "How can you determine if components in your circuit are properly rated for the voltage and current they're experiencing?"
+ };
+
+ String[] diylcQuestions = {
+ "How do I add a component to my layout in DIYLC?",
+ "How can I quickly find a specific component in DIYLC?s component toolbox?",
+ "How do I move or reposition components on the canvas in DIYLC?",
+ "How do I edit or change a component?s properties (e.g. value or color) in DIYLC?",
+ "Is there a shortcut to duplicate or repeat the last component I placed in DIYLC?",
+ "How can I group multiple components so I can move or edit them together in DIYLC?",
+ "What are ?building blocks? in DIYLC and how do I create or use them?",
+ "How do I save my DIYLC project and reopen it later on?",
+ "How do I export my DIYLC layout as an image or PDF file?",
+ "Can DIYLC generate a bill of materials (BOM) for my project, and how would I do that?",
+ "How can I change or hide different layers in a DIYLC project to manage overlapping components?",
+ "Is it possible to view the underside of a board in DIYLC, and how can I enable that?",
+ "What does the ?Highlight Connected Areas? feature do in DIYLC and how do I use it for debugging?",
+ "How can I analyze a guitar wiring diagram using DIYLC?s built-in tools?",
+ "How do I assign a custom keyboard shortcut to a component in DIYLC for quick access?",
+ "What are component variants in DIYLC and how can I create and apply them?",
+ "What is the continuous creation mode in DIYLC and how does it help when adding many components?",
+ "How can I create a custom component to add to DIYLC?s component library?",
+ "Does DIYLC support plug-ins, and how can I add new functionality to the app with them?",
+ "What is the DIYLC cloud feature and how can I share or download projects using it?"
+ };
+
+ String[] circuitQuestions = {
+ "What's the purpose of this specific resistor in my circuit?",
+ "How do I correctly determine capacitor values for my power supply?",
+ "How should I route wiring to reduce interference and noise?",
+ "Which component should I choose for this switching application, a MOSFET or BJT?",
+ "How do I verify if my ground connections are optimal?",
+ "Why might this transistor get hot during operation?",
+ "What's the best approach to simplify this section of my circuit?",
+ "How can I ensure my circuit is safe against short circuits?",
+ "What could be causing voltage instability in this circuit?",
+ "How do I properly size resistors to protect LEDs?",
+ "What are the steps to debug unexpected oscillations in my circuit?",
+ "Should I add a bypass capacitor here, and what value should I use?",
+ "How can I check if my components are operating within their rated specifications?",
+ "Is this the right way to connect multiple power rails in my design?",
+ "How can I test my circuit before physically assembling it?",
+ "What are good layout practices to minimize electromagnetic interference?",
+ "How do I identify if my circuit has any redundant or unnecessary components?",
+ "Why might the voltage regulator not output the expected voltage?",
+ "What's the recommended method for isolating digital and analog grounds?",
+ "How do I safely integrate high-voltage components into my DIY circuit?",
+ "Why isn't my LED lighting up when powered?",
+ "How do I troubleshoot a circuit that's drawing more current than expected?",
+ "Why does my amplifier circuit produce a humming or buzzing sound?",
+ "How can I detect and fix intermittent connections in my circuit?",
+ "What should I check if my circuit isn't responding to input signals as expected?",
+ "How do I determine if my soldering joints are causing reliability issues?",
+ "What steps can I take if my microcontroller circuit isn't functioning as intended?",
+ "How do I troubleshoot a noisy or unstable sensor reading?"
+ };
}
diff --git a/diylc/diylc-core/src/main/java/org/diylc/utils/FileUtils.java b/diylc/diylc-core/src/main/java/org/diylc/utils/FileUtils.java
new file mode 100644
index 00000000..20e3689a
--- /dev/null
+++ b/diylc/diylc-core/src/main/java/org/diylc/utils/FileUtils.java
@@ -0,0 +1,24 @@
+package org.diylc.utils;
+
+import java.io.File;
+
+public class FileUtils {
+
+ /**
+ * Extracts the base file name without extension from a full path.
+ * For example: "/path/to/myfile.diy" returns "myfile"
+ */
+ public static String extractFileName(String path) {
+ if (path == null || path.isEmpty()) {
+ return "Untitled";
+ }
+ // Get the last part after the last separator
+ String fileName = path.substring(path.lastIndexOf(File.separator) + 1);
+ // Remove the extension if present
+ int dotIndex = fileName.lastIndexOf('.');
+ if (dotIndex > 0) {
+ fileName = fileName.substring(0, dotIndex);
+ }
+ return fileName;
+ }
+}
diff --git a/diylc/diylc-library/src/main/java/org/diylc/netlist/GuitarDiagramAnalyzer.java b/diylc/diylc-library/src/main/java/org/diylc/netlist/GuitarDiagramAnalyzer.java
index 1239c7e1..0398f0fb 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/netlist/GuitarDiagramAnalyzer.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/netlist/GuitarDiagramAnalyzer.java
@@ -119,7 +119,7 @@ public class GuitarDiagramAnalyzer extends AbstractNetlistAnalyzer implements IN
return Set.of(NetlistSwitchPreference.WITH);
}
- protected Summary summarize(Netlist netlist, Node preferredOutput) throws TreeException {
+ protected Summary summarize(Netlist netlist) throws TreeException {
List notes = new ArrayList();
Tree tree = constructTree(netlist);
@@ -128,6 +128,28 @@ public class GuitarDiagramAnalyzer extends AbstractNetlistAnalyzer implements IN
return new Summary(netlist, "No pickups are connected to the output jack");
}
+ processTree(tree, notes);
+
+ StringBuilder sb = new StringBuilder();
+
+ String asciiTree = tree.toAsciiString();
+
+ sb.append("
")
+ .append("")
+ .append(asciiTree)
+ .append("");
+ if (!notes.isEmpty()) {
+ Collections.sort(notes);
+ sb.append("
");
+ for (String v : notes) {
+ sb.append(v).append("
");
+ }
+ }
+
+ return new Summary(netlist, sb.toString());
+ }
+
+ private void processTree(Tree tree, List notes) {
Tree pickupTree = tree.filter(PICKUP_TYPES);
if (pickupTree == null || pickupTree.getChildren().isEmpty()) {
@@ -242,165 +264,177 @@ public class GuitarDiagramAnalyzer extends AbstractNetlistAnalyzer implements IN
Set> pots = tree.extractComponents(POT_TYPES);
for (IDIYComponent> pot : pots) {
- TreeLeaf leaf1 = new TreeLeaf(pot, 0, 1);
- TreeLeaf leaf2 = new TreeLeaf(pot, 1, 2);
- Tree tree1 = tree.locate(leaf1, false);
- Tree tree2 = tree.locate(leaf2, false);
-
- if ((tree1 == null && tree2 != null) || (tree1 != null && tree2 == null)) {
- boolean tonePotReversed = tree1 != null;
- Tree t = tree1 == null ? tree2 : tree1;
- Tree p = tree.findParent(t);
- if (p != null && p.getChildren().size() == 2) {
- Set> caps = p.extractComponents(CAP_TYPES);
- if (caps != null && caps.size() == 1) {
- for (Map.Entry, Tree> r : pickupRoots.entrySet()) {
- Tree toneParent = tree.findCommonParent(p, r.getValue());
- if (toneParent != null
- && toneParent.getConnectionType() == TreeConnectionType.Parallel) {
- if (tonePotReversed) {
- List> pickupList = tonePotPickupReverseMap.get(pot);
- if (pickupList == null) {
- pickupList = new ArrayList>();
- tonePotPickupReverseMap.put(pot, pickupList);
- }
- pickupList.add(r.getKey());
- } else {
- List> pickupList = tonePotPickupMap.get(pot);
- if (pickupList == null) {
- pickupList = new ArrayList>();
- tonePotPickupMap.put(pot, pickupList);
- }
- pickupList.add(r.getKey());
- }
- }
- }
- }
- }
- }
-
- // volume
- if (tree1 == null || tree2 == null)
- continue;
- for (Map.Entry, Tree> r : pickupRoots.entrySet()) {
- Tree commonParent1 = tree.findCommonParent(tree1, r.getValue());
- Tree commonParent2 = tree.findCommonParent(tree2, r.getValue());
- locateTrebleBleed(tree, volPotTrebleBleedMap, pot, tree1);
-
- if (commonParent1 != null && commonParent2 != null
- && commonParent1.getConnectionType() == TreeConnectionType.Series
- && commonParent2.getConnectionType() == TreeConnectionType.Parallel) {
- List> pickupList = volPotPickupMap.get(pot);
- if (pickupList == null) {
- pickupList = new ArrayList>();
- volPotPickupMap.put(pot, pickupList);
- }
- pickupList.add(r.getKey());
- } else if (commonParent1 != null && commonParent2 != null
- && commonParent1.getConnectionType() == TreeConnectionType.Parallel
- && commonParent2.getConnectionType() == TreeConnectionType.Series) {
- List> pickupList = volPotPickupReverseMap.get(pot);
- if (pickupList == null) {
- pickupList = new ArrayList>();
- volPotPickupReverseMap.put(pot, pickupList);
- }
- pickupList.add(r.getKey());
- }
- }
+ processPotentiometer(pot, tree, pickupRoots, tonePotPickupReverseMap, tonePotPickupMap,
+ volPotTrebleBleedMap, volPotPickupMap, volPotPickupReverseMap);
}
for (Map.Entry, List>> e : volPotPickupMap.entrySet()) {
- StringBuilder sb = new StringBuilder(
- "'" + e.getKey().getName() + "' potentiometer acts as a volume control for ");
- boolean first = true;
- List pickupNames =
- e.getValue().stream().map(x -> x.getName()).sorted().collect(Collectors.toList());
- for (String pickupName : pickupNames) {
- if (!first)
- sb.append(pickupNames.size() == 2 ? " and " : ", ");
- first = false;
- sb.append("'").append(pickupName).append("'");
- }
- notes.add(sb.toString());
-
- Set> trebleBleedComponents = volPotTrebleBleedMap.get(e.getKey());
- if (trebleBleedComponents != null && trebleBleedComponents.size() > 0) {
-
- String trebleBleadNote = trebleBleedComponents.stream()
- .sorted(Comparator.comparing(c -> c.getName()))
- .map(c -> "'" + c.getName() + "'")
- .collect(Collectors.joining(", ")) + " form a treble bleed network on the '" + e.getKey().getName() + "' volume control";
- notes.add(trebleBleadNote);
- }
+ outputVolumePotentiometer(e, notes, volPotTrebleBleedMap);
}
for (Map.Entry, List>> e : volPotPickupReverseMap
.entrySet()) {
- StringBuilder sb = new StringBuilder(
- "'" + e.getKey().getName() + "' potentiometer acts as a volume control for ");
- boolean first = true;
- List pickupNames =
- e.getValue().stream().map(x -> x.getName()).sorted().collect(Collectors.toList());
- for (String pickupName : pickupNames) {
- if (!first)
- sb.append(pickupNames.size() == 2 ? " and " : ", ");
- first = false;
- sb.append("'").append(pickupName).append("'");
- }
- sb.append(", but is wired in REVERSE!");
- notes.add(sb.toString());
+ outputVolumePotReversed(e, notes);
}
for (Map.Entry, List>> e : tonePotPickupMap.entrySet()) {
- StringBuilder sb = new StringBuilder(
- "'" + e.getKey().getName() + "' potentiometer acts as a tone control for ");
- boolean first = true;
- List pickupNames =
- e.getValue().stream().map(x -> x.getName()).sorted().collect(Collectors.toList());
- for (String pickupName : pickupNames) {
- if (!first)
- sb.append(pickupNames.size() == 2 ? " and " : ", ");
- first = false;
- sb.append("'").append(pickupName).append("'");
- }
- notes.add(sb.toString());
+ outputTonePotentiometer(e, notes);
}
for (Map.Entry, List>> e : tonePotPickupReverseMap
.entrySet()) {
- StringBuilder sb = new StringBuilder(
- "'" + e.getKey().getName() + "' potentiometer acts as a tone control for ");
- boolean first = true;
- List pickupNames =
- e.getValue().stream().map(x -> x.getName()).sorted().collect(Collectors.toList());
- for (String pickupName : pickupNames) {
- if (!first)
- sb.append(pickupNames.size() == 2 ? " and " : ", ");
- first = false;
- sb.append("'").append(pickupName).append("'");
+ outputTonePotentiometerReversed(e, notes);
+ }
+ }
+ }
+
+ private static void outputTonePotentiometerReversed(Map.Entry, List>> e,
+ List notes) {
+ StringBuilder sb = new StringBuilder(
+ "'" + e.getKey().getName() + "' potentiometer acts as a tone control for ");
+ boolean first = true;
+ List pickupNames =
+ e.getValue().stream().map(x -> x.getName()).sorted().collect(Collectors.toList());
+ for (String pickupName : pickupNames) {
+ if (!first)
+ sb.append(pickupNames.size() == 2 ? " and " : ", ");
+ first = false;
+ sb.append("'").append(pickupName).append("'");
+ }
+ sb.append(", but is wired in REVERSE!");
+ notes.add(sb.toString());
+ }
+
+ private static void outputTonePotentiometer(Map.Entry, List>> e,
+ List notes) {
+ StringBuilder sb = new StringBuilder(
+ "'" + e.getKey().getName() + "' potentiometer acts as a tone control for ");
+ boolean first = true;
+ List pickupNames =
+ e.getValue().stream().map(x -> x.getName()).sorted().collect(Collectors.toList());
+ for (String pickupName : pickupNames) {
+ if (!first)
+ sb.append(pickupNames.size() == 2 ? " and " : ", ");
+ first = false;
+ sb.append("'").append(pickupName).append("'");
+ }
+ notes.add(sb.toString());
+ }
+
+ private static void outputVolumePotReversed(Map.Entry, List>> e,
+ List notes) {
+ StringBuilder sb = new StringBuilder(
+ "'" + e.getKey().getName() + "' potentiometer acts as a volume control for ");
+ boolean first = true;
+ List pickupNames =
+ e.getValue().stream().map(x -> x.getName()).sorted().collect(Collectors.toList());
+ for (String pickupName : pickupNames) {
+ if (!first)
+ sb.append(pickupNames.size() == 2 ? " and " : ", ");
+ first = false;
+ sb.append("'").append(pickupName).append("'");
+ }
+ sb.append(", but is wired in REVERSE!");
+ notes.add(sb.toString());
+ }
+
+ private static void outputVolumePotentiometer(Map.Entry, List>> e,
+ List notes, Map, Set>> volPotTrebleBleedMap) {
+ StringBuilder sb = new StringBuilder(
+ "'" + e.getKey().getName() + "' potentiometer acts as a volume control for ");
+ boolean first = true;
+ List pickupNames =
+ e.getValue().stream().map(x -> x.getName()).sorted().collect(Collectors.toList());
+ for (String pickupName : pickupNames) {
+ if (!first)
+ sb.append(pickupNames.size() == 2 ? " and " : ", ");
+ first = false;
+ sb.append("'").append(pickupName).append("'");
+ }
+ notes.add(sb.toString());
+
+ Set> trebleBleedComponents = volPotTrebleBleedMap.get(e.getKey());
+ if (trebleBleedComponents != null && trebleBleedComponents.size() > 0) {
+
+ String trebleBleadNote = trebleBleedComponents.stream()
+ .sorted(Comparator.comparing(c -> c.getName()))
+ .map(c -> "'" + c.getName() + "'")
+ .collect(Collectors.joining(", ")) + " form a treble bleed network on the '" + e.getKey().getName() + "' volume control";
+ notes.add(trebleBleadNote);
+ }
+ }
+
+ private void processPotentiometer(IDIYComponent> pot, Tree tree, Map, Tree> pickupRoots,
+ Map, List>> tonePotPickupReverseMap,
+ Map, List>> tonePotPickupMap,
+ Map, Set>> volPotTrebleBleedMap,
+ Map, List>> volPotPickupMap,
+ Map, List>> volPotPickupReverseMap) {
+ TreeLeaf leaf1 = new TreeLeaf(pot, 0, 1);
+ TreeLeaf leaf2 = new TreeLeaf(pot, 1, 2);
+ Tree tree1 = tree.locate(leaf1, false);
+ Tree tree2 = tree.locate(leaf2, false);
+
+ if ((tree1 == null && tree2 != null) || (tree1 != null && tree2 == null)) {
+ boolean tonePotReversed = tree1 != null;
+ Tree t = tree1 == null ? tree2 : tree1;
+ Tree p = tree.findParent(t);
+ if (p != null && p.getChildren().size() == 2) {
+ Set> caps = p.extractComponents(CAP_TYPES);
+ if (caps != null && caps.size() == 1) {
+ for (Map.Entry, Tree> r : pickupRoots.entrySet()) {
+ Tree toneParent = tree.findCommonParent(p, r.getValue());
+ if (toneParent != null
+ && toneParent.getConnectionType() == TreeConnectionType.Parallel) {
+ if (tonePotReversed) {
+ List> pickupList = tonePotPickupReverseMap.get(pot);
+ if (pickupList == null) {
+ pickupList = new ArrayList>();
+ tonePotPickupReverseMap.put(pot, pickupList);
+ }
+ pickupList.add(r.getKey());
+ } else {
+ List> pickupList = tonePotPickupMap.get(pot);
+ if (pickupList == null) {
+ pickupList = new ArrayList>();
+ tonePotPickupMap.put(pot, pickupList);
+ }
+ pickupList.add(r.getKey());
+ }
+ }
+ }
}
- sb.append(", but is wired in REVERSE!");
- notes.add(sb.toString());
}
}
- StringBuilder sb = new StringBuilder();
-
- String asciiTree = tree.toAsciiString();
+ // volume
+ if (tree1 == null || tree2 == null)
+ return;
+ for (Map.Entry, Tree> r : pickupRoots.entrySet()) {
+ Tree commonParent1 = tree.findCommonParent(tree1, r.getValue());
+ Tree commonParent2 = tree.findCommonParent(tree2, r.getValue());
+ locateTrebleBleed(tree, volPotTrebleBleedMap, pot, tree1);
- sb.append("
")
- .append("")
- .append(asciiTree)
- .append("");
- if (!notes.isEmpty()) {
- Collections.sort(notes);
- sb.append("
");
- for (String v : notes) {
- sb.append(v).append("
");
+ if (commonParent1 != null && commonParent2 != null
+ && commonParent1.getConnectionType() == TreeConnectionType.Series
+ && commonParent2.getConnectionType() == TreeConnectionType.Parallel) {
+ List> pickupList = volPotPickupMap.get(pot);
+ if (pickupList == null) {
+ pickupList = new ArrayList>();
+ volPotPickupMap.put(pot, pickupList);
+ }
+ pickupList.add(r.getKey());
+ } else if (commonParent1 != null && commonParent2 != null
+ && commonParent1.getConnectionType() == TreeConnectionType.Parallel
+ && commonParent2.getConnectionType() == TreeConnectionType.Series) {
+ List> pickupList = volPotPickupReverseMap.get(pot);
+ if (pickupList == null) {
+ pickupList = new ArrayList>();
+ volPotPickupReverseMap.put(pot, pickupList);
+ }
+ pickupList.add(r.getKey());
}
}
-
- return new Summary(netlist, sb.toString());
}
private void locateTrebleBleed(Tree tree,
diff --git a/diylc/diylc-library/src/main/java/org/diylc/netlist/MultimeterAnalyzer.java b/diylc/diylc-library/src/main/java/org/diylc/netlist/MultimeterAnalyzer.java
index 445c2ab8..abf9ac62 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/netlist/MultimeterAnalyzer.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/netlist/MultimeterAnalyzer.java
@@ -51,7 +51,7 @@ public class MultimeterAnalyzer extends AbstractNetlistAnalyzer implements INetl
return EnumSet.allOf(NetlistSwitchPreference.class);
}
- protected Summary summarize(Netlist netlist, Node preferredOutput) throws TreeException {
+ protected Summary summarize(Netlist netlist) throws TreeException {
Tree tree = constructTree(netlist);
if (tree == null) {
diff --git a/diylc/diylc-library/src/main/java/org/diylc/netlist/SpiceAnalyzer.java b/diylc/diylc-library/src/main/java/org/diylc/netlist/SpiceAnalyzer.java
index 0db6676d..eda49bde 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/netlist/SpiceAnalyzer.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/netlist/SpiceAnalyzer.java
@@ -69,7 +69,7 @@ public class SpiceAnalyzer extends AbstractNetlistAnalyzer implements INetlistAn
return EnumSet.allOf(NetlistSwitchPreference.class);
}
- protected Summary summarize(Netlist netlist, Node preferredOutput) throws TreeException {
+ protected Summary summarize(Netlist netlist) throws TreeException {
// grab all components that are in the netlist
List groups = netlist.getSortedGroups();
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/analyze/SummarizeNetlistAction.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/analyze/SummarizeNetlistAction.java
index 9454d663..3f405227 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/analyze/SummarizeNetlistAction.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/actions/analyze/SummarizeNetlistAction.java
@@ -53,7 +53,7 @@ public class SummarizeNetlistAction extends AbstractAction {
throw new Exception("The generated netlist is empty, nothing to show.");
}
- return summarizer.summarize(netlists, null);
+ return summarizer.summarize(netlists);
}
@Override
diff --git a/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/chatbot/ChatbotPane.java b/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/chatbot/ChatbotPane.java
index 517c146a..e7516a73 100644
--- a/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/chatbot/ChatbotPane.java
+++ b/diylc/diylc-swing/src/main/java/org/diylc/swing/plugins/chatbot/ChatbotPane.java
@@ -17,93 +17,6 @@ public class ChatbotPane extends JPanel {
private static final long serialVersionUID = 1L;
private static final Logger LOG = Logger.getLogger(ChatbotPane.class);
-
- public static final String ASSISTANT = "assistant";
- public static final String SYSTEM = "system";
- public static final String USER = "user";
- public static final String TEMPORARY = "temporary";
-
- String[] electronicsQuestions = {
- "What is Ohm's Law, and how do voltage, current, and resistance relate to each other?",
- "Why are resistors important in circuits, and what happens if the resistor value is incorrect?",
- "What is a capacitor, and how does it behave differently from a resistor?",
- "How does an inductor work, and where might you find one in common DIY projects?",
- "What's the difference between AC (Alternating Current) and DC (Direct Current), and where is each used?",
- "How do diodes work, and why are they essential in electronics?",
- "What's the difference between series and parallel circuits, and why does it matter?",
- "How does a transistor function, and what role does it typically play in a circuit?",
- "Why is grounding important in electronic circuits, and what exactly does it do?",
- "What is impedance, and why is it important when connecting speakers or audio equipment?",
- "What exactly is an operational amplifier (op amp), and what are its common uses in audio circuits?",
- "How does a relay work, and when would you choose a relay over a transistor or MOSFET?",
- "What's the purpose of using a fuse or circuit breaker in a DIY electronics project?",
- "Why do certain electronic components need specific voltage ratings?",
- "What is electromagnetic interference (EMI), and how can you minimize it in your projects?",
- "What does polarity mean for components like electrolytic capacitors and diodes, and why is it important?",
- "How does filtering work to remove unwanted noise from audio signals or power supplies?",
- "What is signal clipping in audio circuits, and how can you prevent it?",
- "Why do some circuits require a heatsink, and how do heatsinks help protect components?",
- "What is frequency response, and why is it crucial for audio circuits like guitar pedals and amplifiers?",
- "How do you calculate the correct resistor value for limiting current to an LED?",
- "What is the role of a voltage regulator, and how does it keep voltage stable?",
- "How can you measure and verify voltage and current safely using a multimeter?",
- "What does it mean when a circuit is described as having a 'high input impedance' or 'low output impedance,' and why does it matter?",
- "How can you determine if components in your circuit are properly rated for the voltage and current they're experiencing?"
- };
-
- String[] diylcQuestions = {
- "How do I add a component to my layout in DIYLC?",
- "How can I quickly find a specific component in DIYLC?s component toolbox?",
- "How do I move or reposition components on the canvas in DIYLC?",
- "How do I edit or change a component?s properties (e.g. value or color) in DIYLC?",
- "Is there a shortcut to duplicate or repeat the last component I placed in DIYLC?",
- "How can I group multiple components so I can move or edit them together in DIYLC?",
- "What are ?building blocks? in DIYLC and how do I create or use them?",
- "How do I save my DIYLC project and reopen it later on?",
- "How do I export my DIYLC layout as an image or PDF file?",
- "Can DIYLC generate a bill of materials (BOM) for my project, and how would I do that?",
- "How can I change or hide different layers in a DIYLC project to manage overlapping components?",
- "Is it possible to view the underside of a board in DIYLC, and how can I enable that?",
- "What does the ?Highlight Connected Areas? feature do in DIYLC and how do I use it for debugging?",
- "How can I analyze a guitar wiring diagram using DIYLC?s built-in tools?",
- "How do I assign a custom keyboard shortcut to a component in DIYLC for quick access?",
- "What are component variants in DIYLC and how can I create and apply them?",
- "What is the continuous creation mode in DIYLC and how does it help when adding many components?",
- "How can I create a custom component to add to DIYLC?s component library?",
- "Does DIYLC support plug-ins, and how can I add new functionality to the app with them?",
- "What is the DIYLC cloud feature and how can I share or download projects using it?"
- };
-
- String[] circuitQuestions = {
- "What's the purpose of this specific resistor in my circuit?",
- "How do I correctly determine capacitor values for my power supply?",
- "How should I route wiring to reduce interference and noise?",
- "Which component should I choose for this switching application, a MOSFET or BJT?",
- "How do I verify if my ground connections are optimal?",
- "Why might this transistor get hot during operation?",
- "What's the best approach to simplify this section of my circuit?",
- "How can I ensure my circuit is safe against short circuits?",
- "What could be causing voltage instability in this circuit?",
- "How do I properly size resistors to protect LEDs?",
- "What are the steps to debug unexpected oscillations in my circuit?",
- "Should I add a bypass capacitor here, and what value should I use?",
- "How can I check if my components are operating within their rated specifications?",
- "Is this the right way to connect multiple power rails in my design?",
- "How can I test my circuit before physically assembling it?",
- "What are good layout practices to minimize electromagnetic interference?",
- "How do I identify if my circuit has any redundant or unnecessary components?",
- "Why might the voltage regulator not output the expected voltage?",
- "What's the recommended method for isolating digital and analog grounds?",
- "How do I safely integrate high-voltage components into my DIY circuit?",
- "Why isn't my LED lighting up when powered?",
- "How do I troubleshoot a circuit that's drawing more current than expected?",
- "Why does my amplifier circuit produce a humming or buzzing sound?",
- "How can I detect and fix intermittent connections in my circuit?",
- "What should I check if my circuit isn't responding to input signals as expected?",
- "How do I determine if my soldering joints are causing reliability issues?",
- "What steps can I take if my microcontroller circuit isn't functioning as intended?",
- "How do I troubleshoot a noisy or unstable sensor reading?"
- };
public static Font DEFAULT_FONT = new Font("Square721 BT", Font.PLAIN, 12);
private static final Font MONOSPACED_FONT = new Font("Monospaced", Font.PLAIN, 12);
@@ -113,10 +26,9 @@ public class ChatbotPane extends JPanel {
private ISwingUI swingUI;
private IPlugInPort plugInPort;
+ private ChatbotPresenter chatbotPresenter;
- private JLabel titleLabel;
private JTextArea promptArea;
- private JScrollPane chatScrollPane;
private JEditorPane chatEditorPane;
private JButton askButton;
private JButton clearButton;
@@ -125,6 +37,7 @@ public class ChatbotPane extends JPanel {
super();
this.swingUI = swingUI;
this.plugInPort = plugInPort;
+ this.chatbotPresenter = new ChatbotPresenter(plugInPort);
setName("AI Assistant");
// Set panel background color
@@ -148,17 +61,6 @@ public class ChatbotPane extends JPanel {
gbc.gridwidth = 2; // Span both columns
add(chatScrollPane, gbc);
- // Prompt label
- JLabel promptLabel = new JLabel("Prompt:");
- promptLabel.setForeground(TERMINAL_FG);
- promptLabel.setFont(DEFAULT_FONT);
- gbc.gridx = 0;
- gbc.gridy = 2;
- gbc.weightx = 0.0;
- gbc.weighty = 0.0;
- gbc.gridwidth = 1;
-// add(promptLabel, gbc);
-
// Prompt scroll pane
JScrollPane promptScrollPane = new JScrollPane(getPromptArea(),
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
@@ -310,7 +212,7 @@ public class ChatbotPane extends JPanel {
TERMINAL_FG.getRed(), TERMINAL_FG.getGreen(), TERMINAL_FG.getBlue(),
TERMINAL_BG.getRed(), TERMINAL_BG.getGreen(), TERMINAL_BG.getBlue());
- String sampleChat = getInitialChatContents();
+ String sampleChat = chatbotPresenter.getInitialChatContents();
chatEditorPane.setContentType("text/html");
chatEditorPane.setText(htmlStyle + "" + sampleChat + "
");
@@ -318,29 +220,6 @@ public class ChatbotPane extends JPanel {
return chatEditorPane;
}
- private String getInitialChatContents() {
- Random r = new Random();
-
- String chatHtml =
- "Welcome to the DIYLC AI Assistant!
\n" +
- "I'm here to help you design, build, and troubleshoot your electronics projects using DIY Layout Creator (DIYLC). You can ask me questions about:
\n" +
-// "\n" +
- "\n" +
- "- Electronics theory or concepts: e.g., '" + electronicsQuestions[r.nextInt(
- electronicsQuestions.length)] + "'
\n" +
- "- DIYLC features and usage: e.g., '" + diylcQuestions[r.nextInt(diylcQuestions.length)] + "'
\n" +
- "- Your current circuit project: e.g., '" + circuitQuestions[r.nextInt(circuitQuestions.length)] + "'
\n" +
-// "
\n" +
- "
\n" +
- "Feel free to ask your own question or use one of these examples to get started!
\n";
-
- if (!CloudPresenter.Instance.isLoggedIn()) {
- chatHtml = chatHtml + "Please log into your DIYLC Cloud account in order to use the AI Assistant.
\n";
- }
-
- return chatHtml;
- }
-
public JButton getAskButton() {
if (askButton == null) {
askButton = new JButton("Ask");
@@ -350,11 +229,10 @@ public class ChatbotPane extends JPanel {
askButton.setBorderPainted(true);
askButton.addActionListener(e -> {
final String prompt = getPromptArea().getText();
- appendSection(USER, prompt);
- appendSection(TEMPORARY, "Waiting for the response...");
+ appendSection(ChatbotPresenter.USER, prompt);
+ appendSection(ChatbotPresenter.TEMPORARY, "Waiting for the response...");
getPromptArea().setText(null);
- String currentFile = plugInPort.getCurrentFileName();
- String fileName = extractFileName(currentFile);
+
getAskButton().setEnabled(false);
getClearButton().setEnabled(false);
@@ -362,19 +240,19 @@ public class ChatbotPane extends JPanel {
@Override
public String doInBackground() throws Exception {
- return ChatbotPresenter.Instance.promptChatbot(fileName, "", prompt);
+ return chatbotPresenter.promptChatbot(prompt);
}
@Override
public void failed(Exception e) {
- appendSection(SYSTEM, "Failed to retrieve the response from the server. Error: " + e.getMessage());
+ appendSection(ChatbotPresenter.SYSTEM, "Failed to retrieve the response from the server. Error: " + e.getMessage());
LOG.error("Failed to retrieve the response from the server", e);
getClearButton().setEnabled(true);
}
@Override
public void complete(String result) {
- appendSection(ASSISTANT, result);
+ appendSection(ChatbotPresenter.ASSISTANT, result);
getClearButton().setEnabled(true);
}
}, false);
@@ -396,24 +274,6 @@ public class ChatbotPane extends JPanel {
getChatEditorPane().setText(text);
}
- /**
- * Extracts the base file name without extension from a full path.
- * For example: "/path/to/myfile.diy" returns "myfile"
- */
- private String extractFileName(String path) {
- if (path == null || path.isEmpty()) {
- return "Untitled";
- }
- // Get the last part after the last separator
- String fileName = path.substring(path.lastIndexOf(File.separator) + 1);
- // Remove the extension if present
- int dotIndex = fileName.lastIndexOf('.');
- if (dotIndex > 0) {
- fileName = fileName.substring(0, dotIndex);
- }
- return fileName;
- }
-
public JButton getClearButton() {
if (clearButton == null) {
clearButton = new JButton("Clear");