145 lines
5.2 KiB
JavaScript
145 lines
5.2 KiB
JavaScript
import { sum, harmonicMean as harm, flatten } from './utils.js';
|
|
|
|
class Resistor {
|
|
ohmage;
|
|
constructor(ohmage) {
|
|
this.ohmage = ohmage;
|
|
}
|
|
getOhmage() {
|
|
return this.ohmage;
|
|
}
|
|
equals(other) {
|
|
return this.getOhmage() === other.getOhmage();
|
|
}
|
|
hash() {
|
|
return this.ohmage;
|
|
}
|
|
cost() {
|
|
return 1;
|
|
}
|
|
toString() {
|
|
return `${this.constructor.name}(${this.getOhmage()})`;
|
|
}
|
|
prettyString(depth = 0) {
|
|
return `${'--'.repeat(depth)}${this.toString()}`
|
|
}
|
|
parallel(other) {
|
|
return new ParallelResistor(this, other);
|
|
}
|
|
series(other) {
|
|
return new SeriesResistor(this, other);
|
|
}
|
|
getSVG() {
|
|
var svg = `<svg width="50" heigh="100"><rect x="0" y="0" width="50" height="100" fill="white" stroke="black"/>
|
|
<text x="25" y="50" dominant-baseline="middle" text-anchor="middle">${this.getOhmage()}Ω</text></svg>`
|
|
var [width, height] = [50, 100]
|
|
return [svg, width, height]
|
|
}
|
|
draw(element = document.getElementsByTagName("body")[0]) {
|
|
var [svg, width, height] = this.getSVG();
|
|
var maxHeight = height + 2*25
|
|
var maxWidth = width
|
|
var midPoint = width / 2
|
|
var thesvg = `<svg width="${maxWidth}" height="${maxHeight}" viewbox="0 0 ${maxWidth} ${maxHeight}">
|
|
<line x1="${midPoint}" x2="${midPoint}" y1="${0}" y2="${25}" stroke="black"/>
|
|
<line x1="${midPoint}" x2="${midPoint}" y1="${maxHeight - 25}" y2="${maxHeight}" stroke="black"/>
|
|
<g transform="translate(0, 25)">
|
|
${svg}
|
|
</g>
|
|
</svg>`
|
|
element.innerHTML += thesvg;
|
|
}
|
|
}
|
|
|
|
class NestedResistor extends Resistor {
|
|
children = []
|
|
|
|
constructor(l, func, instance) {
|
|
super(func(l.map(e => e.getOhmage())));
|
|
this.func = func
|
|
this.children = flatten(l, instance.constructor.name);
|
|
}
|
|
cost() {
|
|
return sum(this.children.map(e => e.cost()));
|
|
}
|
|
prettyString(depth = 0) {
|
|
var childrenStrings = this.children.map(c => c.prettyString(depth + 1)).join("\n")
|
|
return `${'--'.repeat(depth)}${this.toString()}\n${childrenStrings}`
|
|
}
|
|
parallel(other) {
|
|
return new ParallelResistor(this, other);
|
|
}
|
|
series(other) {
|
|
return new SeriesResistor(this, other);
|
|
}
|
|
}
|
|
|
|
class SeriesResistor extends NestedResistor {
|
|
constructor(...l) {
|
|
super(l, sum, "SeriesResistor");
|
|
}
|
|
getSVG() {
|
|
var svgs = this.children.map(e => e.getSVG()); // triplets [svg, width, height]
|
|
var n = svgs.length;
|
|
var maxHeight = sum(svgs.map(([svg, width, height]) => height)) + 25 * (n - 1)
|
|
var maxWidth = Math.max(...svgs.map(([svg, width, height]) => width))
|
|
var yOffset = 0; // where to start the next boundin
|
|
var centerLine = maxWidth / 2;
|
|
|
|
var innerSVGs = []
|
|
var i = 0;
|
|
svgs.forEach(([svg, width, height]) => {
|
|
var xStart = (maxWidth - width) / 2
|
|
|
|
var partialInnerSVG = `<g transform="translate(${xStart}, ${yOffset})">${svg}</g>`
|
|
if (i < n - 1)
|
|
partialInnerSVG += `<line x1="${centerLine}" x2="${centerLine}" y1="${yOffset + height}" y2="${yOffset + height + 25}" stroke="black"/>`
|
|
// finally
|
|
yOffset += 25 + height
|
|
i ++;
|
|
innerSVGs.push(partialInnerSVG)
|
|
});
|
|
var svg = innerSVGs.join("")
|
|
return [svg, maxWidth, maxHeight]
|
|
}
|
|
}
|
|
|
|
class ParallelResistor extends NestedResistor {
|
|
constructor(...l) {
|
|
super(l, harm, "ParallelResistor");
|
|
}
|
|
getSVG() {
|
|
var svgs = this.children.map(e => e.getSVG()); // triplets [svg, width, height]
|
|
var n = svgs.length;
|
|
var maxHeight = Math.max(...svgs.map(([svg, width, height]) => height)) + 2 * 25
|
|
var maxWidth = sum(svgs.map(([svg, width, height]) => width)) + 25 * (n - 1)
|
|
var bottomLineStart = svgs[0][1] / 2
|
|
var bottomLineEnd = maxWidth - svgs[n - 1][1] / 2
|
|
var xOffset = 0; // where to start the next boundin
|
|
|
|
var innerSVGs = []
|
|
svgs.forEach(([svg, width, height]) => {
|
|
var antennaX = xOffset + width / 2
|
|
var antennaLength = (maxHeight - height) / 2
|
|
var antennaOneStart = 0
|
|
var antennaOneEnd = antennaLength
|
|
var antennaTwoStart = antennaLength + height
|
|
var antennaTwoEnd = maxHeight
|
|
|
|
var partialInnerSVG = `<g transform="translate(${xOffset}, ${antennaOneEnd})">${svg}</g>
|
|
<line x1="${antennaX}" x2="${antennaX}" y1="${antennaOneStart}" y2="${antennaOneEnd}" stroke="black"/>
|
|
<line x1="${antennaX}" x2="${antennaX}" y1="${antennaTwoStart}" y2="${antennaTwoEnd}" stroke="black"/> `
|
|
// finally
|
|
xOffset += 25 + width
|
|
innerSVGs.push(partialInnerSVG)
|
|
});
|
|
var innerSVG = innerSVGs.join("")
|
|
var svg = `<line x1="${bottomLineStart}" x2="${bottomLineEnd}" y1="0" y2="0" stroke="black"/>
|
|
<line x1="${bottomLineStart}" x2="${bottomLineEnd}" y1="${maxHeight}" y2="${maxHeight}" stroke="black"/>
|
|
${innerSVG}`
|
|
return [svg, maxWidth, maxHeight]
|
|
}
|
|
}
|
|
|
|
export { Resistor, ParallelResistor, SeriesResistor }
|