Re-modeled factory variants of Resistor component type as datasheet in order to make them available to the AI; this will produce more accurate AI-driven edits

This commit is contained in:
Bane Stojkovic
2026-10-31 20:21:04 +01:00
parent 5d92812d3e
commit 15277452f4
12 changed files with 690 additions and 1512 deletions
+7 -1
View File
@@ -12229,6 +12229,7 @@
"description" : "Axial electrolytic capacitor, similar to Sprague Atom, F&T, etc",
"creationMethod" : "POINT_BY_POINT",
"notes" : [ "The two control points are the holes the leads go into and the body is centred between them; 'Length' is the body length, not the hole spacing", "It has no standing mode: keep the control points at least 'Length' apart, or the body is drawn past the holes" ],
"datasheetModels" : [ "F&T Typ A", "Illinois TTA", "JJ ANH", "Sprague TVA Atom" ],
"properties" : [ {
"name" : "Alpha",
"type" : "Percentage",
@@ -12343,6 +12344,7 @@
"description" : "Vertically mounted electrolytic capacitor, polarized or bipolar",
"creationMethod" : "POINT_BY_POINT",
"notes" : [ "The two control points are the holes; the body's own leads are 'Lead Spacing' apart and centred between them, with lead wire drawn out to each hole. Place the points exactly 'Lead Spacing' apart for straight leads", "'Diameter' is the can as seen from above; 'Height' is drawn only when 'Folded' lays the can on its side" ],
"datasheetModels" : [ "Elna Silmic II", "Nichicon FG", "Nichicon FW", "Nichicon KZ", "Panasonic FC", "Panasonic FM", "Panasonic NHG" ],
"properties" : [ {
"name" : "Alpha",
"type" : "Percentage",
@@ -12467,6 +12469,7 @@
"description" : "Axial film capacitor, similar to Mallory 150s",
"creationMethod" : "POINT_BY_POINT",
"notes" : [ "The two control points are the holes the leads go into and the body is centred between them; 'Length' is the body length, not the hole spacing", "If the control points are closer together than 'Length' (0.5in by default) the part is drawn standing, its body over the first point, or over the second with 'Reverse (standing)'; to keep it lying on a tighter footprint, reduce 'Length'" ],
"datasheetModels" : [ "Mallory 150", "Solen Fast" ],
"properties" : [ {
"name" : "Alpha",
"type" : "Percentage",
@@ -12563,6 +12566,7 @@
"description" : "Radial film capacitor, similar to Sprague Orange Drop",
"creationMethod" : "POINT_BY_POINT",
"notes" : [ "The two control points are the holes; the body's own leads are 'Lead Spacing' apart and centred between them, with lead wire drawn out to each hole. Place the points exactly 'Lead Spacing' apart for straight leads", "'Length' and 'Width' are the body as seen from above: 'Length' runs along the line between the leads and 'Width' across it, i.e. the datasheet width and thickness; body height is not drawn" ],
"datasheetModels" : [ "Epcos MKT (5mm)", "Epcos MKT (7.5mm)", "Epcos MKT (10mm)", "Orange Drop 225P", "Orange Drop 715P", "Orange Drop 716P", "WIMA FKP-02 (2.5mm)", "WIMA FKP-2 (5mm)", "WIMA FKS-2 (5mm)", "WIMA MKP-2 (5mm)", "WIMA MKP-4", "WIMA MKS-02 (2.5mm)", "WIMA MKS-2 (5mm)", "WIMA MKS-4" ],
"properties" : [ {
"name" : "Alpha",
"type" : "Percentage",
@@ -12965,6 +12969,7 @@
"description" : "Standard radial mica capacitor",
"creationMethod" : "POINT_BY_POINT",
"notes" : [ "The two control points are the holes; the body's own leads are 'Lead Spacing' apart and centred between them, with lead wire drawn out to each hole. Place the points exactly 'Lead Spacing' apart for straight leads" ],
"datasheetModels" : [ "Cornell Dubilier CD10 (3.6mm)", "Cornell Dubilier CD15 (5.9mm)", "Cornell Dubilier CD19 (8.7mm)", "Cornell Dubilier CDV19 (8.7mm)", "Cornell Dubilier CD30 (11.1mm)", "Cornell Dubilier CDV30 (11.1mm)", "Cornell Dubilier CD42 (27mm)" ],
"properties" : [ {
"name" : "Alpha",
"type" : "Percentage",
@@ -13496,7 +13501,8 @@
"namePrefix" : "R",
"description" : "Resistor layout symbol",
"creationMethod" : "POINT_BY_POINT",
"notes" : [ "The two control points are the holes the leads go into and the body is centred between them; 'Length' is the body length, not the hole spacing", "If the control points are closer together than 'Length' (0.5in by default) the part is drawn standing, its body over the first point; to keep it lying on a tighter footprint, reduce 'Length'" ],
"notes" : [ "The two control points are the holes the leads go into and the body is centred between them; 'Length' is the body length, not the hole spacing", "If the control points are closer together than 'Length' (0.5in by default) the part is drawn standing, its body over the first point; to keep it lying on a tighter footprint, reduce 'Length'", "A datasheet model sets the body size, shape and colors of a resistor family at one power rating but never the resistance; set 'Power Rating' together with the model to pick the matching size" ],
"datasheetModels" : [ "Carbon Comp", "Carbon Film", "Metal Film", "Metal Oxide", "Ceramic", "Dale CMF55", "Dale CMF60" ],
"properties" : [ {
"name" : "Alpha",
"type" : "Percentage",
@@ -25,6 +25,7 @@ import java.awt.geom.Point2D;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class Template {
@@ -35,6 +36,8 @@ public class Template {
@Deprecated
private boolean defaultFlag;
private LocalDateTime createdOn;
// set only on a factory variant that has been withdrawn, which then carries nothing but its name
private LocalDateTime deletedOn;
public Template() {
}
@@ -82,11 +85,20 @@ public class Template {
this.createdOn = createdOn;
}
public LocalDateTime getDeletedOn() {
return deletedOn;
}
public void setDeletedOn(LocalDateTime deletedOn) {
this.deletedOn = deletedOn;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((createdOn == null) ? 0 : createdOn.hashCode());
result = prime * result + ((deletedOn == null) ? 0 : deletedOn.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((points == null) ? 0 : points.hashCode());
result = prime * result + ((values == null) ? 0 : values.hashCode());
@@ -107,6 +119,9 @@ public class Template {
return false;
} else if (!createdOn.equals(other.createdOn))
return false;
if (!Objects.equals(deletedOn, other.deletedOn)) {
return false;
}
if (name == null) {
if (other.name != null)
return false;
@@ -175,6 +175,16 @@ public class ComponentCatalogGenerator {
comp.put("notes", notes);
}
// a datasheet lists one row per part, so the model names are its distinct first column
List<String[]> datasheet = ct.getDatasheet();
if (datasheet != null) {
List<String> models = datasheet.stream()
.map(row -> row[0].trim())
.distinct()
.collect(Collectors.toList());
comp.put("datasheetModels", models);
}
// Extract editable properties
try {
List<PropertyWrapper> properties = processor.extractProperties(ct.getInstanceClass());
@@ -65,6 +65,7 @@ public class VariantManager {
.readObject(IPlugInPort.DEFAULT_TEMPLATES_IMPORT_DATE_KEY, LocalDateTime.MIN);
int importCount = 0;
int deleteCount = 0;
try {
InputStream inputStream = Presenter.class.getResourceAsStream("/" + VARIANTS_FILE_NAME);
@@ -89,7 +90,20 @@ public class VariantManager {
.collect(Collectors.toSet());
for (Template variant : entry.getValue()) {
if ((variant.getCreatedOn() == null || importDate.compareTo(variant.getCreatedOn()) < 0)
// a deletion stub keeps nothing but its name, so a missing createdOn only means an old
// entry when the variant has not been deleted
boolean created = variant.getCreatedOn() == null ? variant.getDeletedOn() == null
: importDate.compareTo(variant.getCreatedOn()) < 0;
boolean deleted =
variant.getDeletedOn() != null && importDate.compareTo(variant.getDeletedOn()) < 0;
// a variant created and deleted since the last import never reached the user, and a
// deletion older than the last import was applied then, so a variant the user has since
// created under the same name stays
if (deleted && !created) {
if (existingVariants.removeIf(x -> variant.getName().equals(x.getName()))) {
deleteCount++;
}
} else if (created && variant.getDeletedOn() == null
&& !existingNames.contains(variant.getName())) {
existingVariants.add(variant);
importCount++;
@@ -104,6 +118,9 @@ public class VariantManager {
if (importCount > 0) {
LOG.info(String.format("Imported default %d variants", importCount));
}
if (deleteCount > 0) {
LOG.info(String.format("Deleted %d withdrawn default variants", deleteCount));
}
} catch (Exception e) {
LOG.error("Could not load default variants", e);
}
File diff suppressed because it is too large Load Diff
+16 -248
View File
@@ -1,253 +1,5 @@
<java.util.Arrays_-ArrayList>
<a class="org.diylc.appframework.update.Version-array">
<org.diylc.appframework.update.Version>
<versionNumber>
<major>5</major>
<minor>10</minor>
<build>0</build>
</versionNumber>
<releaseDate>2026-01-20 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added 'M' and 'N' potentiometer taper options (thank you mm-rnd)</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added E-C-B BJT pinout to TO-92 transistor package</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Fixed the performance issue that happens when groups of components are copy-pasted and the project size grows uncontrollably</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>All building blocks of the same type get added to the same group</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>'Tactile Micro Switch' editor doesn't show up on double click</description>
</org.diylc.appframework.update.Change>
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
<org.diylc.appframework.update.Version>
<versionNumber>
<major>5</major>
<minor>11</minor>
<build>0</build>
</versionNumber>
<releaseDate>2026-02-15 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added ability to export chat history from 'AI Assistant' to a HTML file</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Upgraded AI models for AI-powered tools and improved overall quality of the responses</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Windows installer prompts for installation folder instead of forcing one</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Shape components shouldn't appear in the BOM</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Improved rendering of 'Switch (Latching)' symbol to clearly make visual contact between the terminals</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Consolidate a few keyboard shortcuts for consistency</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Using "Duplicate Selection" results in duplicates of component ids, breaking Project Explorer panel and causing other issues downstream</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Calculated length disappeared from Hookup Wire and similar curved components</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Resize dimensions do not show for 'Chassis Panel' component when dragging a corner point</description>
</org.diylc.appframework.update.Change>
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
<org.diylc.appframework.update.Version>
<versionNumber>
<major>5</major>
<minor>12</minor>
<build>0</build>
</versionNumber>
<releaseDate>2026-03-26 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added 'Auto-Unit Conversion' configuration which automatically converts between metric and imperial units based on the ruler unit preference</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added a new section in the output of 'AI Circuit Analyzer' which provides insights into the operation of the circuit and individual components</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Better error handling for AI tools</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Pressing the 'Esc' key closes selection editor dialog</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Right click (or two finger tap on mac) after selecting a component with a regular click opens editor dialog in addition to the context menu</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Clicking on a component type in the left-hand component tree sometimes does not register and does not instantiate the component</description>
</org.diylc.appframework.update.Change>
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
<org.diylc.appframework.update.Version>
<versionNumber>
<major>5</major>
<minor>13</minor>
<build>0</build>
</versionNumber>
<releaseDate>2026-04-07 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added new 'Heat Sink Resistor' component with a bunch of factory variants covering the most common types</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added new 'Dial Scale' variations - 'Ticks + Numeric (0/5.5/11)' a'la Friedman and another variation of 'Ticks' with more pronounced 9/12/3 o'clock indices</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added 'Core' property to 'Radial Inductor' component that allows selection between Ferrite and Air core inductor models'</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added 'Envelope' property to tube symbol components which can be used to display one side of the outer envelope dashed indicating section A or section B of a tube</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added more ceramic resistor variants to 'Resistor' component</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Uniformized rendering of components while being dragged</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Ability to blank-out previously populated values for unit-type measures, e.g. resistance, capacitance, dimensions, etc</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Improved data model for storing transparency alpha and other properties that are edited using a slider widget; as a result, the editing is more precise and does not randomly change to neighboring values</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Improved editing experience of integer properties (e.g. number of terminals on a tag strip) by using the spinner text field</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Improved logic when moving component(s) that have other components stuck with them; in case there are non-sticky control points within the included components, they will be moved along retaining component shape (e.g. wires or curved traces)</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Decommission 'Loadline Editor' option from the File menu</description>
</org.diylc.appframework.update.Change>
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
<org.diylc.appframework.update.Version>
<versionNumber>
<major>5</major>
<minor>14</minor>
<build>0</build>
</versionNumber>
<releaseDate>2026-06-03 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added 'Potentiometer (Miniature)' component with two variations - right-angled and vertically mounted</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added 'Thonk 3.5mm Jack' component with two variations - mono switched and stereo</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Enable all types of potentiometers and jacks for guitar diagram analysis</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Increase maximum number of switch combination for analysis to 1024</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>'Line' component set to px used to render slightly thicker than 1px, appearing thicker than schematic symbols; changed to match the thickenss of schematic symbols</description>
</org.diylc.appframework.update.Change>
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
<org.diylc.appframework.update.Version>
<versionNumber>
<major>5</major>
<minor>15</minor>
<build>0</build>
</versionNumber>
<releaseDate>2026-06-13 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Add Freeway Blade switches 3B3-01, 5B5-01, 5B5-02 (thank you Martin Morell)</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>IEC variations of fuse and potentiometer symbols</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Detect the style of a treble bleed based on the topology and component values (e.g. Fender, DiMarzio, Kinman, etc)</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Improved quality of AI Assistant responses in some cases</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Improved precision of rendering, in some cases there was a sub-pixel misalignment between the lines that should meet exactly</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Tone capacitor mistaken for treble bleed when connected to the input lug of the volume pot</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Dragging a component from the component tree to the canvas sometimes does not work as expected without clicking on it first and then dragging it</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>'Schaller Megaswitch' not rendered correctly when rotated for 90 or 270 degrees</description>
</org.diylc.appframework.update.Change>
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
<org.diylc.appframework.update.Version>
<versionNumber>
<major>6</major>
@@ -744,5 +496,21 @@
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
<org.diylc.appframework.update.Version>
<versionNumber>
<major>6</major>
<minor>10</minor>
<build>0</build>
</versionNumber>
<releaseDate>2026-10-30 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Re-modeled factory variants of Resistor component type as datasheet in order to make them available to the AI; this will produce more accurate AI-driven edits</description>
</org.diylc.appframework.update.Change>
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
</a>
</java.util.Arrays_-ArrayList>
@@ -5325,5 +5325,253 @@
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
<org.diylc.appframework.update.Version>
<versionNumber>
<major>5</major>
<minor>10</minor>
<build>0</build>
</versionNumber>
<releaseDate>2026-01-20 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added 'M' and 'N' potentiometer taper options (thank you mm-rnd)</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added E-C-B BJT pinout to TO-92 transistor package</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Fixed the performance issue that happens when groups of components are copy-pasted and the project size grows uncontrollably</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>All building blocks of the same type get added to the same group</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>'Tactile Micro Switch' editor doesn't show up on double click</description>
</org.diylc.appframework.update.Change>
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
<org.diylc.appframework.update.Version>
<versionNumber>
<major>5</major>
<minor>11</minor>
<build>0</build>
</versionNumber>
<releaseDate>2026-02-15 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added ability to export chat history from 'AI Assistant' to a HTML file</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Upgraded AI models for AI-powered tools and improved overall quality of the responses</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Windows installer prompts for installation folder instead of forcing one</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Shape components shouldn't appear in the BOM</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Improved rendering of 'Switch (Latching)' symbol to clearly make visual contact between the terminals</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Consolidate a few keyboard shortcuts for consistency</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Using "Duplicate Selection" results in duplicates of component ids, breaking Project Explorer panel and causing other issues downstream</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Calculated length disappeared from Hookup Wire and similar curved components</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Resize dimensions do not show for 'Chassis Panel' component when dragging a corner point</description>
</org.diylc.appframework.update.Change>
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
<org.diylc.appframework.update.Version>
<versionNumber>
<major>5</major>
<minor>12</minor>
<build>0</build>
</versionNumber>
<releaseDate>2026-03-26 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added 'Auto-Unit Conversion' configuration which automatically converts between metric and imperial units based on the ruler unit preference</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added a new section in the output of 'AI Circuit Analyzer' which provides insights into the operation of the circuit and individual components</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Better error handling for AI tools</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Pressing the 'Esc' key closes selection editor dialog</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Right click (or two finger tap on mac) after selecting a component with a regular click opens editor dialog in addition to the context menu</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Clicking on a component type in the left-hand component tree sometimes does not register and does not instantiate the component</description>
</org.diylc.appframework.update.Change>
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
<org.diylc.appframework.update.Version>
<versionNumber>
<major>5</major>
<minor>13</minor>
<build>0</build>
</versionNumber>
<releaseDate>2026-04-07 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added new 'Heat Sink Resistor' component with a bunch of factory variants covering the most common types</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added new 'Dial Scale' variations - 'Ticks + Numeric (0/5.5/11)' a'la Friedman and another variation of 'Ticks' with more pronounced 9/12/3 o'clock indices</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added 'Core' property to 'Radial Inductor' component that allows selection between Ferrite and Air core inductor models'</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added 'Envelope' property to tube symbol components which can be used to display one side of the outer envelope dashed indicating section A or section B of a tube</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added more ceramic resistor variants to 'Resistor' component</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Uniformized rendering of components while being dragged</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Ability to blank-out previously populated values for unit-type measures, e.g. resistance, capacitance, dimensions, etc</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Improved data model for storing transparency alpha and other properties that are edited using a slider widget; as a result, the editing is more precise and does not randomly change to neighboring values</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Improved editing experience of integer properties (e.g. number of terminals on a tag strip) by using the spinner text field</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Improved logic when moving component(s) that have other components stuck with them; in case there are non-sticky control points within the included components, they will be moved along retaining component shape (e.g. wires or curved traces)</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Decommission 'Loadline Editor' option from the File menu</description>
</org.diylc.appframework.update.Change>
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
<org.diylc.appframework.update.Version>
<versionNumber>
<major>5</major>
<minor>14</minor>
<build>0</build>
</versionNumber>
<releaseDate>2026-06-03 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added 'Potentiometer (Miniature)' component with two variations - right-angled and vertically mounted</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added 'Thonk 3.5mm Jack' component with two variations - mono switched and stereo</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Enable all types of potentiometers and jacks for guitar diagram analysis</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Increase maximum number of switch combination for analysis to 1024</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>'Line' component set to px used to render slightly thicker than 1px, appearing thicker than schematic symbols; changed to match the thickenss of schematic symbols</description>
</org.diylc.appframework.update.Change>
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
<org.diylc.appframework.update.Version>
<versionNumber>
<major>5</major>
<minor>15</minor>
<build>0</build>
</versionNumber>
<releaseDate>2026-06-13 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Add Freeway Blade switches 3B3-01, 5B5-01, 5B5-02 (thank you Martin Morell)</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>IEC variations of fuse and potentiometer symbols</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Detect the style of a treble bleed based on the topology and component values (e.g. Fender, DiMarzio, Kinman, etc)</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Improved quality of AI Assistant responses in some cases</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Improved precision of rendering, in some cases there was a sub-pixel misalignment between the lines that should meet exactly</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Tone capacitor mistaken for treble bleed when connected to the input lug of the volume pot</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>Dragging a component from the component tree to the canvas sometimes does not work as expected without clicking on it first and then dragging it</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType>
<description>'Schaller Megaswitch' not rendered correctly when rotated for 90 or 270 degrees</description>
</org.diylc.appframework.update.Change>
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
</a>
</java.util.Arrays_-ArrayList>
@@ -37,6 +37,7 @@ import org.diylc.components.AbstractLeadedComponent;
import org.diylc.components.transform.SimpleComponentTransformer;
import org.diylc.core.CreationMethod;
import org.diylc.core.IDIYComponent;
import org.diylc.core.IDatasheetSupport;
import org.diylc.core.annotations.AiNote;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
@@ -48,10 +49,13 @@ import org.diylc.core.measures.SizeUnit;
@AiNote("The two control points are the holes the leads go into and the body is centred between them; 'Length' is the body length, not the hole spacing")
@AiNote("If the control points are closer together than 'Length' (0.5in by default) the part is drawn standing, its body over the first point; to keep it lying on a tighter footprint, reduce 'Length'")
@AiNote("A datasheet model sets the body size, shape and colors of a resistor family at one power rating but never the resistance; set 'Power Rating' together with the model to pick the matching size")
@ComponentDescriptor(name = "Resistor", author = "Branislav Stojkovic", category = "Passive",
creationMethod = CreationMethod.POINT_BY_POINT, instanceNamePrefix = "R", description = "Resistor layout symbol",
zOrder = IDIYComponent.COMPONENT, transformer = SimpleComponentTransformer.class, enableCache = true)
public class Resistor extends AbstractLeadedComponent<Resistance> implements IGerberComponentSimple {
zOrder = IDIYComponent.COMPONENT, transformer = SimpleComponentTransformer.class, enableCache = true,
enableDatasheet = true, datasheetCreationStepCount = 2)
public class Resistor extends AbstractLeadedComponent<Resistance>
implements IGerberComponentSimple, IDatasheetSupport {
private static final long serialVersionUID = 1L;
@@ -75,6 +79,41 @@ public class Resistor extends AbstractLeadedComponent<Resistance> implements IGe
this.borderColor = BORDER_COLOR;
}
public Resistor(String[] model) {
this();
applyModel(model);
}
// columns: family, power, body length, body width, shape, color code, body color, border color;
// the resistance is not part of a row because the body size depends only on family and power
@Override
public void applyModel(String[] model) {
setPowerNew(org.diylc.core.measures.Power.parseCapacitance(model[1]));
setLength(parseDatasheetSize(model[2]));
setWidth(parseDatasheetSize(model[3]));
setShape(parseDatasheetEnum(ResistorShape.values(), model[4]));
setColorCode(parseDatasheetEnum(ResistorColorCode.values(), model[5]));
setBodyColor(Color.decode(model[6]));
setBorderColor(Color.decode(model[7]));
}
// sizes are in mm unless a unit follows the number, as some families are specified in inches
private static Size parseDatasheetSize(String value) {
String[] parts = value.split(" ");
SizeUnit unit = parts.length > 1 ? SizeUnit.valueOf(parts[1]) : SizeUnit.mm;
return new Size(Double.parseDouble(parts[0]), unit);
}
private static <E extends Enum<E>> E parseDatasheetEnum(E[] values, String name) {
for (E value : values) {
if (value.toString().equalsIgnoreCase(name)) {
return value;
}
}
throw new IllegalArgumentException("Unknown datasheet value: " + name);
}
@Override
protected boolean supportsStandingMode() {
return true;
@@ -0,0 +1,22 @@
Carbon Comp,0.25 W,0.3 in,0.1 in,Tubular,5 band,#8A5E20,#735832
Carbon Comp,0.5 W,0.41 in,0.15 in,Tubular,5 band,#8A5E20,#735832
Carbon Film,0.25 W,7,2.5,Standard,5 band,#E0C68B,#A59268
Carbon Film,0.5 W,9,3.2,Standard,5 band,#E0C68B,#A59268
Metal Film,0.25 W,7,2.5,Standard,5 band,#82CFFD,#5B90B1
Metal Film,0.5 W,9,3.2,Standard,5 band,#82CFFD,#5B90B1
Metal Oxide,1 W,9,3,Standard,5 band,#D2D7DB,#B2B7BB
Metal Oxide,2 W,12,4,Standard,5 band,#D2D7DB,#B2B7BB
Metal Oxide,3 W,16,6,Standard,5 band,#D2D7DB,#B2B7BB
Ceramic,2 W,18,7,Tubular,None,#F6F5F5,#CCCCCC
Ceramic,3 W,22,8,Tubular,None,#F6F5F5,#CCCCCC
Ceramic,5 W,22,9.5,Tubular,None,#F6F5F5,#CCCCCC
Ceramic,7 W,35,9.5,Tubular,None,#F6F5F5,#CCCCCC
Ceramic,10 W,48,9.5,Tubular,None,#F6F5F5,#CCCCCC
Ceramic,15 W,48,13,Tubular,None,#F6F5F5,#CCCCCC
Ceramic,20 W,63,13,Tubular,None,#F6F5F5,#CCCCCC
Ceramic,30 W,75,19,Tubular,None,#F6F5F5,#CCCCCC
Ceramic,50 W,90,19,Tubular,None,#F6F5F5,#CCCCCC
Ceramic,80 W,109,19,Tubular,None,#F6F5F5,#CCCCCC
Ceramic,100 W,135,22,Tubular,None,#F6F5F5,#CCCCCC
Dale CMF55,0.5 W,6.22,2.29,Tubular Beveled,5 band,#D37D5B,#A04C2B
Dale CMF60,1 W,8.75,3.53,Tubular Beveled,5 band,#D37D5B,#A04C2B
@@ -0,0 +1,196 @@
/*
DIY Layout Creator (DIYLC).
Copyright (c) 2009-2025 held jointly by the individual authors.
This file is part of DIYLC.
DIYLC is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DIYLC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diylc.components;
import java.awt.geom.Point2D;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.appframework.miscutils.IConfigListener;
import org.diylc.appframework.miscutils.IConfigurationManager;
import org.diylc.common.IPlugInPort;
import org.diylc.core.Template;
import org.diylc.presenter.VariantManager;
import org.diylc.serialization.ProjectFileManager;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Checks that a factory variant marked {@code deletedOn} in {@code import-defaults/variants.xml} is
* taken out of the user's configuration only when the last import predates the deletion, and is
* never imported.
*/
public class DeletedVariantsTest {
private static final String RESISTOR = "org.diylc.components.passive.Resistor";
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
}
@SuppressWarnings("unchecked")
private static Map<String, List<Template>> loadVariants() {
InputStream in = DeletedVariantsTest.class.getClassLoader()
.getResourceAsStream("import-defaults/variants.xml");
Assert.assertNotNull("variants.xml is not on the classpath", in);
return (Map<String, List<Template>>) ProjectFileManager.xStreamSerializer.fromXML(in);
}
private static Template deletedResistor() {
return loadVariants().get(RESISTOR).stream().filter(t -> t.getDeletedOn() != null)
.findFirst().get();
}
private static InMemoryConfigurationManager configWith(List<Template> userResistors,
LocalDateTime importDate) {
Map<String, List<Template>> variantMap = new HashMap<String, List<Template>>();
variantMap.put(RESISTOR, userResistors);
InMemoryConfigurationManager config = new InMemoryConfigurationManager();
config.writeValue(IPlugInPort.TEMPLATES_KEY, variantMap);
config.writeValue(IPlugInPort.DEFAULT_TEMPLATES_IMPORT_DATE_KEY, importDate);
return config;
}
@SuppressWarnings("unchecked")
private static List<Template> importInto(InMemoryConfigurationManager config) {
new VariantManager(config, null).importDefaultVariants();
return ((Map<String, List<Template>>) config.readObject(IPlugInPort.TEMPLATES_KEY, null))
.get(RESISTOR);
}
private static Template userVariant(String name) {
List<Point2D> points = new ArrayList<Point2D>();
points.add(new Point2D.Double(0, 0));
return new Template(name, new HashMap<String, Object>(), points);
}
@Test
public void deletedVariantsCarryOnlyTheirName() {
for (Map.Entry<String, List<Template>> entry : loadVariants().entrySet()) {
for (Template variant : entry.getValue()) {
if (variant.getDeletedOn() != null) {
String where = entry.getKey() + " / " + variant.getName();
Assert.assertNotNull(where, variant.getName());
Assert.assertNull(where, variant.getValues());
Assert.assertNull(where, variant.getPoints());
}
}
}
}
@Test
public void deletedWhenTheLastImportWasEarlier() {
Template deleted = deletedResistor();
Template own = userVariant("My Resistor");
List<Template> userResistors = new ArrayList<Template>();
userResistors.add(userVariant(deleted.getName()));
userResistors.add(own);
List<Template> remaining =
importInto(configWith(userResistors, deleted.getDeletedOn().minusDays(1)));
Assert.assertEquals(1, remaining.size());
Assert.assertSame(own, remaining.get(0));
}
@Test
public void recreatedByTheUserAfterTheDeletionIsKept() {
Template deleted = deletedResistor();
List<Template> userResistors = new ArrayList<Template>();
userResistors.add(userVariant(deleted.getName()));
List<Template> remaining =
importInto(configWith(userResistors, deleted.getDeletedOn().plusDays(1)));
Assert.assertEquals(1, remaining.size());
Assert.assertEquals(deleted.getName(), remaining.get(0).getName());
}
@Test
public void neverImported() {
List<Template> remaining =
importInto(configWith(new ArrayList<Template>(), LocalDateTime.MIN));
Assert.assertTrue(remaining.stream().noneMatch(t -> t.getDeletedOn() != null));
}
private static class InMemoryConfigurationManager implements IConfigurationManager<Object> {
private final Map<String, Object> values = new HashMap<String, Object>();
@Override
public void addConfigListener(String key, IConfigListener listener) {}
@Override
public boolean readBoolean(String key, boolean defaultValue) {
return (Boolean) values.getOrDefault(key, defaultValue);
}
@Override
public String readString(String key, String defaultValue) {
return (String) values.getOrDefault(key, defaultValue);
}
@Override
public int readInt(String key, int defaultValue) {
return (Integer) values.getOrDefault(key, defaultValue);
}
@Override
public float readFloat(String key, float defaultValue) {
return (Float) values.getOrDefault(key, defaultValue);
}
@Override
public double readDouble(String key, double defaultValue) {
return (Double) values.getOrDefault(key, defaultValue);
}
@Override
public Object readObject(String key, Object defaultValue) {
return values.getOrDefault(key, defaultValue);
}
@Override
public void writeValue(String key, Object value) {
values.put(key, value);
}
@Override
public Object getSerializer() {
return null;
}
@Override
public void initialize(String appName) {}
}
}
@@ -93,6 +93,9 @@ public class FactoryVariantsTest {
for (Template variant : entry.getValue()) {
String where = type.getSimpleName() + " / " + variant.getName();
if (variant.getDeletedOn() != null) {
continue;
}
if (variant.getValues() == null || variant.getValues().isEmpty()) {
problems.add(where + ": sets nothing");
continue;
@@ -0,0 +1,88 @@
/*
DIY Layout Creator (DIYLC).
Copyright (c) 2009-2025 held jointly by the individual authors.
This file is part of DIYLC.
DIYLC is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DIYLC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diylc.components.passive;
import java.awt.Color;
import java.util.List;
import org.diylc.common.ResistorColorCode;
import org.diylc.components.passive.Resistor.ResistorShape;
import org.diylc.core.measures.Power;
import org.diylc.core.measures.PowerUnit;
import org.diylc.core.measures.Resistance;
import org.diylc.core.measures.ResistanceUnit;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
import org.diylc.presenter.DatasheetService;
import org.junit.Assert;
import org.junit.Test;
public class ResistorDatasheetTest {
@Test
public void everyRowApplies() {
List<String[]> datasheet = DatasheetService.getInstance().loadDatasheet(Resistor.class);
Assert.assertNotNull(datasheet);
Assert.assertFalse(datasheet.isEmpty());
for (String[] row : datasheet) {
Resistor resistor = new Resistor(row);
Assert.assertNotNull(String.join(",", row), resistor.getPowerNew());
Assert.assertNull("a row must not set the resistance", resistor.getValue());
}
}
@Test
public void appliesAllColumns() {
Resistor resistor = new Resistor(DatasheetService.getInstance().findSeries(Resistor.class,
"Ceramic").stream().filter(row -> row[1].equals("10 W")).findFirst().get());
Assert.assertEquals(new Power(10d, PowerUnit.W), resistor.getPowerNew());
Assert.assertEquals(new Size(48d, SizeUnit.mm), resistor.getLength());
Assert.assertEquals(new Size(9.5d, SizeUnit.mm), resistor.getWidth());
Assert.assertEquals(ResistorShape.Tubular, resistor.getShape());
Assert.assertEquals(ResistorColorCode.NONE, resistor.getColorCode());
Assert.assertEquals(Color.decode("#F6F5F5"), resistor.getBodyColor());
}
@Test
public void sizeKeepsItsUnit() {
Resistor resistor = new Resistor(new String[] {"Carbon Comp", "0.5 W", "0.41 in", "0.15 in",
"Tubular", "5 band", "#8A5E20", "#735832"});
Assert.assertEquals(new Size(0.41d, SizeUnit.in), resistor.getLength());
}
@Test
public void modelFollowsPowerRatingAndKeepsValue() {
Resistor resistor = new Resistor();
resistor.setValue(new Resistance(10d, ResistanceUnit.K));
resistor.setPowerNew(new Power(0.5d, PowerUnit.W));
DatasheetService service = DatasheetService.getInstance();
String[] model =
service.findModel(resistor, service.findSeries(Resistor.class, "carbon comp"));
Assert.assertNotNull(model);
Assert.assertEquals("0.5 W", model[1]);
resistor.applyModel(model);
Assert.assertEquals(new Resistance(10d, ResistanceUnit.K), resistor.getValue());
Assert.assertEquals(new Size(0.41d, SizeUnit.in), resistor.getLength());
}
}