253 lines
7.3 KiB
C++
253 lines
7.3 KiB
C++
#pragma once
|
||
#include <QObject>
|
||
#include <QVector>
|
||
#include <QDateTime>
|
||
#include <QtMath>
|
||
|
||
struct ForecastResult
|
||
{
|
||
QString message;
|
||
int urgency; // 0-5
|
||
QString colorCode; // "vert", "jaune", ...
|
||
bool snowRisk;
|
||
bool rainRisk;
|
||
bool stormRisk;
|
||
bool blackIce;
|
||
};
|
||
|
||
class BarometerTrend : public QObject
|
||
{
|
||
Q_OBJECT
|
||
public:
|
||
explicit BarometerTrend(QObject *parent = nullptr)
|
||
: QObject(parent)
|
||
{}
|
||
|
||
void addPressure(double pressure_hPa)
|
||
{
|
||
// Enregistrement de la nouvelle mesure
|
||
m_values.append(pressure_hPa);
|
||
m_timestamps.append(QDateTime::currentDateTime());
|
||
|
||
// Limiter la taille de l’historique à 3 heures (360 mesures à 30s d’intervalle)
|
||
const int maxSamples = 360;
|
||
while (m_values.size() > maxSamples)
|
||
{
|
||
m_values.removeFirst();
|
||
m_timestamps.removeFirst();
|
||
}
|
||
}
|
||
|
||
double currentPressure() const
|
||
{
|
||
return m_values.isEmpty() ? 0.0 : m_values.last();
|
||
}
|
||
|
||
// Moyenne glissante sur les dernières N mesures (par ex. 5 minutes)
|
||
double smoothedPressure(int samples = 10) const
|
||
{
|
||
if (m_values.isEmpty())
|
||
{
|
||
return 0.0;
|
||
}
|
||
int n = qMin(samples, m_values.size());
|
||
double sum = 0.0;
|
||
for (int i = m_values.size() - n; i < m_values.size(); ++i)
|
||
sum += m_values[i];
|
||
return sum / n;
|
||
}
|
||
|
||
// Variation de pression sur les dernières 3h
|
||
double deltaPressure3h() const
|
||
{
|
||
if (m_values.size() < 2)
|
||
{
|
||
return 0.0;
|
||
}
|
||
QDateTime now = QDateTime::currentDateTime();
|
||
QDateTime target = now.addSecs(-3 * 3600);
|
||
|
||
// Cherche la valeur la plus proche d’il y a 3 heures
|
||
int idx = -1;
|
||
for (int i = 0; i < m_timestamps.size(); ++i)
|
||
{
|
||
if (m_timestamps[i] >= target)
|
||
{
|
||
idx = i;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (idx == -1)
|
||
{
|
||
idx = 0; // Pas assez vieux, on prend la plus ancienne
|
||
}
|
||
double p_now = smoothedPressure();
|
||
double p_past = m_values[idx];
|
||
return p_now - p_past;
|
||
}
|
||
|
||
ForecastResult forecast(double temperatureC, double humidityPercent) const
|
||
{
|
||
ForecastResult r;
|
||
|
||
double p = currentPressure();
|
||
double d = deltaPressure3h();
|
||
|
||
r.snowRisk = false;
|
||
r.rainRisk = false;
|
||
r.stormRisk = false;
|
||
r.blackIce = false;
|
||
|
||
|
||
// Logique combinée pression / tendance
|
||
if (p >= 1020 && d >= +3)
|
||
{
|
||
r.message = "Très beau temps durable";
|
||
r.urgency = 0;
|
||
r.colorCode = "sunny";
|
||
}else if (p >= 1020 && d >= +1)
|
||
{
|
||
r.message = "Beau temps durable";
|
||
r.urgency = 0;
|
||
r.colorCode = "sunny";
|
||
}else if (p >= 1020 && d < -3)
|
||
{
|
||
r.message = "Beau, mais rapide dégradation";
|
||
r.urgency = 4;
|
||
r.colorCode = "sun_behind_large_cloud";
|
||
}else if (p >= 1020 && d < -1)
|
||
{
|
||
r.message = "Beau, mais possible dégradation";
|
||
r.urgency = 1;
|
||
r.colorCode = "sun_behind_small_cloud";
|
||
}else if (p >= 1020 && d < 0.5)
|
||
{
|
||
r.message = "Beau temps stable";
|
||
r.urgency = 0;
|
||
r.colorCode = "sunny";
|
||
}else if (p >= 1010 && d >= +3)
|
||
{
|
||
r.message = "Rapide amélioration du temps";
|
||
r.urgency = 4;
|
||
r.colorCode = "sun_behind_small_cloud";
|
||
}else if (p >= 1010 && d >= +1)
|
||
{
|
||
r.message = "Amélioration du temps";
|
||
r.urgency = 0;
|
||
r.colorCode = "sun_behind_large_cloud";
|
||
}else if (p >= 1010 && d <= -3)
|
||
{
|
||
r.message = "Fort risque de pluie ou vent";
|
||
r.urgency = 4;
|
||
r.colorCode = "sun_behind_rain_cloud";
|
||
}else if (p >= 1010 && d <= -1)
|
||
{
|
||
r.message = "Risque de pluie ou vent";
|
||
r.urgency = 2;
|
||
r.colorCode = "sun_behind_rain_cloud";
|
||
}else if (p >= 1010 && d <= 0.5)
|
||
{
|
||
r.message = "Nuageux avec des éclaircies";
|
||
r.urgency = 2;
|
||
r.colorCode = "sun_behind_large_cloud";
|
||
}else if (p >= 1000 && d >= +3)
|
||
{
|
||
r.message = "Variable, amélioration rapide";
|
||
r.urgency = 4;
|
||
r.colorCode = "sun_behind_large_cloud";
|
||
}else if (p >= 1000 && d >= +1)
|
||
{
|
||
r.message = "Variable, tendance au beau";
|
||
r.urgency = 0;
|
||
r.colorCode = "sun_behind_large_cloud";
|
||
}else if (p >= 1000 && d <= -3)
|
||
{
|
||
r.message = "Pluie ou perturbation, dégradation rapide";
|
||
r.urgency = 4;
|
||
r.colorCode = "cloud_with_rain";
|
||
}else if (p >= 1000 && d <= -1)
|
||
{
|
||
r.message = "Pluie ou perturbation";
|
||
r.urgency = 2;
|
||
r.colorCode = "cloud_with_rain";
|
||
}else if (p < 990 && d <= -3)
|
||
{
|
||
r.message = "Tempête ou orage";
|
||
r.urgency = 5;
|
||
r.colorCode = "cloud_with_lightning";
|
||
}else if (p < 1000 && d >= +3)
|
||
{
|
||
r.message = "Accalmie temporaire, amélioration rapide";
|
||
r.urgency = 1;
|
||
r.colorCode = "sun_behind_rain_cloud";
|
||
}else if (p < 1000 && d >= +1)
|
||
{
|
||
r.message = "Accalmie temporaire";
|
||
r.urgency = 1;
|
||
r.colorCode = "sun_behind_rain_cloud";
|
||
}else if (p < 1000 && d <= -1)
|
||
{
|
||
r.message = "Mauvais temps durable";
|
||
r.urgency = 4;
|
||
r.colorCode = "cloud_with_rain";
|
||
}
|
||
|
||
if (qAbs(d) < 0.5)
|
||
{
|
||
r.message = "Stable, pas de changement significatif";
|
||
r.urgency = 0;
|
||
}
|
||
|
||
// Risque de neige
|
||
if (p < 1000 && d < -1 && temperatureC <= 1.0 && humidityPercent > 80.0)
|
||
{
|
||
r.snowRisk = true;
|
||
r.message += " — Risque de neige";
|
||
r.urgency = qMax(r.urgency, 3);
|
||
r.colorCode += "snowflake,";
|
||
}
|
||
|
||
// Risque de pluie
|
||
else if (p < 1010 && d < -1 && temperatureC > 1.0 && humidityPercent > 70.0)
|
||
{
|
||
r.rainRisk = true;
|
||
r.message += " — Risque de pluie";
|
||
r.urgency = qMax(r.urgency, 2);
|
||
r.colorCode += "cloud_with_rain,";
|
||
}
|
||
|
||
// Risque d’orage
|
||
if (p < 995 && d < -3 && temperatureC > 20.0 && humidityPercent > 70.0)
|
||
{
|
||
r.stormRisk = true;
|
||
r.message += " ⚡ Risque d’orage";
|
||
r.urgency = qMax(r.urgency, 4);
|
||
r.colorCode += "cloud_with_lightning,";
|
||
}
|
||
|
||
if (temperatureC <= 0.5 && humidityPercent >= 85.0) {
|
||
// conditions classiques de gel
|
||
if (d >= -1 && d <= +1)
|
||
{
|
||
r.blackIce = true; // temps stable = ciel clair = refroidissement
|
||
}else if (d < -1 && p > 995)
|
||
{
|
||
r.blackIce = true; // arrivée d'air humide froid
|
||
}
|
||
}
|
||
|
||
if (r.blackIce)
|
||
{
|
||
r.message += "Risque de verglas";
|
||
r.colorCode += "ice_cube,";
|
||
r.urgency = qMax(r.urgency, 4);
|
||
}
|
||
return r;
|
||
}
|
||
|
||
private:
|
||
QVector<double> m_values;
|
||
QVector<QDateTime> m_timestamps;
|
||
};
|