@tscircuit/checks 0.0.198 → 0.0.200
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +11 -6
- package/dist/index.js +102 -50
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as circuit_json from 'circuit-json';
|
|
2
|
-
import { AnyCircuitElement, PcbPlacementError, PcbPortNotConnectedError, PcbTraceError, PcbComponentOutsideBoardError, PcbViaClearanceError, PcbTraceWarning, PcbTraceMissingError, PcbFootprintOverlapError, PcbPadPadClearanceError, PcbCourtyardOverlapError, PcbComponentMissingCourtyardWarning,
|
|
2
|
+
import { AnyCircuitElement, PcbPlacementError, PcbPortNotConnectedError, PcbTraceError, PcbComponentOutsideBoardError, PcbViaClearanceError, PcbTraceWarning, PcbTraceMissingError, PcbFootprintOverlapError, PcbPadPadClearanceError, PcbCourtyardOverlapError, PcbComponentMissingCourtyardWarning, PcbTraceTooLongError, PcbPadTraceClearanceError, PcbViaTraceClearanceError, SourceComponentMisconfiguredError, SourceComponentPinsUnderspecifiedWarning, SourceNoPowerPinDefinedWarning, SourceNoGroundPinDefinedWarning, SchematicComponentStylingWarning, PcbConnectorNotInAccessibleOrientationWarning, SourceConfusingNetNameWarning, PcbBusLengthSkewError } from 'circuit-json';
|
|
3
3
|
import { ConnectivityMap } from 'circuit-json-to-connectivity-map';
|
|
4
4
|
|
|
5
5
|
/** Detect accidental copper contact, rather than enforcing a clearance margin. */
|
|
@@ -105,7 +105,7 @@ declare function checkPcbComponentOverlap(circuitJson: AnyCircuitElement[]): Pcb
|
|
|
105
105
|
/** Returns warnings for PCB components without courtyards, excluding manually placed vias. */
|
|
106
106
|
declare function checkPcbComponentsMissingCourtyard(circuitJson: AnyCircuitElement[]): PcbComponentMissingCourtyardWarning[];
|
|
107
107
|
|
|
108
|
-
declare const checkPcbTraceLengths: (circuitJson: AnyCircuitElement[]) =>
|
|
108
|
+
declare const checkPcbTraceLengths: (circuitJson: AnyCircuitElement[]) => PcbTraceTooLongError[];
|
|
109
109
|
|
|
110
110
|
/** Return a routing error when a source trace exceeds its maximum via count. */
|
|
111
111
|
declare const checkPcbTraceViaCounts: (circuitJson: AnyCircuitElement[]) => PcbTraceError[];
|
|
@@ -216,8 +216,8 @@ declare function runAllNetlistChecks(circuitJson: AnyCircuitElement[]): Promise<
|
|
|
216
216
|
} | circuit_json.SourceComponentMisconfiguredError | circuit_json.SourceConfusingNetNameWarning)[]>;
|
|
217
217
|
declare function runAllSchematicChecks(circuitJson: AnyCircuitElement[]): Promise<circuit_json.SchematicComponentStylingWarning[]>;
|
|
218
218
|
declare function runAllPinSpecificationChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.SourceComponentPinsUnderspecifiedWarning | circuit_json.SourceNoPowerPinDefinedWarning | circuit_json.SourceNoGroundPinDefinedWarning)[]>;
|
|
219
|
-
declare function runAllRoutingChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.PcbPlacementError | circuit_json.PcbPortNotConnectedError | circuit_json.PcbTraceError | circuit_json.PcbViaClearanceError | circuit_json.PcbTraceMissingError | circuit_json.PcbPadPadClearanceError | circuit_json.
|
|
220
|
-
declare function runAllChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.PcbPlacementError | circuit_json.PcbPortNotConnectedError | circuit_json.PcbTraceError | circuit_json.PcbComponentOutsideBoardError | circuit_json.PcbViaClearanceError | circuit_json.PcbTraceMissingError | PcbComponentOverlapError | circuit_json.PcbPadPadClearanceError | circuit_json.PcbCourtyardOverlapError | circuit_json.PcbComponentMissingCourtyardWarning | circuit_json.
|
|
219
|
+
declare function runAllRoutingChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.PcbPlacementError | circuit_json.PcbPortNotConnectedError | circuit_json.PcbTraceError | circuit_json.PcbViaClearanceError | circuit_json.PcbTraceMissingError | circuit_json.PcbPadPadClearanceError | circuit_json.PcbTraceTooLongError | circuit_json.PcbPadTraceClearanceError | circuit_json.PcbViaTraceClearanceError | circuit_json.PcbBusLengthSkewError)[]>;
|
|
220
|
+
declare function runAllChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.PcbPlacementError | circuit_json.PcbPortNotConnectedError | circuit_json.PcbTraceError | circuit_json.PcbComponentOutsideBoardError | circuit_json.PcbViaClearanceError | circuit_json.PcbTraceMissingError | PcbComponentOverlapError | circuit_json.PcbPadPadClearanceError | circuit_json.PcbCourtyardOverlapError | circuit_json.PcbComponentMissingCourtyardWarning | circuit_json.PcbTraceTooLongError | circuit_json.PcbPadTraceClearanceError | circuit_json.PcbViaTraceClearanceError | {
|
|
221
221
|
type: "source_pin_must_be_connected_error";
|
|
222
222
|
source_pin_must_be_connected_error_id: string;
|
|
223
223
|
error_type: "source_pin_must_be_connected_error";
|
|
@@ -225,7 +225,7 @@ declare function runAllChecks(circuitJson: AnyCircuitElement[]): Promise<(circui
|
|
|
225
225
|
source_component_id: string;
|
|
226
226
|
source_port_id: string;
|
|
227
227
|
subcircuit_id?: string;
|
|
228
|
-
} | circuit_json.SourceComponentMisconfiguredError | circuit_json.SourceComponentPinsUnderspecifiedWarning | circuit_json.SourceNoPowerPinDefinedWarning | circuit_json.SourceNoGroundPinDefinedWarning | circuit_json.SchematicComponentStylingWarning | circuit_json.SourceConfusingNetNameWarning | circuit_json.PcbConnectorNotInAccessibleOrientationWarning)[]>;
|
|
228
|
+
} | circuit_json.SourceComponentMisconfiguredError | circuit_json.SourceComponentPinsUnderspecifiedWarning | circuit_json.SourceNoPowerPinDefinedWarning | circuit_json.SourceNoGroundPinDefinedWarning | circuit_json.SchematicComponentStylingWarning | circuit_json.PcbBusLengthSkewError | circuit_json.SourceConfusingNetNameWarning | circuit_json.PcbConnectorNotInAccessibleOrientationWarning)[]>;
|
|
229
229
|
|
|
230
230
|
declare function checkConnectorAccessibleOrientation(circuitJson: AnyCircuitElement[]): PcbConnectorNotInAccessibleOrientationWarning[];
|
|
231
231
|
|
|
@@ -239,4 +239,9 @@ declare function checkTestPointAccessibility(circuitJson: AnyCircuitElement[]):
|
|
|
239
239
|
/** Warn once per name when its source nets belong to multiple electrical islands. */
|
|
240
240
|
declare function checkSameNameNetsAreConnected(circuitJson: AnyCircuitElement[]): SourceConfusingNetNameWarning[];
|
|
241
241
|
|
|
242
|
-
|
|
242
|
+
/** Compare total routed lengths of resolved bus members. Unrouted members are
|
|
243
|
+
* left to connectivity checks, never treated as zero-length routes.
|
|
244
|
+
*/
|
|
245
|
+
declare const checkPcbBusLengthSkew: (circuitJson: AnyCircuitElement[]) => PcbBusLengthSkewError[];
|
|
246
|
+
|
|
247
|
+
export { NetManager, type PcbComponentOverlapError, checkAllPinsInComponentAreUnderspecified, checkConnectorAccessibleOrientation, checkCopperPourShorts, checkCopperToBoardEdgeClearance, checkDifferentNetViaSpacing, checkEachPcbPortConnectedToPcbTraces, checkEachPcbTraceNonOverlapping, checkNoGroundPinDefined, checkNoPowerPinDefined, checkPadPadClearance, checkPadTraceClearance, checkPcbBusLengthSkew, checkPcbComponentOverCutout, checkPcbComponentOverlap, checkPcbComponentsMissingCourtyard, checkPcbComponentsOutOfBoard, checkPcbCopperOverKeepout, checkPcbTraceLengths, checkPcbTraceViaCounts, checkPcbTracesOutOfBoard, checkPinMustBeConnected, checkSameNameNetsAreConnected, checkSameNetViaSpacing, checkSchematicComponentExcessiveVerticalPadding, checkSchematicComponentMissingReferenceDesignatorText, checkSchematicComponentPortsOutsideBody, checkSourceTracesHavePcbTraces, checkSourceTracesMatchPcbTraceThickness, checkTestPointAccessibility, checkTracesAreContiguous, checkTwoTerminalSwitchContactsOnDifferentNets, checkViaPadClearance, checkViaTraceClearance, checkViasInPads, checkViasOffBoard, consolidatePcbOverlapErrors, dedupePcbDrcErrors, runAllChecks, runAllNetlistChecks, runAllPinSpecificationChecks, runAllPlacementChecks, runAllRoutingChecks, runAllSchematicChecks };
|
package/dist/index.js
CHANGED
|
@@ -1239,7 +1239,7 @@ function getCopperPourConnectivity(circuitJson, connectivity) {
|
|
|
1239
1239
|
polygon: getSmtPadPolygon(copper),
|
|
1240
1240
|
layers: [copper.layer],
|
|
1241
1241
|
netId,
|
|
1242
|
-
|
|
1242
|
+
portIds: copper.pcb_port_id ? [copper.pcb_port_id] : []
|
|
1243
1243
|
});
|
|
1244
1244
|
} else if (copper.type === "pcb_plated_hole") {
|
|
1245
1245
|
add({
|
|
@@ -1249,7 +1249,7 @@ function getCopperPourConnectivity(circuitJson, connectivity) {
|
|
|
1249
1249
|
),
|
|
1250
1250
|
layers: copper.layers,
|
|
1251
1251
|
netId,
|
|
1252
|
-
|
|
1252
|
+
portIds: copper.pcb_port_id ? [copper.pcb_port_id] : []
|
|
1253
1253
|
});
|
|
1254
1254
|
} else {
|
|
1255
1255
|
add({
|
|
@@ -1259,7 +1259,8 @@ function getCopperPourConnectivity(circuitJson, connectivity) {
|
|
|
1259
1259
|
copper.hole_diameter
|
|
1260
1260
|
),
|
|
1261
1261
|
layers: copper.layers,
|
|
1262
|
-
netId
|
|
1262
|
+
netId,
|
|
1263
|
+
portIds: copper.pcb_port_ids
|
|
1263
1264
|
});
|
|
1264
1265
|
}
|
|
1265
1266
|
}
|
|
@@ -1300,10 +1301,12 @@ function getCopperPourConnectivity(circuitJson, connectivity) {
|
|
|
1300
1301
|
);
|
|
1301
1302
|
const rootsByPort = /* @__PURE__ */ new Map();
|
|
1302
1303
|
for (const [i, conductor] of conductors.entries()) {
|
|
1303
|
-
if (!
|
|
1304
|
-
const
|
|
1305
|
-
|
|
1306
|
-
|
|
1304
|
+
if (!pourRoots.has(find(i))) continue;
|
|
1305
|
+
for (const portId of conductor.portIds ?? []) {
|
|
1306
|
+
const roots = rootsByPort.get(portId) ?? /* @__PURE__ */ new Set();
|
|
1307
|
+
roots.add(find(i));
|
|
1308
|
+
rootsByPort.set(portId, roots);
|
|
1309
|
+
}
|
|
1307
1310
|
}
|
|
1308
1311
|
const portsByNet = /* @__PURE__ */ new Map();
|
|
1309
1312
|
for (const port of circuitJson) {
|
|
@@ -4134,30 +4137,30 @@ function checkPcbComponentsMissingCourtyard(circuitJson) {
|
|
|
4134
4137
|
});
|
|
4135
4138
|
}
|
|
4136
4139
|
|
|
4137
|
-
// lib/
|
|
4138
|
-
var
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
if (
|
|
4147
|
-
|
|
4148
|
-
|
|
4140
|
+
// lib/util/get-pcb-trace-length.ts
|
|
4141
|
+
var getPcbTraceLength = (trace) => {
|
|
4142
|
+
if (trace.trace_length !== void 0) return trace.trace_length;
|
|
4143
|
+
let length = 0;
|
|
4144
|
+
let previousEnd;
|
|
4145
|
+
for (const point2 of trace.route) {
|
|
4146
|
+
const start = point2.route_type === "through_pad" ? point2.start : point2;
|
|
4147
|
+
if (previousEnd)
|
|
4148
|
+
length += Math.hypot(start.x - previousEnd.x, start.y - previousEnd.y);
|
|
4149
|
+
if (point2.route_type === "via") length += 1.6;
|
|
4150
|
+
if (point2.route_type === "through_pad") {
|
|
4151
|
+
length += Math.hypot(
|
|
4152
|
+
point2.end.x - point2.start.x,
|
|
4153
|
+
point2.end.y - point2.start.y
|
|
4154
|
+
);
|
|
4155
|
+
previousEnd = point2.end;
|
|
4156
|
+
} else {
|
|
4157
|
+
previousEnd = point2;
|
|
4149
4158
|
}
|
|
4150
|
-
const nextRoutePoint = pcbTrace.route[routePointIndex + 1];
|
|
4151
|
-
if (!nextRoutePoint) continue;
|
|
4152
|
-
const routePointPosition = getRoutePointPosition(routePoint);
|
|
4153
|
-
const nextRoutePointPosition = getRoutePointPosition(nextRoutePoint);
|
|
4154
|
-
traceLength += Math.hypot(
|
|
4155
|
-
nextRoutePointPosition.x - routePointPosition.x,
|
|
4156
|
-
nextRoutePointPosition.y - routePointPosition.y
|
|
4157
|
-
);
|
|
4158
4159
|
}
|
|
4159
|
-
return
|
|
4160
|
+
return length;
|
|
4160
4161
|
};
|
|
4162
|
+
|
|
4163
|
+
// lib/check-pcb-trace-lengths.ts
|
|
4161
4164
|
var getReferencedPcbPortIds = (pcbTrace) => {
|
|
4162
4165
|
const pcbPortIds = /* @__PURE__ */ new Set();
|
|
4163
4166
|
for (const routePoint of pcbTrace.route) {
|
|
@@ -4171,7 +4174,7 @@ var getReferencedPcbPortIds = (pcbTrace) => {
|
|
|
4171
4174
|
}
|
|
4172
4175
|
return pcbPortIds;
|
|
4173
4176
|
};
|
|
4174
|
-
var
|
|
4177
|
+
var getPcbTracesBySourceTraceId = (circuitJson) => {
|
|
4175
4178
|
const sourceTraces = circuitJson.filter(
|
|
4176
4179
|
(element) => element.type === "source_trace"
|
|
4177
4180
|
);
|
|
@@ -4181,12 +4184,6 @@ var checkPcbTraceLengths = (circuitJson) => {
|
|
|
4181
4184
|
const pcbPorts = circuitJson.filter(
|
|
4182
4185
|
(element) => element.type === "pcb_port"
|
|
4183
4186
|
);
|
|
4184
|
-
const sourceTracesById = new Map(
|
|
4185
|
-
sourceTraces.map((sourceTrace) => [
|
|
4186
|
-
sourceTrace.source_trace_id,
|
|
4187
|
-
sourceTrace
|
|
4188
|
-
])
|
|
4189
|
-
);
|
|
4190
4187
|
const pcbPortIdsBySourcePortId = /* @__PURE__ */ new Map();
|
|
4191
4188
|
for (const pcbPort of pcbPorts) {
|
|
4192
4189
|
if (!pcbPort.source_port_id) continue;
|
|
@@ -4225,23 +4222,35 @@ var checkPcbTraceLengths = (circuitJson) => {
|
|
|
4225
4222
|
);
|
|
4226
4223
|
}
|
|
4227
4224
|
}
|
|
4228
|
-
const
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4225
|
+
for (const [id, exactIds] of exactEndpointPcbTraceIdsBySourceTraceId) {
|
|
4226
|
+
pcbTracesBySourceTraceId.set(
|
|
4227
|
+
id,
|
|
4228
|
+
pcbTracesBySourceTraceId.get(id).filter((trace) => exactIds.has(trace.pcb_trace_id))
|
|
4229
|
+
);
|
|
4230
|
+
}
|
|
4231
|
+
return pcbTracesBySourceTraceId;
|
|
4232
|
+
};
|
|
4233
|
+
var checkPcbTraceLengths = (circuitJson) => {
|
|
4234
|
+
const sourceTracesById = new Map(
|
|
4235
|
+
circuitJson.filter((e) => e.type === "source_trace").map((e) => [e.source_trace_id, e])
|
|
4236
|
+
);
|
|
4237
|
+
const pcbTracesBySourceTraceId = getPcbTracesBySourceTraceId(circuitJson);
|
|
4238
|
+
const errors = [];
|
|
4239
|
+
for (const [sourceTraceId, pcbTraces] of pcbTracesBySourceTraceId) {
|
|
4240
|
+
const pcbTrace = pcbTraces[0];
|
|
4241
|
+
const sourceTrace = sourceTracesById.get(sourceTraceId);
|
|
4232
4242
|
if (!sourceTrace) continue;
|
|
4233
4243
|
const maximumTraceLength = sourceTrace.max_length;
|
|
4234
4244
|
if (typeof maximumTraceLength !== "number") continue;
|
|
4235
|
-
const
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
warning_type: "pcb_trace_too_long_warning",
|
|
4245
|
+
const actualTraceLength = pcbTraces.reduce(
|
|
4246
|
+
(sum, trace) => sum + getPcbTraceLength(trace),
|
|
4247
|
+
0
|
|
4248
|
+
);
|
|
4249
|
+
if (actualTraceLength <= maximumTraceLength + 1e-9) continue;
|
|
4250
|
+
errors.push({
|
|
4251
|
+
type: "pcb_trace_too_long_error",
|
|
4252
|
+
pcb_trace_too_long_error_id: `pcb_trace_too_long_error_${pcbTrace.pcb_trace_id}`,
|
|
4253
|
+
error_type: "pcb_trace_too_long_error",
|
|
4245
4254
|
message: `PCB trace is ${actualTraceLength.toFixed(2)}mm long, exceeding the ${maximumTraceLength}mm maximum`,
|
|
4246
4255
|
pcb_trace_id: pcbTrace.pcb_trace_id,
|
|
4247
4256
|
source_trace_id: sourceTrace.source_trace_id,
|
|
@@ -4251,7 +4260,7 @@ var checkPcbTraceLengths = (circuitJson) => {
|
|
|
4251
4260
|
subcircuit_id: pcbTrace.subcircuit_id ?? sourceTrace.subcircuit_id
|
|
4252
4261
|
});
|
|
4253
4262
|
}
|
|
4254
|
-
return
|
|
4263
|
+
return errors;
|
|
4255
4264
|
};
|
|
4256
4265
|
|
|
4257
4266
|
// lib/check-pcb-trace-via-counts.ts
|
|
@@ -5116,6 +5125,47 @@ function checkSchematicComponentPortsOutsideBody(circuitJson) {
|
|
|
5116
5125
|
return warnings;
|
|
5117
5126
|
}
|
|
5118
5127
|
|
|
5128
|
+
// lib/check-pcb-bus-length-skew.ts
|
|
5129
|
+
var checkPcbBusLengthSkew = (circuitJson) => {
|
|
5130
|
+
const buses = circuitJson.filter(
|
|
5131
|
+
(e) => e.type === "source_bus"
|
|
5132
|
+
);
|
|
5133
|
+
const tracesBySource = getPcbTracesBySourceTraceId(circuitJson);
|
|
5134
|
+
const errors = [];
|
|
5135
|
+
for (const bus of buses) {
|
|
5136
|
+
if (bus.max_length_skew === void 0) continue;
|
|
5137
|
+
const members = [...new Set(bus.source_trace_ids)].flatMap((id) => {
|
|
5138
|
+
const traces = tracesBySource.get(id)?.filter((t) => t.trace_length !== void 0 || t.route.length > 1);
|
|
5139
|
+
if (!traces?.length) return [];
|
|
5140
|
+
return [
|
|
5141
|
+
{
|
|
5142
|
+
id,
|
|
5143
|
+
traces,
|
|
5144
|
+
length: traces.reduce((sum, t) => sum + getPcbTraceLength(t), 0)
|
|
5145
|
+
}
|
|
5146
|
+
];
|
|
5147
|
+
});
|
|
5148
|
+
if (members.length < 2) continue;
|
|
5149
|
+
const skew = Math.max(...members.map((m) => m.length)) - Math.min(...members.map((m) => m.length));
|
|
5150
|
+
if (skew <= bus.max_length_skew + 1e-9) continue;
|
|
5151
|
+
errors.push({
|
|
5152
|
+
type: "pcb_bus_length_skew_error",
|
|
5153
|
+
pcb_bus_length_skew_error_id: `pcb_bus_length_skew_error_${bus.source_bus_id}`,
|
|
5154
|
+
error_type: "pcb_bus_length_skew_error",
|
|
5155
|
+
message: `PCB bus ${bus.name ?? bus.source_bus_id} has ${skew.toFixed(2)}mm length skew, exceeding the ${bus.max_length_skew}mm maximum`,
|
|
5156
|
+
source_bus_id: bus.source_bus_id,
|
|
5157
|
+
source_trace_ids: members.map((m) => m.id),
|
|
5158
|
+
pcb_trace_ids: members.flatMap(
|
|
5159
|
+
(m) => m.traces.map((t) => t.pcb_trace_id)
|
|
5160
|
+
),
|
|
5161
|
+
actual_length_skew: skew,
|
|
5162
|
+
maximum_length_skew: bus.max_length_skew,
|
|
5163
|
+
subcircuit_id: bus.subcircuit_id
|
|
5164
|
+
});
|
|
5165
|
+
}
|
|
5166
|
+
return errors;
|
|
5167
|
+
};
|
|
5168
|
+
|
|
5119
5169
|
// lib/consolidate-pcb-overlap-errors.ts
|
|
5120
5170
|
import { getPrimaryId as getPrimaryId10 } from "@tscircuit/circuit-json-util";
|
|
5121
5171
|
function consolidatePcbOverlapErrors(circuitJson, errors) {
|
|
@@ -5604,6 +5654,7 @@ async function runAllRoutingChecks(circuitJson) {
|
|
|
5604
5654
|
...checkEachPcbPortConnectedToPcbTraces(circuitJson),
|
|
5605
5655
|
...checkSourceTracesHavePcbTraces(circuitJson),
|
|
5606
5656
|
...checkPcbTraceLengths(circuitJson),
|
|
5657
|
+
...checkPcbBusLengthSkew(circuitJson),
|
|
5607
5658
|
...checkPcbTraceViaCounts(circuitJson),
|
|
5608
5659
|
...checkEachPcbTraceNonOverlapping(circuitJson),
|
|
5609
5660
|
...checkCopperPourShorts(circuitJson),
|
|
@@ -5638,6 +5689,7 @@ export {
|
|
|
5638
5689
|
checkNoPowerPinDefined,
|
|
5639
5690
|
checkPadPadClearance,
|
|
5640
5691
|
checkPadTraceClearance,
|
|
5692
|
+
checkPcbBusLengthSkew,
|
|
5641
5693
|
checkPcbComponentOverCutout,
|
|
5642
5694
|
checkPcbComponentOverlap,
|
|
5643
5695
|
checkPcbComponentsMissingCourtyard,
|