Co-authored-by: Richard Pavlikán <richardpavlikan@gmail.com>
This commit is contained in:
Matyáš Caras 2023-03-08 22:09:25 +01:00
parent 95b26b4063
commit f7eaf804bd
32 changed files with 4664 additions and 1487 deletions

152
lib/utils/csv.dart Normal file
View file

@ -0,0 +1,152 @@
import 'dart:convert';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:csv/csv.dart';
import 'package:denikprogramatora/utils/datum_cas.dart';
import 'package:denikprogramatora/utils/loading_widget.dart';
import 'package:file_picker/file_picker.dart';
import 'package:firebase_auth/firebase_auth.dart';
final csvHeader = "id,date,time_spent,language,rating,description".split(",");
Future<int> importCsv(String name) async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
dialogTitle: "Vyberte CSV soubor s databází",
type: FileType.custom,
allowedExtensions: ['csv']);
if (result == null) return -1;
var content = const CsvToListConverter(eol: "\n").convert(
String.fromCharCodes(
result.files.first.bytes!)); // načíst a rozdělit na řádky
// Zkontrolovat počet sloupců
if (content.first.length != csvHeader.length) {
throw "CSV soubor není v platném formátu: neplatný počet sloupců";
}
Map<String, List<dynamic>> csv = {};
var nazvySloupcu = [];
for (var radek in content) {
if (nazvySloupcu.isEmpty) {
// získat názvy sloupců
nazvySloupcu = radek;
if (nazvySloupcu.any((element) => !csvHeader.contains(element))) {
throw "CSV soubor není v platném formátu: neznámý název sloupce";
}
for (var nazevSloupce in nazvySloupcu) {
csv[nazevSloupce] = [];
}
continue;
}
if (radek.length != nazvySloupcu.length) continue;
// zkontrolovat, že máme všechny potřebné údaje v řádku
var j = 0;
var neplatny = false;
for (var sloupec in radek) {
if ((nazvySloupcu[j] != "description") && sloupec == "") {
neplatny = true;
break;
}
j++;
}
if (neplatny) continue;
// přiřadit hodnotu sloupce do mapy
var i = 0;
for (var sloupec in radek) {
csv[nazvySloupcu[i]]!.add(sloupec);
i++;
}
}
var userDoc = await FirebaseFirestore.instance
.collection("users/${FirebaseAuth.instance.currentUser!.uid}/records")
.get();
var p = 0;
var pouzitaId = <String>[];
for (var i = 0; i < csv[nazvySloupcu[0]]!.length; i++) {
var id = csv[nazvySloupcu[nazvySloupcu.indexOf("id")]]![i];
if (pouzitaId.contains(id)) continue;
pouzitaId.add(id);
if (userDoc.docs.any((element) => element.id == id)) {
continue;
} // přeskočit dokumenty se stejným ID
var date = csv[nazvySloupcu[nazvySloupcu.indexOf("date")]]![i].split("-");
var timeToSec = textToSec(
csv[nazvySloupcu[nazvySloupcu.indexOf("time_spent")]]![i] as String);
if (timeToSec == null) continue;
var timeSpent = Duration(seconds: timeToSec);
var lang = csv[nazvySloupcu[nazvySloupcu.indexOf("language")]]![i];
Map<String, dynamic> jazyk = {};
if (jazyky.any((element) => element["jazyk"] == lang)) {
jazyk = jazyky.where((element) => element["jazyk"] == lang).toList()[0];
} else {
jazyk = {"jazyk": lang, "barva": 0xffffffff};
}
var rating = csv[nazvySloupcu[nazvySloupcu.indexOf("rating")]]![i];
if (rating > 5 || rating < 0) rating = 0;
var desc = csv[nazvySloupcu[nazvySloupcu.indexOf("description")]]![i];
DateTime? d;
try {
d = DateTime.parse(
"${date[2]}-${int.parse(date[1]) < 10 ? '0${date[1]}' : date[1]}-${int.parse(date[0]) < 10 ? "0${date[0]}" : date[0]}");
} catch (e) {
continue;
}
await FirebaseFirestore.instance
.collection("users/${FirebaseAuth.instance.currentUser!.uid}/records")
.doc(id)
.set({
"date": d,
"time_spent": timeSpent.durationText,
"time_spentRaw": timeSpent.inSeconds,
"programming_language": jazyk,
"rating": rating,
"descriptionRaw": desc,
"description": null,
"programmer": FirebaseAuth.instance.currentUser!.uid,
"categories": []
});
p++;
}
return p;
}
Future<List<int>> exportCsv() async {
List<List<dynamic>> csv = [csvHeader];
var records = await FirebaseFirestore.instance
.collection("users/${FirebaseAuth.instance.currentUser!.uid}/records")
.get();
for (var rec in records.docs) {
var data = rec.data();
csv.add([
rec.id,
(data['date'] as Timestamp).toDate().rawDateString,
Duration(seconds: data['time_spentRaw']).durationText,
data['programming_language']['jazyk'],
data['rating'],
data['descriptionRaw']
]);
}
return utf8.encode(const ListToCsvConverter(eol: "\n").convert(csv));
}
/// Převede `40 hodin 50 minut` na sekundy
int? textToSec(String vstup) {
var match =
RegExp(r'(\d+) hodin(?: |y |a )(\d+) minut(?:$|a$|y$)').firstMatch(vstup);
if (match == null) return null;
print(match.group(1));
print(match.group(2));
var h = int.tryParse(match.group(1)!);
var m = int.tryParse(match.group(2)!);
if (h == null || m == null) return null;
return h * 3600 + m * 60;
}