Compare commits
1 Commits
785d036dc6
...
2dd419dbf4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2dd419dbf4 |
@@ -178,7 +178,7 @@
|
||||
// (dryRunLevel, overfillLevel) that are shown both in the diagram
|
||||
// and next to the safety-% fields. Same formulas as
|
||||
// specificClass._validateThresholdOrdering.
|
||||
const DIAG = { topY: 40, botY: 560 };
|
||||
const DIAG = { topY: 40, botY: 380 };
|
||||
const fNum = (id) => {
|
||||
const v = parseFloat(document.getElementById(`node-input-${id}`)?.value);
|
||||
return Number.isFinite(v) ? v : null;
|
||||
@@ -188,32 +188,24 @@
|
||||
const y = DIAG.botY - (val / basinH) * (DIAG.botY - DIAG.topY);
|
||||
return Math.max(DIAG.topY - 8, Math.min(DIAG.botY + 8, y));
|
||||
};
|
||||
// Place a right-column item. yLine is the threshold's true
|
||||
// proportional position on the tank; yInput is where the label
|
||||
// and input box land (may be nudged away from yLine to avoid
|
||||
// overlap with neighbouring items). A dashed leader line is
|
||||
// shown only when the two differ by more than a pixel or two.
|
||||
const placeItem = (id, yLine, yInput) => {
|
||||
// Place a row — line, label, input, unit all share the same y.
|
||||
// The diagram is a schematic ordered list (value order is
|
||||
// preserved, but the y-positions are distributed with a
|
||||
// guaranteed minimum gap for readability), not a strictly
|
||||
// proportional rendering.
|
||||
const placeItem = (id, y) => {
|
||||
const line = document.getElementById(`ps-line-${id}`);
|
||||
const label = document.getElementById(`ps-label-${id}`);
|
||||
const unit = document.getElementById(`ps-unit-${id}`);
|
||||
const fo = document.getElementById(`ps-fo-${id}`);
|
||||
const sub = document.getElementById(`ps-sub-${id}`);
|
||||
const lead = document.getElementById(`ps-leader-${id}`);
|
||||
if (line) { line.setAttribute('y1', yLine); line.setAttribute('y2', yLine); }
|
||||
if (label) label.setAttribute('y', yInput + 4);
|
||||
if (unit) unit.setAttribute('y', yInput + 4);
|
||||
if (fo) fo.setAttribute('y', yInput - 11);
|
||||
if (sub) sub.setAttribute('y', yInput + 15);
|
||||
if (lead) {
|
||||
if (Math.abs(yLine - yInput) > 2) {
|
||||
lead.setAttribute('x1', 325); lead.setAttribute('y1', yLine);
|
||||
lead.setAttribute('x2', 420); lead.setAttribute('y2', yInput);
|
||||
lead.setAttribute('visibility', 'visible');
|
||||
} else {
|
||||
lead.setAttribute('visibility', 'hidden');
|
||||
}
|
||||
}
|
||||
if (line) { line.setAttribute('y1', y); line.setAttribute('y2', y); }
|
||||
if (label) label.setAttribute('y', y + 4);
|
||||
if (unit) unit.setAttribute('y', y + 4);
|
||||
if (fo) fo.setAttribute('y', y - 11);
|
||||
if (sub) sub.setAttribute('y', y + 15);
|
||||
if (lead) lead.setAttribute('visibility', 'hidden');
|
||||
};
|
||||
|
||||
const redraw = () => {
|
||||
@@ -229,36 +221,29 @@
|
||||
const ovfLvl = (ovf != null && ovfPct != null) ? ovf * (ovfPct / 100) : null;
|
||||
|
||||
// Build the right-column items. basinHeight is pinned at the
|
||||
// rim (DIAG.topY); others float on the proportional axis and
|
||||
// get nudged apart so the input boxes don't overlap.
|
||||
// tank rim; others are sorted by their proportional y and then
|
||||
// pushed apart so every dashed line gets a minimum vertical
|
||||
// gap for readability. The diagram is a schematic ordered
|
||||
// list, not a strictly to-scale rendering.
|
||||
const items = [
|
||||
{ id: 'basinHeight', yLine: DIAG.topY, pinned: true },
|
||||
{ id: 'overflowLevel', yLine: yForLevel(fNum('overflowLevel'), basinH) },
|
||||
{ id: 'maxLevel', yLine: yForLevel(fNum('maxLevel'), basinH) },
|
||||
{ id: 'startLevel', yLine: yForLevel(fNum('startLevel'), basinH) },
|
||||
{ id: 'minLevel', yLine: yForLevel(fNum('minLevel'), basinH) },
|
||||
{ id: 'dryRunLevel', yLine: yForLevel(dryLvl, basinH) },
|
||||
{ id: 'outflowLevel', yLine: yForLevel(fNum('outflowLevel'), basinH) },
|
||||
].filter(it => it.yLine != null);
|
||||
{ id: 'basinHeight', yIdeal: DIAG.topY, pinned: true },
|
||||
{ id: 'overflowLevel', yIdeal: yForLevel(fNum('overflowLevel'), basinH) },
|
||||
{ id: 'maxLevel', yIdeal: yForLevel(fNum('maxLevel'), basinH) },
|
||||
{ id: 'startLevel', yIdeal: yForLevel(fNum('startLevel'), basinH) },
|
||||
{ id: 'minLevel', yIdeal: yForLevel(fNum('minLevel'), basinH) },
|
||||
{ id: 'dryRunLevel', yIdeal: yForLevel(dryLvl, basinH) },
|
||||
{ id: 'outflowLevel', yIdeal: yForLevel(fNum('outflowLevel'), basinH) },
|
||||
].filter(it => it.yIdeal != null);
|
||||
|
||||
const GAP = 30;
|
||||
items.sort((a, b) => a.yLine - b.yLine);
|
||||
const GAP = 36;
|
||||
items.sort((a, b) => a.yIdeal - b.yIdeal);
|
||||
let prev = -Infinity;
|
||||
for (const it of items) {
|
||||
if (it.pinned) { it.yInput = it.yLine; prev = it.yInput; continue; }
|
||||
it.yInput = Math.max(it.yLine, prev + GAP);
|
||||
prev = it.yInput;
|
||||
if (it.pinned) { it.y = it.yIdeal; prev = it.y; continue; }
|
||||
it.y = Math.max(it.yIdeal, prev + GAP);
|
||||
prev = it.y;
|
||||
}
|
||||
|
||||
// Hide leader lines for items whose input is cleared
|
||||
const active = new Set(items.map(it => it.id));
|
||||
['overflowLevel','maxLevel','startLevel','minLevel','dryRunLevel','outflowLevel'].forEach(id => {
|
||||
if (!active.has(id)) {
|
||||
const lead = document.getElementById(`ps-leader-${id}`);
|
||||
if (lead) lead.setAttribute('visibility', 'hidden');
|
||||
}
|
||||
});
|
||||
for (const it of items) placeItem(it.id, it.yLine, it.yInput);
|
||||
for (const it of items) placeItem(it.id, it.y);
|
||||
|
||||
// Inlet arrow — sole item on the left, no stacking concerns
|
||||
const inflowY = yForLevel(fNum('inflowLevel'), basinH);
|
||||
@@ -275,12 +260,14 @@
|
||||
if (unit) unit.setAttribute('y', inflowY + 4);
|
||||
}
|
||||
|
||||
// Dead-volume band: from outflowLevel down to the floor
|
||||
const outflowY = yForLevel(fNum('outflowLevel'), basinH);
|
||||
const deadvol = document.getElementById('ps-deadvol');
|
||||
if (deadvol && outflowY != null) {
|
||||
deadvol.setAttribute('y', outflowY);
|
||||
deadvol.setAttribute('height', Math.max(0, DIAG.botY - outflowY));
|
||||
// Dead-volume band: from the (possibly-nudged) outflow line
|
||||
// down to the floor. Use the nudged y so the band meets the
|
||||
// outflow line exactly.
|
||||
const outflowItem = items.find(it => it.id === 'outflowLevel');
|
||||
const deadvol = document.getElementById('ps-deadvol');
|
||||
if (deadvol && outflowItem) {
|
||||
deadvol.setAttribute('y', outflowItem.y);
|
||||
deadvol.setAttribute('height', Math.max(0, DIAG.botY - outflowItem.y));
|
||||
}
|
||||
|
||||
// dryRunLevel label text (derived, read-only)
|
||||
@@ -385,7 +372,7 @@
|
||||
#ps-basin-diagram input[type=number]:focus { outline: 1px solid #0c99d9; border-color: #0c99d9; }
|
||||
</style>
|
||||
|
||||
<svg id="ps-basin-diagram" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 620"
|
||||
<svg id="ps-basin-diagram" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 430"
|
||||
style="display:block;width:100%;max-width:540px;margin:0 0 12px 0;background:#fff;border:1px solid #e5e5e5;border-radius:4px;"
|
||||
font-family="Arial,sans-serif" font-size="11">
|
||||
<defs>
|
||||
@@ -395,7 +382,7 @@
|
||||
</defs>
|
||||
|
||||
<!-- Tank body -->
|
||||
<rect x="200" y="40" width="120" height="520" fill="#F0F8FF" stroke="#333" stroke-width="1.5" />
|
||||
<rect x="200" y="40" width="120" height="340" fill="#F0F8FF" stroke="#333" stroke-width="1.5" />
|
||||
<!-- Dead-volume band (y + height updated dynamically below outflowLevel) -->
|
||||
<rect id="ps-deadvol" x="201" width="118" fill="#AACCE0" />
|
||||
|
||||
@@ -462,8 +449,8 @@
|
||||
<text id="ps-unit-outflowLevel" x="500" fill="#555">m</text>
|
||||
|
||||
<!-- Floor / datum -->
|
||||
<line x1="195" y1="560" x2="325" y2="560" stroke="#000" stroke-width="2" />
|
||||
<text x="330" y="564" fill="#000">0 m (datum)</text>
|
||||
<line x1="195" y1="380" x2="325" y2="380" stroke="#000" stroke-width="2" />
|
||||
<text x="330" y="384" fill="#000">0 m (datum)</text>
|
||||
|
||||
<!-- Leader lines: shown when the input row had to be nudged off its threshold's ideal y -->
|
||||
<line id="ps-leader-basinHeight" x1="0" y1="0" x2="0" y2="0" stroke="#bbb" stroke-width="0.6" stroke-dasharray="2 2" visibility="hidden" />
|
||||
@@ -475,7 +462,7 @@
|
||||
<line id="ps-leader-outflowLevel" x1="0" y1="0" x2="0" y2="0" stroke="#bbb" stroke-width="0.6" stroke-dasharray="2 2" visibility="hidden" />
|
||||
|
||||
<!-- Ordering-warning ribbon -->
|
||||
<text id="ps-warning" x="260" y="600" text-anchor="middle" fill="#C0392B" font-size="10" font-style="italic" visibility="hidden"></text>
|
||||
<text id="ps-warning" x="260" y="410" text-anchor="middle" fill="#C0392B" font-size="10" font-style="italic" visibility="hidden"></text>
|
||||
</svg>
|
||||
|
||||
<div class="form-row">
|
||||
|
||||
Reference in New Issue
Block a user