WillTools: precast shop-ticket QC and panel handling tools
ci / test (push) Has been cancelled

Public demo snapshot of an in-house pyRevit extension for precast concrete
shop-ticket QC (37 checks / 46 checklist rows) and a standalone panel
handling solver (PCI Chapter 8).

- No client, job, plant or product data: knowledge layers ship as
  structural templates only.
- Ticket QC's model-read escalation targets a LAN model server endpoint
  (configurable), not a cloud provider.
- Built from the private development repo via tools/make_dist.py.
This commit is contained in:
2026-09-03 16:33:47 -05:00
commit 52d94303bc
281 changed files with 155656 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
"""Concrete of the cast piece that is not the panel rectangle.
A slab-seat ledge is modelled as its own family inside the assembly. It is
real concrete -- on WP371 it carried 8.99 ft3 = 1,349 lb, 7.5% of the piece
-- and leaving it out made the weight reconciliation accuse a correct model.
The lump rides at no station, so it is added to the geometric weight whole;
the statics rescale to the stated weight regardless, and this is what makes
that reconciliation honest.
"""
import pytest
from panellift import cli, section
from conftest import make_panel
LEDGE_FT3 = 8.992 # what WP371's LEDGE family actually measured
LEDGE_LB = LEDGE_FT3 * 150.0
def test_extra_cast_is_added_to_the_geometric_weight():
"""The ledge is weight whether or not it sits at a station."""
bare = make_panel()
ledged = make_panel()
ledged.extra_cast_ft3 = LEDGE_FT3
expected = section.geometric_weight_lb(bare) + LEDGE_LB
assert section.geometric_weight_lb(ledged) == pytest.approx(expected)
def test_reconciliation_clears_when_the_ledge_is_counted():
"""A panel whose stated weight includes the ledge must not be accused."""
panel = make_panel()
panel.extra_cast_ft3 = LEDGE_FT3
panel.weight_lb = section.geometric_weight_lb(panel)
_geom, _stated, error = section.weight_reconciliation(panel)
assert abs(error) < 0.001
def test_reconciliation_still_catches_a_missing_ledge():
"""Without the field, the old wrong answer is still visible.
The ledge here is sized as a share of THIS panel -- on the smaller
WP371 it was 7.5% of the piece, and check_weight warns past 5%.
"""
panel = make_panel()
ledge_ft3 = 0.075 * (panel.length_ft * panel.width_ft *
panel.thickness_ft)
panel.weight_lb = (section.geometric_weight_lb(panel)
+ ledge_ft3 * panel.unit_weight_pcf)
_geom, _stated, error = section.weight_reconciliation(panel)
assert error < -0.05 # we are light by more than 5%
def test_cli_reads_extra_cast_ft3():
"""The job file carries the ledge, and the reader keeps it."""
import json
panel = make_panel()
panel.extra_cast_ft3 = LEDGE_FT3
data = json.loads(json.dumps({
'mark': panel.mark,
'length_ft': panel.length_ft,
'width_ft': panel.width_ft,
'thickness_in': panel.thickness_in,
'unit_weight_pcf': panel.unit_weight_pcf,
'extra_cast_ft3': LEDGE_FT3,
}))
assert cli.read_panel(data).extra_cast_ft3 == pytest.approx(LEDGE_FT3)
def test_cli_treats_a_missing_field_as_no_ledge():
"""Old job files without the key keep working, as zero."""
import json
data = json.loads(json.dumps({
'mark': 'OLD-1',
'length_ft': 32.0,
'width_ft': 10.0,
'thickness_in': 8.75,
}))
assert cli.read_panel(data).extra_cast_ft3 == 0.0