chatbot enhancements

This commit is contained in:
Bane Stojkovic
2025-04-03 20:10:58 +02:00
parent aa3ae65a80
commit 1b82d8c7df
10 changed files with 425 additions and 303 deletions
@@ -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<String> notes = new ArrayList<String>();
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("<br><br>")
.append("<font face='Courier New'>")
.append(asciiTree)
.append("</font>");
if (!notes.isEmpty()) {
Collections.sort(notes);
sb.append("<br><br>");
for (String v : notes) {
sb.append(v).append("<br>");
}
}
return new Summary(netlist, sb.toString());
}
private void processTree(Tree tree, List<String> 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<IDIYComponent<?>> 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<IDIYComponent<?>> caps = p.extractComponents(CAP_TYPES);
if (caps != null && caps.size() == 1) {
for (Map.Entry<IDIYComponent<?>, Tree> r : pickupRoots.entrySet()) {
Tree toneParent = tree.findCommonParent(p, r.getValue());
if (toneParent != null
&& toneParent.getConnectionType() == TreeConnectionType.Parallel) {
if (tonePotReversed) {
List<IDIYComponent<?>> pickupList = tonePotPickupReverseMap.get(pot);
if (pickupList == null) {
pickupList = new ArrayList<IDIYComponent<?>>();
tonePotPickupReverseMap.put(pot, pickupList);
}
pickupList.add(r.getKey());
} else {
List<IDIYComponent<?>> pickupList = tonePotPickupMap.get(pot);
if (pickupList == null) {
pickupList = new ArrayList<IDIYComponent<?>>();
tonePotPickupMap.put(pot, pickupList);
}
pickupList.add(r.getKey());
}
}
}
}
}
}
// volume
if (tree1 == null || tree2 == null)
continue;
for (Map.Entry<IDIYComponent<?>, 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<IDIYComponent<?>> pickupList = volPotPickupMap.get(pot);
if (pickupList == null) {
pickupList = new ArrayList<IDIYComponent<?>>();
volPotPickupMap.put(pot, pickupList);
}
pickupList.add(r.getKey());
} else if (commonParent1 != null && commonParent2 != null
&& commonParent1.getConnectionType() == TreeConnectionType.Parallel
&& commonParent2.getConnectionType() == TreeConnectionType.Series) {
List<IDIYComponent<?>> pickupList = volPotPickupReverseMap.get(pot);
if (pickupList == null) {
pickupList = new ArrayList<IDIYComponent<?>>();
volPotPickupReverseMap.put(pot, pickupList);
}
pickupList.add(r.getKey());
}
}
processPotentiometer(pot, tree, pickupRoots, tonePotPickupReverseMap, tonePotPickupMap,
volPotTrebleBleedMap, volPotPickupMap, volPotPickupReverseMap);
}
for (Map.Entry<IDIYComponent<?>, List<IDIYComponent<?>>> e : volPotPickupMap.entrySet()) {
StringBuilder sb = new StringBuilder(
"'" + e.getKey().getName() + "' potentiometer acts as a volume control for ");
boolean first = true;
List<String> 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<IDIYComponent<?>> 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<IDIYComponent<?>, List<IDIYComponent<?>>> e : volPotPickupReverseMap
.entrySet()) {
StringBuilder sb = new StringBuilder(
"'" + e.getKey().getName() + "' potentiometer acts as a volume control for ");
boolean first = true;
List<String> 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<IDIYComponent<?>, List<IDIYComponent<?>>> e : tonePotPickupMap.entrySet()) {
StringBuilder sb = new StringBuilder(
"'" + e.getKey().getName() + "' potentiometer acts as a tone control for ");
boolean first = true;
List<String> 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<IDIYComponent<?>, List<IDIYComponent<?>>> e : tonePotPickupReverseMap
.entrySet()) {
StringBuilder sb = new StringBuilder(
"'" + e.getKey().getName() + "' potentiometer acts as a tone control for ");
boolean first = true;
List<String> 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<IDIYComponent<?>, List<IDIYComponent<?>>> e,
List<String> notes) {
StringBuilder sb = new StringBuilder(
"'" + e.getKey().getName() + "' potentiometer acts as a tone control for ");
boolean first = true;
List<String> 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<IDIYComponent<?>, List<IDIYComponent<?>>> e,
List<String> notes) {
StringBuilder sb = new StringBuilder(
"'" + e.getKey().getName() + "' potentiometer acts as a tone control for ");
boolean first = true;
List<String> 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<IDIYComponent<?>, List<IDIYComponent<?>>> e,
List<String> notes) {
StringBuilder sb = new StringBuilder(
"'" + e.getKey().getName() + "' potentiometer acts as a volume control for ");
boolean first = true;
List<String> 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<IDIYComponent<?>, List<IDIYComponent<?>>> e,
List<String> notes, Map<IDIYComponent<?>, Set<IDIYComponent<?>>> volPotTrebleBleedMap) {
StringBuilder sb = new StringBuilder(
"'" + e.getKey().getName() + "' potentiometer acts as a volume control for ");
boolean first = true;
List<String> 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<IDIYComponent<?>> 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<IDIYComponent<?>, Tree> pickupRoots,
Map<IDIYComponent<?>, List<IDIYComponent<?>>> tonePotPickupReverseMap,
Map<IDIYComponent<?>, List<IDIYComponent<?>>> tonePotPickupMap,
Map<IDIYComponent<?>, Set<IDIYComponent<?>>> volPotTrebleBleedMap,
Map<IDIYComponent<?>, List<IDIYComponent<?>>> volPotPickupMap,
Map<IDIYComponent<?>, List<IDIYComponent<?>>> 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<IDIYComponent<?>> caps = p.extractComponents(CAP_TYPES);
if (caps != null && caps.size() == 1) {
for (Map.Entry<IDIYComponent<?>, Tree> r : pickupRoots.entrySet()) {
Tree toneParent = tree.findCommonParent(p, r.getValue());
if (toneParent != null
&& toneParent.getConnectionType() == TreeConnectionType.Parallel) {
if (tonePotReversed) {
List<IDIYComponent<?>> pickupList = tonePotPickupReverseMap.get(pot);
if (pickupList == null) {
pickupList = new ArrayList<IDIYComponent<?>>();
tonePotPickupReverseMap.put(pot, pickupList);
}
pickupList.add(r.getKey());
} else {
List<IDIYComponent<?>> pickupList = tonePotPickupMap.get(pot);
if (pickupList == null) {
pickupList = new ArrayList<IDIYComponent<?>>();
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<IDIYComponent<?>, 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("<br><br>")
.append("<font face='Courier New'>")
.append(asciiTree)
.append("</font>");
if (!notes.isEmpty()) {
Collections.sort(notes);
sb.append("<br><br>");
for (String v : notes) {
sb.append(v).append("<br>");
if (commonParent1 != null && commonParent2 != null
&& commonParent1.getConnectionType() == TreeConnectionType.Series
&& commonParent2.getConnectionType() == TreeConnectionType.Parallel) {
List<IDIYComponent<?>> pickupList = volPotPickupMap.get(pot);
if (pickupList == null) {
pickupList = new ArrayList<IDIYComponent<?>>();
volPotPickupMap.put(pot, pickupList);
}
pickupList.add(r.getKey());
} else if (commonParent1 != null && commonParent2 != null
&& commonParent1.getConnectionType() == TreeConnectionType.Parallel
&& commonParent2.getConnectionType() == TreeConnectionType.Series) {
List<IDIYComponent<?>> pickupList = volPotPickupReverseMap.get(pot);
if (pickupList == null) {
pickupList = new ArrayList<IDIYComponent<?>>();
volPotPickupReverseMap.put(pot, pickupList);
}
pickupList.add(r.getKey());
}
}
return new Summary(netlist, sb.toString());
}
private void locateTrebleBleed(Tree tree,
@@ -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) {
@@ -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<Group> groups = netlist.getSortedGroups();