imrishabh18/pedometer
This code defines and assembles a simple radio receiver hardware circuit using specific imported capacitors, inductors, RF connectors, and oscillator components with precise footprints and schematic attributes.
- Version
- 1.1.3
- License
- unset
- Stars
- 0
scripts/audit-imported-footprints.ts
import fs from "node:fs";
import { createHash } from "node:crypto";
import assert from "node:assert/strict";
import { routingPreservationSnapshot } from "./check-routing-preserved";
const hash = (path: string) => createHash("sha256").update(fs.readFileSync(path)).digest("hex");
const read = (path: string) => JSON.parse(fs.readFileSync(path, "utf8"));
const c: any[] = read("dist/index/circuit.json");
const baseline: any[] = read("review/footprint-baseline-v1.1.2.json");
const provenance = read("review/footprint-import-provenance.json");
const mm = (value: string | number) => Number.parseFloat(String(value));
const near = (actual: number, expected: number, label: string, tolerance = 1e-6) =>
assert.ok(Math.abs(actual - expected) <= tolerance, `${label}: ${actual} != ${expected}`);
const records: any[] = [];
for (const item of provenance.parts) {
assert.equal(hash(item.file), item.sha256, `Raw import changed: ${item.file}`);
const Part = (await import(`../${item.file}`))[item.export];
const raw = Part({ name: "audit" }).props;
const importedPads = raw.footprint.props.children.flat(Infinity).filter((e: any) => e?.type === "smtpad");
assert.equal(importedPads.length, 2);
for (const ref of item.references) {
const source = c.find(e => e.type === "source_component" && e.name === ref);
assert.equal(source.manufacturer_part_number, raw.manufacturerPartNumber, `${ref} MPN`);
assert.deepEqual(source.supplier_part_numbers.jlcpcb, [item.code], `${ref} JLC code`);
const component = c.find(e => e.type === "pcb_component" && e.source_component_id === source.source_component_id);
const actualPads = c.filter(e => e.type === "pcb_smtpad" && e.pcb_component_id === component.pcb_component_id);
assert.equal(actualPads.length, importedPads.length, `${ref} pad count`);
const angle = component.rotation * Math.PI / 180;
const cos = Math.cos(angle), sin = Math.sin(angle);
const pads: any[] = [];
for (const element of importedPads) {
const p = element.props;
const pin = p.portHints[0];
const actual = actualPads.find(e => e.port_hints.includes(pin));
assert.ok(actual, `${ref}.${pin} pad missing`);
const expected = { x: component.center.x + mm(p.pcbX) * cos - mm(p.pcbY) * sin,
y: component.center.y + mm(p.pcbX) * sin + mm(p.pcbY) * cos,
width: Math.abs(cos) * mm(p.width) + Math.abs(sin) * mm(p.height),
height: Math.abs(sin) * mm(p.width) + Math.abs(cos) * mm(p.height) };
assert.equal(actual.shape, p.shape, `${ref}.${pin} shape`);
assert.equal(actual.layer, "top");
for (const key of ["x", "y", "width", "height"] as const) near(actual[key], expected[key], `${ref}.${pin}.${key}`);
const pcbPort = c.find(e => e.type === "pcb_port" && e.pcb_port_id === actual.pcb_port_id);
const sourcePort = c.find(e => e.type === "source_port" && e.source_port_id === pcbPort.source_port_id);
assert.equal(sourcePort.pin_number, Number(pin.replace("pin", "")), `${ref} physical pin mapping`);
pads.push({ pin, imported: { x: mm(p.pcbX), y: mm(p.pcbY), width: mm(p.width), height: mm(p.height) }, built: expected });
}
records.push({ reference: ref, code: item.code, mpn: raw.manufacturerPartNumber, rotation: component.rotation, pads });
}
}
// Electrical invariants are independent of this deliberately changed placement.
// Keep the older routing-only preservation check intact for its original use.
const electrical = (elements: any[]) => elements.filter(e => e.type === "source_component").map(e =>
Object.fromEntries(["name", "ftype", "manufacturer_part_number", "supplier_part_numbers", "capacitance", "resistance", "inductance", "max_voltage_rating", "max_current_rating"]
.filter(key => e[key] !== undefined).map(key => [key, e[key]]))).sort((a, b) => a.name.localeCompare(b.name));
assert.deepEqual(electrical(c), electrical(baseline), "Component identity/value/rating changed");
const before = routingPreservationSnapshot(baseline), after = routingPreservationSnapshot(c);
for (const key of ["netlist", "simulation", "pourPolicies", "viaDimensions"] as const)
assert.deepEqual(after[key], before[key], `Changed ${key}`);
const boardRules = (elements: any[]) => {
const { pcb_board_id, source_board_id, ...rules } = elements.find(e => e.type === "pcb_board");
return rules;
};
assert.deepEqual(boardRules(c), boardRules(baseline), "Board geometry/design rules changed");
const report = { result: "PASS", circuitSha256: hash("dist/index/circuit.json"),
baselineSha256: hash("review/footprint-baseline-v1.1.2.json"), importedComponents: records.length,
checkedPads: records.reduce((sum, p) => sum + p.pads.length, 0),
electricalNetlistUnchanged: true, componentValuesAndCodesUnchanged: true, boardRulesUnchanged: true,
records };
fs.writeFileSync("review/imported-footprint-audit.json", JSON.stringify(report, null, 2) + "\n");
console.log(`PASS: ${report.importedComponents} imported components / ${report.checkedPads} exact pads; electrical design and board rules unchanged.`);