98 lines
2.8 KiB
TypeScript
98 lines
2.8 KiB
TypeScript
import {
|
|
brightProgression,
|
|
dreamyProgression,
|
|
melancholicProgression,
|
|
tenseProgression,
|
|
warmProgression,
|
|
etherealProgression,
|
|
type ChordProgression
|
|
} from './chord-progressions';
|
|
|
|
interface WeatherConditions {
|
|
temperature2m: number;
|
|
relativeHumidity2m: number;
|
|
cloudCover: number;
|
|
windSpeed10m: number;
|
|
precipitation: number;
|
|
isDay: boolean;
|
|
}
|
|
|
|
/**
|
|
* Calculate a weather mood score based on various conditions
|
|
* Returns values between 0 (harsh/extreme) and 1 (pleasant)
|
|
*/
|
|
export function calculateComfortScore(conditions: WeatherConditions): number {
|
|
const { temperature2m, relativeHumidity2m, cloudCover, windSpeed10m, precipitation } =
|
|
conditions;
|
|
|
|
// Temperature comfort: ideal 15-25°C, drops off outside this range
|
|
let tempScore = 1.0;
|
|
if (temperature2m < 15) {
|
|
tempScore = Math.max(0, 1 - Math.abs(15 - temperature2m) / 30);
|
|
} else if (temperature2m > 25) {
|
|
tempScore = Math.max(0, 1 - Math.abs(temperature2m - 25) / 20);
|
|
}
|
|
|
|
// Humidity comfort: ideal 40-60%, drops off outside
|
|
let humidityScore = 1.0;
|
|
if (relativeHumidity2m < 40) {
|
|
humidityScore = Math.max(0, relativeHumidity2m / 40);
|
|
} else if (relativeHumidity2m > 60) {
|
|
humidityScore = Math.max(0, 1 - (relativeHumidity2m - 60) / 40);
|
|
}
|
|
|
|
// Cloud cover: some clouds (30-70%) is pleasant, extremes less so
|
|
const cloudScore = 1 - Math.abs(cloudCover - 50) / 50;
|
|
|
|
// Wind: light breeze (0-15 km/h) is nice, strong wind less so
|
|
const windScore = Math.max(0, 1 - windSpeed10m / 40);
|
|
|
|
// Precipitation: any is somewhat unpleasant
|
|
const precipScore = Math.max(0, 1 - precipitation / 10);
|
|
|
|
// Weighted average
|
|
return (
|
|
tempScore * 0.35 +
|
|
humidityScore * 0.2 +
|
|
cloudScore * 0.15 +
|
|
windScore * 0.15 +
|
|
precipScore * 0.15
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Select the appropriate chord progression based on weather conditions
|
|
*/
|
|
export function selectChordProgression(conditions: WeatherConditions): ChordProgression {
|
|
const comfortScore = calculateComfortScore(conditions);
|
|
const { temperature2m, precipitation, cloudCover, isDay } = conditions;
|
|
|
|
// Stormy/extreme conditions (heavy rain, very harsh)
|
|
if (precipitation > 5 || comfortScore < 0.2) {
|
|
return tenseProgression;
|
|
}
|
|
|
|
// Very hot conditions
|
|
if (temperature2m > 30) {
|
|
return warmProgression;
|
|
}
|
|
|
|
// Cold/rainy/gloomy conditions
|
|
if (temperature2m < 5 || (precipitation > 1 && cloudCover > 70)) {
|
|
return melancholicProgression;
|
|
}
|
|
|
|
// Foggy/misty conditions (high humidity + clouds, low wind)
|
|
if (conditions.relativeHumidity2m > 80 && cloudCover > 60 && temperature2m > 5) {
|
|
return etherealProgression;
|
|
}
|
|
|
|
// Pleasant conditions - choose based on day/night
|
|
if (comfortScore > 0.6) {
|
|
return isDay ? brightProgression : dreamyProgression;
|
|
}
|
|
|
|
// Default: slightly unpleasant but not extreme
|
|
return isDay ? dreamyProgression : melancholicProgression;
|
|
}
|