Merge any-colour slot assignment order
All checks were successful
build-and-push / docker (push) Successful in 15s

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
dlawler489 2026-09-17 13:40:37 +10:00
commit 122f9d53ce
3 changed files with 22 additions and 2 deletions

View file

@ -68,7 +68,9 @@ function assignSpools(filaments, spools) {
for (const slot of slots) { for (const slot of slots) {
for (const spool of shelf) { for (const spool of shelf) {
if (spool.material !== slot.material) continue; if (spool.material !== slot.material) continue;
if (slot.colour === null) { pairs.push({ slot: slot.index, spool: spool.key, d: 0 }); continue; } // A slot that takes any colour is filled last, from whatever is left:
// scoring it 0 would let it claim a spool an exact-match slot needs.
if (slot.colour === null) { pairs.push({ slot: slot.index, spool: spool.key, d: Number.MAX_SAFE_INTEGER }); continue; }
const d = colourDistance(slot.colour, spool.colour); const d = colourDistance(slot.colour, spool.colour);
if (d !== null && d <= COLOUR_TOLERANCE) pairs.push({ slot: slot.index, spool: spool.key, d }); if (d !== null && d <= COLOUR_TOLERANCE) pairs.push({ slot: slot.index, spool: spool.key, d });
} }

View file

@ -328,7 +328,9 @@ function printability(m) {
for (const slot of slots) { for (const slot of slots) {
for (const spool of shelf) { for (const spool of shelf) {
if (spool.material !== slot.material) continue; if (spool.material !== slot.material) continue;
if (slot.colour === null) { pairs.push({ slot: slot.index, spool: spool.key, d: 0 }); continue; } // Filled last, from what's left: scoring it 0 would let an "any colour"
// slot take the spool an exact-match slot needs.
if (slot.colour === null) { pairs.push({ slot: slot.index, spool: spool.key, d: Number.MAX_SAFE_INTEGER }); continue; }
const d = colourDistance(slot.colour, spool.colour); const d = colourDistance(slot.colour, spool.colour);
if (d !== null && d <= COLOUR_TOLERANCE) pairs.push({ slot: slot.index, spool: spool.key, d }); if (d !== null && d <= COLOUR_TOLERANCE) pairs.push({ slot: slot.index, spool: spool.key, d });
} }

View file

@ -130,3 +130,19 @@ test('a slot with no colour is filled by any spool of that material', () => {
assert.equal(filaments.isPrintable([{ type: 'PLA', colour: null }, { type: 'PLA', colour: null }], assert.equal(filaments.isPrintable([{ type: 'PLA', colour: null }, { type: 'PLA', colour: null }],
[{ id: 1, material: 'PLA', colour_hex: '#123456', colour: 'Anything', remaining_g: 200 }]), false); [{ id: 1, material: 'PLA', colour_hex: '#123456', colour: 'Anything', remaining_g: 200 }]), false);
}); });
test('an "any colour" slot takes what’s left, not what another slot needs', () => {
// Reported from the live library: editing slot 2 of a bookmark to "any
// colour" stole the one white spool, leaving the slot that actually wanted
// #FFFFFF empty and the verdict no better than before.
const shelf = [{ id: 1, material: 'PLA', colour_hex: '#FFFFFF', colour: 'Jade White', remaining_g: 1000 }];
const slots = filaments.assignSpools([{ type: 'PLA', colour: null }, { type: 'PLA', colour: '#FFFFFF' }], shelf);
assert.equal(slots[1].filled, true, 'the slot that asks for white gets the white spool');
assert.equal(slots[1].by, 'Jade White');
assert.equal(slots[0].filled, false, 'the any-colour slot goes without');
// With two spools, both are filled and the exact match still gets white.
const two = shelf.concat({ id: 2, material: 'PLA', colour_hex: '#123456', colour: 'Anything', remaining_g: 500 });
const both = filaments.assignSpools([{ type: 'PLA', colour: null }, { type: 'PLA', colour: '#FFFFFF' }], two);
assert.deepEqual(both.map((s) => s.by), ['Anything', 'Jade White']);
});