import { usePileCapStore } from '../../store/pileCapStore';
export const DetailedReport = () => {
const { geometry, materials, results, reinforcement } = usePileCapStore();
if (!results) {
return
No results available.
;
}
const fmt = (n: number, d: number = 2) => n.toFixed(d);
const fmt1 = (n: number) => n.toFixed(1);
const fmt4 = (n: number) => n.toFixed(4);
// --- Constants & Intermediate Calculations ---
const densityConcrete = 0.150; // kcf
const densitySoil = 0.110; // kcf
const pedestalHeight = 3.0; // ft
const pileCount = geometry.pileRows * geometry.pileColumns;
// Weights
const footingWeight = geometry.length * geometry.width * (geometry.depth / 12) * densityConcrete;
const pedestalWeight = (geometry.columnLength / 12) * (geometry.columnWidth / 12) * pedestalHeight * densityConcrete;
const soilWeight = (geometry.length * geometry.width - (geometry.columnLength / 12) * (geometry.columnWidth / 12)) * geometry.soilCover * densitySoil;
const buoyancy = 0.0; // Placeholder
// Arms
const armX = geometry.width / 2;
const armZ = geometry.length / 2;
// Forces & Moments for Overturning
const P = results.columnDesign.axialLoad;
const Mx = results.columnDesign.demandX;
const Mz = results.columnDesign.demandY;
const Vx = 0.0; // Placeholder
const Vz = 0.0; // Placeholder
const R_v = footingWeight + pedestalWeight + soilWeight - buoyancy + P;
const R_M_X = footingWeight * armX + pedestalWeight * armX + soilWeight * armX + buoyancy * armX + P * armX; // Simplified arm assumption from user text
const R_M_Z = footingWeight * armZ + pedestalWeight * armZ + soilWeight * armZ + buoyancy * armZ + P * armZ;
// One-Way Shear Intermediates
const OB = (footingWeight + soilWeight - buoyancy) / (geometry.length * geometry.width);
const d_bot_x = geometry.depth - reinforcement.bottomConcreteCover - 0.5; // Approx db/2
const d_bot_z = geometry.depth - reinforcement.bottomConcreteCover - 1.0 - 0.5; // Approx
const d_avg = (d_bot_x + d_bot_z) / 2;
// Punching Shear Intermediates
const bo_d2 = 2 * (geometry.columnLength + d_avg) + 2 * (geometry.columnWidth + d_avg); // Approx
const Abo = (geometry.columnLength + d_avg) * (geometry.columnWidth + d_avg);
const Fu_punch = P + pedestalWeight + OB * (Abo / 144) - 0; // Simplified
// Column Intermediates
const Ec = 57 * Math.sqrt(materials.fc);
const fr = 7.5 * Math.sqrt(materials.fc) / 1000;
// Parse Bar Size
const barSizeNum = parseInt(reinforcement.columnBarSize.replace('#', '')) || 6;
const db = barSizeNum / 8;
const As_bar = Math.PI * Math.pow(db / 2, 2);
const cover = 2.5; // Clear cover
const d_prime = cover + db / 2;
// Helper Components
const SectionHeader = ({ title }: { title: string }) => (
{title}
);
const MathLine = ({ label, formula, value, unit = '' }: { label?: string, formula: string, value?: string, unit?: string }) => (
{label && {label}}
{formula}
{value && = {value} {unit}}
);
const CheckLine = ({ label, val1, val2, status }: { label: string, val1: string, val2: string, status: boolean }) => (
{label}
{val1} < {val2} {status ? 'OK' : 'NG'}
);
return (
{/* GEOMETRY */}
| Parameter | Value |
| Pile Cap Length (X-dir) | {fmt(geometry.length)} ft |
| Pile Cap Width (Z-dir) | {fmt(geometry.width)} ft |
| Pile Cap Thickness | {fmt1(geometry.depth)} in OK |
| Soil Cover | {fmt(geometry.soilCover)} ft |
| Batter | 0.0 deg |
| Column Length (X-dir) | {fmt1(geometry.columnLength)} in |
| Column Width (Z-dir) | {fmt1(geometry.columnWidth)} in |
| Column Offset (X-dir) | {fmt1(geometry.columnOffsetX)} in OK |
| Column Offset (Z-dir) | {fmt1(geometry.columnOffsetZ)} in OK |
{/* PILE REACTIONS */}
| Parameter | Value | Unit |
| Number of Piles | {pileCount} | |
| Size | {geometry.pileSize} | in |
| Pile Spacing | {fmt(geometry.pileSpacingX)} | ft |
| Edge | {fmt(geometry.pileEdgeDistance)} | ft |
| Acc. Offset | {geometry.accidentalOffset} | in |
| Top Emb. | {geometry.pileTopEmbed} | in |
| Pile Compression Capacity | {fmt1(geometry.pileCompressionCapacity)} | kip |
| Pile Tension Capacity | {fmt1(geometry.pileTensionCapacity)} | kip |
| Pile Lateral Capacity | {fmt1(geometry.pileLateralCapacity)} | kip |
| Pile Axial Capacity Ratio | {fmt(results.maxPileReaction / geometry.pileCompressionCapacity)} | {results.maxPileReaction <= geometry.pileCompressionCapacity ? "OK" : "NG"} |
| Pile Group Hor. Capacity Ratio | 0.00 | OK |
{/* APPLIED LOADS */}
| Load Type | Dead | Live | RLive | Snow | Wind | Seismic | Unit |
{(() => {
const govCase = usePileCapStore.getState().loads.cases.find(c => c.id === results.governingCaseId);
if (!govCase) return null;
return (
<>
| Axial Force P | {fmt(govCase.deadLoad)} | {fmt(govCase.liveLoad)} | {fmt(govCase.roofLiveLoad)} | {fmt(govCase.snowLoad)} | {fmt(govCase.windLoad)} | {fmt(govCase.seismicLoad)} | kip |
| Moment about X Mx | {fmt(govCase.momentX)} | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | k-ft |
| Moment about Z Mz | {fmt(govCase.momentY)} | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | k-ft |
| Shear Force Vx | {fmt(govCase.shearX)} | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | kip |
| Shear Force Vz | {fmt(govCase.shearY)} | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | kip |
>
);
})()}
{/* OVERTURNING */}
Overturning about X-X
Overturning moment X-X = {fmt(Mx)} k-ft
Resisting about X-X
Resisting force Rv = {fmt(R_v)} kip
Resisting moment X-X = {fmt(R_M_X)} k-ft
Overturning about Z-Z
Overturning moment Z-Z = {fmt(Mz)} k-ft
Resisting about Z-Z
Resisting force Rv = {fmt(R_v)} kip
Resisting moment Z-Z = {fmt(R_M_Z)} k-ft
{/* ONE-WAY SHEAR */}
| Concrete fc | {materials.fc / 1000} ksi |
| Soil density | {densitySoil * 1000} pcf |
- Shear at 'd' from column face
{results.shearChecks.filter(c => c.type.includes('One-Way')).map((check, i) => (
))}
{/* BENDING */}
- Bottom Bars
{/* Placeholder capacity */}
{/* PUNCHING SHEAR */}
- Punching at 'd/2' from column face
c.type.includes('Punching'))?.ratio || 0 * 100)} unit="psi" />
c.type.includes('Punching'))?.capacity || 0 / 1000)} unit="psi" />
c.type.includes('Punching'))?.ratio || 0)} val2="1.0" status={true} />
{/* LOAD TRANSFER */}
Maximum Axial Compression
Pile Axial Table
{results.pileReactions.map((p, i) => (
P{i + 1}: {fmt1(p.reaction)}k
))}
{/* COLUMN CALCULATIONS */}
| As (in2) | d (in) | Strain | fs (ksi) | fc (ksi) | Fs (kip) | Ms (k-ft) | Is (in4) |
{(() => {
const h = geometry.columnLength;
const c = 0.3 * (h - cover); // Trial value
const eps_c = 0.003;
// Generate layers based on assumed 12-bar arrangement (4x4)
// Top: 4 bars at d_prime
// Bottom: 4 bars at h - d_prime
// Sides: 2 bars each side, distributed
// For simplicity, let's just show top, bottom, and 2 intermediate layers
const layers = [];
// Top Layer (4 bars)
layers.push({ d: d_prime, As: 4 * As_bar });
// Intermediate Layers (2 bars each, say 2 layers)
const spacing = (h - 2 * d_prime) / 3;
layers.push({ d: d_prime + spacing, As: 2 * As_bar });
layers.push({ d: d_prime + 2 * spacing, As: 2 * As_bar });
// Bottom Layer (4 bars)
layers.push({ d: h - d_prime, As: 4 * As_bar });
return layers.map((layer, i) => {
const strain = eps_c * (c - layer.d) / c;
const fs = Math.max(Math.min(strain * 29000, 60), -60);
const fc_stress = strain > 0 ? 0 : 0; // Simplified
const Fs = layer.As * (fs - fc_stress);
const Ms = Fs * (h / 2 - layer.d) / 12;
const Is = layer.As * Math.pow(h / 2 - layer.d, 2);
return (
| {fmt(layer.As)} | {fmt1(layer.d)} | {fmt4(strain)} | {fmt1(fs)} | {fmt1(fc_stress)} | {fmt1(Fs)} | {fmt1(Ms)} | {fmt1(Is)} |
);
});
})()}
);
};