192 lines
5 KiB
TypeScript
192 lines
5 KiB
TypeScript
import { pond } from "protobuf-ts/pond";
|
|
import GrainDescriber from "./GrainDescriber";
|
|
|
|
export enum Equation {
|
|
"none",
|
|
"oswin",
|
|
"halsey",
|
|
"henderson",
|
|
"chungPfost"
|
|
}
|
|
|
|
const toERH = (humidity: number): number => {
|
|
return humidity >= 100 ? 0.99999 : humidity / 100;
|
|
};
|
|
|
|
export function ExtractMoisture(
|
|
type: pond.Grain | undefined,
|
|
celsius: number,
|
|
humidity: number,
|
|
customGrain?: pond.GrainSettings
|
|
): number {
|
|
if (humidity <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (
|
|
type === undefined ||
|
|
type === pond.Grain.GRAIN_NONE ||
|
|
type === pond.Grain.GRAIN_INVALID ||
|
|
(type === pond.Grain.GRAIN_CUSTOM && customGrain === undefined)
|
|
) {
|
|
return humidity;
|
|
}
|
|
|
|
let dry = humidity;
|
|
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, 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(
|
|
type: pond.Grain | undefined,
|
|
celsius: number,
|
|
wetMC: number
|
|
): number {
|
|
if (wetMC <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (type === undefined || type === pond.Grain.GRAIN_NONE || type === pond.Grain.GRAIN_INVALID) {
|
|
return wetMC;
|
|
}
|
|
|
|
const dryMC = wetToDry(wetMC);
|
|
let ctx = GrainDescriber(type);
|
|
return dryMoistureToHumidity(ctx.equation, celsius, dryMC, ctx.a, ctx.b, ctx.c);
|
|
}
|
|
|
|
function dryToWet(dryMC: number): number {
|
|
return (100 * dryMC) / (dryMC + 100);
|
|
}
|
|
|
|
function wetToDry(wetMC: number): number {
|
|
return -((100 * wetMC) / (wetMC - 100));
|
|
}
|
|
|
|
function toDryMoisture(
|
|
eq: pond.MoistureEquation,
|
|
T: number,
|
|
RH: number,
|
|
a: number,
|
|
b: number,
|
|
c: number
|
|
): number {
|
|
const ERH: number = toERH(RH);
|
|
switch (eq) {
|
|
case pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST:
|
|
return chungPfost(T, ERH, a, b, c);
|
|
case pond.MoistureEquation.MOISTURE_EQUATION_HALSEY:
|
|
return halsey(T, ERH, a, b, c);
|
|
case pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON:
|
|
return henderson(T, ERH, a, b, c);
|
|
case pond.MoistureEquation.MOISTURE_EQUATION_OSWIN:
|
|
return oswin(T, ERH, a, b, c);
|
|
default:
|
|
return RH;
|
|
}
|
|
}
|
|
|
|
function dryMoistureToHumidity(
|
|
eq: pond.MoistureEquation,
|
|
celsius: number,
|
|
dryMC: number,
|
|
a: number,
|
|
b: number,
|
|
c: number
|
|
): number {
|
|
let ERH = 0;
|
|
switch (eq) {
|
|
case pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST:
|
|
ERH = chungPfostInverse(celsius, dryMC, a, b, c);
|
|
break;
|
|
case pond.MoistureEquation.MOISTURE_EQUATION_HALSEY:
|
|
ERH = halseyInverse(celsius, dryMC, a, b, c);
|
|
break;
|
|
case pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON:
|
|
ERH = hendersonInverse(celsius, dryMC, a, b, c);
|
|
break;
|
|
case pond.MoistureEquation.MOISTURE_EQUATION_OSWIN:
|
|
ERH = oswinInverse(celsius, dryMC, a, b, c);
|
|
break;
|
|
default:
|
|
return dryMC;
|
|
}
|
|
|
|
let RH = ERH * 100;
|
|
return RH;
|
|
}
|
|
|
|
function chungPfost(celsius: number, ERH: number, a: number, b: number, c: number): number {
|
|
const T = celsius;
|
|
return Math.log((-Math.log(ERH) * (T + c)) / a) / -b;
|
|
}
|
|
|
|
function halsey(celsius: number, ERH: number, a: number, b: number, c: number): number {
|
|
const T = celsius;
|
|
return Math.pow(-Math.exp(a + b * T) / Math.log(ERH), 1 / c);
|
|
}
|
|
|
|
function henderson(celsius: number, ERH: number, a: number, b: number, c: number): number {
|
|
const T = celsius;
|
|
return Math.pow(Math.log(1 - ERH) / (-a * (T + c)), 1 / b);
|
|
}
|
|
|
|
function oswin(celsius: number, ERH: number, a: number, b: number, c: number): number {
|
|
const T = celsius;
|
|
return (a + b * T) / Math.pow(Math.pow(ERH, -1) - 1, 1 / c);
|
|
}
|
|
|
|
function chungPfostInverse(
|
|
celsius: number,
|
|
dryMC: number,
|
|
a: number,
|
|
b: number,
|
|
c: number
|
|
): number {
|
|
const T = celsius;
|
|
return Math.exp(-(a / (T + c)) * Math.exp(-b * dryMC));
|
|
}
|
|
|
|
function halseyInverse(celsius: number, dryMC: number, a: number, b: number, c: number): number {
|
|
const T = celsius;
|
|
return Math.exp(-(Math.exp(a + b * T) / Math.pow(dryMC, c)));
|
|
}
|
|
|
|
function hendersonInverse(celsius: number, dryMC: number, a: number, b: number, c: number): number {
|
|
const T = celsius;
|
|
return 1 - Math.exp(-a * (T + c) * Math.pow(dryMC, b));
|
|
}
|
|
|
|
function oswinInverse(celsius: number, dryMC: number, a: number, b: number, c: number): number {
|
|
const T = celsius;
|
|
return Math.pow(Math.pow((a + b * T) / dryMC, c) + 1, -1);
|
|
}
|