Merge branch 'branch_percobaan'
This commit is contained in:
commit
c5f5b7d900
|
|
@ -30,10 +30,14 @@ Future<void> exportWindSpeedPdf({
|
|||
title: 'Data Terkini',
|
||||
subtitle: 'Periode: $period',
|
||||
items: [
|
||||
SummaryItem('Kecepatan', '${currentSpeed.toStringAsFixed(1)} m/s', '💨'),
|
||||
SummaryItem('Rata-rata', '${stats['avg']!.toStringAsFixed(1)} m/s', '📊'),
|
||||
SummaryItem('Maksimum', '${stats['max']!.toStringAsFixed(1)} m/s', '⬆️'),
|
||||
SummaryItem('Minimum', '${stats['min']!.toStringAsFixed(1)} m/s', '⬇️'),
|
||||
SummaryItem(
|
||||
'Kecepatan', '${currentSpeed.toStringAsFixed(1)} m/s', '💨'),
|
||||
SummaryItem(
|
||||
'Rata-rata', '${stats['avg']!.toStringAsFixed(1)} m/s', '📊'),
|
||||
SummaryItem(
|
||||
'Maksimum', '${stats['max']!.toStringAsFixed(1)} m/s', '⬆️'),
|
||||
SummaryItem(
|
||||
'Minimum', '${stats['min']!.toStringAsFixed(1)} m/s', '⬇️'),
|
||||
],
|
||||
),
|
||||
pw.SizedBox(height: 24),
|
||||
|
|
@ -63,11 +67,15 @@ pw.Widget _buildPeriodTable(List<double> speeds, String period) {
|
|||
final labels = _periodLabels(speeds.length, period);
|
||||
return buildDataTable(
|
||||
headers: ['No', 'Label', 'Kecepatan (m/s)'],
|
||||
rows: speeds.asMap().entries.map((e) => [
|
||||
'${e.key + 1}',
|
||||
labels[e.key],
|
||||
e.value.toStringAsFixed(2),
|
||||
]).toList(),
|
||||
rows: speeds
|
||||
.asMap()
|
||||
.entries
|
||||
.map((e) => [
|
||||
'${e.key + 1}',
|
||||
labels[e.key],
|
||||
e.value.toStringAsFixed(2),
|
||||
])
|
||||
.toList(),
|
||||
colWidths: {
|
||||
0: const pw.FixedColumnWidth(30),
|
||||
1: const pw.FlexColumnWidth(2),
|
||||
|
|
@ -78,7 +86,7 @@ pw.Widget _buildPeriodTable(List<double> speeds, String period) {
|
|||
|
||||
pw.Widget _buildHistoryTable(List<Map<String, dynamic>> data) {
|
||||
return buildDataTable(
|
||||
headers: ['No', 'Waktu', 'Kecepatan (m/s)', 'Pulse'],
|
||||
headers: ['No', 'Waktu', 'Kecepatan (m/s)'],
|
||||
rows: data.asMap().entries.map((e) {
|
||||
final d = e.value;
|
||||
final ts = d['timestamp'] as DateTime?;
|
||||
|
|
@ -86,21 +94,20 @@ pw.Widget _buildHistoryTable(List<Map<String, dynamic>> data) {
|
|||
'${e.key + 1}',
|
||||
ts != null ? pdfFullFormat.format(ts) : '-',
|
||||
(d['speed'] as double? ?? 0).toStringAsFixed(2),
|
||||
'${d['pulse'] ?? 0}',
|
||||
];
|
||||
}).toList(),
|
||||
colWidths: {
|
||||
0: const pw.FixedColumnWidth(25),
|
||||
1: const pw.FlexColumnWidth(2.5),
|
||||
2: const pw.FlexColumnWidth(1.5),
|
||||
3: const pw.FlexColumnWidth(1),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
List<String> _periodLabels(int count, String period) {
|
||||
if (period == 'Hari Ini') {
|
||||
return List.generate(count, (i) => 'Jam ${i.toString().padLeft(2, '0')}:00');
|
||||
return List.generate(
|
||||
count, (i) => 'Jam ${i.toString().padLeft(2, '0')}:00');
|
||||
} else if (period == 'Minggu Ini') {
|
||||
const days = ['Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab', 'Min'];
|
||||
return List.generate(count, (i) => days[i % 7]);
|
||||
|
|
|
|||
|
|
@ -163,7 +163,12 @@ class WindSpeedBloc extends Bloc<WindSpeedEvent, WindSpeedState> {
|
|||
final updatedGraph = TimeSeriesMapper.smooth(raw);
|
||||
|
||||
emit(state.copyWith(
|
||||
dailySpeeds: updatedGraph,
|
||||
dailySpeeds:
|
||||
event.period == "Hari Ini" ? updatedGraph : state.dailySpeeds,
|
||||
weeklySpeeds:
|
||||
event.period == "Minggu Ini" ? updatedGraph : state.weeklySpeeds,
|
||||
monthlySpeeds:
|
||||
event.period == "Bulan Ini" ? updatedGraph : state.monthlySpeeds,
|
||||
isLoading: false,
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@ class WindSpeedScreen extends StatelessWidget {
|
|||
.map((e) => {
|
||||
'timestamp': e.timestamp,
|
||||
'speed': e.speed,
|
||||
'pulse': e.pulse,
|
||||
})
|
||||
.toList();
|
||||
|
||||
|
|
|
|||
|
|
@ -51,11 +51,19 @@ class FirebaseMonitoringRepo implements MonitoringRepository {
|
|||
if (snapshot.exists && snapshot.value is Map) {
|
||||
final Map<dynamic, dynamic> data = snapshot.value as Map;
|
||||
|
||||
// Karena RTDB push() menghasilkan Map dengan ID unik,
|
||||
// kita ambil values-nya saja dan ubah jadi List objek
|
||||
return data.values.map((item) {
|
||||
final list = data.values.map((item) {
|
||||
return mapper(item as Map<dynamic, dynamic>);
|
||||
}).toList();
|
||||
|
||||
// ✅ Sort by timestamp — Firebase push tidak jamin urutan
|
||||
list.sort((a, b) {
|
||||
if (a is MyWindSpeed && b is MyWindSpeed) {
|
||||
return a.timestamp.compareTo(b.timestamp);
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
return [];
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -1,26 +1,22 @@
|
|||
class MyWindSpeed {
|
||||
double speed;
|
||||
int pulse;
|
||||
|
||||
DateTime timestamp;
|
||||
|
||||
MyWindSpeed({
|
||||
required this.speed,
|
||||
required this.pulse,
|
||||
required this.timestamp,
|
||||
});
|
||||
MyWindSpeed({required this.speed, required this.timestamp});
|
||||
|
||||
static final empty = MyWindSpeed(
|
||||
speed: 0.0,
|
||||
pulse: 0,
|
||||
|
||||
timestamp: DateTime.fromMillisecondsSinceEpoch(0),
|
||||
);
|
||||
|
||||
factory MyWindSpeed.fromJson(Map<dynamic, dynamic> json) {
|
||||
return MyWindSpeed(
|
||||
speed: (json['speed'] ?? 0).toDouble(),
|
||||
pulse: (json['pulse'] ?? 0) as int,
|
||||
|
||||
timestamp: DateTime.fromMillisecondsSinceEpoch(
|
||||
(json['timesTamp'] ?? 0) * 1000, // kalau dari Unix detik
|
||||
(json['timestamp'] ?? 0) * 1000, // kalau dari Unix detik
|
||||
).toLocal(),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue