summaryrefslogtreecommitdiff
path: root/bin/extract-zugbildung-for-today
blob: 43922e4760fe7344e6f96e12d271720e444bb5c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/env perl
# Copyright (C) 2020 Daniel Friesel
#
# SPDX-License-Identifier: BSD-2-Clause

use strict;
use warnings;
use 5.020;
use utf8;

use DateTime;
use DateTime::Format::Strptime;
use File::Slurp qw(read_file);
use JSON;

my $strp = DateTime::Format::Strptime->new(
	pattern   => '%F',
	time_zone => 'Europe/Berlin'
);
my $now = DateTime->now( time_zone => 'Europe/Berlin' );

sub range_is_today {
	my ($range) = @_;

	if ( $range =~ m{^(.*)/(.*)$} ) {
		my $dt1 = $strp->parse_datetime($1);
		my $dt2 = $strp->parse_datetime($2);
		if ( $dt1 and $dt2 and $dt1->epoch < $now->epoch < $dt2->epoch ) {
			return 1;
		}
	}
	else {
		if ( my $dt = $strp->parse_datetime($range) ) {
			if ( $dt->ymd eq $now->ymd ) {
				return 1;
			}
		}
	}
	return;
}

sub weekday_is_today {
	my ($weekdys) = @_;

	return ( ${ $weekdys->[ $now->day_of_week - 1 ] } == 1 );
}

if ( @ARGV == 0 ) {
	exit 1;
}

my $data = JSON->new->utf8->decode( read_file( $ARGV[0] ) );

my %map = %{ $data->{train_variants} };
my %smap;

for my $train_no ( keys %map ) {
	if ( @{ $map{$train_no} } == 1 ) {
		$smap{$train_no} = $map{$train_no}[0];
	}
	else {
		my $latest_valid;
		my $valid_count = 0;
		for my $train ( @{ $map{$train_no} } ) {
			my $is_valid = 0;
			for my $schedule ( @{ $train->{schedules} // [] } ) {
				for my $valid ( @{ $schedule->{valid} // [] } ) {
					if ( range_is_today($valid) ) {
						$is_valid = 1;
					}
				}

				# invalid may override valid for certain days
				for my $invalid ( @{ $schedule->{invalid} // [] } ) {
					if ( range_is_today($invalid) ) {
						$is_valid = 0;
					}
				}
			}
			if ($is_valid) {
				$latest_valid = $train;
				$valid_count++;
			}
		}
		if ( $valid_count == 1 ) {
			$smap{$train_no} = $latest_valid;
		}
		else {
			$valid_count  = 0;
			$latest_valid = undef;
			for my $train ( @{ $map{$train_no} } ) {
				my $is_valid = 0;
				for my $schedule ( @{ $train->{schedules} // [] } ) {
					for my $valid ( @{ $schedule->{valid} // [] } ) {
						if (    range_is_today($valid)
							and weekday_is_today( $schedule->{weekdays} ) )
						{
							$is_valid = 1;
						}
					}

					# invalid may override valid for certain days
					for my $invalid ( @{ $schedule->{invalid} // [] } ) {
						if ( range_is_today($invalid) ) {
							$is_valid = 0;
						}
					}
				}
				if ($is_valid) {
					$latest_valid = $train;
					$valid_count++;
				}
			}
			if ( $valid_count == 1 ) {
				$smap{$train_no} = $latest_valid;
			}
		}
	}
}

delete $data->{train_variants};
$data->{train} = {%smap};

say JSON->new->utf8->canonical->encode($data);