Merge branch 'branch_percobaan'

This commit is contained in:
kleponijo 2026-04-27 20:40:06 +07:00
commit c5f5b7d900
5 changed files with 42 additions and 27 deletions

View File

@ -30,10 +30,14 @@ Future<void> exportWindSpeedPdf({
title: 'Data Terkini', title: 'Data Terkini',
subtitle: 'Periode: $period', subtitle: 'Periode: $period',
items: [ items: [
SummaryItem('Kecepatan', '${currentSpeed.toStringAsFixed(1)} m/s', '💨'), SummaryItem(
SummaryItem('Rata-rata', '${stats['avg']!.toStringAsFixed(1)} m/s', '📊'), 'Kecepatan', '${currentSpeed.toStringAsFixed(1)} m/s', '💨'),
SummaryItem('Maksimum', '${stats['max']!.toStringAsFixed(1)} m/s', '⬆️'), SummaryItem(
SummaryItem('Minimum', '${stats['min']!.toStringAsFixed(1)} m/s', '⬇️'), '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), pw.SizedBox(height: 24),
@ -63,11 +67,15 @@ pw.Widget _buildPeriodTable(List<double> speeds, String period) {
final labels = _periodLabels(speeds.length, period); final labels = _periodLabels(speeds.length, period);
return buildDataTable( return buildDataTable(
headers: ['No', 'Label', 'Kecepatan (m/s)'], headers: ['No', 'Label', 'Kecepatan (m/s)'],
rows: speeds.asMap().entries.map((e) => [ rows: speeds
'${e.key + 1}', .asMap()
labels[e.key], .entries
e.value.toStringAsFixed(2), .map((e) => [
]).toList(), '${e.key + 1}',
labels[e.key],
e.value.toStringAsFixed(2),
])
.toList(),
colWidths: { colWidths: {
0: const pw.FixedColumnWidth(30), 0: const pw.FixedColumnWidth(30),
1: const pw.FlexColumnWidth(2), 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) { pw.Widget _buildHistoryTable(List<Map<String, dynamic>> data) {
return buildDataTable( return buildDataTable(
headers: ['No', 'Waktu', 'Kecepatan (m/s)', 'Pulse'], headers: ['No', 'Waktu', 'Kecepatan (m/s)'],
rows: data.asMap().entries.map((e) { rows: data.asMap().entries.map((e) {
final d = e.value; final d = e.value;
final ts = d['timestamp'] as DateTime?; final ts = d['timestamp'] as DateTime?;
@ -86,21 +94,20 @@ pw.Widget _buildHistoryTable(List<Map<String, dynamic>> data) {
'${e.key + 1}', '${e.key + 1}',
ts != null ? pdfFullFormat.format(ts) : '-', ts != null ? pdfFullFormat.format(ts) : '-',
(d['speed'] as double? ?? 0).toStringAsFixed(2), (d['speed'] as double? ?? 0).toStringAsFixed(2),
'${d['pulse'] ?? 0}',
]; ];
}).toList(), }).toList(),
colWidths: { colWidths: {
0: const pw.FixedColumnWidth(25), 0: const pw.FixedColumnWidth(25),
1: const pw.FlexColumnWidth(2.5), 1: const pw.FlexColumnWidth(2.5),
2: const pw.FlexColumnWidth(1.5), 2: const pw.FlexColumnWidth(1.5),
3: const pw.FlexColumnWidth(1),
}, },
); );
} }
List<String> _periodLabels(int count, String period) { List<String> _periodLabels(int count, String period) {
if (period == 'Hari Ini') { 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') { } else if (period == 'Minggu Ini') {
const days = ['Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab', 'Min']; const days = ['Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab', 'Min'];
return List.generate(count, (i) => days[i % 7]); return List.generate(count, (i) => days[i % 7]);

View File

@ -163,7 +163,12 @@ class WindSpeedBloc extends Bloc<WindSpeedEvent, WindSpeedState> {
final updatedGraph = TimeSeriesMapper.smooth(raw); final updatedGraph = TimeSeriesMapper.smooth(raw);
emit(state.copyWith( 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, isLoading: false,
)); ));
} }

View File

@ -55,7 +55,6 @@ class WindSpeedScreen extends StatelessWidget {
.map((e) => { .map((e) => {
'timestamp': e.timestamp, 'timestamp': e.timestamp,
'speed': e.speed, 'speed': e.speed,
'pulse': e.pulse,
}) })
.toList(); .toList();

View File

@ -51,11 +51,19 @@ class FirebaseMonitoringRepo implements MonitoringRepository {
if (snapshot.exists && snapshot.value is Map) { if (snapshot.exists && snapshot.value is Map) {
final Map<dynamic, dynamic> data = snapshot.value as Map; final Map<dynamic, dynamic> data = snapshot.value as Map;
// Karena RTDB push() menghasilkan Map dengan ID unik, final list = data.values.map((item) {
// kita ambil values-nya saja dan ubah jadi List objek
return data.values.map((item) {
return mapper(item as Map<dynamic, dynamic>); return mapper(item as Map<dynamic, dynamic>);
}).toList(); }).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 []; return [];
} catch (e) { } catch (e) {

View File

@ -1,26 +1,22 @@
class MyWindSpeed { class MyWindSpeed {
double speed; double speed;
int pulse;
DateTime timestamp; DateTime timestamp;
MyWindSpeed({ MyWindSpeed({required this.speed, required this.timestamp});
required this.speed,
required this.pulse,
required this.timestamp,
});
static final empty = MyWindSpeed( static final empty = MyWindSpeed(
speed: 0.0, speed: 0.0,
pulse: 0,
timestamp: DateTime.fromMillisecondsSinceEpoch(0), timestamp: DateTime.fromMillisecondsSinceEpoch(0),
); );
factory MyWindSpeed.fromJson(Map<dynamic, dynamic> json) { factory MyWindSpeed.fromJson(Map<dynamic, dynamic> json) {
return MyWindSpeed( return MyWindSpeed(
speed: (json['speed'] ?? 0).toDouble(), speed: (json['speed'] ?? 0).toDouble(),
pulse: (json['pulse'] ?? 0) as int,
timestamp: DateTime.fromMillisecondsSinceEpoch( timestamp: DateTime.fromMillisecondsSinceEpoch(
(json['timesTamp'] ?? 0) * 1000, // kalau dari Unix detik (json['timestamp'] ?? 0) * 1000, // kalau dari Unix detik
).toLocal(), ).toLocal(),
); );
} }