{"status":"online","service":"Piping Calculator v28.0.0 (Pool-Type Specific with 50mm Support & Check Valves)","version":"28.0.0","database_available":true,"v28.0.0_fix":{"description":"Pool-type specific connection logic with 50mm support and Check Valves","changes":["Skimmer Pool: Main Drain, Skimmer, Return, Waste ONLY","Overflow Pool: Main Drain, Gutter, Return, Waste, Balance Tank Suction ONLY","Infinity Pool: Main Drain, Pool Basin, Return, Waste, Balance Tank Suction ONLY","Freeform Pool: Follows Overflow logic","Jacuzzi Spa: Main Drain, Return Jets, Air Blower, Waste ONLY","Dynamic pump room distance (never hardcoded)","50mm pipe fully supported","No cross-pollution between pool types","Check Valves fully implemented with pool-type specific logic","FIX: Check Valves appear in BOQ and Results Page","FIX: Puddle Flanges use exact-match only (no fallback)","FIX: Check Valve logic mirrors Ball Valve diameter rows"],"tier_table":{"400-450mm":{"pipe_dias":[25,32,50,63,75],"valve_dias":[32,50,63,75],"check_valve_dias":[32,50,63,75],"flange_dias":[25,32,50,63,75]},"450-600mm":{"pipe_dias":[25,32,50,63,75,90],"valve_dias":[32,50,63,75,90],"check_valve_dias":[32,50,63,75,90],"flange_dias":[25,32,50,63,75,90]},"600-900mm":{"pipe_dias":[25,32,50,63,75,90,110,160],"valve_dias":[32,50,63,75,90,110,160],"check_valve_dias":[32,50,63,75,90,110,160],"flange_dias":[25,32,50,63,75,90,110,160]},"900-2000mm":{"pipe_dias":[25,32,50,63,75,90,110,160,200,250,300],"valve_dias":[32,50,63,75,90,110,160,200],"check_valve_dias":[32,50,63,75,90,110,160,200],"flange_dias":[25,32,50,63,75,90,110,160,200]},"2000mm+":{"pipe_dias":[25,32,50,63,75,90,110,160,200,250,300],"valve_dias":[32,50,63,75,90,110,160,200],"check_valve_dias":[32,50,63,75,90,110,160,200],"flange_dias":[25,32,50,63,75,90,110,160,200]}},"pool_type_component_mapping":{"skimmer":["Main Drain","Skimmer","Return","Waste","Electrical"],"overflow":["Main Drain","Gutter","Return","Waste","Balance Tank Suction","Electrical"],"infinity":["Main Drain","Pool Basin","Return","Waste","Balance Tank Suction","Electrical"],"freeform":["Main Drain","Gutter","Return","Waste","Balance Tank Suction","Electrical"],"jacuzzi":["Main Drain","Return Jets","Air Blower","Waste","Electrical"]},"example_6x3x1.2_overflow":{"filter_dia":"450mm","pipe_diameters":["25mm","32mm","50mm","63mm","75mm"],"components":["Main Drain","Gutter","Return","Waste","Balance Tank Suction"],"ball_valves":["32mm","50mm","63mm","75mm"],"check_valves":["32mm","50mm","63mm","75mm"],"puddle_flanges":["25mm","32mm","50mm","63mm","75mm"]},"backward_compatible":true},"db_master_tables":{"pipes_master":"25,32,50,63,75,90,110,140,160,200,250,300 mm","ball_valves_master":"32,50,63,75,90,110,160,200 mm  (NO 25, NO 140)","check_valves_master":"32,50,63,75,90,110,160,200 mm  (same as ball valves)","puddle_flanges_master":"25,32,50,63,75,90,110,160,200 mm  (EXPANDED)","closest_dia_fallback":"auto via find_closest_dia() with validation warnings"},"pool_types":["skimmer","overflow","infinity","freeform","jacuzzi","spa"],"pool_type_logic":{"skimmer":{"balance_tank":false,"gutter":false,"float_valve":false,"gutter_drain":false,"pool_basin":false,"air_blower":false,"check_valves":"Mirrors Ball Valve diameters","components":["Skimmers","Main Drains","Return Inlets","Vacuum Point","Waste"]},"overflow":{"balance_tank":true,"gutter":true,"float_valve":true,"gutter_drain":true,"pool_basin":false,"air_blower":false,"check_valves":"Mirrors Ball Valve diameters","components":["Gutter","Balance Tank","Float Valve","Return Inlets","Waste"]},"infinity":{"balance_tank":true,"gutter":false,"float_valve":true,"gutter_drain":false,"pool_basin":true,"air_blower":false,"check_valves":"Mirrors Ball Valve diameters","components":["Infinity Weir","Pool Basin","Balance Tank","Float Valve","Return Inlets","Waste"]},"freeform":{"balance_tank":"Depends on construction_type","gutter":"Depends on construction_type","float_valve":"Depends on construction_type","gutter_drain":"Depends on construction_type","pool_basin":"Depends on construction_type","air_blower":false,"check_valves":"Mirrors Ball Valve diameters","components":"Follows Skimmer OR Overflow logic"},"jacuzzi":{"balance_tank":false,"gutter":false,"float_valve":false,"gutter_drain":false,"pool_basin":false,"air_blower":true,"check_valves":"Mirrors Ball Valve diameters","components":["Main Drain","Return Jets","Air Blower","Waste"]}},"check_valve_logic":{"description":"Check valves mirror Ball Valve diameter rows","method":"Check Valve diameter list matches Ball Valve diameter list exactly","result":"All diameters that appear in Ball Valves also appear in Check Valves","benefit":"Check Valve BOQ mirrors Ball Valve BOQ for consistency","example_skimmer":{"ball_valves":{"32mm":2,"50mm":2,"63mm":1,"75mm":1},"check_valves":{"32mm":1,"50mm":1,"63mm":1,"75mm":1}},"guarantee":"Every Ball Valve diameter row has a corresponding Check Valve diameter row"},"pipe_allocation":{"method":"ALL hydraulic systems contribute pipe lengths","systems":{"skimmer":["Main Drain","Skimmer","Return","Waste"],"overflow":["Main Drain","Gutter","Return","Waste","Balance Tank Suction"],"infinity":["Main Drain","Pool Basin","Return","Waste","Balance Tank Suction"],"jacuzzi":["Main Drain","Return","Air Blower","Waste"]},"accumulation":"Using += (never overwrite)","reconciliation":"Backfill missing pipe_dias with minimum branch length","example":"pipes[dia] = pipes.get(dia, 0) + quantity","critical":"Guarantees all pipe_dias including 50mm appear as BOQ rows"},"valves_flanges_v28_fix":{"rule":"Ball valves & puddle flanges assigned PER DIAMETER using tier-based eligibility","ball_valves":"32,50,63,75,90,110,160,200  (25mm NOT eligible)","check_valves":"32,50,63,75,90,110,160,200  (25mm NOT eligible) - mirrors Ball Valve diameters","puddle_flanges":"25,32,50,63,75,90,110,160,200  (25mm AND 32mm eligible)","distribution":"Proportional across valid diameters","validation":"sum(valves) == total_valves, sum(flanges) == total_flanges","no_hardcoded_cutoff":"Eligibility determined ONLY by valve_dias/check_valve_dias/flange_dias being non-empty","puddle_flange_rule":"EXACT MATCH ONLY — no fallback substitution","check_valve_rule":"MIRROR BALL VALVE DIAMETERS — every Ball Valve diameter gets a Check Valve diameter row"},"check_valves":{"description":"Check valves fully implemented with Ball Valve diameter mirroring","method":"Generates Check Valve diameter rows that mirror Ball Valve diameter rows","diameter_coverage":"Every diameter that appears in Ball Valves also appears in Check Valves","tier_eligibility":"Uses check_valve_dias from tier data","consistency":"Check Valve BOQ matches Ball Valve BOQ for diameter rows"},"50mm_support":{"description":"50mm pipe is now fully supported in all tiers","equipment_mapping_update":{"skimmer":"50mm","return_inlet":"50mm"},"tier_400_450":{"pipe_dias":[25,32,50,63,75],"valve_dias":[32,50,63,75],"check_valve_dias":[32,50,63,75],"flange_dias":[25,32,50,63,75]}},"dynamic_distance":{"description":"Pump room distance is dynamically controlled by frontend","default_fallback":"5m (only when frontend sends None, null, or 0)","never_hardcoded":"15m removed as default"},"puddle_flange_fix":{"description":"Puddle flanges now use EXACT MATCH ONLY — no fallback substitution","why":"Prevents duplicate 63mm puddle flanges when 50mm is missing from database","behavior":"If requested diameter not found in puddle_flanges_master, skip it entirely","affected_components":"Puddle Flanges only","unchanged_components":"Pipes (fallback allowed), Ball Valves (fallback allowed), Check Valves (fallback allowed)"},"check_valve_fix_v2":{"description":"Check valves now mirror Ball Valve diameter rows exactly","why":"Ensures Check Valve BOQ has the same diameter rows as Ball Valve BOQ","behavior":"Every Ball Valve diameter gets a corresponding Check Valve diameter with quantity 1","result":"Check Valve section shows the same items (diameters) as Ball Valve section","example":"Ball Valves: 32, 50, 63, 75 → Check Valves: 32, 50, 63, 75"}}