352 lines
10 KiB
TypeScript
352 lines
10 KiB
TypeScript
import GrainDescriber from "grain/GrainDescriber";
|
|
import { cloneDeep } from "lodash";
|
|
import { MarkerData } from "maps/mapMarkers/Markers";
|
|
import { User } from "models";
|
|
import { pond } from "protobuf-ts/pond";
|
|
import { stringToMaterialColour } from "utils/strings";
|
|
import { or } from "utils/types";
|
|
|
|
export class Bin {
|
|
public settings: pond.BinSettings = pond.BinSettings.create();
|
|
public status: pond.BinStatus = pond.BinStatus.create();
|
|
public permissions: pond.Permission[] = [];
|
|
|
|
public static create(pb?: pond.Bin): Bin {
|
|
let my = new Bin();
|
|
if (pb) {
|
|
my.settings = pond.BinSettings.fromObject(cloneDeep(or(pb.settings, {})));
|
|
my.status = pond.BinStatus.fromObject(cloneDeep(or(pb.status, {})));
|
|
my.permissions = pb.binPermissions;
|
|
}
|
|
return my;
|
|
}
|
|
|
|
public static clone(other?: Bin): Bin {
|
|
if (other) {
|
|
return Bin.create(
|
|
pond.Bin.fromObject({
|
|
settings: cloneDeep(other.settings),
|
|
status: cloneDeep(other.status),
|
|
binPermissions: cloneDeep(other.permissions)
|
|
})
|
|
);
|
|
}
|
|
return Bin.create();
|
|
}
|
|
|
|
public static any(data: any): Bin {
|
|
return Bin.create(pond.Bin.fromObject(cloneDeep(data)));
|
|
}
|
|
|
|
public setLocation(long: number, lat: number): void {
|
|
this.settings.location = pond.Location.create();
|
|
this.settings.location.longitude = long;
|
|
this.settings.location.latitude = lat;
|
|
}
|
|
|
|
public removeLocation(): void {
|
|
this.settings.location = null;
|
|
}
|
|
|
|
public binShape(): pond.BinShape | undefined {
|
|
return this.settings.specs?.shape;
|
|
}
|
|
|
|
public diameter(): number {
|
|
return this.settings.specs?.diameterCm ?? 0;
|
|
}
|
|
|
|
public height(): number {
|
|
return this.settings.specs?.heightCm ?? 0;
|
|
}
|
|
|
|
public sidewallHeight(): number {
|
|
return this.settings.specs?.advancedDimensions?.sidewallHeight ?? 0;
|
|
}
|
|
|
|
public roofHeight() : number {
|
|
return this.settings.specs?.advancedDimensions?.topConeHeight ?? 0;
|
|
}
|
|
|
|
public hopperHeight() : number {
|
|
return this.settings.specs?.advancedDimensions?.hopperHeight ?? 0;
|
|
}
|
|
|
|
public roofAngle() : number {
|
|
return this.settings.specs?.advancedDimensions?.roofAngle ?? 0;
|
|
}
|
|
|
|
public hopperAngle() : number {
|
|
return this.settings.specs?.advancedDimensions?.hopperAngle ?? 0;
|
|
}
|
|
|
|
public key(): string {
|
|
return this.settings.key;
|
|
}
|
|
|
|
public name(): string {
|
|
return this.settings.name !== "" ? this.settings.name : "Bin " + this.key();
|
|
}
|
|
|
|
public grain(): pond.Grain {
|
|
let g: pond.Grain = pond.Grain.GRAIN_NONE;
|
|
if (this.settings.inventory) {
|
|
g = this.settings.inventory.grainType;
|
|
}
|
|
return g;
|
|
}
|
|
|
|
public getLocation(): pond.Location | null | undefined {
|
|
return this.settings.location;
|
|
}
|
|
|
|
public binMapped(): boolean {
|
|
let location = this.getLocation();
|
|
return (
|
|
location !== undefined &&
|
|
location !== null &&
|
|
location.latitude !== 0 &&
|
|
location.longitude !== 0
|
|
);
|
|
}
|
|
|
|
public storage(): pond.BinStorage {
|
|
return !this.settings.storage
|
|
? pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN
|
|
: this.settings.storage;
|
|
}
|
|
|
|
public customType(): string {
|
|
let c = "";
|
|
if (this.settings.inventory) {
|
|
if (this.settings.inventory.customGrain){
|
|
c = this.settings.inventory.customGrain.name
|
|
}else{
|
|
c = this.settings.inventory.customTypeName;
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
|
|
public objectType(): pond.ObjectType {
|
|
return pond.ObjectType.OBJECT_TYPE_BIN;
|
|
}
|
|
|
|
public objectTypeString(): string {
|
|
return "Bin";
|
|
}
|
|
|
|
public subtype(): string {
|
|
return this.settings.inventory?.grainSubtype ?? "";
|
|
}
|
|
|
|
public grainColour(): string {
|
|
let colour = "";
|
|
if (this.settings.inventory) {
|
|
if (this.grain() === pond.Grain.GRAIN_CUSTOM) {
|
|
if (this.customType() !== "") {
|
|
colour = stringToMaterialColour(this.customType());
|
|
}
|
|
} else {
|
|
colour = GrainDescriber(this.grain()).colour;
|
|
}
|
|
}
|
|
return colour;
|
|
}
|
|
|
|
/**
|
|
* this function returns the number of bushels in the bin, if using the automatic lidar or libracart to control inventory it will use the bushels in status
|
|
* otherwise will use the bushels in the inventory found in settings
|
|
* @returns (number) the current bushels in the bin
|
|
*/
|
|
public bushels(): number {
|
|
let control = this.settings.inventory?.inventoryControl;
|
|
let bushels = this.settings.inventory?.grainBushels || 0
|
|
if (control === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC_LIDAR ||
|
|
control === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_LIBRACART){
|
|
bushels = this.status.grainBushels
|
|
}
|
|
return bushels
|
|
}
|
|
|
|
/**
|
|
* this function returns the bushelCapacity in the bins specs as it is stored or 0 if the specs are undefined
|
|
* @returns (number) the capacity of the bin in bushels
|
|
*/
|
|
public bushelCapacity(): number {
|
|
return this.settings.specs?.bushelCapacity ?? 0
|
|
}
|
|
|
|
public fillPercent(): number {
|
|
let fill = 0;
|
|
if (this.settings.inventory && this.settings.specs) {
|
|
let bushels = this.settings.inventory.grainBushels
|
|
if (this.settings.inventory.inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC_LIDAR ||
|
|
this.settings.inventory.inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_LIBRACART){
|
|
bushels = this.status.grainBushels
|
|
}
|
|
fill = Math.round(
|
|
(bushels / this.settings.specs.bushelCapacity) * 100
|
|
);
|
|
}
|
|
return fill;
|
|
}
|
|
|
|
public grainName(): string {
|
|
if (this.grain() !== pond.Grain.GRAIN_INVALID) {
|
|
if (this.grain() === pond.Grain.GRAIN_CUSTOM) {
|
|
//this will prioritize the new style of custom grain types
|
|
let cg = this.customGrain()
|
|
if(cg !== undefined){
|
|
return cg.name
|
|
}
|
|
return this.customType(); //this is still here for bins that are using the old custom grain where it was just a string
|
|
} else {
|
|
return GrainDescriber(this.grain()).name;
|
|
}
|
|
} else {
|
|
return "None";
|
|
}
|
|
}
|
|
|
|
public grainGroup(): string {
|
|
if (this.grain() !== pond.Grain.GRAIN_INVALID) {
|
|
let cg = this.customGrain()
|
|
if (this.grain() === pond.Grain.GRAIN_CUSTOM && cg) {
|
|
return cg.group
|
|
} else {
|
|
return GrainDescriber(this.grain()).group;
|
|
}
|
|
}
|
|
return "None";
|
|
}
|
|
|
|
public binFillCap(): string {
|
|
let fillCap = "";
|
|
if (this.settings.specs && this.settings.inventory) {
|
|
fillCap = this.settings.inventory.grainBushels + "/" + this.settings.specs.bushelCapacity;
|
|
}
|
|
return fillCap;
|
|
}
|
|
|
|
public location(): pond.Location | undefined | null {
|
|
let loc = this.settings.location;
|
|
return loc;
|
|
}
|
|
|
|
public fanID(): number {
|
|
return this.settings.fanId;
|
|
}
|
|
|
|
public supportedGrain(): boolean {
|
|
let s = false;
|
|
if (
|
|
this.grain() !== pond.Grain.GRAIN_NONE &&
|
|
this.grain() !== pond.Grain.GRAIN_CUSTOM &&
|
|
this.grain() !== pond.Grain.GRAIN_INVALID
|
|
) {
|
|
s = true;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
public getMarkerData(
|
|
clickFunc?: (event: React.PointerEvent<HTMLElement>, index: number, isMobile: boolean) => void,
|
|
updateFunc?: (location: pond.Location) => void
|
|
): MarkerData {
|
|
let m: MarkerData = {
|
|
centered: true,
|
|
longitude: this.location()?.longitude ?? 0,
|
|
latitude: this.location()?.latitude ?? 0,
|
|
title: this.name(),
|
|
colour: this.grainColour(),
|
|
visibleLevels: { min: 17 },
|
|
graphPercent: this.fillPercent(),
|
|
customSize: this.settings.theme?.height,
|
|
details: [this.name() + ", " + this.binFillCap()],
|
|
clickFunc: clickFunc,
|
|
updateFunc: updateFunc
|
|
};
|
|
return m;
|
|
}
|
|
|
|
/**
|
|
* returns the bushels per tonne set in the bins settings, if not set will return 1
|
|
* @returns 1 or bushels per tonne
|
|
*/
|
|
public bushelsPerTonne(): number {
|
|
//trying to avoid a divide by 0 error by only returning a value greater than 0
|
|
//since to get the weight you divide the current bushels by the bushels per tonne
|
|
let bpt = 1;
|
|
if (this.settings.inventory) {
|
|
if (this.settings.inventory.bushelsPerTonne > 0) {
|
|
bpt = this.settings.inventory.bushelsPerTonne;
|
|
}
|
|
}
|
|
return bpt;
|
|
}
|
|
|
|
/**
|
|
* this function returns a bins stored inventory in the unit of the passed in user,
|
|
* it can return it in bushels, US tons, or metric Tonnes
|
|
* @param user the user object
|
|
* @returns (number) bins current stored inventory
|
|
*/
|
|
public grainInventory(user: User): number {
|
|
let grain = this.bushels()
|
|
if(user.grainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && this.bushelsPerTonne() > 1){
|
|
grain = this.bushels() / this.bushelsPerTonne()
|
|
}else if (user.grainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && this.bushelsPerTonne() > 1){
|
|
grain = this.bushels() / (this.bushelsPerTonne() * 0.907)
|
|
}
|
|
return Math.round(grain*100)/100
|
|
}
|
|
|
|
/**
|
|
* this function returns a bins capacity in the unit of the passed in user,
|
|
* it can return it in bushels, US tons, or metric Tonnes
|
|
* @param user the user object
|
|
* @returns (number) bins max capacity
|
|
*/
|
|
public grainCapacity(user: User): number {
|
|
let capacity = this.bushelCapacity()
|
|
if(user.grainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && this.bushelsPerTonne() > 1){
|
|
capacity = capacity / this.bushelsPerTonne()
|
|
}else if (user.grainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && this.bushelsPerTonne() > 1){
|
|
capacity = capacity / (this.bushelsPerTonne() * 0.907)
|
|
}
|
|
return Math.round(capacity*100)/100
|
|
}
|
|
|
|
/**
|
|
* gets the enum value for the inventory control in the bins inventory
|
|
*/
|
|
public inventoryControl(): pond.BinInventoryControl {
|
|
let c = pond.BinInventoryControl.BIN_INVENTORY_CONTROL_UNKNOWN;
|
|
if (this.settings.inventory) {
|
|
return this.settings.inventory.inventoryControl;
|
|
}
|
|
return c;
|
|
}
|
|
|
|
//changed this to just use the target temp rather than the upper limit as we are deprecating the limits
|
|
public targetTemp(): number {
|
|
return this.settings.inventory?.targetTemperature ?? 0
|
|
}
|
|
|
|
public lowerTempThreshold(): number {
|
|
return this.settings.lowTemp
|
|
}
|
|
|
|
public targetMoisture(): number {
|
|
return this.settings.inventory?.targetMoisture ?? 0
|
|
}
|
|
}
|