# WillTools Precast engineering tooling for Revit: shop-ticket QC against the design summary, and PCI Chapter 8 handling calculations. Built for one precast plant's workflow and shared here so a colleague can try it against their own. Two halves, deliberately kept apart. `WillTools.extension` runs inside Revit, on the model. `panellift` is plain CPython outside Revit — the same handling arithmetic, testable in seconds with no Revit licence at all. ## Quick start ```bash git clone https://github.com/will123song/pyrevit-dev.git cd pyrevit-dev python tools/setup_machine.py ``` That installs the host-side Python dependencies and proves the install with real answers — not just exit codes: it runs `panellift` against a published worked example and checks the arithmetic against the number the article prints. Read [INSTALL.md](INSTALL.md) for what to do with the output, and for pointing pyRevit at the extension so the ribbon shows up in Revit. Try the handling calculator immediately, no Revit needed: ```bash python -m panellift examples/example-panel.job.json -o report.html ``` ## What works without knowledge layers, and what stands down This distribution ships **no knowledge** — not a plant's parameter names, not its casting-bed conventions, not even the published hardware catalogue. See [`knowledge/README.md`](knowledge/README.md) for why and what the shape of a real layer looks like. Runs fully, with no knowledge at all: - `panellift`'s handling checks against a job file — the example above, or one you build by hand. - The ribbon itself, and **Self Check**, which tells you exactly what is and is not configured on this machine. - `python tools/setup_machine.py --check` — reports the no-knowledge state as a **pass**, not a failure. A knowledge-less trial install is an expected, first-class state here, not a broken one. Stands down cleanly, with a stated reason rather than a wrong or silent answer: anything that needs a plant's parameter mapping, the published hardware catalogue, or the master shop-ticket checklist — most visibly, **Ticket QC**, which refuses to open with a one-line reason rather than rendering a report that looks like every ticket passed. Ask the owner for real knowledge layers once you are ready to point this at an actual job. ## `WillTools.extension` — inside Revit A pyRevit extension. Runs on IronPython 2.7 on Revit's UI thread, so it does the things that need the model and nothing that needs testing. One tab, **WillTools**, four panels. The four tools that are finished are the four large buttons on **Tools**; everything else is one click down behind a pulldown, which is what keeps them apart. | Panel | Button | | | --- | --- | --- | | Tools | **Reinforce** | Suggests reinforcing for a design from what comparable designs already carry. | | | **Panel Lift** | PCI Chapter 8 handling check on the piece, from the insert positions the model already holds. | | | **Ticket QC** | Checks every shop ticket of a design against its spec — f'c, f'ci, I.T., strand count/grade/diameter, W.W.F., unit weight, pattern legend, size envelope. Needs a knowledge layer; see above. | | | **Snapshot** | Takes a timestamped detached copy of the model at close-out. | | Setup | **Config** ▾ | A pulldown. The commands you run to get a job ready or to look at it sideways, rather than the four you press all day. | | | ↳ Project Config | Writes the project config layer: every setting that is the engineer's to make, in one file, wherever they want it. | | | ↳ Design Extract | Scrapes a design packet — every sheet whose number reduces to the design, and every view placed on them — reads it with the regex/geometry parser in-process, writes a reviewable `spec.json`. No AI call, no subprocess, nothing that leaves Revit. Run once per design. | | | ↳ Self Check | Probes everything the tools assume about this machine, this Revit and this model. Run it first on a new computer. | | | ↳ Job Recon | Reconciles the issued ticket set against the whole job — the question no per-ticket check can answer, because a ticket that is not there cannot be checked. | | | ↳ Takeoff | What the job contains, per piece and in total: hardware by part number, reinforcing by bar mark. | | Design | **DesignHub** ▾ | A pulldown, and a quarantine: both rows below are buttons-and-docs only. | | | ↳ Gravity (WIP) | Gravity load chasing. Unfinished; today the button writes nothing at all. | | | ↳ Lateral (WIP) | Lateral extraction. Unfinished; today it writes a JSON model, two CSVs, and a RISA draft that is deliberately not a real RISA input yet. | Anything half-built lives behind the **Design** panel's pulldown and carries `(WIP)` in its name, so nothing unfinished ever sits beside a tool that works. The design intent lands on disk as JSON that a human reads and corrects before anything trusts it. Repeated checking is then pure arithmetic — no model, no judgement, same answer every time. See [INSTALL.md](INSTALL.md) to deploy it, including on a different Revit version. ## `panellift` — outside Revit PCI Design Handbook Chapter 8 handling checks: stripping and yard handling of flat panels, from the insert positions the model already holds. Plain CPython, **no dependencies**, and no Revit import anywhere. That is the point — a calculation whose output reaches a plant has to be verifiable, and verifiable means a test suite that runs in seconds without a licence. It reproduces every published number in the ASPIRE Winter 2019 worked examples (which reprint PCI Table 8.3.1 and Figure 8.3.2), and it *derives* PCI's 0.0214 moment coefficient from the beam solution rather than quoting it: ```bash cd panellift && python -m pytest ``` **Run it rather than trusting a number printed here** — a suite grows every day and a README does not. See [panellift/PLAN.md](panellift/PLAN.md) for what is built, what is next, and the idealisations that are known to be idealisations. ## Filing feedback Please do — that is what this trial is for. Two templates when you open an issue: **Bug report** for something that crashed or gave a wrong answer, **Question** for something that was unclear. One thing worth knowing before you file: **this tool refuses rather than guesses, by design.** A row that reads "NOT JUDGED" with a stated reason — an unmapped parameter, a missing knowledge layer, a check that legitimately has nothing to say about this piece — is very often the tool working *correctly*, not a bug. The bug report template asks you to tell these two apart: - **Wrong answer** — it computed something, and the something is wrong, or it crashed. That is a code bug; file the Bug report template, and paste `python tools/setup_machine.py --check`'s full output — it is the single most diagnostic thing you can attach. - **Refused, and I think it shouldn't have** — it declined to answer and you believe it had enough information to. That is usually knowledge-layer work (a parameter role that needs mapping, a rating that needs publishing) rather than a code fix — file it as a Question, and say what you expected it to know. **No client or job data in an issue, a PR, or a screenshot — ever.** See [CONTRIBUTING.md](CONTRIBUTING.md) for the placeholder convention this project uses everywhere instead. ### What to ask the owner for This distribution ships no knowledge on purpose. To point it at a real job you will want, from the owner directly (not filed as an issue — these are not code, and they identify a real plant): - a **plant knowledge layer** — your office's parameter names, casting-bed conventions, and rigging defaults; - the **published hardware catalogue** — manufacturer ratings for lifting inserts and connectors, plus the master shop-ticket checklist Ticket QC reads; - sample decks or a walkthrough, if you want a guided first run rather than starting from the example in `examples/`. ## Working on this - **Never use pyRevit → Reload. Restart Revit.** A reload leaves the routes handler pointing at a dead engine and the next bridge request kills Revit. - IronPython 2.7 syntax under `WillTools.extension/`; modern Python is fine in `tools/` and `panellift/`. - Any change to a model needs a Transaction. Internal units are decimal feet. - Scope every `FilteredElementCollector`. An unfiltered one crashed Revit. See [CONTRIBUTING.md](CONTRIBUTING.md) before opening a PR.