139 lines
3.7 KiB
TypeScript
139 lines
3.7 KiB
TypeScript
import { create } from 'zustand';
|
|
import {
|
|
calculateGlobalWindData,
|
|
type TerrainCategory,
|
|
type StructureClass,
|
|
} from '../lib/wind-kernel';
|
|
import { computeCpiSimplified, clampCpi, type PermeabilityCase } from '../lib/internal-pressure';
|
|
|
|
export interface GlobalWindState {
|
|
// Entradas (Inputs)
|
|
v0: number;
|
|
s1: number;
|
|
s3: number;
|
|
s3Group: 1 | 2 | 3 | 4 | 5;
|
|
terrainCategory: TerrainCategory;
|
|
largestDimension: number;
|
|
heightZ: number;
|
|
|
|
// Saídas (Calculados)
|
|
structureClass: StructureClass;
|
|
s2: number;
|
|
vk: number;
|
|
q: number;
|
|
|
|
// Pressão interna e Vento
|
|
windAngle: 0 | 90;
|
|
permeabilityCase: PermeabilityCase;
|
|
cpiRatio: number;
|
|
cpi: number;
|
|
|
|
// Ações
|
|
updateCalculations: () => void;
|
|
setV0: (val: number) => void;
|
|
setS1: (val: number) => void;
|
|
setS3: (val: number) => void;
|
|
setS3Group: (group: 1 | 2 | 3 | 4 | 5) => void;
|
|
setTerrainCategory: (cat: TerrainCategory) => void;
|
|
setDimensions: (largestDim: number, z: number) => void;
|
|
setWindAngle: (angle: 0 | 90) => void;
|
|
setPermeabilityCase: (c: PermeabilityCase) => void;
|
|
setCpiRatio: (r: number) => void;
|
|
setCpiManual: (c: number) => void;
|
|
}
|
|
|
|
function calcCpi(permeabilityCase: PermeabilityCase, ratio: number, windAngle: 0 | 90): number {
|
|
if (permeabilityCase === 'airtight') return 0; // Just as an example, computeCpiSimplified handles it
|
|
const value = computeCpiSimplified({
|
|
case: permeabilityCase,
|
|
ratio,
|
|
windAngle,
|
|
});
|
|
return clampCpi(value);
|
|
}
|
|
|
|
export const useWindStore = create<GlobalWindState>((set, get) => {
|
|
const recalc = (state: GlobalWindState): Partial<GlobalWindState> => {
|
|
const calc = calculateGlobalWindData(
|
|
state.v0,
|
|
state.s1,
|
|
state.s3,
|
|
state.terrainCategory,
|
|
state.largestDimension,
|
|
state.heightZ,
|
|
);
|
|
return {
|
|
structureClass: calc.structClass,
|
|
s2: calc.s2,
|
|
vk: calc.vk,
|
|
q: calc.q,
|
|
cpi: calcCpi(state.permeabilityCase, state.cpiRatio, state.windAngle),
|
|
};
|
|
};
|
|
|
|
return {
|
|
v0: 40,
|
|
s1: 1.0,
|
|
s3: 1.0,
|
|
s3Group: 3,
|
|
terrainCategory: 'II',
|
|
largestDimension: 30,
|
|
heightZ: 10,
|
|
|
|
structureClass: 'B',
|
|
s2: 1.06,
|
|
vk: 42.4,
|
|
q: 1.1024,
|
|
|
|
windAngle: 0,
|
|
permeabilityCase: 'four-equally-permeable',
|
|
cpiRatio: 1.0,
|
|
cpi: calcCpi('four-equally-permeable', 1.0, 0),
|
|
|
|
updateCalculations: () => set((state) => recalc(state)),
|
|
|
|
setV0: (val) => {
|
|
set({ v0: val });
|
|
get().updateCalculations();
|
|
},
|
|
setS1: (val) => {
|
|
set({ s1: val });
|
|
get().updateCalculations();
|
|
},
|
|
setS3: (val) => {
|
|
set({ s3: val });
|
|
get().updateCalculations();
|
|
},
|
|
setS3Group: (group) => {
|
|
const newS3 = group === 1 ? 1.10 : group === 2 ? 1.08 : group === 3 ? 1.0 : group === 4 ? 0.95 : 0.83;
|
|
set({ s3Group: group, s3: newS3 });
|
|
get().updateCalculations();
|
|
},
|
|
setTerrainCategory: (cat) => {
|
|
set({ terrainCategory: cat });
|
|
get().updateCalculations();
|
|
},
|
|
setDimensions: (largestDim, z) => {
|
|
set({ largestDimension: largestDim, heightZ: z });
|
|
get().updateCalculations();
|
|
},
|
|
setWindAngle: (angle) => {
|
|
set({ windAngle: angle });
|
|
get().updateCalculations();
|
|
},
|
|
setPermeabilityCase: (c) => {
|
|
set({ permeabilityCase: c });
|
|
get().updateCalculations();
|
|
},
|
|
setCpiRatio: (r) => {
|
|
set({ cpiRatio: r });
|
|
get().updateCalculations();
|
|
},
|
|
setCpiManual: (c) => {
|
|
set({ cpi: clampCpi(c) });
|
|
// Not calling updateCalculations to avoid overriding it immediately if permeabilityCase applies,
|
|
// but if the user overrides manually we might want to switch permeabilityCase to 'custom' ?
|
|
// Wait, there is no 'custom'. We just set the value.
|
|
},
|
|
};
|
|
}); |