5 |
|
|
6 |
use XML::Simple; |
use XML::Simple; |
7 |
use Data::Dump qw(dump); |
use Data::Dump qw(dump); |
8 |
|
use DateTime; |
9 |
|
|
10 |
|
my $step = 1; # min |
11 |
|
|
12 |
my $tv = XMLin( 'tv.xml', |
my $tv = XMLin( 'tv.xml', |
13 |
ContentKey => '-content', |
ContentKey => '-content', |
28 |
background: #eee; |
background: #eee; |
29 |
} |
} |
30 |
|
|
31 |
th,odd { |
td.blank { |
32 |
|
background: #fff; |
33 |
|
} |
34 |
|
|
35 |
|
th.odd { |
36 |
background: #eef; |
background: #eef; |
37 |
} |
} |
38 |
|
|
46 |
float: right; |
float: right; |
47 |
} |
} |
48 |
|
|
49 |
|
span.date { |
50 |
|
color: #fff; |
51 |
|
font-size: 150%; |
52 |
|
} |
53 |
|
|
54 |
</style> |
</style> |
55 |
|
|
56 |
</head> |
</head> |
71 |
|
|
72 |
my $programs; |
my $programs; |
73 |
|
|
74 |
sub hh { substr $_[0], 8, 2 } |
my $date; |
75 |
sub mm { substr $_[0], 10, 2 } |
|
76 |
|
sub iso_to_dt { |
77 |
|
my ( $date, $timezone ) = split(/\s/,shift); |
78 |
|
DateTime->new( |
79 |
|
year => substr($date, 0, 4), |
80 |
|
month => substr($date, 4, 2), |
81 |
|
day => substr($date, 6, 2), |
82 |
|
hour => substr($date, 8, 2), |
83 |
|
minute => substr($date, 10, 2), |
84 |
|
second => substr($date, 12, 2), |
85 |
|
# timezone => $timezone, |
86 |
|
); |
87 |
|
} |
88 |
|
|
89 |
|
sub duration_min { |
90 |
|
my $dt = shift; |
91 |
|
return |
92 |
|
$dt->hours * 60 |
93 |
|
+ $dt->minutes |
94 |
|
# + $dt->seconds |
95 |
|
; |
96 |
|
} |
97 |
|
|
98 |
|
sub dt_hhmm { |
99 |
|
sprintf( '%02d:%02d', $_[0]->hour, $_[0]->minute ); |
100 |
|
} |
101 |
|
|
102 |
sub in_mins { hh($_[0]) * 60 + mm($_[0]) } |
foreach my $p ( sort { $a->{start} cmp $b->{start} } @{ $tv->{programme} } ) { |
103 |
|
|
|
foreach my $p ( @{ $tv->{programme} } ) { |
|
104 |
warn "# p ",dump $p; |
warn "# p ",dump $p; |
105 |
my $t_start = in_mins $p->{start}; |
my $dt_start = iso_to_dt $p->{start}; |
106 |
my $t_stop = in_mins $p->{stop}; |
my $dt_stop = iso_to_dt $p->{stop}; |
107 |
|
|
108 |
|
my $t_diff = $dt_stop - $dt_start; |
109 |
|
my $duration = duration_min( $dt_stop - $dt_start ); |
110 |
|
|
111 |
|
warn "# t $dt_start - $dt_stop [$duration]\n"; |
112 |
|
|
113 |
warn "# t $t_start - $t_stop\n"; |
if ( ! $date ) { |
114 |
if ( ! defined $programs->{ $p->{channel} } ) { |
$date = $dt_start->clone; |
|
push @{ $programs->{ $p->{channel} } }, [ 0, $t_start ]; |
|
115 |
} |
} |
116 |
push @{ $programs->{ $p->{channel} } }, [ $t_start, $t_stop - $t_start, $p ]; |
|
117 |
|
push @{ $programs->{ $p->{channel} } }, [ $dt_start, $duration, $p ]; |
118 |
} |
} |
119 |
|
|
120 |
warn "# programs ", dump $programs; |
warn "# programs ", dump $programs; |
121 |
|
|
122 |
foreach my $hh ( 0 .. 23 ) { |
warn "# date $date\n"; |
123 |
foreach my $mm ( 0 .. 59 ) { |
|
124 |
|
#$date->set_hour( 0 ); |
125 |
|
$date->set_minute( 0 ); |
126 |
|
$date->set_second( 0 ); |
127 |
|
|
128 |
|
print qq|<tr><th colspan=|, $#channels + 2, qq|>$date</th></tr>\n|; |
129 |
|
foreach my $c ( @channels ) { |
130 |
|
my $start = $programs->{$c}->[0]->[0] || die "no first $c in ", dump $programs->{$c}; |
131 |
|
my $duration = duration_min( $start - $date ); |
132 |
|
warn "# padding $c $start $duration\n"; |
133 |
|
unshift @{ $programs->{$c} }, [ $date, $duration ]; |
134 |
|
} |
135 |
|
|
136 |
|
my $more = 1; |
137 |
|
|
138 |
|
while ( $more ) { |
139 |
|
|
140 |
|
my @td; |
141 |
|
|
142 |
|
$more = 0; |
143 |
|
|
144 |
|
foreach my $c ( @channels ) { |
145 |
|
|
146 |
|
next unless defined $programs->{$c}->[0]; |
147 |
|
$more++ unless $more; |
148 |
|
|
149 |
my $hhmm = sprintf '%02d:%02d', $hh, $mm; |
my $first_start = $programs->{$c}->[0]->[0]; |
150 |
|
|
151 |
print "<!-- $hh$mm -->\n"; |
warn "# first_start $c $first_start $date\n"; |
152 |
|
|
153 |
my @td; |
if ( $first_start <= $date ) { |
154 |
|
|
155 |
foreach my $c ( @channels ) { |
my $p = shift @{ $programs->{$c} }; |
|
if ( $programs->{$c}->[0]->[0] == $hh * 60 + $mm ) { |
|
|
my $p = shift @{ $programs->{$c} }; |
|
|
my $span = $p->[1]; # - 1; |
|
156 |
|
|
157 |
my $html = ''; |
my $td_attr = 'rowspan=' . int( $p->[1] / $step ); |
158 |
$html = join("\n" |
|
159 |
, qq|<span class="hhmm">$hhmm<br>$span</span>| |
my $hhmm = dt_hhmm $p->[0]; |
160 |
|
|
161 |
|
my $html = ''; |
162 |
|
if ( $p->[2] ) { |
163 |
|
$html .= join("\n" |
164 |
|
, qq|<span class="hhmm">$hhmm<br>$p->[1]</span>| |
165 |
, $p->[2]->{title}->{content} |
, $p->[2]->{title}->{content} |
166 |
, "<!-- $c -->" |
, "<!-- $c -->" |
167 |
) if $p->[2]; |
); |
168 |
|
} else { |
169 |
push @td, qq|<td rowspan=$span>$html</td>|; |
$td_attr .= ' class=blank'; |
170 |
} |
} |
171 |
|
|
172 |
|
push @td, qq|<td $td_attr>$html</td>|; |
173 |
} |
} |
174 |
|
} |
175 |
|
|
|
my $class = $hh % 2 == 0 ? 'even' : 'odd'; |
|
176 |
|
|
177 |
my $th = ''; |
my $th = ''; |
178 |
$th = qq|<th rowspan=60 class=$class>$hh</th>| if $mm == 0; |
if ( $date->minute == 0 ) { |
179 |
|
$th = $date->hour; |
180 |
|
$th = qq|<span class=date title="$date">| . $date->day . qq|</span><br>$th| if $th == 0; |
181 |
|
|
182 |
|
my $span = 60 / $step; |
183 |
|
my $class = $date->hour % 2 == 0 ? 'even' : 'odd'; |
184 |
|
$th = qq|<th rowspan=$span class=$class>$th</th>|; |
185 |
|
|
|
print qq|<tr>$th|, join('', @td), qq|</tr>\n|; |
|
186 |
} |
} |
187 |
|
|
188 |
|
print "<!-- $date -->\n"; |
189 |
|
print qq|<tr>$th|, join('', @td), qq|</tr>\n|; |
190 |
|
|
191 |
|
$date->add( minutes => $step ); |
192 |
|
|
193 |
} |
} |
194 |
|
|
195 |
print qq| |
print qq| |