fix(dashboard): « Plan de la journée » retirée — cinquième donnée inventée, et la dernière
DayPlan.demo() fabriquait vingt-quatre heures de flux : une gaussienne solaire et des coefficients écrits en dur — solToEcs = excédent × 0,35, solToVe × 0,3, solToBatt × 0,15, battToHouse = déficit × 0,55 — sous le titre « Plan de la journée · aujourd'hui », sans la moindre mention. Y compris une batterie alimentant la maison à partir de 17 h, sur une installation qui n'a pas de batterie. Cinquième après les deux MPPT, les 38 % de PAC, les 82 % de part solaire et le SOC à 62 %. Même réponse à chaque fois : il n'y a rien derrière. Un plan suppose de savoir ce qui VA arriver — il demande une prévision PV et une source tarifaire, dont aucune n'existe. La carte reviendra avec elles. Le code de fabrication part AVEC la carte : DayPlan, HourlyFlow, WeatherPoint, WeatherKind et le painter sont supprimés, pas mis de côté. Un générateur de données plausibles laissé dans le dépôt se rebranche — c'est exactement ce qui s'est passé quatre fois déjà. 339 tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GKM8FDNHZWogAsjjfB8pSw
This commit is contained in:
parent
5a51582729
commit
5944d3a24a
@ -1,104 +1,16 @@
|
||||
import 'dart:math' as math;
|
||||
/// Modèles du tableau de bord.
|
||||
///
|
||||
/// 🔴 `HourlyFlow`, `WeatherPoint` et `DayPlan` ont été **supprimés** le 2026-09-08 avec la
|
||||
/// carte « Plan de la journée » qu'ils alimentaient. `DayPlan.demo()` fabriquait vingt-quatre
|
||||
/// heures de flux à partir d'une gaussienne et de coefficients écrits en dur, présentées sans
|
||||
/// mention comme la journée en cours.
|
||||
///
|
||||
/// Le code part **avec** la carte, délibérément : un générateur de données plausibles laissé
|
||||
/// dans le dépôt se rebranche — c'est ce qui s'était passé pour les deux MPPT, les 38 % de
|
||||
/// PAC, les 82 % de part solaire et le SOC à 62 %. Un plan reviendra quand il y aura une
|
||||
/// prévision PV et une source tarifaire ; il se réécrira sur des données, pas sur celles-ci.
|
||||
library;
|
||||
|
||||
enum WeatherKind { sun, partlyCloudy, cloudy, moon }
|
||||
|
||||
class HourlyFlow {
|
||||
final int hour;
|
||||
final double solToHouse;
|
||||
final double solToEcs;
|
||||
final double solToVe;
|
||||
final double solToBatt;
|
||||
final double solToGrid;
|
||||
final double battToHouse;
|
||||
final double gridToHouse;
|
||||
|
||||
const HourlyFlow({
|
||||
required this.hour,
|
||||
this.solToHouse = 0,
|
||||
this.solToEcs = 0,
|
||||
this.solToVe = 0,
|
||||
this.solToBatt = 0,
|
||||
this.solToGrid = 0,
|
||||
this.battToHouse = 0,
|
||||
this.gridToHouse = 0,
|
||||
});
|
||||
|
||||
double get totalPositive =>
|
||||
solToHouse + solToEcs + solToVe + solToBatt + solToGrid;
|
||||
double get totalNegative => battToHouse + gridToHouse;
|
||||
}
|
||||
|
||||
class WeatherPoint {
|
||||
final int hour;
|
||||
final WeatherKind kind;
|
||||
final int tempC;
|
||||
|
||||
const WeatherPoint({
|
||||
required this.hour,
|
||||
required this.kind,
|
||||
required this.tempC,
|
||||
});
|
||||
}
|
||||
|
||||
class DayPlan {
|
||||
final List<HourlyFlow> hours;
|
||||
final List<WeatherPoint> weather;
|
||||
final double nowHour;
|
||||
|
||||
const DayPlan({
|
||||
required this.hours,
|
||||
required this.weather,
|
||||
required this.nowHour,
|
||||
});
|
||||
|
||||
static DayPlan demo() {
|
||||
final now = DateTime.now();
|
||||
final nowHour = now.hour + now.minute / 60.0;
|
||||
|
||||
final hours = List.generate(24, (h) {
|
||||
final solar = h >= 6 && h <= 20
|
||||
? 3.8 * math.exp(-math.pow(h - 13, 2) / 18.0)
|
||||
: 0.0;
|
||||
final baseHouse = 1.2;
|
||||
final peakHouse = (h >= 7 && h <= 9) || (h >= 18 && h <= 21) ? 0.7 : 0.0;
|
||||
final house = baseHouse + peakHouse;
|
||||
|
||||
final excess = math.max(0.0, solar - house);
|
||||
final deficit = math.max(0.0, house - solar);
|
||||
|
||||
final solToHouse = math.min(solar, house);
|
||||
final solToEcs = excess > 0.5 ? math.min(excess * 0.35, 0.7) : 0.0;
|
||||
final solToVe = excess > 1.2 ? math.min(excess * 0.3, 1.1) : 0.0;
|
||||
final solToBatt = excess > 0.3 ? math.min(excess * 0.15, 0.4) : 0.0;
|
||||
final solToGrid = math.max(0.0, excess - solToEcs - solToVe - solToBatt);
|
||||
|
||||
final battToHouse = h >= 17 ? math.min(deficit * 0.55, 0.8) : 0.0;
|
||||
final gridToHouse = math.max(0.0, deficit - battToHouse);
|
||||
|
||||
return HourlyFlow(
|
||||
hour: h,
|
||||
solToHouse: solToHouse,
|
||||
solToEcs: solToEcs,
|
||||
solToVe: solToVe,
|
||||
solToBatt: solToBatt,
|
||||
solToGrid: solToGrid,
|
||||
battToHouse: battToHouse,
|
||||
gridToHouse: gridToHouse,
|
||||
);
|
||||
});
|
||||
|
||||
final weather = [
|
||||
const WeatherPoint(hour: 0, kind: WeatherKind.moon, tempC: 17),
|
||||
const WeatherPoint(hour: 4, kind: WeatherKind.moon, tempC: 15),
|
||||
const WeatherPoint(hour: 8, kind: WeatherKind.partlyCloudy, tempC: 19),
|
||||
const WeatherPoint(hour: 12, kind: WeatherKind.sun, tempC: 25),
|
||||
const WeatherPoint(hour: 16, kind: WeatherKind.sun, tempC: 27),
|
||||
const WeatherPoint(hour: 20, kind: WeatherKind.partlyCloudy, tempC: 22),
|
||||
];
|
||||
|
||||
return DayPlan(hours: hours, weather: weather, nowHour: nowHour);
|
||||
}
|
||||
}
|
||||
|
||||
class HeosAction {
|
||||
final String iconKey;
|
||||
|
||||
@ -1,296 +0,0 @@
|
||||
import 'dart:math' as math;
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../theme/etm_tokens.dart';
|
||||
import '../models/dashboard_models.dart';
|
||||
|
||||
class DayPlanPainter extends CustomPainter {
|
||||
final DayPlan plan;
|
||||
final Color surfaceColor;
|
||||
final Color lineColor;
|
||||
final Color inkColor;
|
||||
final Color mutedColor;
|
||||
final bool isDark;
|
||||
|
||||
const DayPlanPainter({
|
||||
required this.plan,
|
||||
required this.surfaceColor,
|
||||
required this.lineColor,
|
||||
required this.inkColor,
|
||||
required this.mutedColor,
|
||||
required this.isDark,
|
||||
});
|
||||
|
||||
static const double _weatherH = 44.0;
|
||||
static const double _xAxisH = 22.0;
|
||||
static const double _leftPad = 28.0;
|
||||
static const double _maxPosKwh = 4.0;
|
||||
static const double _maxNegKwh = 1.8;
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final chartH = size.height - _weatherH - _xAxisH;
|
||||
final chartW = size.width - _leftPad;
|
||||
final zeroY = _weatherH + chartH * (_maxPosKwh / (_maxPosKwh + _maxNegKwh));
|
||||
|
||||
final posScale = chartH * (_maxPosKwh / (_maxPosKwh + _maxNegKwh)) / _maxPosKwh;
|
||||
final negScale = chartH * (_maxNegKwh / (_maxPosKwh + _maxNegKwh)) / _maxNegKwh;
|
||||
|
||||
final nowX = _leftPad + plan.nowHour / 24 * chartW;
|
||||
|
||||
// ── Future background
|
||||
if (nowX < size.width) {
|
||||
canvas.drawRect(
|
||||
Rect.fromLTRB(nowX, _weatherH, size.width, _weatherH + chartH),
|
||||
Paint()
|
||||
..color = (isDark
|
||||
? const Color(0xFF06141D)
|
||||
: const Color(0xFFEEF2F5))
|
||||
.withValues(alpha: 0.55),
|
||||
);
|
||||
_drawHatch(canvas, Rect.fromLTRB(nowX, _weatherH, size.width, _weatherH + chartH));
|
||||
}
|
||||
|
||||
// ── Bars (24 hours)
|
||||
final barW = chartW / 24;
|
||||
for (final h in plan.hours) {
|
||||
final x = _leftPad + h.hour * barW;
|
||||
_drawStackedBars(canvas, x, barW, zeroY, posScale, negScale, h);
|
||||
}
|
||||
|
||||
// ── Y axis labels
|
||||
_drawYLabels(canvas, zeroY, posScale, size);
|
||||
|
||||
// ── Zero line
|
||||
canvas.drawLine(
|
||||
Offset(_leftPad, zeroY),
|
||||
Offset(size.width, zeroY),
|
||||
Paint()
|
||||
..color = lineColor
|
||||
..strokeWidth = 1.0,
|
||||
);
|
||||
|
||||
// ── X axis labels (0h 6h 12h 18h 24h)
|
||||
for (final h in [0, 6, 12, 18, 24]) {
|
||||
final x = _leftPad + h / 24 * chartW;
|
||||
_paintText(
|
||||
canvas,
|
||||
h == 24 ? '24h' : '${h}h',
|
||||
Offset(x, _weatherH + chartH + 4),
|
||||
mutedColor,
|
||||
9,
|
||||
center: true,
|
||||
);
|
||||
}
|
||||
|
||||
// ── "Now" line + label
|
||||
if (nowX > _leftPad && nowX < size.width) {
|
||||
canvas.drawLine(
|
||||
Offset(nowX, _weatherH),
|
||||
Offset(nowX, _weatherH + chartH),
|
||||
Paint()
|
||||
..color = inkColor.withValues(alpha: 0.6)
|
||||
..strokeWidth = 1.2
|
||||
..style = PaintingStyle.stroke,
|
||||
);
|
||||
final now = DateTime.now();
|
||||
final label =
|
||||
'${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}';
|
||||
_drawNowBadge(canvas, nowX, _weatherH, label);
|
||||
}
|
||||
|
||||
// ── Weather band
|
||||
_drawWeatherBand(canvas, chartW, plan.weather);
|
||||
}
|
||||
|
||||
void _drawStackedBars(Canvas canvas, double x, double barW, double zeroY,
|
||||
double posScale, double negScale, HourlyFlow h) {
|
||||
const gap = 1.5;
|
||||
final bw = barW - gap;
|
||||
|
||||
// Positive stack (upward from zeroY)
|
||||
double topY = zeroY;
|
||||
void stackPos(double kWh, Color color) {
|
||||
if (kWh < 0.01) return;
|
||||
final h2 = kWh * posScale;
|
||||
canvas.drawRRect(
|
||||
RRect.fromRectAndRadius(
|
||||
Rect.fromLTWH(x + gap / 2, topY - h2, bw, h2),
|
||||
const Radius.circular(1.5),
|
||||
),
|
||||
Paint()..color = color,
|
||||
);
|
||||
topY -= h2;
|
||||
}
|
||||
|
||||
stackPos(h.solToHouse, EtmTokens.solToHouse);
|
||||
stackPos(h.solToEcs, EtmTokens.solToEcs);
|
||||
stackPos(h.solToVe, EtmTokens.solToVe);
|
||||
stackPos(h.solToBatt, EtmTokens.solToBatt);
|
||||
stackPos(h.solToGrid, EtmTokens.solToGrid);
|
||||
|
||||
// Negative stack (downward from zeroY)
|
||||
double botY = zeroY;
|
||||
void stackNeg(double kWh, Color color) {
|
||||
if (kWh < 0.01) return;
|
||||
final h2 = kWh * negScale;
|
||||
canvas.drawRRect(
|
||||
RRect.fromRectAndRadius(
|
||||
Rect.fromLTWH(x + gap / 2, botY, bw, h2),
|
||||
const Radius.circular(1.5),
|
||||
),
|
||||
Paint()..color = color.withValues(alpha: 0.7),
|
||||
);
|
||||
botY += h2;
|
||||
}
|
||||
|
||||
stackNeg(h.battToHouse, EtmTokens.battToHouse);
|
||||
stackNeg(h.gridToHouse, EtmTokens.gridToHouse);
|
||||
}
|
||||
|
||||
void _drawHatch(Canvas canvas, Rect rect) {
|
||||
canvas.save();
|
||||
canvas.clipRect(rect);
|
||||
final hatchPaint = Paint()
|
||||
..color = surfaceColor.withValues(alpha: 0.5)
|
||||
..strokeWidth = 1.0
|
||||
..style = PaintingStyle.stroke;
|
||||
const step = 8.0;
|
||||
for (double d = -rect.height; d < rect.width + rect.height; d += step) {
|
||||
canvas.drawLine(
|
||||
Offset(rect.left + d, rect.top),
|
||||
Offset(rect.left + d + rect.height, rect.bottom),
|
||||
hatchPaint,
|
||||
);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void _drawYLabels(Canvas canvas, double zeroY, double posScale, Size size) {
|
||||
for (final kWh in [2.0, 4.0]) {
|
||||
final y = zeroY - kWh * posScale;
|
||||
_paintText(canvas, '${kWh.toInt()}', Offset(0, y - 5), mutedColor, 8);
|
||||
canvas.drawLine(
|
||||
Offset(_leftPad, y),
|
||||
Offset(size.width, y),
|
||||
Paint()
|
||||
..color = lineColor.withValues(alpha: 0.6)
|
||||
..strokeWidth = 0.5,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _drawNowBadge(Canvas canvas, double x, double top, String label) {
|
||||
final tp = TextPainter(
|
||||
text: TextSpan(
|
||||
text: label,
|
||||
style: TextStyle(
|
||||
fontFamily: 'IBMPlexMono',
|
||||
fontSize: 9,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: surfaceColor,
|
||||
),
|
||||
),
|
||||
textDirection: TextDirection.ltr,
|
||||
)..layout();
|
||||
const pad = 4.0;
|
||||
final rect = Rect.fromCenter(
|
||||
center: Offset(x, top - tp.height / 2 - pad - 2),
|
||||
width: tp.width + pad * 2,
|
||||
height: tp.height + pad,
|
||||
);
|
||||
canvas.drawRRect(
|
||||
RRect.fromRectAndRadius(rect, const Radius.circular(4)),
|
||||
Paint()..color = inkColor.withValues(alpha: 0.75),
|
||||
);
|
||||
tp.paint(canvas, Offset(rect.left + pad, rect.top + pad / 2));
|
||||
}
|
||||
|
||||
void _drawWeatherBand(
|
||||
Canvas canvas, double chartW, List<WeatherPoint> points) {
|
||||
for (final p in points) {
|
||||
final x = _leftPad + p.hour / 24 * chartW;
|
||||
final iconColor = p.kind == WeatherKind.sun || p.kind == WeatherKind.partlyCloudy
|
||||
? EtmTokens.solar
|
||||
: mutedColor;
|
||||
_drawWeatherIcon(canvas, Offset(x, 12), p.kind, iconColor);
|
||||
_paintText(
|
||||
canvas,
|
||||
'${p.tempC}°',
|
||||
Offset(x, 26),
|
||||
mutedColor,
|
||||
9,
|
||||
center: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _drawWeatherIcon(
|
||||
Canvas canvas, Offset center, WeatherKind kind, Color color) {
|
||||
final paint = Paint()..color = color..style = PaintingStyle.fill;
|
||||
switch (kind) {
|
||||
case WeatherKind.sun:
|
||||
_drawSun(canvas, center, color);
|
||||
case WeatherKind.partlyCloudy:
|
||||
_drawSun(canvas, center + const Offset(-3, -3), color, r: 5);
|
||||
_drawCloud(canvas, center + const Offset(2, 2), color.withValues(alpha: 0.9));
|
||||
case WeatherKind.cloudy:
|
||||
_drawCloud(canvas, center, mutedColor);
|
||||
case WeatherKind.moon:
|
||||
_drawMoon(canvas, center, color, paint);
|
||||
}
|
||||
}
|
||||
|
||||
void _drawSun(Canvas canvas, Offset c, Color color, {double r = 6}) {
|
||||
final p = Paint()..color = color..style = PaintingStyle.fill;
|
||||
canvas.drawCircle(c, r, p);
|
||||
final rp = Paint()
|
||||
..color = color
|
||||
..strokeWidth = 1.2
|
||||
..style = PaintingStyle.stroke;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
final a = i * math.pi / 4;
|
||||
canvas.drawLine(
|
||||
c + Offset(math.cos(a), math.sin(a)) * (r + 2),
|
||||
c + Offset(math.cos(a), math.sin(a)) * (r + 5),
|
||||
rp,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _drawCloud(Canvas canvas, Offset c, Color color) {
|
||||
final p = Paint()..color = color..style = PaintingStyle.fill;
|
||||
canvas.drawCircle(c + const Offset(-4, 1), 4, p);
|
||||
canvas.drawCircle(c + const Offset(1, -1), 5.5, p);
|
||||
canvas.drawCircle(c + const Offset(6, 2), 3.5, p);
|
||||
canvas.drawRect(
|
||||
Rect.fromLTWH(c.dx - 7, c.dy + 1, 16, 4),
|
||||
p,
|
||||
);
|
||||
}
|
||||
|
||||
void _drawMoon(Canvas canvas, Offset c, Color color, Paint paint) {
|
||||
final path = Path()..addOval(Rect.fromCircle(center: c, radius: 7));
|
||||
final cut = Path()..addOval(Rect.fromCircle(center: c + const Offset(4, -3), radius: 6));
|
||||
final crescent = Path.combine(PathOperation.difference, path, cut);
|
||||
canvas.drawPath(crescent, paint);
|
||||
}
|
||||
|
||||
void _paintText(Canvas canvas, String text, Offset pos, Color color,
|
||||
double size, {bool center = false}) {
|
||||
final tp = TextPainter(
|
||||
text: TextSpan(
|
||||
text: text,
|
||||
style: TextStyle(fontSize: size, color: color, fontWeight: FontWeight.w500),
|
||||
),
|
||||
textDirection: TextDirection.ltr,
|
||||
)..layout();
|
||||
tp.paint(
|
||||
canvas,
|
||||
center ? Offset(pos.dx - tp.width / 2, pos.dy) : pos,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(DayPlanPainter old) =>
|
||||
old.plan != plan || old.isDark != isDark;
|
||||
}
|
||||
@ -1,97 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../theme/etm_tokens.dart';
|
||||
import '../models/dashboard_models.dart';
|
||||
import '../painters/day_plan_painter.dart';
|
||||
|
||||
class DayPlanCard extends StatelessWidget {
|
||||
const DayPlanCard({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final plan = DayPlan.demo();
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: EtmTokens.surfaceOf(context),
|
||||
borderRadius: BorderRadius.circular(EtmTokens.radiusCard),
|
||||
boxShadow: EtmTokens.cardShadowOf(context),
|
||||
),
|
||||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('Plan de la journée',
|
||||
style: EtmTokens.sans(
|
||||
size: 15,
|
||||
weight: FontWeight.w600,
|
||||
color: EtmTokens.inkOf(context))),
|
||||
Text("aujourd'hui",
|
||||
style: EtmTokens.sans(
|
||||
size: 12, color: EtmTokens.mutedOf(context))),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(
|
||||
height: 180,
|
||||
child: CustomPaint(
|
||||
painter: DayPlanPainter(
|
||||
plan: plan,
|
||||
surfaceColor: EtmTokens.surfaceOf(context),
|
||||
lineColor: EtmTokens.lineOf(context),
|
||||
inkColor: EtmTokens.inkOf(context),
|
||||
mutedColor: EtmTokens.mutedOf(context),
|
||||
isDark: isDark,
|
||||
),
|
||||
size: const Size(double.infinity, 180),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_Legend(context: context),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _Legend extends StatelessWidget {
|
||||
final BuildContext context;
|
||||
const _Legend({required this.context});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext _) {
|
||||
final items = [
|
||||
('Maison', EtmTokens.solToHouse),
|
||||
('ECS', EtmTokens.solToEcs),
|
||||
('VE', EtmTokens.solToVe),
|
||||
('Batterie', EtmTokens.solToBatt),
|
||||
('Réseau', EtmTokens.solToGrid),
|
||||
('Batt.→maison', EtmTokens.battToHouse),
|
||||
];
|
||||
return Wrap(
|
||||
spacing: 12,
|
||||
runSpacing: 6,
|
||||
children: items.map((e) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
width: 10, height: 10,
|
||||
decoration: BoxDecoration(
|
||||
color: e.$2,
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(e.$1,
|
||||
style: EtmTokens.sans(
|
||||
size: 10, color: EtmTokens.mutedOf(context))),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -13,7 +13,6 @@ import '../theme/etm_tokens.dart';
|
||||
import '../features/dashboard/widgets/energy_flow_card.dart';
|
||||
import '../features/dashboard/widgets/kpi_row.dart';
|
||||
import '../features/dashboard/widgets/heos_decision_card.dart';
|
||||
import '../features/dashboard/widgets/day_plan_card.dart';
|
||||
|
||||
class DashboardScreen extends StatefulWidget {
|
||||
const DashboardScreen({super.key});
|
||||
@ -183,7 +182,26 @@ class _DashboardScreenState extends State<DashboardScreen> {
|
||||
const SizedBox(height: 14),
|
||||
const HeosDecisionCard(),
|
||||
const SizedBox(height: 14),
|
||||
const DayPlanCard(),
|
||||
// ── « Plan de la journée » : RETIRÉE le 2026-09-08 ──────────
|
||||
//
|
||||
// Elle affichait `DayPlan.demo()` — vingt-quatre heures fabriquées
|
||||
// par une gaussienne solaire et des coefficients écrits en dur
|
||||
// (`solToEcs = excédent × 0,35`, `solToVe × 0,3`, `solToBatt × 0,15`,
|
||||
// `battToHouse = déficit × 0,55`), sous le titre « Plan de la
|
||||
// journée · aujourd'hui » et sans la moindre mention. Y compris une
|
||||
// batterie alimentant la maison à partir de 17 h, sur une
|
||||
// installation qui n'a pas de batterie.
|
||||
//
|
||||
// **Cinquième donnée inventée de ce tableau de bord** — après les
|
||||
// deux MPPT, les 38 % de PAC, les 82 % de part solaire et le SOC à
|
||||
// 62 %. Même réponse à chaque fois, et elle vaut encore : il n'y a
|
||||
// rien derrière.
|
||||
//
|
||||
// Un plan suppose de savoir ce qui VA arriver : il demande une
|
||||
// prévision PV et une source tarifaire, dont aucune n'existe. La
|
||||
// carte reviendra avec elles, et elle dira alors quelque chose. Le
|
||||
// code de fabrication part avec elle : laissé en place, il se
|
||||
// rebranche.
|
||||
const SizedBox(height: 8),
|
||||
]),
|
||||
),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user