feat(understand): cable_takeoff - one row per load, rounded to the metre
cable_rows reads each load's power, phases, voltage, neutral and VFD from the P&ID's electrical texts near its tag, and its panel from the layout's wiring callouts (else the P&ID's), names normalised CP 1 -> CP-1. The length is the Manhattan distance on the layout from the tag to its panel, and the cable ROUNDUP(length x (1 + allowance)) to the metre, on the length rounded to 1e-6 m so binary noise never buys a metre. Power is never invented: a load with no stated kW keeps an empty cell and an open item. Without a layout the lengths stay empty with an open item per row. Room and panel totals count a panel package's power once, never its children's as well; the rule is on the method sheet. Sections only from the caller's section_rules - no standard table exists here. The workbook gains the cable shape (Metraj, Ozet by room and panel, Kontrol as the open-items list, Metodoloji) in the same three languages; cable_takeoff joins SECTION 27. Inventory regenerated; README snapshot 243 tools (238 advertised); registry snapshot analysis: 14. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
653535bcc1
commit
459d3b9228
@@ -15,9 +15,15 @@ import math
|
||||
from engineering.understand.network import build_network
|
||||
from engineering.understand.report import check_lang, write_workbook
|
||||
from engineering.understand.snapshot import take_snapshot
|
||||
from engineering.understand.takeoff import check_pipe_options, pipe_rows
|
||||
from engineering.understand.takeoff import (
|
||||
cable_rows,
|
||||
check_allowance,
|
||||
check_pipe_options,
|
||||
check_section_rules,
|
||||
pipe_rows,
|
||||
)
|
||||
|
||||
__all__ = ["run_pipe_takeoff"]
|
||||
__all__ = ["run_cable_takeoff", "run_pipe_takeoff"]
|
||||
|
||||
|
||||
def _check_tol(tol) -> float:
|
||||
@@ -84,3 +90,30 @@ async def run_pipe_takeoff(
|
||||
else None
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
async def run_cable_takeoff(
|
||||
backend,
|
||||
*,
|
||||
pid_path: str | None = None,
|
||||
layout_path: str | None = None,
|
||||
output: str | None = None,
|
||||
lang: str = "en",
|
||||
allowance: float = 0.20,
|
||||
section_rules=None,
|
||||
) -> dict:
|
||||
"""`cable_rows` over a P&ID and an optional layout, plus the workbook when `output` is named."""
|
||||
check_lang(lang)
|
||||
allowance = check_allowance(allowance)
|
||||
rules = check_section_rules(section_rules)
|
||||
pid = await take_snapshot(backend, pid_path)
|
||||
layout = await take_snapshot(backend, layout_path) if layout_path else None
|
||||
result = await asyncio.to_thread(
|
||||
cable_rows, pid, layout, allowance=allowance, section_rules=list(rules) or None
|
||||
)
|
||||
result["files"] = (
|
||||
await asyncio.to_thread(write_workbook, result, kind="cable", lang=lang, path=output)
|
||||
if output
|
||||
else None
|
||||
)
|
||||
return result
|
||||
|
||||
Reference in New Issue
Block a user