updated the grain describers to use the new enum in the pond for the moisture calculation, changed the extract moisture function to account for custom grain types, and if there is no equation set it will return the humidity, updated instances where the bin uses that function to pass in the grain settings in its inventory
This commit is contained in:
parent
bdddcfc103
commit
d6c670fb78
16 changed files with 596 additions and 140 deletions
|
|
@ -417,6 +417,7 @@ export default function BinCard(props: Props) {
|
|||
hottestNodeTemp={valDisplay === "high" ? hotNode?.temp : undefined}
|
||||
coldestNodeTemp={valDisplay === "low" ? coldNode?.temp : undefined}
|
||||
inventoryControl={bin.inventoryControl()}
|
||||
customGrain={bin.customGrain()}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -39,11 +39,12 @@ interface Props {
|
|||
heaters?: Controller[];
|
||||
fans?: Controller[];
|
||||
grain?: pond.Grain;
|
||||
customGrain?: pond.GrainSettings
|
||||
}
|
||||
|
||||
export default function BinConditioningCard(props: Props) {
|
||||
const classes = useStyles();
|
||||
const { interactions, interactionDevices, plenums, ambients, heaters, fans, grain, mode } = props;
|
||||
const { interactions, interactionDevices, plenums, ambients, heaters, fans, grain, mode, customGrain } = props;
|
||||
const [sourceMap, setSourceMap] = useState<Map<string, Component>>(new Map());
|
||||
const [sinkMap, setSinkMap] = useState<Map<string, Component>>(new Map());
|
||||
|
||||
|
|
@ -87,6 +88,7 @@ export default function BinConditioningCard(props: Props) {
|
|||
sink={sink}
|
||||
source={source}
|
||||
grain={grain}
|
||||
customGrain={customGrain}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,10 +84,11 @@ interface Props {
|
|||
source: Component;
|
||||
sink: Component;
|
||||
grain?: pond.Grain;
|
||||
customGrain?: pond.GrainSettings
|
||||
}
|
||||
|
||||
export default function BinConditioningInteraction(props: Props) {
|
||||
const { interaction, source, sink, grain, deviceId } = props;
|
||||
const { interaction, source, sink, grain, deviceId, customGrain } = props;
|
||||
const [sliderVals, setSliderVals] = useState<Map<quack.MeasurementType, number>>(new Map());
|
||||
const [sliderMarks, setSliderMarks] = useState<Map<quack.MeasurementType, number>>(new Map());
|
||||
//this is the emc value calculated from the interactions temp and humidity conditions
|
||||
|
|
@ -127,7 +128,6 @@ export default function BinConditioningInteraction(props: Props) {
|
|||
if (
|
||||
grain !== undefined &&
|
||||
grain !== pond.Grain.GRAIN_INVALID &&
|
||||
grain !== pond.Grain.GRAIN_CUSTOM &&
|
||||
temp &&
|
||||
hum
|
||||
) {
|
||||
|
|
@ -135,8 +135,9 @@ export default function BinConditioningInteraction(props: Props) {
|
|||
//the emc calc needs the temp to be in celsius
|
||||
temp = fahrenheitToCelsius(temp);
|
||||
}
|
||||
let emc = ExtractMoisture(grain, temp, hum);
|
||||
setBaseEMC(emc);
|
||||
let emc = ExtractMoisture(grain, temp, hum, customGrain)
|
||||
setBaseEMC(emc === hum ? undefined : emc);
|
||||
|
||||
}
|
||||
}, [sliderVals, grain]);
|
||||
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ interface Props {
|
|||
hottestNodeTemp?: number;
|
||||
coldestNodeTemp?: number;
|
||||
inventoryControl?: pond.BinInventoryControl;
|
||||
customGrain?: pond.GrainSettings;
|
||||
}
|
||||
|
||||
interface GrainNodePoint {
|
||||
|
|
@ -211,7 +212,8 @@ export default function BinSVGV2(props: Props) {
|
|||
hottestNodeTemp,
|
||||
coldestNodeTemp,
|
||||
inventoryControl,
|
||||
co2Sensors
|
||||
co2Sensors,
|
||||
customGrain
|
||||
} = props;
|
||||
const [{ user }] = useGlobalState();
|
||||
const [extraDetails, setExtraDetails] = useState<"temps" | "hums">("temps");
|
||||
|
|
@ -683,7 +685,7 @@ export default function BinSVGV2(props: Props) {
|
|||
x: cablePos,
|
||||
y: nodeY + 10,
|
||||
stroke: "green",
|
||||
value: ExtractMoisture(props.grainType, temp, cable.humidities[index] ?? 0).toFixed(1)+"%",
|
||||
value: ExtractMoisture(props.grainType, temp, cable.humidities[index] ?? 0, customGrain).toFixed(1)+"%",
|
||||
})
|
||||
!showTempHum &&
|
||||
nodeClickData.push({
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ import { getDistanceUnit, or, getTemperatureUnit, getGrainUnit } from "utils";
|
|||
import { makeStyles } from "@mui/styles";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import BinSelector from "./BinSelector";
|
||||
import CustomGrainForm from "grain/CustomGrainForm";
|
||||
// import BinSelector from "./BinSelector";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => {
|
||||
|
|
@ -205,6 +206,7 @@ export default function BinSettings(props: Props) {
|
|||
const libracartAPI = useLibraCartProxyAPI()
|
||||
const [lcDestination, setlcDestination] = useState<Option | null>()
|
||||
const [lcDestinationOptions, setlcDestinationOptions] = useState<Option[]>([])
|
||||
const [customGrain, setCustomGrain] = useState<pond.GrainSettings>()
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
|
|
@ -236,6 +238,9 @@ export default function BinSettings(props: Props) {
|
|||
initForm.inventory.grainType
|
||||
).bushelsPerTonne;
|
||||
}
|
||||
if (initForm.inventory.customGrain){
|
||||
setCustomGrain(initForm.inventory.customGrain)
|
||||
}
|
||||
//if the target temp is not set (older bins) make it the midpoint of the high and low temps assuming they are set otherwise make it 15
|
||||
if (!initForm.inventory.targetTemperature || initForm.inventory.targetTemperature) {
|
||||
if (initForm.highTemp && initForm.lowTemp) {
|
||||
|
|
@ -493,6 +498,7 @@ export default function BinSettings(props: Props) {
|
|||
form.inventory.autoThreshold = autoFillThreshold
|
||||
//if the users preferences are in feet convert the distance to cm otherwise it was entered as cm so use that
|
||||
form.inventory.lidarDropCm = getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET ? lidarDropDistance * 30.48 : lidarDropDistance
|
||||
form.inventory.customGrain = customGrain
|
||||
}
|
||||
binAPI
|
||||
.updateBin(bin.key(), form, as)
|
||||
|
|
@ -1014,7 +1020,37 @@ export default function BinSettings(props: Props) {
|
|||
{isCustom ? "Custom" : "Grain"}
|
||||
</Typography> */}
|
||||
<Box>
|
||||
{!isCustomInventory && (
|
||||
{isCustomInventory ?
|
||||
<React.Fragment>
|
||||
{storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER ?
|
||||
<React.Fragment>
|
||||
<TextField
|
||||
label="Type"
|
||||
value={customTypeName}
|
||||
type="text"
|
||||
onChange={event => {
|
||||
updateForm(
|
||||
"inventory",
|
||||
pond.BinInventory.create({
|
||||
...form.inventory,
|
||||
customTypeName: event.target.value
|
||||
})
|
||||
);
|
||||
updateFormExtension("customTypeName", event.target.value);
|
||||
}}
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
className={classes.bottomSpacing}
|
||||
/>
|
||||
</React.Fragment>
|
||||
:
|
||||
<Box sx={{border: "1px solid white", borderRadius: 2, padding: 2, marginBottom: 2}}>
|
||||
<CustomGrainForm grainSettings={customGrain} onGrainSettingsChange={(newGrainSettings) => {setCustomGrain(newGrainSettings)}}/>
|
||||
</Box>
|
||||
}
|
||||
</React.Fragment>
|
||||
:
|
||||
<React.Fragment>
|
||||
<Box className={classes.bottomSpacing}>
|
||||
<SearchSelect
|
||||
label="Type"
|
||||
|
|
@ -1040,49 +1076,6 @@ export default function BinSettings(props: Props) {
|
|||
options={grainOptions}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
{isCustomInventory ? (
|
||||
<React.Fragment>
|
||||
<TextField
|
||||
label="Type"
|
||||
value={customTypeName}
|
||||
type="text"
|
||||
onChange={event => {
|
||||
updateForm(
|
||||
"inventory",
|
||||
pond.BinInventory.create({
|
||||
...form.inventory,
|
||||
customTypeName: event.target.value
|
||||
})
|
||||
);
|
||||
updateFormExtension("customTypeName", event.target.value);
|
||||
}}
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
className={classes.bottomSpacing}
|
||||
/>
|
||||
{storageType !== pond.BinStorage.BIN_STORAGE_FERTILIZER && (
|
||||
<TextField
|
||||
label="Bushels Per Tonne"
|
||||
value={bushPerTonne}
|
||||
type="number"
|
||||
onChange={event => {
|
||||
updateForm(
|
||||
"inventory",
|
||||
pond.BinInventory.create({
|
||||
...form.inventory,
|
||||
bushelsPerTonne: +event.target.value
|
||||
})
|
||||
);
|
||||
updateFormExtension("bushelsPerTonne", event.target.value);
|
||||
}}
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
className={classes.bottomSpacing}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<TextField
|
||||
label="Grain Variant"
|
||||
value={grainSubtype}
|
||||
|
|
@ -1102,7 +1095,8 @@ export default function BinSettings(props: Props) {
|
|||
disabled={!grainType}
|
||||
className={classes.bottomSpacing}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
}
|
||||
{getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_BUSHELS ||
|
||||
storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER ||
|
||||
formExtension.bushelsPerTonne === "0" ||
|
||||
|
|
|
|||
|
|
@ -1404,6 +1404,7 @@ export default function BinVisualizer(props: Props) {
|
|||
}
|
||||
}}
|
||||
inventoryControl={bin.inventoryControl()}
|
||||
customGrain={bin.customGrain()}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
@ -1574,6 +1575,12 @@ export default function BinVisualizer(props: Props) {
|
|||
const fanPerformance = () => {
|
||||
let totalCFM = bin.status.fanCfm;
|
||||
let bushelCFM = bin.status.cfmPerBushel;
|
||||
let emc = ExtractMoisture(
|
||||
bin.grain(),
|
||||
activePlenum?.tempHumidity?.temperature ?? 0,
|
||||
activePlenum?.tempHumidity?.humidity ?? 0,
|
||||
bin.customGrain()
|
||||
)
|
||||
return (
|
||||
<Box>
|
||||
<Typography style={{ fontSize: isMobile ? "0.85rem" : "1.0rem", fontWeight: 650 }}>
|
||||
|
|
@ -1616,20 +1623,18 @@ export default function BinVisualizer(props: Props) {
|
|||
{cfmDryWarning(bushelCFM)}
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid >
|
||||
<Box className={classes.lightBox}>
|
||||
<Typography align="center" style={{ fontWeight: 650, color: emcColour }}>
|
||||
{ExtractMoisture(
|
||||
bin.grain(),
|
||||
activePlenum?.tempHumidity?.temperature ?? 0,
|
||||
activePlenum?.tempHumidity?.humidity ?? 0
|
||||
).toFixed(2)}
|
||||
%
|
||||
</Typography>
|
||||
<Typography align="center" style={{ fontWeight: 650 }}>
|
||||
Plenum EMC
|
||||
</Typography>
|
||||
</Box>
|
||||
<Grid>
|
||||
{emc !== activePlenum?.tempHumidity?.humidity &&
|
||||
<Box className={classes.lightBox}>
|
||||
<Typography align="center" style={{ fontWeight: 650, color: emcColour }}>
|
||||
{emc.toFixed(2)}
|
||||
%
|
||||
</Typography>
|
||||
<Typography align="center" style={{ fontWeight: 650 }}>
|
||||
Plenum EMC
|
||||
</Typography>
|
||||
</Box>
|
||||
}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
|
|
@ -1638,6 +1643,12 @@ export default function BinVisualizer(props: Props) {
|
|||
};
|
||||
|
||||
const ambientDisplay = () => {
|
||||
let emc = ExtractMoisture(
|
||||
bin.grain(),
|
||||
ambient?.temperature ?? 0,
|
||||
ambient?.humidity ?? 0,
|
||||
bin.customGrain()
|
||||
)
|
||||
return (
|
||||
<Box>
|
||||
<Typography style={{ fontSize: isMobile ? "0.85rem" : "1.0rem", fontWeight: 650 }}>
|
||||
|
|
@ -1677,19 +1688,17 @@ export default function BinVisualizer(props: Props) {
|
|||
</Box>
|
||||
</Grid>
|
||||
<Grid >
|
||||
<Box className={classes.lightBox}>
|
||||
<Typography align="center" style={{ fontWeight: 650, color: emcColour }}>
|
||||
{ExtractMoisture(
|
||||
bin.grain(),
|
||||
ambient?.temperature ?? 0,
|
||||
ambient?.humidity ?? 0
|
||||
).toFixed(2)}
|
||||
%
|
||||
</Typography>
|
||||
<Typography align="center" style={{ fontWeight: 650 }}>
|
||||
Ambient EMC
|
||||
</Typography>
|
||||
</Box>
|
||||
{emc !== ambient?.humidity &&
|
||||
<Box className={classes.lightBox}>
|
||||
<Typography align="center" style={{ fontWeight: 650, color: emcColour }}>
|
||||
{emc.toFixed(2)}
|
||||
%
|
||||
</Typography>
|
||||
<Typography align="center" style={{ fontWeight: 650 }}>
|
||||
Ambient EMC
|
||||
</Typography>
|
||||
</Box>
|
||||
}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -92,7 +92,8 @@ export default function BinGraphsTrending(props: Props) {
|
|||
trend: ExtractMoisture(
|
||||
bin.grain(),
|
||||
val.values[0],
|
||||
plenumHumidity.values[i].values[0]
|
||||
plenumHumidity.values[i].values[0],
|
||||
bin.customGrain()
|
||||
)
|
||||
};
|
||||
trendData.push(trendPoint);
|
||||
|
|
|
|||
286
src/grain/CustomGrainForm.tsx
Normal file
286
src/grain/CustomGrainForm.tsx
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
import { Box, Button, MenuItem, TextField, Typography } from "@mui/material"
|
||||
import SearchSelect, { Option } from "common/SearchSelect"
|
||||
import { cloneDeep } from "lodash"
|
||||
import { pond } from "protobuf-ts/pond"
|
||||
import { useGlobalState } from "providers"
|
||||
import { useGrainAPI } from "providers/pond/grainAPI"
|
||||
import React, { useEffect, useState } from "react"
|
||||
|
||||
interface Props {
|
||||
grainSettings?: pond.GrainSettings
|
||||
onGrainSettingsChange: (settings: pond.GrainSettings) => void
|
||||
}
|
||||
|
||||
export default function CustomGrainForm(props: Props) {
|
||||
const {grainSettings, onGrainSettingsChange} = props
|
||||
const grainAPI = useGrainAPI()
|
||||
const [{as}] = useGlobalState()
|
||||
const [name, setName] = useState("")
|
||||
const [group, setGroup] = useState("")
|
||||
const [equation, setEquation] = useState<pond.MoistureEquation>(pond.MoistureEquation.MOISTURE_EQUATION_NONE)
|
||||
const [constantA, setConstantA] = useState("0")
|
||||
const [constantB, setConstantB] = useState("0")
|
||||
const [constantC, setConstantC] = useState("0")
|
||||
const [kgPerBushel, setKgPerBushel] = useState("0")
|
||||
const [bushelsPerTonne, setBushelsPerTonne] = useState("0")
|
||||
const [newGrainSettings, setNewGrainSettings] = useState(pond.GrainSettings.create())
|
||||
const [grainMap, setGrainMap] = useState<Map<string, pond.GrainObject>>(new Map())
|
||||
const [grainOptions, setGrainOptions] = useState<Option[]>([])
|
||||
const [isNew, setIsNew] = useState(false)
|
||||
const [selectedOption, setSelectedOption] = useState<Option | null>(null)
|
||||
|
||||
useEffect(()=>{
|
||||
if(grainSettings){
|
||||
setNewGrainSettings(grainSettings)
|
||||
setName(grainSettings.name)
|
||||
setGroup(grainSettings.group)
|
||||
setEquation(grainSettings.equation)
|
||||
setConstantA(grainSettings.a.toString())
|
||||
setConstantB(grainSettings.b.toString())
|
||||
setConstantC(grainSettings.c.toString())
|
||||
setKgPerBushel(grainSettings.kgPerBushel.toString())
|
||||
setBushelsPerTonne(grainSettings.bushelsPerTonne.toString())
|
||||
}
|
||||
},[grainSettings])
|
||||
|
||||
useEffect(()=>{
|
||||
grainAPI.listGrains(0, 0, "asc", "name", undefined, undefined, undefined, as).then(resp => {
|
||||
if (resp.data.grains){
|
||||
let map: Map<string, pond.GrainObject> = new Map()
|
||||
let options: Option[] = []
|
||||
resp.data.grains.forEach(grain => {
|
||||
map.set(grain.key, grain)
|
||||
options.push({
|
||||
label: grain.name,
|
||||
value: grain.key,
|
||||
group: grain.settings?.group,
|
||||
})
|
||||
})
|
||||
setGrainOptions(options)
|
||||
setGrainMap(map)
|
||||
}
|
||||
})
|
||||
},[grainAPI])
|
||||
|
||||
const invalid = () => {
|
||||
if (name === "") return true
|
||||
if (group === "") return true
|
||||
if (isNaN(parseFloat(constantA))) return true
|
||||
if (isNaN(parseFloat(constantB))) return true
|
||||
if (isNaN(parseFloat(constantA))) return true
|
||||
if (isNaN(parseFloat(kgPerBushel))) return true
|
||||
if (isNaN(parseFloat(bushelsPerTonne))) return true
|
||||
return false
|
||||
}
|
||||
|
||||
const saveGrain = () => {
|
||||
// console.log(newGrainSettings)
|
||||
grainAPI.addGrain(newGrainSettings, as).then(resp => {
|
||||
console.log("grain added")
|
||||
}).catch(err => {
|
||||
console.log("err")
|
||||
})
|
||||
}
|
||||
|
||||
const settingsChanged = (newSettings: pond.GrainSettings) => {
|
||||
setSelectedOption(null)
|
||||
setNewGrainSettings(newSettings)
|
||||
onGrainSettingsChange(newSettings)
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Box sx={{marginBottom: 2}}>
|
||||
<SearchSelect
|
||||
label="My Grains"
|
||||
selected={selectedOption}
|
||||
changeSelection={option => {
|
||||
setIsNew(false)
|
||||
setSelectedOption(option)
|
||||
//when an option is selected set all of the state variables controlling the form entries
|
||||
let grain = grainMap.get(option?.value)
|
||||
if(grain && grain.settings){
|
||||
//set the form values
|
||||
setName(grain.name)
|
||||
setGroup(grain.settings.group)
|
||||
setEquation(grain.settings.equation)
|
||||
setConstantA(grain.settings.a.toString())
|
||||
setConstantB(grain.settings.b.toString())
|
||||
setConstantC(grain.settings.c.toString())
|
||||
setKgPerBushel(grain.settings.kgPerBushel.toString())
|
||||
setBushelsPerTonne(grain.settings.bushelsPerTonne.toString())
|
||||
//the the new grain settings object
|
||||
setNewGrainSettings(grain.settings)
|
||||
//pass that settings object back up
|
||||
settingsChanged(grain.settings)
|
||||
}
|
||||
}}
|
||||
group
|
||||
options={grainOptions}
|
||||
/>
|
||||
</Box>
|
||||
<Typography sx={{marginBottom: 1}}>Custom Grain Properties</Typography>
|
||||
<TextField
|
||||
sx={{marginBottom: 2}}
|
||||
fullWidth
|
||||
label="Name*"
|
||||
value={name}
|
||||
onChange={(e) => {
|
||||
let name = e.target.value
|
||||
setName(name)
|
||||
setIsNew(true)
|
||||
let settings = cloneDeep(newGrainSettings)
|
||||
settings.name = name
|
||||
settingsChanged(settings)
|
||||
}}/>
|
||||
<TextField
|
||||
sx={{marginBottom: 2}}
|
||||
fullWidth
|
||||
label="Group*"
|
||||
value={group}
|
||||
onChange={(e) => {
|
||||
let group = e.target.value
|
||||
setGroup(group)
|
||||
setIsNew(true)
|
||||
let settings = cloneDeep(newGrainSettings)
|
||||
settings.group = group
|
||||
settingsChanged(settings)
|
||||
}}/>
|
||||
<TextField
|
||||
sx={{marginBottom: 2}}
|
||||
fullWidth
|
||||
value={equation}
|
||||
helperText={"Not selecting an EMC equation to use will return the humidity instead of EMC"}
|
||||
label="EMC Equation"
|
||||
onChange={(e) => {
|
||||
let enumVal = parseFloat(e.target.value)
|
||||
setEquation(enumVal)
|
||||
setIsNew(true)
|
||||
let settings = cloneDeep(newGrainSettings)
|
||||
settings.equation = enumVal
|
||||
settingsChanged(settings)
|
||||
}}
|
||||
select>
|
||||
<MenuItem key={pond.MoistureEquation.MOISTURE_EQUATION_NONE} value={pond.MoistureEquation.MOISTURE_EQUATION_NONE}>
|
||||
None
|
||||
</MenuItem>
|
||||
<MenuItem key={pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST} value={pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST}>
|
||||
Chung-Pfost
|
||||
</MenuItem>
|
||||
<MenuItem key={pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON} value={pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON}>
|
||||
Henderson
|
||||
</MenuItem>
|
||||
<MenuItem key={pond.MoistureEquation.MOISTURE_EQUATION_HALSEY} value={pond.MoistureEquation.MOISTURE_EQUATION_HALSEY}>
|
||||
Halsey
|
||||
</MenuItem>
|
||||
<MenuItem key={pond.MoistureEquation.MOISTURE_EQUATION_OSWIN} value={pond.MoistureEquation.MOISTURE_EQUATION_OSWIN}>
|
||||
Oswin
|
||||
</MenuItem>
|
||||
</TextField>
|
||||
<TextField
|
||||
sx={{marginBottom: 2}}
|
||||
fullWidth
|
||||
type="number"
|
||||
value={constantA}
|
||||
error={isNaN(parseFloat(constantA))}
|
||||
helperText={isNaN(parseFloat(constantA)) ? "Must be a valid number" : ""}
|
||||
onChange={(e) => {
|
||||
let val = e.target.value
|
||||
setConstantA(val)
|
||||
setIsNew(true)
|
||||
if(!isNaN(parseFloat(val))){
|
||||
let settings = cloneDeep(newGrainSettings)
|
||||
settings.a = parseFloat(val)
|
||||
settingsChanged(settings)
|
||||
}
|
||||
}}
|
||||
label="Constant A"/>
|
||||
<TextField
|
||||
sx={{marginBottom: 2}}
|
||||
fullWidth
|
||||
type="number"
|
||||
value={constantB}
|
||||
error={isNaN(parseFloat(constantB))}
|
||||
helperText={isNaN(parseFloat(constantB)) ? "Must be a valid number" : ""}
|
||||
onChange={(e) => {
|
||||
let val = e.target.value
|
||||
setConstantB(val)
|
||||
setIsNew(true)
|
||||
if(!isNaN(parseFloat(val))){
|
||||
let settings = cloneDeep(newGrainSettings)
|
||||
settings.b = parseFloat(val)
|
||||
settingsChanged(settings)
|
||||
}
|
||||
}}
|
||||
label="Constant B"/>
|
||||
<TextField
|
||||
sx={{marginBottom: 2}}
|
||||
fullWidth
|
||||
type="number"
|
||||
value={constantC}
|
||||
error={isNaN(parseFloat(constantC))}
|
||||
helperText={isNaN(parseFloat(constantC)) ? "Must be a valid number" : ""}
|
||||
onChange={(e) => {
|
||||
let val = e.target.value
|
||||
setConstantC(val)
|
||||
setIsNew(true)
|
||||
if(!isNaN(parseFloat(val))){
|
||||
let settings = cloneDeep(newGrainSettings)
|
||||
settings.c = parseFloat(val)
|
||||
settingsChanged(settings)
|
||||
}
|
||||
}}
|
||||
label="Constant C"/>
|
||||
<TextField
|
||||
sx={{marginBottom: 2}}
|
||||
fullWidth
|
||||
type="number"
|
||||
value={kgPerBushel}
|
||||
error={isNaN(parseFloat(kgPerBushel))}
|
||||
helperText={isNaN(parseFloat(kgPerBushel)) ? "Must be a valid number" : ""}
|
||||
onChange={(e) => {
|
||||
let val = e.target.value
|
||||
setKgPerBushel(val)
|
||||
setIsNew(true)
|
||||
if(!isNaN(parseFloat(val))){
|
||||
let settings = cloneDeep(newGrainSettings)
|
||||
settings.kgPerBushel = parseFloat(val)
|
||||
settingsChanged(settings)
|
||||
}
|
||||
}}
|
||||
label="kg per Bushel"/>
|
||||
<TextField
|
||||
sx={{marginBottom: 2}}
|
||||
fullWidth
|
||||
type="number"
|
||||
value={bushelsPerTonne}
|
||||
error={isNaN(parseFloat(bushelsPerTonne))}
|
||||
helperText={isNaN(parseFloat(bushelsPerTonne)) ? "Must be a valid number" : ""}
|
||||
onChange={(e) => {
|
||||
let val = e.target.value
|
||||
setBushelsPerTonne(val)
|
||||
setIsNew(true)
|
||||
if(!isNaN(parseFloat(val))){
|
||||
let settings = cloneDeep(newGrainSettings)
|
||||
settings.bushelsPerTonne = parseFloat(val)
|
||||
settingsChanged(settings)
|
||||
}
|
||||
}}
|
||||
label="Bushels per Tonne"/>
|
||||
{isNew &&
|
||||
<Box display='flex' justifyContent="flex-end">
|
||||
<Button
|
||||
variant="contained"
|
||||
disabled={invalid()}
|
||||
onClick={() => {
|
||||
saveGrain()
|
||||
setIsNew(false)
|
||||
}}
|
||||
color="primary">
|
||||
Save Custom Grain
|
||||
</Button>
|
||||
</Box>
|
||||
}
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
|
|
@ -14,12 +14,11 @@ import WheatImg from "assets/grain/wheat.jpg";
|
|||
import { Option } from "common/SearchSelect";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { Equation } from "./GrainMoisture";
|
||||
|
||||
export interface GrainExtension {
|
||||
name: string;
|
||||
group: string;
|
||||
equation: Equation;
|
||||
equation: pond.MoistureEquation;
|
||||
a: number;
|
||||
b: number;
|
||||
c: number;
|
||||
|
|
@ -37,7 +36,7 @@ const defaultSetTemp = 30.0;
|
|||
const defaultGrain: GrainExtension = {
|
||||
name: "None",
|
||||
group: "",
|
||||
equation: Equation.none,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_NONE,
|
||||
a: 0,
|
||||
b: 0,
|
||||
c: 0,
|
||||
|
|
@ -56,7 +55,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Custom Type",
|
||||
group: "",
|
||||
equation: Equation.none,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_NONE,
|
||||
a: 0,
|
||||
b: 0,
|
||||
c: 0,
|
||||
|
|
@ -72,7 +71,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Barley",
|
||||
group: "Barley",
|
||||
equation: Equation.chungPfost,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||
a: 475.12,
|
||||
b: 0.14843,
|
||||
c: 71.996,
|
||||
|
|
@ -89,7 +88,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Buckwheat",
|
||||
group: "Buckwheat",
|
||||
equation: Equation.chungPfost,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||
a: 103540000,
|
||||
b: 0.1646,
|
||||
c: 15853000,
|
||||
|
|
@ -106,7 +105,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Canola",
|
||||
group: "Canola",
|
||||
equation: Equation.halsey,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||
a: 3.489,
|
||||
b: -0.010553,
|
||||
c: 1.86,
|
||||
|
|
@ -124,7 +123,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Rapeseed",
|
||||
group: "Canola",
|
||||
equation: Equation.halsey,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||
a: 3.0026,
|
||||
b: -0.0048967,
|
||||
c: 1.7607,
|
||||
|
|
@ -141,7 +140,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Corn (Henderson)",
|
||||
group: "Corn",
|
||||
equation: Equation.henderson,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||
a: 0.000066612,
|
||||
b: 1.9677,
|
||||
c: 42.143,
|
||||
|
|
@ -158,7 +157,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Corn (Chung-Pfost)",
|
||||
group: "Corn",
|
||||
equation: Equation.chungPfost,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||
a: 374.34,
|
||||
b: 0.18662,
|
||||
c: 31.696,
|
||||
|
|
@ -175,7 +174,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Corn (Oswin)",
|
||||
group: "Corn",
|
||||
equation: Equation.oswin,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_OSWIN,
|
||||
a: 15.303,
|
||||
b: -0.10164,
|
||||
c: 3.0358,
|
||||
|
|
@ -192,7 +191,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Maize White",
|
||||
group: "Corn",
|
||||
equation: Equation.henderson,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||
a: 0.000066612,
|
||||
b: 1.9677,
|
||||
c: 70.143,
|
||||
|
|
@ -209,7 +208,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Maize Yellow",
|
||||
group: "Corn",
|
||||
equation: Equation.henderson,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||
a: 0.000066612,
|
||||
b: 1.9677,
|
||||
c: 65.143,
|
||||
|
|
@ -226,7 +225,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Oats (Henderson)",
|
||||
group: "Oats",
|
||||
equation: Equation.henderson,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||
a: 0.000085511,
|
||||
b: 2.0087,
|
||||
c: 37.811,
|
||||
|
|
@ -243,7 +242,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Oats (Chung-Pfost)",
|
||||
group: "Oats",
|
||||
equation: Equation.chungPfost,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||
a: 442.85,
|
||||
b: 0.21228,
|
||||
c: 35.803,
|
||||
|
|
@ -260,7 +259,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Oats (Oswin)",
|
||||
group: "Oats",
|
||||
equation: Equation.oswin,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_OSWIN,
|
||||
a: 12.412,
|
||||
b: -0.060707,
|
||||
c: 2.9397,
|
||||
|
|
@ -277,7 +276,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Peanuts",
|
||||
group: "Peanuts",
|
||||
equation: Equation.oswin,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_OSWIN,
|
||||
a: 8.6588,
|
||||
b: -0.057904,
|
||||
c: 2.6204,
|
||||
|
|
@ -294,7 +293,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Long Grain Rice",
|
||||
group: "Rice",
|
||||
equation: Equation.henderson,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||
a: 0.000041276,
|
||||
b: 2.1191,
|
||||
c: 49.828,
|
||||
|
|
@ -311,7 +310,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Medium Grain Rice",
|
||||
group: "Rice",
|
||||
equation: Equation.henderson,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||
a: 0.000035502,
|
||||
b: 2.31,
|
||||
c: 27.396,
|
||||
|
|
@ -328,7 +327,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Short Grain Rice",
|
||||
group: "Rice",
|
||||
equation: Equation.henderson,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||
a: 0.000048524,
|
||||
b: 2.0794,
|
||||
c: 45.646,
|
||||
|
|
@ -345,7 +344,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Sorghum",
|
||||
group: "Sorghum",
|
||||
equation: Equation.chungPfost,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||
a: 797.33,
|
||||
b: 0.18159,
|
||||
c: 52.238,
|
||||
|
|
@ -362,7 +361,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Soybeans",
|
||||
group: "Soybeans",
|
||||
equation: Equation.chungPfost,
|
||||
//equation: Equation.chungPfost,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||
a: 228.2,
|
||||
b: 0.2072,
|
||||
c: 30,
|
||||
|
|
@ -379,7 +379,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Sunflower",
|
||||
group: "Sunflower",
|
||||
equation: Equation.henderson,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||
a: 0.00031,
|
||||
b: 1.7459,
|
||||
c: 66.603,
|
||||
|
|
@ -396,7 +396,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Durum Wheat",
|
||||
group: "Wheat",
|
||||
equation: Equation.oswin,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_OSWIN,
|
||||
a: 13.101,
|
||||
b: -0.052626,
|
||||
c: 2.9987,
|
||||
|
|
@ -413,7 +413,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Hard Red Wheat",
|
||||
group: "Wheat",
|
||||
equation: Equation.chungPfost,
|
||||
//equation: Equation.chungPfost,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||
a: 610.34,
|
||||
b: 0.15526,
|
||||
c: 93.213,
|
||||
|
|
@ -430,7 +431,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Wheat SAWOS",
|
||||
group: "Wheat",
|
||||
equation: Equation.chungPfost,
|
||||
//equation: Equation.chungPfost,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||
a: 610.34,
|
||||
b: 0.15526,
|
||||
c: 93.213,
|
||||
|
|
@ -447,7 +449,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Un-retted Flax",
|
||||
group: "Flax",
|
||||
equation: Equation.halsey,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||
a: 5.11,
|
||||
b: Math.pow(-8.46 * 10, -3),
|
||||
c: 2.26,
|
||||
|
|
@ -464,7 +466,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Dew-retted Flax",
|
||||
group: "Flax",
|
||||
equation: Equation.oswin,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_OSWIN,
|
||||
a: 6.5,
|
||||
b: Math.pow(-1.68 * 10, -2),
|
||||
c: 3.2,
|
||||
|
|
@ -481,7 +483,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Yellow Peas",
|
||||
group: "Peas",
|
||||
equation: Equation.oswin,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_OSWIN,
|
||||
a: 14.81,
|
||||
b: -0.109,
|
||||
c: 3.019,
|
||||
|
|
@ -498,7 +500,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Blaze Lentils",
|
||||
group: "Lentils",
|
||||
equation: Equation.halsey,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||
a: 5.39,
|
||||
b: -0.015,
|
||||
c: 2.273,
|
||||
|
|
@ -515,7 +517,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Redberry Lentils",
|
||||
group: "Lentils",
|
||||
equation: Equation.halsey,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||
a: 4.749,
|
||||
b: -0.0116,
|
||||
c: 2.066,
|
||||
|
|
@ -532,7 +534,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Robin Lentils",
|
||||
group: "Lentils",
|
||||
equation: Equation.halsey,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||
a: 5.176,
|
||||
b: -0.0065,
|
||||
c: 2.337,
|
||||
|
|
@ -549,7 +551,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Dry Beans Red",
|
||||
group: "Dry Beans",
|
||||
equation: Equation.halsey,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||
a: 4.2669,
|
||||
b: -0.013382,
|
||||
c: 1.6933,
|
||||
|
|
@ -564,7 +566,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Dry Beans Black",
|
||||
group: "Dry Beans",
|
||||
equation: Equation.halsey,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||
a: 5.2003,
|
||||
b: -0.022685,
|
||||
c: 1.9656,
|
||||
|
|
@ -579,7 +581,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Rye (Henderson)",
|
||||
group: "Rye",
|
||||
equation: Equation.henderson,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||
a: 0.00006343,
|
||||
b: 2.2060,
|
||||
c: 13.1810,
|
||||
|
|
@ -594,7 +596,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Rye (Chung-Pfost)",
|
||||
group: "Rye",
|
||||
equation: Equation.chungPfost,
|
||||
//equation: Equation.chungPfost,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||
a: 461.0230,
|
||||
b: 0.1840,
|
||||
c: 36.7410,
|
||||
|
|
@ -609,7 +612,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Rye (Halsey)",
|
||||
group: "Rye",
|
||||
equation: Equation.halsey,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||
a: 4.2970,
|
||||
b: 0.380,
|
||||
c: 2.2710,
|
||||
|
|
@ -624,7 +627,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
|||
{
|
||||
name: "Rye (Oswin)",
|
||||
group: "Rye",
|
||||
equation: Equation.oswin,
|
||||
equation: pond.MoistureEquation.MOISTURE_EQUATION_OSWIN,
|
||||
a: 11.8870,
|
||||
b: 0.0210,
|
||||
c: 3.2620,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ const toERH = (humidity: number): number => {
|
|||
export function ExtractMoisture(
|
||||
type: pond.Grain | undefined,
|
||||
celsius: number,
|
||||
humidity: number
|
||||
humidity: number,
|
||||
customGrain?: pond.GrainSettings
|
||||
): number {
|
||||
if (humidity <= 0) {
|
||||
return 0;
|
||||
|
|
@ -26,20 +27,43 @@ export function ExtractMoisture(
|
|||
type === undefined ||
|
||||
type === pond.Grain.GRAIN_NONE ||
|
||||
type === pond.Grain.GRAIN_INVALID ||
|
||||
type === pond.Grain.GRAIN_CUSTOM
|
||||
(type === pond.Grain.GRAIN_CUSTOM && customGrain === undefined)
|
||||
) {
|
||||
return humidity;
|
||||
}
|
||||
|
||||
let dry = humidity;
|
||||
let ctx = GrainDescriber(type);
|
||||
dry = toDryMoisture(ctx.equation, celsius, humidity, ctx.a, ctx.b, ctx.c);
|
||||
let eq: pond.MoistureEquation
|
||||
let constA: number
|
||||
let constB: number
|
||||
let constC: number
|
||||
if(type === pond.Grain.GRAIN_CUSTOM && customGrain){
|
||||
if(customGrain.equation === pond.MoistureEquation.MOISTURE_EQUATION_NONE) return humidity
|
||||
eq = customGrain.equation
|
||||
constA = customGrain.a
|
||||
constB = customGrain.b
|
||||
constC = customGrain.c
|
||||
}else{
|
||||
let ctx = GrainDescriber(type);
|
||||
eq = ctx.equation
|
||||
constA = ctx.a
|
||||
constB = ctx.b
|
||||
constC = ctx.c
|
||||
}
|
||||
|
||||
dry = toDryMoisture(eq, celsius, humidity, constA, constB, constC);
|
||||
return dryToWet(dry);
|
||||
}
|
||||
|
||||
export function WaterContent(type: pond.Grain, bushels: number, moistureContent: number): number {
|
||||
let grain = GrainDescriber(type);
|
||||
return bushels * grain.weightConversionKg * moistureContent;
|
||||
export function WaterContent(type: pond.Grain, bushels: number, moistureContent: number, customGrain?: pond.GrainSettings): number {
|
||||
//kg per bushel conversion
|
||||
let conversion = 0
|
||||
if(type === pond.Grain.GRAIN_CUSTOM && customGrain){
|
||||
conversion = customGrain.kgPerBushel
|
||||
}else{
|
||||
conversion = GrainDescriber(type).weightConversionKg;
|
||||
}
|
||||
return bushels * conversion * moistureContent;
|
||||
}
|
||||
|
||||
export function MoistureToHumidity(
|
||||
|
|
@ -69,7 +93,7 @@ function wetToDry(wetMC: number): number {
|
|||
}
|
||||
|
||||
function toDryMoisture(
|
||||
eq: Equation,
|
||||
eq: pond.MoistureEquation,
|
||||
T: number,
|
||||
RH: number,
|
||||
a: number,
|
||||
|
|
@ -78,13 +102,13 @@ function toDryMoisture(
|
|||
): number {
|
||||
const ERH: number = toERH(RH);
|
||||
switch (eq) {
|
||||
case Equation.chungPfost:
|
||||
case pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST:
|
||||
return chungPfost(T, ERH, a, b, c);
|
||||
case Equation.halsey:
|
||||
case pond.MoistureEquation.MOISTURE_EQUATION_HALSEY:
|
||||
return halsey(T, ERH, a, b, c);
|
||||
case Equation.henderson:
|
||||
case pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON:
|
||||
return henderson(T, ERH, a, b, c);
|
||||
case Equation.oswin:
|
||||
case pond.MoistureEquation.MOISTURE_EQUATION_OSWIN:
|
||||
return oswin(T, ERH, a, b, c);
|
||||
default:
|
||||
return RH;
|
||||
|
|
@ -92,7 +116,7 @@ function toDryMoisture(
|
|||
}
|
||||
|
||||
function dryMoistureToHumidity(
|
||||
eq: Equation,
|
||||
eq: pond.MoistureEquation,
|
||||
celsius: number,
|
||||
dryMC: number,
|
||||
a: number,
|
||||
|
|
@ -101,16 +125,16 @@ function dryMoistureToHumidity(
|
|||
): number {
|
||||
let ERH = 0;
|
||||
switch (eq) {
|
||||
case Equation.chungPfost:
|
||||
case pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST:
|
||||
ERH = chungPfostInverse(celsius, dryMC, a, b, c);
|
||||
break;
|
||||
case Equation.halsey:
|
||||
case pond.MoistureEquation.MOISTURE_EQUATION_HALSEY:
|
||||
ERH = halseyInverse(celsius, dryMC, a, b, c);
|
||||
break;
|
||||
case Equation.henderson:
|
||||
case pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON:
|
||||
ERH = hendersonInverse(celsius, dryMC, a, b, c);
|
||||
break;
|
||||
case Equation.oswin:
|
||||
case pond.MoistureEquation.MOISTURE_EQUATION_OSWIN:
|
||||
ERH = oswinInverse(celsius, dryMC, a, b, c);
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -95,6 +95,10 @@ export class Bin {
|
|||
return c;
|
||||
}
|
||||
|
||||
public customGrain(): pond.GrainSettings | undefined {
|
||||
return this.settings.inventory?.customGrain ?? undefined
|
||||
}
|
||||
|
||||
public empty(): boolean {
|
||||
return this.settings.inventory?.empty || (this.settings.inventory !== undefined && this.settings.inventory !== null && this.bushels() < 5);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -819,6 +819,7 @@ export default function Bin(props: Props) {
|
|||
fans={fans}
|
||||
heaters={heaters}
|
||||
grain={bin.grain()}
|
||||
customGrain={bin.customGrain()}
|
||||
/>
|
||||
)}
|
||||
<Box marginTop={2}>
|
||||
|
|
@ -980,6 +981,7 @@ export default function Bin(props: Props) {
|
|||
fans={fans}
|
||||
heaters={heaters}
|
||||
grain={bin.grain()}
|
||||
customGrain={bin.customGrain()}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
|
|
|
|||
123
src/providers/pond/grainAPI.tsx
Normal file
123
src/providers/pond/grainAPI.tsx
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
import { useHTTP } from "hooks";
|
||||
import { createContext, PropsWithChildren, useContext } from "react";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { pondURL } from "./pond";
|
||||
import { AxiosResponse } from "axios";
|
||||
import { useGlobalState } from "providers";
|
||||
import { or } from "utils";
|
||||
|
||||
export interface IGrainInterface {
|
||||
addGrain: (
|
||||
settings: pond.GrainSettings,
|
||||
otherTeam?: string
|
||||
) => Promise<AxiosResponse<pond.AddGrainResponse>>;
|
||||
getGrain: (key: string, otherTeam?: string) => Promise<AxiosResponse<pond.GetGrainResponse>>
|
||||
listGrains: (
|
||||
limit: number,
|
||||
offset: number,
|
||||
order?: "asc" | "desc",
|
||||
orderBy?: string,
|
||||
search?: string,
|
||||
keys?: string[],
|
||||
types?: string[],
|
||||
otherTeam?: string,
|
||||
) => Promise<AxiosResponse<pond.ListGrainsResponse>>;
|
||||
removeGrain: (key: string, otherTeam?: string) => Promise<AxiosResponse<pond.RemoveGrainResponse>>;
|
||||
}
|
||||
|
||||
export const GrainAPIcontext = createContext<IGrainInterface>({} as IGrainInterface);
|
||||
|
||||
interface Props {}
|
||||
|
||||
export default function GrainProvider(props: PropsWithChildren<Props>) {
|
||||
const { children } = props;
|
||||
const { get, del, post } = useHTTP();
|
||||
const [{ as }] = useGlobalState();
|
||||
|
||||
//add
|
||||
const addGrain = (settings: pond.GrainSettings, otherTeam?: string) => {
|
||||
const view = otherTeam ? otherTeam : as
|
||||
if (view) {
|
||||
return post<pond.AddGrainResponse>(
|
||||
pondURL("/grains?&as=" + view),
|
||||
settings
|
||||
);
|
||||
}
|
||||
return post<pond.AddGrainResponse>(pondURL("/grains"), settings);
|
||||
};
|
||||
|
||||
//get
|
||||
const getGrain = (key: string, otherTeam?: string) => {
|
||||
const view = otherTeam ? otherTeam : as
|
||||
const url = "/grains/" + key + (view ? "?as=" + view : "")
|
||||
return new Promise<AxiosResponse<pond.GetGrainResponse>>((resolve, reject)=>{
|
||||
get<pond.GetGrainResponse>(pondURL(url))
|
||||
.then(resp => {
|
||||
if (resp.data.grain){
|
||||
resp.data.grain = pond.GrainObject.fromObject(resp.data.grain)
|
||||
}
|
||||
resolve(resp)
|
||||
})
|
||||
.catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
//list
|
||||
const listGrains = (
|
||||
limit: number,
|
||||
offset: number,
|
||||
order?: "asc" | "desc",
|
||||
orderBy?: string,
|
||||
search?: string,
|
||||
keys?: string[],
|
||||
types?: string[],
|
||||
otherTeam?: string
|
||||
) => {
|
||||
return new Promise<AxiosResponse<pond.ListGrainsResponse>>((resolve, reject)=>{
|
||||
const view = otherTeam ? otherTeam : as
|
||||
get<pond.ListGrainsResponse>(
|
||||
pondURL(
|
||||
"/grains?limit=" +
|
||||
"?limit=" +
|
||||
limit +
|
||||
"&offset=" +
|
||||
offset +
|
||||
("&order=" + or(order, "asc")) +
|
||||
("&by=" + or(orderBy, "key")) +
|
||||
(search ? "&search=" + search : "") +
|
||||
(keys ? "&keys=" + keys.join(",") : "") +
|
||||
(types ? "&types=" + types.join(",") : "") +
|
||||
(view ? "&as=" + view : "")
|
||||
)
|
||||
).then(resp => {
|
||||
resp.data = pond.ListGrainsResponse.fromObject(resp.data);
|
||||
return resolve(resp)
|
||||
}).catch(err => {
|
||||
return reject(err)
|
||||
})
|
||||
})
|
||||
};
|
||||
//remove
|
||||
const removeGrain = (key: string, otherTeam?: string) => {
|
||||
const view = otherTeam ? otherTeam : as
|
||||
if (view) {
|
||||
return del<pond.RemoveGrainResponse>(pondURL("/grains/" + key + "?as=" + view));
|
||||
}
|
||||
return del<pond.RemoveGrainResponse>(pondURL("/grains/" + key));
|
||||
};
|
||||
|
||||
return (
|
||||
<GrainAPIcontext.Provider
|
||||
value={{
|
||||
addGrain,
|
||||
getGrain,
|
||||
listGrains,
|
||||
removeGrain
|
||||
}}>
|
||||
{children}
|
||||
</GrainAPIcontext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export const useGrainAPI = () => useContext(GrainAPIcontext);
|
||||
|
|
@ -38,6 +38,7 @@ import JohnDeereProvider, { useJohnDeereProxyAPI } from "./johnDeereProxyAPI";
|
|||
import LibraCartProvider, { useLibraCartProxyAPI } from "./libracartProxyAPI";
|
||||
import CNHiProvider, { useCNHiProxyAPI } from "./cnhiProxyAPI";
|
||||
import DevicePresetProvider, { useDevicePresetAPI } from "./devicePresetAPI";
|
||||
import GrainProvider, { useGrainAPI } from "./grainAPI";
|
||||
// import NoteProvider from "providers/noteAPI";
|
||||
|
||||
export const pondURL = (partial: string, demo: boolean = false): string => {
|
||||
|
|
@ -93,7 +94,9 @@ export default function PondProvider(props: PropsWithChildren<any>) {
|
|||
<KeyManagerProvider>
|
||||
<DevicePresetProvider>
|
||||
<ImagekitProvider>
|
||||
{children}
|
||||
<GrainProvider>
|
||||
{children}
|
||||
</GrainProvider>
|
||||
</ImagekitProvider>
|
||||
</DevicePresetProvider>
|
||||
</KeyManagerProvider>
|
||||
|
|
@ -173,5 +176,6 @@ export {
|
|||
useJohnDeereProxyAPI,
|
||||
useCNHiProxyAPI,
|
||||
useLibraCartProxyAPI,
|
||||
useDevicePresetAPI
|
||||
useDevicePresetAPI,
|
||||
useGrainAPI
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue