Skip to content

Commit

Permalink
fix: Merge pull request #5 from tscircuit/readable-fns
Browse files Browse the repository at this point in the history
readable fns
  • Loading branch information
seveibar authored Jul 26, 2024
2 parents 4ccac6d + 8149d20 commit 91ed67e
Show file tree
Hide file tree
Showing 13 changed files with 330 additions and 3 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/npm-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Created using @tscircuit/plop (npm install -g @tscircuit/plop)
name: NPM Test

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: 20

- name: Install dependencies
run: npm ci

- name: Build
run: |
npm run build || true
- name: Run tests
run: npm run test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
.vscode
dist
.aider*
9 changes: 9 additions & 0 deletions lib/get-element-by-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { AnySoupElement } from "@tscircuit/soup"
import { getElementId } from "./get-element-id"

export const getElementById = (
soup: AnySoupElement[],
id: string,
): AnySoupElement | null => {
return soup.find((elm) => getElementId(elm) === id) ?? null
}
7 changes: 7 additions & 0 deletions lib/get-element-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { AnySoupElement } from "@tscircuit/soup"

export const getElementId = (elm: AnySoupElement): string => {
const type = elm.type
const id = (elm as any)[`${type}_id`]
return id
}
29 changes: 29 additions & 0 deletions lib/readable-name-functions/get-readable-name-for-element.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { AnySoupElement } from "@tscircuit/soup"
import { getReadableNameForPcbTrace } from "./get-readable-name-for-pcb-trace"
import { getReadableNameForPcbSmtpad } from "./get-readable-name-for-pcb-smtpad"
import { getReadableNameForPcbPort } from "./get-readable-name-for-pcb-port"
import { getElementById } from "lib/get-element-by-id"
import { getElementId } from "lib/get-element-id"

export const getReadableNameForElement = (
soup: AnySoupElement[],
elm: AnySoupElement | string,
): string => {
if (typeof elm === "string") {
const elmObj = getElementById(soup, elm)
if (!elmObj) `unknown (could not find element with id ${elm})`
return getReadableNameForElement(soup, elmObj as any)
}
switch (elm.type) {
case "pcb_port":
return getReadableNameForPcbPort(soup, elm.pcb_port_id)
case "pcb_smtpad":
return getReadableNameForPcbSmtpad(soup, elm.pcb_smtpad_id)
case "pcb_trace":
return getReadableNameForPcbTrace(soup, elm.pcb_trace_id)
case "source_component":
return `source_component[${elm.name}]`
default:
return `${elm.type}[#${getElementId(elm)}]`
}
}
47 changes: 47 additions & 0 deletions lib/readable-name-functions/get-readable-name-for-pcb-port.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { AnySoupElement } from "@tscircuit/soup"
import { su } from "../su"

export const getReadableNameForPcbPort = (
soup: AnySoupElement[],
pcb_port_id: string,
): string => {
const pcbPort = su(soup).pcb_port.get(pcb_port_id)
if (!pcbPort) {
return `pcb_port[#${pcb_port_id}]`
}

// Get the component information
const pcbComponent = su(soup).pcb_component.get(pcbPort?.pcb_component_id)

if (!pcbComponent) {
return `pcb_port[#${pcb_port_id}]`
}

// Get the source component information
const sourceComponent = su(soup).source_component.get(
pcbComponent.source_component_id,
)

if (!sourceComponent) {
return `pcb_port[#${pcb_port_id}]`
}

// Get the source port information
const sourcePort = su(soup).source_port.get(pcbPort.source_port_id)

if (!sourcePort) {
return `pcb_port[#${pcb_port_id}]`
}

// Determine the pad number or hint
let padIdentifier: string
if (sourcePort?.port_hints && sourcePort.port_hints.length > 0) {
padIdentifier = sourcePort.port_hints[0]
} else if (sourcePort.port_hints && sourcePort.port_hints.length > 0) {
padIdentifier = sourcePort.port_hints[0]
} else {
padIdentifier = pcb_port_id
}

return `pcb_port[.${sourceComponent.name} > .${padIdentifier}]`
}
17 changes: 17 additions & 0 deletions lib/readable-name-functions/get-readable-name-for-pcb-smtpad.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { AnySoupElement } from "@tscircuit/soup"
import { su } from "../su"
import { getReadableNameForPcbPort } from "./get-readable-name-for-pcb-port"

export function getReadableNameForPcbSmtpad(
soup: AnySoupElement[],
pcb_smtpad_id: string,
): string {
// Find the pcb_smtpad object
const pcbSmtpad = su(soup).pcb_smtpad.get(pcb_smtpad_id)

if (!pcbSmtpad || !pcbSmtpad.pcb_port_id) {
return `smtpad[${pcb_smtpad_id}]`
}

return getReadableNameForPcbPort(soup, pcbSmtpad.pcb_port_id)
}
55 changes: 55 additions & 0 deletions lib/readable-name-functions/get-readable-name-for-pcb-trace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type { AnySoupElement } from "@tscircuit/soup"
import { su } from "../su"

