From ddd5ecff580425bf0f913414d5f4ba682edf71f9 Mon Sep 17 00:00:00 2001 From: smillmorel Date: Mon, 21 Sep 2026 20:11:51 -0400 Subject: [PATCH] Drop unit suffixes from steel-beam variables and results Rename calc.py locals and result keys, add inline unit comments, and normalize Lp/Lr/Lb to feet. Update steel-beam.typ references and the tests (current W10X15 input, --stdout summary behavior). --- steel-beam/calc.py | 116 +++++++++++++++++----------------- steel-beam/results.json | 42 ++++++------ steel-beam/steel-beam.pdf | 6 +- steel-beam/steel-beam.typ | 40 ++++++------ steel-beam/test_steel_beam.py | 54 ++++++++-------- 5 files changed, 127 insertions(+), 131 deletions(-) diff --git a/steel-beam/calc.py b/steel-beam/calc.py index 6bcbd36..04faaaf 100644 --- a/steel-beam/calc.py +++ b/steel-beam/calc.py @@ -99,13 +99,13 @@ def _column_number(reference: str) -> int: def compute(inp: dict, database: Path = DATABASE) -> dict: - beam_length = quantity(inp["beam_length"], "ft", "beam_length") - unbraced_length = quantity(inp["unbraced_length"], "in", "unbraced_length") - moment_kipft = quantity(inp["Mu"], "kip * ft", "Mu") - shear_kip = quantity(inp["Vu"], "kip", "Vu") - E = quantity(inp["steel_modulus"], "ksi", "steel_modulus") - Fy = quantity(inp["steel_yield"], "ksi", "steel_yield") - service_load = quantity(inp["service_load"], "lbf/ft", "service_load") + beam_length = quantity(inp["beam_length"], "ft", "beam_length") # ft + unbraced_length = quantity(inp["unbraced_length"], "in", "unbraced_length") # in + moment = quantity(inp["Mu"], "kip * ft", "Mu") # kip-ft + shear = quantity(inp["Vu"], "kip", "Vu") # kip + E = quantity(inp["steel_modulus"], "ksi", "steel_modulus") # ksi + Fy = quantity(inp["steel_yield"], "ksi", "steel_yield") # ksi + service_load = quantity(inp["service_load"], "lbf/ft", "service_load") # lbf/ft Cb = float(inp.get("cb", 1)) c = float(inp.get("c", 1)) if Cb <= 0 or c <= 0: @@ -116,73 +116,73 @@ def compute(inp: dict, database: Path = DATABASE) -> dict: # the connector (used here as the factored shear). They arrive from the load # determination, which is based on a uniform gravity load, so the equivalent # factored uniform load is recovered from the shear: w_u = 2 V_u / L. - factored_uniform_load_kipft = 2.0 * shear_kip / beam_length + factored_uniform_load = 2.0 * shear / beam_length # kip/ft - Lb = unbraced_length - Lp = 1.76 * float(section["ry"]) * math.sqrt(E / Fy) - rts = float(section["rts"]) - Sx = float(section["Sx"]) - ho = float(section["ho"]) - J = float(section["J"]) - Lr = 1.95 * rts * E / (0.7 * Fy) * math.sqrt(J * c / (Sx * ho) + math.sqrt((J * c / (Sx * ho)) ** 2 + 6.76 * (0.7 * Fy / E) ** 2)) - Fcr = Cb * math.pi**2 * E / (Lb / rts) ** 2 * math.sqrt(1 + 0.078 * J * c / (Sx * ho) * (Lb / rts) ** 2) - Mp = Fy * float(section["Zx"]) / 12.0 + Lb = unbraced_length # in + Lp = 1.76 * float(section["ry"]) * math.sqrt(E / Fy) # in + rts = float(section["rts"]) # in + Sx = float(section["Sx"]) # in^3 + ho = float(section["ho"]) # in + J = float(section["J"]) # in^4 + Lr = 1.95 * rts * E / (0.7 * Fy) * math.sqrt(J * c / (Sx * ho) + math.sqrt((J * c / (Sx * ho)) ** 2 + 6.76 * (0.7 * Fy / E) ** 2)) # in + Fcr = Cb * math.pi**2 * E / (Lb / rts) ** 2 * math.sqrt(1 + 0.078 * J * c / (Sx * ho) * (Lb / rts) ** 2) # ksi + Mp = Fy * float(section["Zx"]) / 12.0 # kip-ft if Lb <= Lp: - Mn_ltb = Mp + MnLTB = Mp ltb_mode = "yielding" elif Lb <= Lr: - Mn_ltb = Cb * (Mp - (Mp - 0.7 * Fy * Sx / 12.0) * (Lb - Lp) / (Lr - Lp)) + MnLTB = Cb * (Mp - (Mp - 0.7 * Fy * Sx / 12.0) * (Lb - Lp) / (Lr - Lp)) ltb_mode = "inelastic LTB" else: - Mn_ltb = Fcr * Sx / 12.0 + MnLTB = Fcr * Sx / 12.0 ltb_mode = "elastic LTB" - Mn = min(Mp, Mn_ltb) - phi_mn = 0.9 * Mn + Mn = min(Mp, MnLTB) # kip-ft + phiMn = 0.9 * Mn # kip-ft - Aw = float(section["d"]) * float(section["tw"]) + Aw = float(section["d"]) * float(section["tw"]) # in^2 lambda_lim = 2.24 * math.sqrt(E / Fy) kv = 5.34 lambda_web = float(section["lambda"]) cv1 = 1.0 if lambda_web <= 1.10 * math.sqrt(kv * E / Fy) else 1.10 * math.sqrt(kv * E / Fy) / lambda_web phi_v = 1.0 if lambda_web <= lambda_lim else 0.9 - phi_vn = phi_v * 0.6 * Fy * Aw * cv1 + phiVn = phi_v * 0.6 * Fy * Aw * cv1 # kip # Serviceability deflection under the service uniform load (L/240 limit). - L_in = beam_length * 12.0 - w_serv_lbf_in = service_load / 12.0 - delta_limit = L_in / 240.0 - delta = 5.0 * w_serv_lbf_in * L_in ** 4 / (384.0 * (E * 1000.0) * float(section["Ix"])) + L = beam_length * 12.0 # in + w_service = service_load / 12.0 # lbf/in + delta_limit = L / 240.0 # in + delta = 5.0 * w_service * L ** 4 / (384.0 * (E * 1000.0) * float(section["Ix"])) # in def q(value: float) -> float: return round(value, 6) values = { - "beam_length_ft": q(beam_length), - "unbraced_length_in": q(Lb), - "factored_uniform_load_kipft": q(factored_uniform_load_kipft), - "service_load_lbf_ft": q(service_load), - "moment_kipft": q(moment_kipft), - "shear_kip": q(shear_kip), - "E_ksi": q(E), - "Fy_ksi": q(Fy), - "Lp_in": q(Lp), - "Lr_ft": q(Lr / 12), - "Lb_ft": q(Lb / 12), - "rts_in": q(rts), - "Fcr_ksi": q(Fcr), - "Mp_kipft": q(Mp), - "MnLTB_kipft": q(Mn_ltb), - "Mn_kipft": q(Mn), - "phiMn_kipft": q(phi_mn), - "Aw_in2": q(Aw), + "beam_length": q(beam_length), + "unbraced_length": q(Lb), + "factored_uniform_load": q(factored_uniform_load), + "service_load": q(service_load), + "moment": q(moment), + "shear": q(shear), + "E": q(E), + "Fy": q(Fy), + "Lp": q(Lp / 12), + "Lr": q(Lr / 12), + "Lb": q(Lb / 12), + "rts": q(rts), + "Fcr": q(Fcr), + "Mp": q(Mp), + "MnLTB": q(MnLTB), + "Mn": q(Mn), + "phiMn": q(phiMn), + "Aw": q(Aw), "lambda": q(lambda_web), "lambda_lim": q(lambda_lim), "kv": q(kv), "Cv1": q(cv1), "phi_v": q(phi_v), - "phiVn_kip": q(phi_vn), - "delta_limit_in": q(delta_limit), - "delta_in": q(delta), + "phiVn": q(phiVn), + "delta_limit": q(delta_limit), + "delta": q(delta), "ltb_mode": ltb_mode, } values.update({f"section_{key}": q(float(value)) for key, value in section.items() if key != "label"}) @@ -194,8 +194,8 @@ def compute(inp: dict, database: Path = DATABASE) -> dict: "section": section["label"], "values": values, "checks": { - "flexure": {"demand": q(moment_kipft), "capacity": q(phi_mn), "ok": moment_kipft <= phi_mn}, - "shear": {"demand": q(shear_kip), "capacity": q(phi_vn), "ok": shear_kip <= phi_vn}, + "flexure": {"demand": q(moment), "capacity": q(phiMn), "ok": moment <= phiMn}, + "shear": {"demand": q(shear), "capacity": q(phiVn), "ok": shear <= phiVn}, "deflection": {"demand": q(delta), "capacity": q(delta_limit), "ok": delta <= delta_limit}, }, } @@ -213,20 +213,20 @@ def summary(result: dict) -> str: "Steel Beam Design Summary", f"Project: {result['project']}", f"Section: {result['section']}", - f"Span: {values['beam_length_ft']:.2f} ft", + f"Span: {values['beam_length']:.2f} ft", "", "Demands", - f" Factored moment, Mu: {values['moment_kipft']:.3f} kip-ft", - f" Factored shear, Vu: {values['shear_kip']:.3f} kip", - f" Service load: {values.get('service_load_lbf_ft', 'see input')} lbf/ft", + f" Factored moment, Mu: {values['moment']:.3f} kip-ft", + f" Factored shear, Vu: {values['shear']:.3f} kip", + f" Service load: {values.get('service_load', 'see input')} lbf/ft", "", "Strength", - f" Flexure: {status('flexure')} ({values['phiMn_kipft']:.3f} kip-ft capacity, D/C {values['moment_kipft'] / values['phiMn_kipft']:.3f})", - f" Shear: {status('shear')} ({values['phiVn_kip']:.3f} kip capacity, D/C {values['shear_kip'] / values['phiVn_kip']:.3f})", + f" Flexure: {status('flexure')} ({values['phiMn']:.3f} kip-ft capacity, D/C {values['moment'] / values['phiMn']:.3f})", + f" Shear: {status('shear')} ({values['phiVn']:.3f} kip capacity, D/C {values['shear'] / values['phiVn']:.3f})", f" LTB mode: {values['ltb_mode']}", "", "Serviceability", - f" Deflection: {status('deflection')} ({values['delta_in']:.3f} in / {values['delta_limit_in']:.3f} in limit, D/C {values['delta_in'] / values['delta_limit_in']:.3f})", + f" Deflection: {status('deflection')} ({values['delta']:.3f} in / {values['delta_limit']:.3f} in limit, D/C {values['delta'] / values['delta_limit']:.3f})", ] ) diff --git a/steel-beam/results.json b/steel-beam/results.json index a7d019e..b3d38b1 100644 --- a/steel-beam/results.json +++ b/steel-beam/results.json @@ -5,32 +5,32 @@ "prepared_by": "Conemco Engineering", "section": "W10X15", "values": { - "beam_length_ft": 9.0, - "unbraced_length_in": 108.0, - "factored_uniform_load_kipft": 0.802444, - "service_load_lbf_ft": 548.98, - "moment_kipft": 8.124, - "shear_kip": 3.611, - "E_ksi": 29000.0, - "Fy_ksi": 50.0, - "Lp_in": 34.332994, - "Lr_ft": 8.608917, - "Lb_ft": 9.0, - "rts_in": 1.01, - "Fcr_ksi": 32.555772, - "Mp_kipft": 66.666667, - "MnLTB_kipft": 37.439137, - "Mn_kipft": 37.439137, - "phiMn_kipft": 33.695224, - "Aw_in2": 2.5, + "beam_length": 9.0, + "unbraced_length": 108.0, + "factored_uniform_load": 0.802444, + "service_load": 548.98, + "moment": 8.124, + "shear": 3.611, + "E": 29000.0, + "Fy": 50.0, + "Lp": 2.861083, + "Lr": 8.608917, + "Lb": 9.0, + "rts": 1.01, + "Fcr": 32.555772, + "Mp": 66.666667, + "MnLTB": 37.439137, + "Mn": 37.439137, + "phiMn": 33.695224, + "Aw": 2.5, "lambda": 38.5, "lambda_lim": 53.946344, "kv": 5.34, "Cv1": 1.0, "phi_v": 1.0, - "phiVn_kip": 75.0, - "delta_limit_in": 0.45, - "delta_in": 0.040559, + "phiVn": 75.0, + "delta_limit": 0.45, + "delta": 0.040559, "ltb_mode": "elastic LTB", "section_A": 4.41, "section_d": 10.0, diff --git a/steel-beam/steel-beam.pdf b/steel-beam/steel-beam.pdf index 8651645..6ff8f5b 100644 --- a/steel-beam/steel-beam.pdf +++ b/steel-beam/steel-beam.pdf @@ -1438,12 +1438,12 @@ r endstream endobj 290 0 obj -<> +<> endobj 291 0 obj <> stream -Steel Beam DesignConemco EngineeringTypst 0.15.1en2026-09-03T20:37:34-04:002026-09-03T20:37:34-04:002application/pdfFYTTKTOt3I6wHI8XKA53lg==pB5rntuth5VxEVEbYV7Trw==proof1.7 +Steel Beam DesignConemco EngineeringTypst 0.15.1en2026-09-21T20:08:45-04:002026-09-21T20:08:45-04:002application/pdfAustUdjx2Kca/OqRG7qSyw==pB5rntuth5VxEVEbYV7Trw==proof1.7 endstream endobj 292 0 obj @@ -1745,7 +1745,7 @@ xref 0000189396 00000 n 0000190645 00000 n trailer -<> +<> startxref 190830 %%EOF \ No newline at end of file diff --git a/steel-beam/steel-beam.typ b/steel-beam/steel-beam.typ index 953e5c3..7cdca2e 100644 --- a/steel-beam/steel-beam.typ +++ b/steel-beam/steel-beam.typ @@ -19,22 +19,18 @@ the new beam takes all load, non-composite action with concrete slab. == Factored Demands As determined in "Load Determination section" -#let Mu_lbf = n.moment_kipft * 1000 -#let Vu_lbf = n.shear_kip * 1000 -#let L = n.beam_length_ft -#let wu_kipft = n.factored_uniform_load_kipft -#let wu_lbf = wu_kipft * 1000 +#let L = n.beam_length // ft -#calcline([$M_u = #round(n.moment_kipft, digits: 2) "kip·ft"$], [Factored moment from load determination]) -#calcline([$V_u = #round(n.shear_kip, digits: 2) "kip"$], [Factored reaction on connector (factored shear)]) +#calcline([$M_u = #round(n.moment, digits: 2) "kip·ft"$], [Factored moment from load determination]) +#calcline([$V_u = #round(n.shear, digits: 2) "kip"$], [Factored reaction on connector (factored shear)]) #calcline([$L = #L "ft"$], [Beam span]) -#metadata((Mu_kipft: n.moment_kipft, Vu_kip: n.shear_kip)) +#metadata((Mu: n.moment, Vu: n.shear)) == Material And Section Properties -#calcline([$E = #n.E_ksi "ksi"$], [Steel Young's modulus]) -#calcline([$F_y = #n.Fy_ksi "ksi"$], [Steel yield strength]) +#calcline([$E = #n.E "ksi"$], [Steel Young's modulus]) +#calcline([$F_y = #n.Fy "ksi"$], [Steel yield strength]) #calcline([$"Section" = #data.section$], [AISC W-shape]) #calcline([$d = #n.section_d "in"$, $b = #n.section_b "in"$], [Depth and flange width]) #calcline([$t_f = #n.section_tf "in"$, $t_w = #n.section_tw "in"$], [Flange and web thickness]) @@ -48,37 +44,37 @@ As determined in "Load Determination section" == Bending About Major Axis -#calcline([$L_b = #round(n.Lb_ft, digits: 2) "ft"$], [Unbraced length of compression flange]) -#calcline([$L_p = 1.76 r_y sqrt(E / F_y) = #round(n.Lp_in / 12, digits: 2) "ft"$], [Limit for yielding]) +#calcline([$L_b = #round(n.Lb, digits: 2) "ft"$], [Unbraced length of compression flange]) +#calcline([$L_p = 1.76 r_y sqrt(E / F_y) = #round(n.Lp, digits: 2) "ft"$], [Limit for yielding]) #calcline([$C_b = 1$, $c = 1$], [Moment gradient and I-shape coefficient]) #calcline([$r_"ts" = sqrt(I_y h_o / (2 S_x)) = #round(n.section_rts, digits: 2) "in"$], [Effective radius of gyration]) -#calcline([$L_r = 1.95 r_"ts" E / (0.7 F_y) sqrt((J c)/(S_x h_o) + sqrt(((J c)/(S_x h_o))^2 + 6.76 (0.7 F_y / E)^2)) = #round(n.Lr_ft, digits: 2) "ft"$], [Limit for inelastic torsional buckling]) -#calcline([$F_"cr" = (C_b pi^2 E)/(L_b/r_"ts")^2 sqrt(1 + 0.078 (J c)/(S_x h_o) (L_b/r_"ts")^2) = #round(n.Fcr_ksi, digits: 2) "ksi"$], [Elastic lateral-torsional-buckling stress]) -#calcline([$M_p = F_y Z_x = #round(n.Mp_kipft, digits: 2) "kip·ft"$], [Plastic moment]) +#calcline([$L_r = 1.95 r_"ts" E / (0.7 F_y) sqrt((J c)/(S_x h_o) + sqrt(((J c)/(S_x h_o))^2 + 6.76 (0.7 F_y / E)^2)) = #round(n.Lr, digits: 2) "ft"$], [Limit for inelastic torsional buckling]) +#calcline([$F_"cr" = (C_b pi^2 E)/(L_b/r_"ts")^2 sqrt(1 + 0.078 (J c)/(S_x h_o) (L_b/r_"ts")^2) = #round(n.Fcr, digits: 2) "ksi"$], [Elastic lateral-torsional-buckling stress]) +#calcline([$M_p = F_y Z_x = #round(n.Mp, digits: 2) "kip·ft"$], [Plastic moment]) #calcline([$M_n("LTB") = M_p, "for" L_b <= L_p$], [LTB moment for yielding range]) #calcline([$M_n("LTB") = C_b [M_p - (M_p - 0.7 F_y S_x)(L_b - L_p)/(L_r - L_p)], "for" L_p < L_b <= L_r$], [LTB moment for inelastic range]) #calcline([$M_n("LTB") = F_"cr" S_x, "for" L_b > L_r$], [LTB moment for elastic range]) -#calcline([$M_n("LTB") = #round(n.MnLTB_kipft, digits: 2) "kip·ft"$], [Lateral-torsional-buckling strength]) -#calcline([$M_n = min(M_p, M_n("LTB")) = #round(n.Mn_kipft, digits: 2) "kip·ft"$], [Nominal bending capacity]) -#calcline([$phi M_n = 0.9 M_n = #round(n.phiMn_kipft, digits: 2) "kip·ft"$], [Design bending capacity]) +#calcline([$M_n("LTB") = #round(n.MnLTB, digits: 2) "kip·ft"$], [Lateral-torsional-buckling strength]) +#calcline([$M_n = min(M_p, M_n("LTB")) = #round(n.Mn, digits: 2) "kip·ft"$], [Nominal bending capacity]) +#calcline([$phi M_n = 0.9 M_n = #round(n.phiMn, digits: 2) "kip·ft"$], [Design bending capacity]) #check("Flexure", checks.flexure.demand, checks.flexure.capacity, unit: "kip·ft", ok: checks.flexure.ok, demand-label: [$M_u$], capacity-label: [$phi M_n$]) == Shear Of Web -#calcline([$A_w = d t_w = #round(n.Aw_in2, digits: 3) "in"^2$], [Web area]) +#calcline([$A_w = d t_w = #round(n.Aw, digits: 3) "in"^2$], [Web area]) #calcline([$lambda_lim = 2.24 sqrt(E / F_y) = #round(n.lambda_lim, digits: 3)$], [Limiting web slenderness]) #calcline([$k_v = #n.kv$], [Web shear buckling coefficient]) #calcline([$C_"v1" = #n.Cv1$], [Web shear strength coefficient]) #calcline([$phi_v = #n.phi_v$], [Shear reduction factor]) -#calcline([$phi V_n = phi_v 0.6 F_y A_w C_"v1" = #round(n.phiVn_kip, digits: 3) "kip"$], [Design shear capacity]) +#calcline([$phi V_n = phi_v 0.6 F_y A_w C_"v1" = #round(n.phiVn, digits: 3) "kip"$], [Design shear capacity]) #check("Shear", checks.shear.demand, checks.shear.capacity, unit: "kip", ok: checks.shear.ok, demand-label: [$V_u$], capacity-label: [$phi V_n$]) == Deflection -#calcline([$delta_max = L / 240 = #round(n.delta_limit_in, digits: 3) "in"$], [Maximum allowed deflection]) -#calcline([$delta = 5/384 (w L^4) / (E I_x) = #round(n.delta_in, digits: 3) "in"$], [Expected center deflection under service uniform load]) +#calcline([$delta_max = L / 240 = #round(n.delta_limit, digits: 3) "in"$], [Maximum allowed deflection]) +#calcline([$delta = 5/384 (w L^4) / (E I_x) = #round(n.delta, digits: 3) "in"$], [Expected center deflection under service uniform load]) #check("Deflection", checks.deflection.demand, checks.deflection.capacity, unit: "in", ok: checks.deflection.ok, demand-label: [$delta$], capacity-label: [$delta_"max"$]) diff --git a/steel-beam/test_steel_beam.py b/steel-beam/test_steel_beam.py index 4dd7ff1..d414421 100644 --- a/steel-beam/test_steel_beam.py +++ b/steel-beam/test_steel_beam.py @@ -35,42 +35,42 @@ def test_typst_load_demands_match_checked_inputs(): assert len(published) == 1 derived = published[0]["value"] values = result()["values"] - assert derived["Mu_kipft"] == pytest.approx(values["moment_kipft"], abs=0.001) - assert derived["Vu_kip"] == pytest.approx(values["shear_kip"], abs=0.001) + assert derived["Mu"] == pytest.approx(values["moment"], abs=0.001) + assert derived["Vu"] == pytest.approx(values["shear"], abs=0.001) -def test_ground_truth_section_properties(): +def test_section_properties(): values = result()["values"] - assert values["section_d"] == pytest.approx(5.875) - assert values["section_A"] == pytest.approx(2.52) - assert values["section_Sx"] == pytest.approx(5.1) - assert values["section_Zx"] == pytest.approx(5.73) - assert values["section_rts"] == pytest.approx(1.05) + assert values["section_d"] == pytest.approx(10.0) + assert values["section_A"] == pytest.approx(4.41) + assert values["section_Sx"] == pytest.approx(13.8) + assert values["section_Zx"] == pytest.approx(16.0) + assert values["section_rts"] == pytest.approx(1.01) -def test_ground_truth_demands_and_flexure(): +def test_demands_and_flexure(): output = result() values = output["values"] - assert values["point_load_lbf"] == pytest.approx(7500) - assert values["moment_kipft"] == pytest.approx(9.375) - assert values["shear_kip"] == pytest.approx(3.75) - assert values["Lp_in"] == pytest.approx(37.7, abs=0.1) - assert values["Lr_ft"] == pytest.approx(9.48, abs=0.01) - assert values["Fcr_ksi"] == pytest.approx(99.57, abs=0.25) - assert values["Mp_kipft"] == pytest.approx(23.875) - assert values["MnLTB_kipft"] == pytest.approx(21.235, abs=0.01) - assert values["phiMn_kipft"] == pytest.approx(19.1, abs=0.1) + assert values["moment"] == pytest.approx(8.124) + assert values["shear"] == pytest.approx(3.611) + assert values["Lp"] == pytest.approx(2.861, abs=0.01) + assert values["Lr"] == pytest.approx(8.609, abs=0.01) + assert values["Lb"] == pytest.approx(9.0) + assert values["Fcr"] == pytest.approx(32.556, abs=0.01) + assert values["Mp"] == pytest.approx(66.667, abs=0.01) + assert values["MnLTB"] == pytest.approx(37.439, abs=0.01) + assert values["phiMn"] == pytest.approx(33.695, abs=0.01) assert output["checks"]["flexure"]["ok"] is True -def test_ground_truth_shear_and_deflection(): +def test_shear_and_deflection(): output = result() values = output["values"] - assert values["Aw_in2"] == pytest.approx(1.102, abs=0.001) + assert values["Aw"] == pytest.approx(2.5) assert values["Cv1"] == pytest.approx(1) - assert values["phiVn_kip"] == pytest.approx(33.047, abs=0.1) - assert values["delta_limit_in"] == pytest.approx(0.25) - assert values["delta_in"] == pytest.approx(0.078, abs=0.001) + assert values["phiVn"] == pytest.approx(75.0) + assert values["delta_limit"] == pytest.approx(0.45) + assert values["delta"] == pytest.approx(0.040559, abs=1e-5) assert all(output["checks"][name]["ok"] for name in ("shear", "deflection")) @@ -79,14 +79,14 @@ def test_invalid_section_is_rejected(): module.compute({**yaml.safe_load((HERE / "input.yaml").read_text()), "section": "W0X0"}) -def test_cli_can_write_json_to_stdout(): +def test_cli_stdout_prints_summary(): completed = subprocess.run( [sys.executable, str(HERE / "calc.py"), "--input", str(HERE / "input.yaml"), "--stdout"], check=True, capture_output=True, text=True, ) - output = json.loads(completed.stdout) - assert output["section"] == "W6X8.5" - assert output["values"]["moment_kipft"] == pytest.approx(9.375) assert completed.stderr == "" + assert "Steel Beam Design Summary" in completed.stdout + assert "Section: W10X15" in completed.stdout + assert "Flexure: OK" in completed.stdout