Add project time phase profiles and related functions

This commit is contained in:
2026-04-12 14:06:52 +02:00
parent 8963adbee1
commit b54f688406

View File

@@ -1,10 +1,42 @@
export const HOURS_PER_DAY = 24 as const;
export const DEFAULT_PROJECT_DAY_LENGTH_MINUTES = 24 as const;
export const DEFAULT_PROJECT_START_DAY_NUMBER = 1 as const;
export const DEFAULT_PROJECT_START_TIME_OF_DAY_HOURS = 9 as const;
export const DEFAULT_PROJECT_SUNRISE_TIME_OF_DAY_HOURS = 6.5 as const;
export const DEFAULT_PROJECT_SUNSET_TIME_OF_DAY_HOURS = 18.5 as const;
export const DEFAULT_PROJECT_DAWN_DURATION_HOURS = 1.5 as const;
export const DEFAULT_PROJECT_DUSK_DURATION_HOURS = 1.5 as const;
export type ProjectTimePhase = "dawn" | "dusk" | "night";
export interface ProjectTimePhaseProfile {
skyTopColorHex: string;
skyBottomColorHex: string;
ambientColorHex: string;
ambientIntensityFactor: number;
lightColorHex: string;
lightIntensityFactor: number;
}
export interface ProjectTimeSettings {
startDayNumber: number;
startTimeOfDayHours: number;
dayLengthMinutes: number;
sunriseTimeOfDayHours: number;
sunsetTimeOfDayHours: number;
dawnDurationHours: number;
duskDurationHours: number;
dawn: ProjectTimePhaseProfile;
dusk: ProjectTimePhaseProfile;
night: ProjectTimePhaseProfile;
}
export function normalizeProjectStartDayNumber(dayNumber: number): number {
if (!Number.isFinite(dayNumber)) {
return DEFAULT_PROJECT_START_DAY_NUMBER;
}
return Math.max(DEFAULT_PROJECT_START_DAY_NUMBER, Math.floor(dayNumber));
}
export function normalizeTimeOfDayHours(hours: number): number {
@@ -21,10 +53,79 @@ export function formatTimeOfDayHours(hours: number): string {
return `${String(wholeHours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`;
}
export function createDefaultProjectTimePhaseProfile(
phase: ProjectTimePhase
): ProjectTimePhaseProfile {
switch (phase) {
case "dawn":
return {
skyTopColorHex: "#5877b2",
skyBottomColorHex: "#f6a66f",
ambientColorHex: "#ffd7b0",
ambientIntensityFactor: 0.72,
lightColorHex: "#ffc98d",
lightIntensityFactor: 0.78
};
case "dusk":
return {
skyTopColorHex: "#304076",
skyBottomColorHex: "#f08b5b",
ambientColorHex: "#f0b69a",
ambientIntensityFactor: 0.6,
lightColorHex: "#ffae7d",
lightIntensityFactor: 0.66
};
case "night":
return {
skyTopColorHex: "#081120",
skyBottomColorHex: "#1a2438",
ambientColorHex: "#1d2d45",
ambientIntensityFactor: 0.24,
lightColorHex: "#99b5ff",
lightIntensityFactor: 0.16
};
}
}
export function cloneProjectTimePhaseProfile(
profile: ProjectTimePhaseProfile
): ProjectTimePhaseProfile {
return {
skyTopColorHex: profile.skyTopColorHex,
skyBottomColorHex: profile.skyBottomColorHex,
ambientColorHex: profile.ambientColorHex,
ambientIntensityFactor: profile.ambientIntensityFactor,
lightColorHex: profile.lightColorHex,
lightIntensityFactor: profile.lightIntensityFactor
};
}
export function areProjectTimePhaseProfilesEqual(
left: ProjectTimePhaseProfile,
right: ProjectTimePhaseProfile
): boolean {
return (
left.skyTopColorHex === right.skyTopColorHex &&
left.skyBottomColorHex === right.skyBottomColorHex &&
left.ambientColorHex === right.ambientColorHex &&
left.ambientIntensityFactor === right.ambientIntensityFactor &&
left.lightColorHex === right.lightColorHex &&
left.lightIntensityFactor === right.lightIntensityFactor
);
}
export function createDefaultProjectTimeSettings(): ProjectTimeSettings {
return {
startDayNumber: DEFAULT_PROJECT_START_DAY_NUMBER,
startTimeOfDayHours: DEFAULT_PROJECT_START_TIME_OF_DAY_HOURS,
dayLengthMinutes: DEFAULT_PROJECT_DAY_LENGTH_MINUTES
dayLengthMinutes: DEFAULT_PROJECT_DAY_LENGTH_MINUTES,
sunriseTimeOfDayHours: DEFAULT_PROJECT_SUNRISE_TIME_OF_DAY_HOURS,
sunsetTimeOfDayHours: DEFAULT_PROJECT_SUNSET_TIME_OF_DAY_HOURS,
dawnDurationHours: DEFAULT_PROJECT_DAWN_DURATION_HOURS,
duskDurationHours: DEFAULT_PROJECT_DUSK_DURATION_HOURS,
dawn: createDefaultProjectTimePhaseProfile("dawn"),
dusk: createDefaultProjectTimePhaseProfile("dusk"),
night: createDefaultProjectTimePhaseProfile("night")
};
}
@@ -32,8 +133,16 @@ export function cloneProjectTimeSettings(
settings: ProjectTimeSettings
): ProjectTimeSettings {
return {
startDayNumber: settings.startDayNumber,
startTimeOfDayHours: settings.startTimeOfDayHours,
dayLengthMinutes: settings.dayLengthMinutes
dayLengthMinutes: settings.dayLengthMinutes,
sunriseTimeOfDayHours: settings.sunriseTimeOfDayHours,
sunsetTimeOfDayHours: settings.sunsetTimeOfDayHours,
dawnDurationHours: settings.dawnDurationHours,
duskDurationHours: settings.duskDurationHours,
dawn: cloneProjectTimePhaseProfile(settings.dawn),
dusk: cloneProjectTimePhaseProfile(settings.dusk),
night: cloneProjectTimePhaseProfile(settings.night)
};
}
@@ -42,7 +151,15 @@ export function areProjectTimeSettingsEqual(
right: ProjectTimeSettings
): boolean {
return (
left.startDayNumber === right.startDayNumber &&
left.startTimeOfDayHours === right.startTimeOfDayHours &&
left.dayLengthMinutes === right.dayLengthMinutes
left.dayLengthMinutes === right.dayLengthMinutes &&
left.sunriseTimeOfDayHours === right.sunriseTimeOfDayHours &&
left.sunsetTimeOfDayHours === right.sunsetTimeOfDayHours &&
left.dawnDurationHours === right.dawnDurationHours &&
left.duskDurationHours === right.duskDurationHours &&
areProjectTimePhaseProfilesEqual(left.dawn, right.dawn) &&
areProjectTimePhaseProfilesEqual(left.dusk, right.dusk) &&
areProjectTimePhaseProfilesEqual(left.night, right.night)
);
}