diff --git a/config/ansible/tasks/global/utils/flitsmeister.go b/config/ansible/tasks/global/utils/flitsmeister.go new file mode 100644 index 0000000..2ca5371 --- /dev/null +++ b/config/ansible/tasks/global/utils/flitsmeister.go @@ -0,0 +1,127 @@ +package main + +import ( + "encoding/csv" + "fmt" + "os" + "sort" + "strconv" + "strings" + "time" +) + +func main() { + if len(os.Args) < 2 { + fmt.Println("Usage: flitsmeister ") + return + } + + file, err := os.Open(os.Args[1]) + if err != nil { + panic(err) + } + defer file.Close() + + reader := csv.NewReader(file) + reader.Comma = ',' + records, err := reader.ReadAll() + if err != nil { + panic(err) + } + + // Dutch to English month translation + dutchMonths := map[string]string{ + "januari": "January", "februari": "February", "maart": "March", + "april": "April", "mei": "May", "juni": "June", "juli": "July", + "augustus": "August", "september": "September", "oktober": "October", + "november": "November", "december": "December", + } + + monthlyTotals := make(map[string]float64) + monthlyCounts := make(map[string]int) + monthlyLongest := make(map[string]float64) + monthlyShortest := make(map[string]float64) + + // Skip header row + for _, record := range records[1:] { + if len(record) < 8 { + continue + } + + // Parse date with Dutch month names + dateParts := strings.Split(record[1], " ") + if len(dateParts) < 4 { + continue + } + + // Translate Dutch month to English + dutchMonth := strings.ToLower(dateParts[1]) + engMonth, ok := dutchMonths[dutchMonth] + if !ok { + fmt.Printf("Unknown month: %s\n", dutchMonth) + continue + } + + // Rebuild date string with English month + dateStr := fmt.Sprintf("%s %s %s %s", + dateParts[0], engMonth, dateParts[2], dateParts[3]) + + // Parse date (single-digit days allowed) + tripDate, err := time.Parse("2 January 2006 15:04", dateStr) + if err != nil { + fmt.Printf("Error parsing date: %v\n", err) + continue + } + + // Create month key (format: YYYY-MM) + monthKey := fmt.Sprintf("%d-%02d", tripDate.Year(), tripDate.Month()) + + // Parse distance + distance, err := strconv.ParseFloat(record[7], 64) + if err != nil { + fmt.Printf("Error parsing distance: %v\n", err) + continue + } + + monthlyTotals[monthKey] += distance + monthlyCounts[monthKey]++ + + // Track longest and shortest trip + if _, exists := monthlyLongest[monthKey]; !exists { + monthlyLongest[monthKey] = distance + monthlyShortest[monthKey] = distance + } else { + if distance > monthlyLongest[monthKey] { + monthlyLongest[monthKey] = distance + } + if distance < monthlyShortest[monthKey] { + monthlyShortest[monthKey] = distance + } + } + } + + // Sort months chronologically + var months []string + for k := range monthlyTotals { + months = append(months, k) + } + sort.Strings(months) + + // Print table header + fmt.Printf("%-10s | %-12s | %-7s | %-12s | %-12s | %-12s\n", "Month", "Total KM", "Trips", "Avg KM/Trip", "Longest", "Shortest") + fmt.Println(strings.Repeat("-", 77)) + + // Print stats per month + for _, month := range months { + total := monthlyTotals[month] + trips := monthlyCounts[month] + avg := 0.0 + if trips > 0 { + avg = total / float64(trips) + } + longest := monthlyLongest[month] + shortest := monthlyShortest[month] + fmt.Printf("%-10s | %-12.2f | %-7d | %-12.2f | %-12.2f | %-12.2f\n", + month, total, trips, avg, longest, shortest) + } +} diff --git a/config/home-manager/flake.lock b/config/home-manager/flake.lock index d237533..bd1bd9b 100644 --- a/config/home-manager/flake.lock +++ b/config/home-manager/flake.lock @@ -39,11 +39,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1747542820, - "narHash": "sha256-GaOZntlJ6gPPbbkTLjbd8BMWaDYafhuuYRNrxCGnPJw=", + "lastModified": 1747744144, + "narHash": "sha256-W7lqHp0qZiENCDwUZ5EX/lNhxjMdNapFnbErcbnP11Q=", "owner": "nixos", "repo": "nixpkgs", - "rev": "292fa7d4f6519c074f0a50394dbbe69859bb6043", + "rev": "2795c506fe8fb7b03c36ccb51f75b6df0ab2553f", "type": "github" }, "original": {