diff --git a/diylc/diylc-core/src/org/diylc/netlist/Tree.java b/diylc/diylc-core/src/org/diylc/netlist/Tree.java
index 42520387..f9ee373a 100644
--- a/diylc/diylc-core/src/org/diylc/netlist/Tree.java
+++ b/diylc/diylc-core/src/org/diylc/netlist/Tree.java
@@ -22,11 +22,14 @@
package org.diylc.netlist;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
+
import org.diylc.core.IDIYComponent;
public class Tree {
@@ -157,6 +160,27 @@ public class Tree {
return sb.toString();
}
+ public String toAsciiString() {
+ return String.join("
", toAscii());
+ }
+
+ private List toAscii() {
+ if (leaf != null) {
+ return Arrays.asList(TreeAsciiUtil.generateString(TreeAsciiUtil.BOXH, 1) + " " + leaf.toHTML() + " " + TreeAsciiUtil.generateString(TreeAsciiUtil.BOXH, 1));
+ }
+
+ List children = getOrderedChildren();
+
+ List> childrenAscii =
+ children.stream().map(c -> c.toAscii()).collect(Collectors.toList());
+
+ if (TreeConnectionType.Series.equals(connectionType)) {
+ return TreeAsciiUtil.concatenateMultiLineSerial(TreeAsciiUtil.generateString(TreeAsciiUtil.BOXH, 1), childrenAscii);
+ } else {
+ return TreeAsciiUtil.concatenateMultiLineParallel(childrenAscii);
+ }
+ }
+
@Override
protected Object clone() throws CloneNotSupportedException {
if (leaf != null)
diff --git a/diylc/diylc-core/src/org/diylc/netlist/TreeAsciiUtil.java b/diylc/diylc-core/src/org/diylc/netlist/TreeAsciiUtil.java
new file mode 100644
index 00000000..878a3b1a
--- /dev/null
+++ b/diylc/diylc-core/src/org/diylc/netlist/TreeAsciiUtil.java
@@ -0,0 +1,209 @@
+package org.diylc.netlist;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class TreeAsciiUtil {
+
+ public static final String BOXVR = "├";
+ public static final String BOXUL = "┘";
+ public static final String BOXDL = "┐";
+ public static final String BOXH = "─";
+ public static final String NBSP = " ";
+ public static final String BOXDR = "┌";
+ public static final String BOXUR = "└";
+ public static final String BOXVH = "┼";
+ public static final String BOXVL = "┤";
+ public static final String BOXV = "│";
+
+ public static List concatenateMultiLineParallel(List> elementLines) {
+
+ List lineCounts = elementLines.stream()
+ .map(lines -> lines.size())
+ .collect(Collectors.toList());
+ List lineLengths = elementLines.stream()
+ .map(element -> element.stream()
+ .map(TreeAsciiUtil::htmlLength)
+ .max(Integer::compare)
+ .orElse(0))
+ .collect(Collectors.toList());
+ int maxLineLength = Collections.max(lineLengths);
+ int targetLineCount = lineCounts.stream()
+ .mapToInt(Integer::intValue)
+ .sum() + elementLines.size() - 1;
+ int centerLine = targetLineCount / 2;
+
+ List results = new ArrayList();
+ int overallLineCount = 0;
+ for (int i = 0; i < elementLines.size(); i++) {
+ List lines = elementLines.get(i);
+
+ int lineLength = lineLengths.get(i);
+
+ String leftBuffer = "";
+ String rightBuffer = "";
+ if (lineLength < maxLineLength) {
+ leftBuffer = generateString(" ", (maxLineLength - lineLength) / 2);
+ rightBuffer = generateString(" ", (maxLineLength - lineLength) - (maxLineLength - lineLength) / 2);
+ }
+
+ String leftBufferCentral = "";
+ String rightBufferCentral = "";
+ if (lineLength < maxLineLength) {
+ leftBufferCentral = generateString(BOXH, (maxLineLength - lineLength) / 2);
+ rightBufferCentral = generateString(BOXH, (maxLineLength - lineLength) - (maxLineLength - lineLength) / 2);
+ }
+
+ int elementCenterLine = lines.size() / 2;
+
+ for (int j = 0; j < lines.size(); j++) {
+ String line = lines.get(j);
+
+ StringBuilder sb = new StringBuilder();
+
+ if (overallLineCount == centerLine) {
+ sb.append(BOXH);
+ } else {
+ sb.append(NBSP);
+ }
+
+ if ((j < elementCenterLine && i == 0) || (j > elementCenterLine && i == elementLines.size() - 1)) {
+ sb.append(NBSP);
+ } else if (j == elementCenterLine && i == 0) {
+ sb.append(BOXDR);
+ } else if (i == elementLines.size() - 1 && j == elementCenterLine) {
+ sb.append(BOXUR);
+ } else if (overallLineCount == centerLine) {
+ if (j == elementCenterLine && i > 0 && i < elementLines.size() - 1) {
+ sb.append(BOXVH);
+ } else {
+ sb.append(BOXVL);
+ }
+ } else {
+ if (j == elementCenterLine && i > 0 && i < elementLines.size() - 1) {
+ sb.append(BOXVR);
+ } else {
+ sb.append(BOXV);
+ }
+ }
+
+ if (j == elementCenterLine) {
+ sb.append(leftBufferCentral);
+ } else {
+ sb.append(leftBuffer);
+ }
+ sb.append(line);
+ if (j == elementCenterLine) {
+ sb.append(rightBufferCentral);
+ } else {
+ sb.append(rightBuffer);
+ }
+
+ if ((j < elementCenterLine && i == 0) || (j > elementCenterLine && i == elementLines.size() - 1)) {
+ sb.append(NBSP);
+ } else if (j == elementCenterLine && i == 0) {
+ sb.append(BOXDL);
+ } else if (i == elementLines.size() - 1 && j == elementCenterLine) {
+ sb.append(BOXUL);
+ } else if (overallLineCount == centerLine) {
+ if (j == elementCenterLine && i > 0 && i < elementLines.size() - 1) {
+ sb.append(BOXVH);
+ } else {
+ sb.append(BOXVR);
+ }
+ } else {
+ if (j == elementCenterLine && i > 0 && i < elementLines.size() - 1) {
+ sb.append(BOXVL);
+ } else {
+ sb.append(BOXV);
+ }
+ }
+
+ if (overallLineCount == centerLine) {
+ sb.append(BOXH);
+ } else {
+ sb.append(NBSP);
+ }
+
+ results.add(sb.toString());
+ overallLineCount++;
+ }
+
+
+ if (i < elementLines.size() - 1) {
+ String leftEnding;
+ String rightEnding;
+ if (overallLineCount == centerLine) {
+ leftEnding = BOXH + BOXVL;
+ rightEnding = BOXVR + BOXH;
+ } else {
+ leftEnding = NBSP + BOXV;
+ rightEnding = BOXV + NBSP;
+ }
+ String emptyLine = leftEnding + generateString(NBSP, maxLineLength) + rightEnding;
+ results.add(emptyLine);
+ overallLineCount++;
+ }
+ }
+
+ return results;
+ }
+
+ public static List concatenateMultiLineSerial(String separator, List> elementLines) {
+ List lineCounts = elementLines.stream()
+ .map(lines -> lines.size())
+ .collect(Collectors.toList());
+ String blankSeparator = generateString(NBSP, htmlLength(separator));
+ int maxLineCount = lineCounts.stream().mapToInt(Integer::intValue).max().orElse(0);
+ int centerLine = maxLineCount / 2;
+ List lineLengths = elementLines.stream()
+ .map(element -> element.stream()
+ .map(TreeAsciiUtil::htmlLength)
+ .max(Integer::compare)
+ .orElse(0))
+ .collect(Collectors.toList());
+ List results = new ArrayList<>();
+ for (int line = 0; line < maxLineCount; line++) {
+
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < elementLines.size(); i++) {
+ int elementLineCount = lineCounts.get(i);
+ int elementCenterLine = elementLineCount / 2;
+ int elementLineLength = lineLengths.get(i);
+ if (line < centerLine - elementCenterLine
+ || line > centerLine - elementCenterLine + elementLineCount) {
+ sb.append(generateString(NBSP, elementLineLength));
+ } else {
+ int lineIndex = line + elementCenterLine - centerLine;
+ List element = elementLines.get(i);
+ String elementLine;
+ if (lineIndex < element.size()) {
+ elementLine = element.get(lineIndex);
+ } else {
+ elementLine = generateString(NBSP, elementLineLength);
+ }
+ sb.append(elementLine);
+ }
+ if (i < elementLines.size() - 1) {
+ if (line == centerLine) {
+ sb.append(separator);
+ } else {
+ sb.append(blankSeparator);
+ }
+ }
+ }
+ results.add(sb.toString());
+ }
+ return results;
+ }
+
+ public static String generateString(String seed, int n) {
+ return String.join("", Collections.nCopies(n, seed));
+ }
+
+ public static int htmlLength(String s) {
+ return s.replaceAll("\\&.*?\\;", "x").length();
+ }
+}
diff --git a/diylc/diylc-core/src/org/diylc/netlist/TreeLeaf.java b/diylc/diylc-core/src/org/diylc/netlist/TreeLeaf.java
index 737fcff7..11cfcd37 100644
--- a/diylc/diylc-core/src/org/diylc/netlist/TreeLeaf.java
+++ b/diylc/diylc-core/src/org/diylc/netlist/TreeLeaf.java
@@ -107,6 +107,6 @@ public class TreeLeaf implements ITree {
}
public String toHTML() {
- return toString().replace("<", "<").replace(">", ">");
+ return toString().replace("<", "<").replace(">", ">");
}
}
diff --git a/diylc/diylc-core/src/org/diylc/presenter/update.xml b/diylc/diylc-core/src/org/diylc/presenter/update.xml
index d97f2743..0510c9d5 100644
--- a/diylc/diylc-core/src/org/diylc/presenter/update.xml
+++ b/diylc/diylc-core/src/org/diylc/presenter/update.xml
@@ -4425,5 +4425,25 @@
https://github.com/bancika/diy-layout-creator/releases
+
+
+ 4
+ 40
+ 0
+
+ 2025-01-25 00:00:00.000 CET
+
+
+
+ NEW_FEATURE
+ Guitar wiring analyzer can now detect treble bleed circuit on volume controls
+
+
+ IMPROVEMENT
+ Better rendering of the effective circuit graph in the guitar wiring analyzer, showing series and parallel connections in a more intuitive way
+
+
+ https://github.com/bancika/diy-layout-creator/releases
+
diff --git a/diylc/diylc-core/test/org/diylc/netlist/TreeAsciiUtilTest.java b/diylc/diylc-core/test/org/diylc/netlist/TreeAsciiUtilTest.java
new file mode 100644
index 00000000..ee1df9e1
--- /dev/null
+++ b/diylc/diylc-core/test/org/diylc/netlist/TreeAsciiUtilTest.java
@@ -0,0 +1,57 @@
+package org.diylc.netlist;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+public class TreeAsciiUtilTest {
+
+ @Test
+ public void testConcatenateMultiLineSerial() {
+ List result = TreeAsciiUtil.concatenateMultiLineSerial("-",
+ Arrays.asList(Arrays.asList("xx", "yy"), Arrays.asList("xxx", "yyy", "aaa")));
+ assertNotNull(result);
+ assertEquals(3, result.size());
+ assertEquals("xx xxx", result.get(0));
+ assertEquals("yy-yyy", result.get(1));
+ assertEquals(" aaa", result.get(2));
+ }
+
+ @Test
+ public void testConcatenateMultiLineSerial_singleInput() {
+ List> elementList = Arrays.asList(Arrays.asList("xx", "yy"));
+ List result = TreeAsciiUtil.concatenateMultiLineSerial("-", elementList);
+ assertNotNull(result);
+ assertEquals(Arrays.asList("xx", "yy"), result);
+ }
+
+ @Test
+ public void testConcatenateMultiLineParallel() {
+ List result = TreeAsciiUtil.concatenateMultiLineParallel(
+ Arrays.asList(Arrays.asList("xx", "yy"), Arrays.asList("xxx", "yyy", "aaa")));
+
+ System.out.println("" + String.join("
", result) +"");
+ assertNotNull(result);
+// assertEquals(3, result.size());
+// assertEquals("xx xxx", result.get(0));
+// assertEquals("yy-yyy", result.get(1));
+// assertEquals(" aaa", result.get(2));
+ }
+
+ @Test
+ public void testConcatenateMultiLineParallel_4_lines() {
+ List result = TreeAsciiUtil.concatenateMultiLineParallel(
+ Arrays.asList(Arrays.asList("xx"), Arrays.asList("xx"), Arrays.asList("xx"), Arrays.asList("xx")));
+
+ System.out.println("" + String.join("
", result) +"");
+ assertNotNull(result);
+// assertEquals(3, result.size());
+// assertEquals("xx xxx", result.get(0));
+// assertEquals("yy-yyy", result.get(1));
+// assertEquals(" aaa", result.get(2));
+ }
+}
diff --git a/diylc/diylc-library/lib/diylc-core.jar b/diylc/diylc-library/lib/diylc-core.jar
index e2d1f91c..ed04129e 100644
Binary files a/diylc/diylc-library/lib/diylc-core.jar and b/diylc/diylc-library/lib/diylc-core.jar differ
diff --git a/diylc/diylc-library/src/org/diylc/netlist/GuitarDiagramAnalyzer.java b/diylc/diylc-library/src/org/diylc/netlist/GuitarDiagramAnalyzer.java
index dc225c06..5827f814 100644
--- a/diylc/diylc-library/src/org/diylc/netlist/GuitarDiagramAnalyzer.java
+++ b/diylc/diylc-library/src/org/diylc/netlist/GuitarDiagramAnalyzer.java
@@ -20,6 +20,7 @@ package org.diylc.netlist;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -42,6 +43,7 @@ import org.diylc.components.passive.PotentiometerPanel;
import org.diylc.components.passive.RadialCeramicDiskCapacitor;
import org.diylc.components.passive.RadialFilmCapacitor;
import org.diylc.components.passive.RadialMicaCapacitor;
+import org.diylc.components.passive.Resistor;
import org.diylc.core.IDIYComponent;
import org.diylc.netlist.Tree.ITreeWalker;
@@ -51,6 +53,9 @@ public class GuitarDiagramAnalyzer extends NetlistAnalyzer implements INetlistAn
private static Set POT_TYPES = new HashSet();
private static Set PICKUP_TYPES = new HashSet();
private static Set CAP_TYPES = new HashSet();
+ private static Set RESISTOR_TYPES = new HashSet();
+ private static Set RC_TYPES = new HashSet();
+
static {
JACK_TYPES.add(OpenJack1_4.class.getCanonicalName());
JACK_TYPES.add(ClosedJack1_4.class.getCanonicalName());
@@ -68,6 +73,11 @@ public class GuitarDiagramAnalyzer extends NetlistAnalyzer implements INetlistAn
CAP_TYPES.add(RadialMicaCapacitor.class.getCanonicalName());
CAP_TYPES.add(RadialFilmCapacitor.class.getCanonicalName());
CAP_TYPES.add(AxialFilmCapacitor.class.getCanonicalName());
+
+ RESISTOR_TYPES.add(Resistor.class.getCanonicalName());
+
+ RC_TYPES.addAll(CAP_TYPES);
+ RC_TYPES.addAll(RESISTOR_TYPES);
}
@Override
@@ -203,6 +213,8 @@ public class GuitarDiagramAnalyzer extends NetlistAnalyzer implements INetlistAn
// locate volume and tone pots
Map, List>> volPotPickupMap =
new HashMap, List>>();
+ Map, Set>> volPotTrebleBleedMap =
+ new HashMap, Set>>();
Map, List>> tonePotPickupMap =
new HashMap, List>>();
Map, List>> tonePotPickupReverseMap =
@@ -253,20 +265,22 @@ public class GuitarDiagramAnalyzer extends NetlistAnalyzer implements INetlistAn
if (tree1 == null || tree2 == null)
continue;
for (Map.Entry, Tree> r : pickupRoots.entrySet()) {
- Tree parent1 = tree.findCommonParent(tree1, r.getValue());
- Tree parent2 = tree.findCommonParent(tree2, r.getValue());
- if (parent1 != null && parent2 != null
- && parent1.getConnectionType() == TreeConnectionType.Series
- && parent2.getConnectionType() == TreeConnectionType.Parallel) {
+ 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 (parent1 != null && parent2 != null
- && parent1.getConnectionType() == TreeConnectionType.Parallel
- && parent2.getConnectionType() == TreeConnectionType.Series) {
+ } 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>();
@@ -290,6 +304,16 @@ public class GuitarDiagramAnalyzer extends NetlistAnalyzer implements INetlistAn
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);
+ }
}
for (Map.Entry, List>> e : volPotPickupReverseMap
@@ -343,19 +367,39 @@ public class GuitarDiagramAnalyzer extends NetlistAnalyzer implements INetlistAn
}
StringBuilder sb = new StringBuilder();
+
+ String asciiTree = tree.toAsciiString();
- sb.append("Parallel/Series connectivity tree:
").append(tree.toHTML(0));
+ sb.append("
")
+ .append("")
+ .append(asciiTree)
+ .append("");
if (!notes.isEmpty()) {
Collections.sort(notes);
- sb.append("
Notes:
");
+ sb.append("
");
for (String v : notes) {
- sb.append(" ").append(v).append("
");
+ sb.append(v).append("
");
}
}
return new Summary(netlist, sb.toString());
}
+ private void locateTrebleBleed(Tree tree,
+ Map, Set>> volPotTrebleBleedMap, IDIYComponent> pot,
+ Tree tree1) {
+ Tree parent1 = tree1;
+ do {
+ parent1 = tree.findParent(parent1);
+ } while (parent1 != null && parent1.getChildren().size() <= 1);
+ if (parent1 != null) {
+ Set> trebleBleedComponents = parent1.extractComponents(RC_TYPES);
+ if (trebleBleedComponents.stream().anyMatch(c -> CAP_TYPES.contains(c.getClass().getCanonicalName()))) {
+ volPotTrebleBleedMap.computeIfAbsent(pot, k -> new HashSet>()).addAll(trebleBleedComponents);
+ }
+ }
+ }
+
public Tree constructTree(Netlist netlist) throws TreeException {
List jackTipNodes = find(JACK_TYPES, "Tip", netlist);
List jackSleeveNodes = find(JACK_TYPES, "Sleeve", netlist);
diff --git a/diylc/diylc-swing/lib/diylc-core.jar b/diylc/diylc-swing/lib/diylc-core.jar
index e2d1f91c..ed04129e 100644
Binary files a/diylc/diylc-swing/lib/diylc-core.jar and b/diylc/diylc-swing/lib/diylc-core.jar differ
diff --git a/diylc/diylc-swing/library/main.jar b/diylc/diylc-swing/library/main.jar
index 590473f8..d0b20f5b 100644
Binary files a/diylc/diylc-swing/library/main.jar and b/diylc/diylc-swing/library/main.jar differ