1 |
#!/usr/bin/perl |
2 |
|
3 |
use warnings; |
4 |
use strict; |
5 |
|
6 |
use XML::Simple; |
7 |
use Data::Dump qw(dump); |
8 |
use DateTime; |
9 |
|
10 |
my $step = 1; # min |
11 |
|
12 |
my $tv = XMLin( 'tv.xml', |
13 |
ContentKey => '-content', |
14 |
); |
15 |
|
16 |
warn dump $tv; |
17 |
|
18 |
print qq| |
19 |
<html> |
20 |
<head> |
21 |
<meta charset=utf-8> |
22 |
|
23 |
<style type="text/css"> |
24 |
|
25 |
td { |
26 |
font-family:sans-serif; |
27 |
vertical-align: top; |
28 |
background: #eee; |
29 |
} |
30 |
|
31 |
td.blank { |
32 |
background: #fff; |
33 |
} |
34 |
|
35 |
th.odd { |
36 |
background: #eef; |
37 |
} |
38 |
|
39 |
th.even { |
40 |
background: #fcc; |
41 |
} |
42 |
|
43 |
.hhmm { |
44 |
font-size: 50%; |
45 |
color: #888; |
46 |
float: right; |
47 |
} |
48 |
|
49 |
span.date { |
50 |
color: #fff; |
51 |
font-size: 150%; |
52 |
} |
53 |
|
54 |
</style> |
55 |
|
56 |
</head> |
57 |
<body> |
58 |
|
59 |
<table> |
60 |
<tr><td></td> |
61 |
|; |
62 |
|
63 |
my @channels = keys %{ $tv->{channel} }; |
64 |
warn "# channels ",dump @channels; |
65 |
|
66 |
print qq|<th><img src="|, $_->{'icon'}->{'src'}, qq|"><br>|, $_->{'display-name'}->{'content'}, qq|</th>| foreach map { $tv->{channel}->{$_} } @channels; |
67 |
|
68 |
print qq| |
69 |
</tr> |
70 |
|; |
71 |
|
72 |
my $programs; |
73 |
|
74 |
my $date; |
75 |
|
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 |
foreach my $p ( sort { $a->{start} cmp $b->{start} } @{ $tv->{programme} } ) { |
103 |
|
104 |
warn "# p ",dump $p; |
105 |
my $dt_start = iso_to_dt $p->{start}; |
106 |
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 |
if ( ! $date ) { |
114 |
$date = $dt_start->clone; |
115 |
} |
116 |
|
117 |
push @{ $programs->{ $p->{channel} } }, [ $dt_start, $duration, $p ]; |
118 |
} |
119 |
|
120 |
warn "# programs ", dump $programs; |
121 |
|
122 |
warn "# date $date\n"; |
123 |
|
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 $first_start = $programs->{$c}->[0]->[0]; |
150 |
|
151 |
warn "# first_start $c $first_start $date\n"; |
152 |
|
153 |
if ( $first_start <= $date ) { |
154 |
|
155 |
my $p = shift @{ $programs->{$c} }; |
156 |
|
157 |
my $td_attr = 'rowspan=' . int( $p->[1] / $step ); |
158 |
|
159 |
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} |
166 |
, "<!-- $c -->" |
167 |
); |
168 |
} else { |
169 |
$td_attr .= ' class=blank'; |
170 |
} |
171 |
|
172 |
push @td, qq|<td $td_attr>$html</td>|; |
173 |
} |
174 |
} |
175 |
|
176 |
|
177 |
my $th = ''; |
178 |
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 |
|
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| |
196 |
</table> |
197 |
|
198 |
</body> |
199 |
|
200 |
</html> |
201 |
|; |