export function getReadableNameForPcbTrace(
soup: AnySoupElement[],
pcb_trace_id: string,
) {
// Find the pcb_trace object
const pcbTrace = su(soup).pcb_trace.get(pcb_trace_id)

if (!pcbTrace) {
return `trace[${pcb_trace_id}]`
}

// Get the connected ports
const connectedPcbPortIds: string[] = pcbTrace.route
.flatMap((point: any) => [point.start_pcb_port_id, point.end_pcb_port_id])
.filter(Boolean)

if (connectedPcbPortIds.length === 0) {
return `trace[${pcb_trace_id}]`
}

// Function to get component name and port hint
function getComponentAndPortInfo(pcb_port_id: string) {
const pcbPort = su(soup).pcb_port.get(pcb_port_id)
if (!pcbPort) return null

const pcbComponent = su(soup).pcb_component.get(pcbPort.pcb_component_id)
if (!pcbComponent) return null
const sourceComponent = su(soup).source_component.get(
pcbComponent.source_component_id,
)
if (!sourceComponent) return null

const sourcePort = su(soup).source_port.get(pcbPort.source_port_id)
const portHint = sourcePort?.port_hints ? sourcePort.port_hints[1] : ""

return {
componentName: sourceComponent.name,
portHint: portHint,
}
}

// Generate the readable selector
const selectorParts = connectedPcbPortIds.map((portId) => {
const info = getComponentAndPortInfo(portId)
if (info) {
return `.${info.componentName} > port.${info.portHint}`
}
return `port[${portId}]`
})

return `trace[${selectorParts.join(", ")}]`
}
128 changes: 128 additions & 0 deletions tests/get-readable-name-for-element.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import test from "ava"
import { getReadableNameForElement } from "../lib/readable-name-functions/get-readable-name-for-element"
import type { AnySoupElement } from "@tscircuit/soup"

test("getReadableNameForElement for pcb_port, pcb_smtpad, and pcb_trace", (t) => {
const soup: AnySoupElement[] = [
{
type: "source_component",
source_component_id: "sc1",
name: "R1",
ftype: "simple_resistor",
resistance: 100,
},
{
type: "source_port",
source_port_id: "sp1",
source_component_id: "sc1",
name: "left",
port_hints: ["1", "left"],
},
{
type: "pcb_component",
pcb_component_id: "pc1",
source_component_id: "sc1",
width: 10,
height: 5,
rotation: 0,
center: { x: 5, y: 5 },
layer: "top",
},
{
type: "pcb_port",
pcb_port_id: "pp1",
pcb_component_id: "pc1",
source_port_id: "sp1",
x: 0,
y: 0,
layers: ["top"],
},
{
type: "pcb_smtpad",
pcb_smtpad_id: "ps1",
pcb_port_id: "pp1",
x: 0,
y: 0,
width: 2,
height: 2,
layer: "top",
shape: "rect",
},
{
type: "pcb_trace",
pcb_trace_id: "pt1",
route: [
{
x: 0,
y: 0,
width: 1,
layer: "top",
route_type: "wire",
start_pcb_port_id: "pp1",
},
{
x: 1,
y: 0,
width: 1,
layer: "top",
route_type: "wire",
end_pcb_port_id: "pp2",
},
],
},
{
type: "pcb_port",
pcb_port_id: "pp2",
pcb_component_id: "pc2",
source_port_id: "sp2",
x: 0,
y: 0,
layers: ["top"],
},
{
type: "source_component",
source_component_id: "sc2",
name: "C1",
ftype: "simple_capacitor",
capacitance: 10,
},
{
type: "source_port",
source_port_id: "sp2",
source_component_id: "sc2",
name: "positive",
port_hints: ["1", "positive"],
},
{
type: "pcb_component",
pcb_component_id: "pc2",
source_component_id: "sc2",
width: 10,
height: 5,
rotation: 0,
center: { x: 0, y: 0 },
layer: "top",
},
]

// Test pcb_port
t.is(
getReadableNameForElement(soup, "pp1"),
"pcb_port[.R1 > .1]",
"PCB port readable name",
)

// Test pcb_smtpad
t.is(
getReadableNameForElement(soup, "ps1"),
"pcb_port[.R1 > .1]",
"PCB SMT pad readable name",
)

// Test pcb_trace
t.is(
getReadableNameForElement(soup, "pt1"),
"trace[.R1 > port.left, .C1 > port.positive]",
"PCB trace readable name",
)
})
2 changes: 1 addition & 1 deletion tests/get-using.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { AnySoupElementInput } from "@tscircuit/soup"
import su from "../index"
import { su } from "../index"
import test from "ava"

test("getUsing", (t) => {
Expand Down
2 changes: 1 addition & 1 deletion tests/get.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { AnySoupElement } from "@tscircuit/soup"
import su from "../index"
import { su } from "../index"
import test from "ava"

test("get", (t) => {
Expand Down
2 changes: 1 addition & 1 deletion tests/select.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { AnySoupElement } from "@tscircuit/soup"
import su from "../index"
import { su } from "../index"
import test from "ava"

test("select", (t) => {
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"compilerOptions": {
// Base Options recommended for all projects
"baseUrl": ".",
"esModuleInterop": true,
"skipLibCheck": true,
"target": "es2022",
Expand Down

0 comments on commit 91ed67e

Please sign in to comment.