85 lines
3.3 KiB
JavaScript
85 lines
3.3 KiB
JavaScript
import mongoose from "mongoose";
|
||
import {
|
||
DEFAULT_PRODUCE_ICON,
|
||
PRODUCE_ICON_IDS,
|
||
} from "../../constants/produceIcons.js";
|
||
|
||
const SUNLIGHT_VALUES = ["fullSun", "partialShade", "fullShade"];
|
||
const WATER_NEEDS_VALUES = ["low", "medium", "high"];
|
||
|
||
const patchSchema = new mongoose.Schema(
|
||
{
|
||
deviceId: {
|
||
type: mongoose.Schema.Types.ObjectId,
|
||
ref: "Device",
|
||
required: true,
|
||
index: true,
|
||
},
|
||
patchId: { type: String, required: true },
|
||
name: { type: String, default: "" },
|
||
description: { type: String, default: "" },
|
||
/** Produce icon id (basename under client assets/svg/produce). */
|
||
icon: {
|
||
type: String,
|
||
enum: PRODUCE_ICON_IDS,
|
||
default: DEFAULT_PRODUCE_ICON,
|
||
},
|
||
/** Plant grid rows on the bed visualisation. */
|
||
rows: { type: Number, default: 3, min: 1 },
|
||
/** Plant grid columns on the bed visualisation. */
|
||
columns: { type: Number, default: 8, min: 1 },
|
||
/** Growth stage passed to the plant Lottie (derived from lifecycle + time; not user-edited). */
|
||
currentGrowingPosition: { type: Number, default: 0 },
|
||
/** Withering tint 0–100 for plant Lottie (derived from lifecycle + time; not user-edited). */
|
||
currentWithering: { type: Number, default: 0 },
|
||
/** Visible leaf count 0–6 for plant Lottie (derived from lifecycle + time; not user-edited). */
|
||
currentLeaves: { type: Number, default: 0, min: 0, max: 6 },
|
||
/** Visible flower count 0–3 for plant Lottie (derived from lifecycle + time; not user-edited). */
|
||
currentFlowers: { type: Number, default: 0, min: 0, max: 3 },
|
||
/** Fruit development 0–100 for plant Lottie (derived from lifecycle + time; not user-edited). */
|
||
currentFruiting: { type: Number, default: 0, min: 0, max: 100 },
|
||
/** Active lifecycle phase name/index from last server-side recalculation. */
|
||
currentGrowingPhase: {
|
||
type: new mongoose.Schema(
|
||
{
|
||
name: { type: String, default: "" },
|
||
index: { type: Number, default: 0 },
|
||
},
|
||
{ _id: false },
|
||
),
|
||
default: null,
|
||
},
|
||
soilHumidity: { type: Number, default: 0 },
|
||
soilTemperature: { type: Number, default: 21 },
|
||
sunlight: {
|
||
type: String,
|
||
enum: SUNLIGHT_VALUES,
|
||
default: "fullSun",
|
||
},
|
||
soilPhMin: { type: Number, default: 5.5, min: 0, max: 14 },
|
||
soilPhMax: { type: Number, default: 6.5, min: 0, max: 14 },
|
||
waterNeeds: {
|
||
type: String,
|
||
enum: WATER_NEEDS_VALUES,
|
||
default: "medium",
|
||
},
|
||
/** Biennial: sow/plant date anchor for offset-based lifecycle (ISO date in API). */
|
||
plantedAt: { type: Date, default: null },
|
||
/**
|
||
* Biennial: { type, durationWeeks, phases[{ name, startOffsetWeeks, endOffsetWeeks, growingPosition 0–100, withering 0–100, leaves 0–6, flowers 0–3, fruiting 0–100 }] }
|
||
* Perennial: { type, recurring, phases[{ name, startWeek, endWeek, growingPosition 0–100, withering 0–100, leaves 0–6, flowers 0–3, fruiting 0–100 }] }
|
||
*/
|
||
lifecycle: { type: mongoose.Schema.Types.Mixed, default: undefined },
|
||
/** Ordered gallery image references (see `Image` model). */
|
||
images: {
|
||
type: [{ type: mongoose.Schema.Types.ObjectId, ref: "Image" }],
|
||
default: [],
|
||
},
|
||
},
|
||
{ timestamps: true },
|
||
);
|
||
|
||
patchSchema.index({ deviceId: 1, patchId: 1 }, { unique: true });
|
||
|
||
export const Patch = mongoose.model("Patch", patchSchema);
|