#!/mod/bin/jimsh package require cgi source /mod/webif/lib/setup require rsv.class epg.class system.class classdump set debug 0 noheader set renderstart [clock milliseconds] set events [rsv allevents [[settings] hidevisualota]] set pending [rsv list pending] # hSvc -> usSvcId map lmap i \ [$::channeldb query {select hSvc, usSvcid from TBL_SVC}] \ { set hmap([lindex $i 1]) [lindex $i 3] } # usSvcId -> hSvc map #set svcmap [lreverse $hmap] proc lsum {l} { expr [join [linsert $l 0 0] +] } proc pop_event {} { uplevel { lassign [lindex $events $eindex] \ start end hsvc eid slotid kind sclass incr eindex if {$debug > 2} { puts " -------------------------------------------------- EVENT$eindex START: $start [clock format $start] END: $end [clock format $end] HSVC: $hsvc EID: $eid SID: $slotid KIND: $kind SCLASS: $sclass " } } } set pendingclasses { 1 "pending-unschedule" 2 "pending-ar" 3 "pending-ar" 4 "pending-folder" 5 "pending-skip" 6 "pending-refresh" } foreach p $pending { set action [$p get action] # Add - already handled. if {$action eq "0"} continue set s [rsv fetch "TBL_RESERVATION" \ [$p get ersvtype] [$p get hsvc] 0 [$p get usevtid]] if {$s eq "0"} continue set slot [$s get ulslot] set elen [llength $events] set eindex 0 while {$eindex < $elen} { pop_event if {$slotid ne [$s get ulslot]} continue if {$action eq "5" && $start != [$p start]} continue lset events $($eindex - 1) 6 $pendingclasses($action) } } # Event array keys: # 0: start # 1: end # 2: hSvc # 3: event_id # 4: Schedule Slot ID # 5: ucRecKind # 6: class (live, pending) # Filter events array set skip [rsv _skiplist] if {[llength $skip]} { set events [lmap i $events { lassign $i x x s e if {"$s:$e" in $::skip} continue function $i }] } # Sort final events array set events [lsort -index 0 -integer [lsort -index 2 -integer $events]] if {$debug} { puts "
"
	foreach ev $events {
		puts -nonewline $ev
		lassign $ev start end hsvc eid slotid kind sclass
		catch {
			set s [rsv slot $sclass $slotid]
			set shour [clock format $start -format "%H"]
			set ehour [clock format $end -format "%H"]
			set elapsed $($end - $start)
			puts -nonewline "  = $shour,$ehour ($elapsed) - [$s name]"
		}
		puts ""
	}
	puts "
" } ###################################################################### # Visualisation functions # Intend 40 pixels / hour for fully populated timeline. set width $(40 * 24) # This is the total padding/margin/border width. set pad 4 set padadj 0 # Returns an absolute number of pixels from the left corresponding # to a number of seconds into the day. proc secstopx {daysecs hourpx usedhours} { set max [expr {int($daysecs / 3600)}] # Subtract any unused hours from $daysecs. for {set i 0} {$i < $max} {incr i} { if {$i >= 24} break if {![lindex $usedhours $i]} { incr daysecs -3600 } } return [expr {int($daysecs * $hourpx / 3600)}] } # daysecs - absolute number of seconds into the day that needs to be reached. # pxpos - current pixel position. proc showpad {daysecs hourpx &pxpos usedhours} { global debug pad padadj # Determine required pixel position. set newpos [set p [secstopx $daysecs $hourpx $usedhours]] # Calculate required width of spacer incr p -$pxpos # Account for padding and any pending adjustment incr p $(-($pad + $padadj)) if {$p <= 0} { # If too narrow, show bare skip at full required width. incr p $($pad + $padadj) # Bare skip set class "ct_bskip" } else { set class "ct_skip" if {$debug} { append class " ct_debug" } } if {$p > 0} { puts -nonewline \ "
" if {$debug} { puts [format "@%d-%d s=%d w=%dpx @%dpx" \ $pxpos $padadj $daysecs $p $newpos] } puts -nonewline "
" set pxpos $newpos set padadj 0 } } proc showevent {s class &overflow &tomorrow &pxpos start end usedhours daystart dayend hourpx service event sclass} { global debug pad padadj dev # Required pixel position of event start. set p [secstopx $($start - $daystart) $hourpx $usedhours] if {$p < $pxpos} { # Backwards move => tuner conflict. lappend overflow [list $s $start $end $service $event $sclass] return } # Show padding up to event. showpad $($start - $daystart) $hourpx pxpos $usedhours # And now the event itself. set name [set channel "Unknown"] set slotid -1 if {$s ne "0"} { set name [$s name] set channel [$s channel_name] set slotid [$s get ulslot] } if {$service > 0} { set epgs [epg dbfetch dump \ -service $service -event $event -sort ""] if {[llength $epgs] == 1} { lassign $epgs epg set name [$epg get name] $epg get_channel_info set channel [$epg get channel_name] } } if {[string match -nocase "New:*" $name]} { set name [string trim [string range $name 4 end]] } set name [cgi_quote_html $name] if {$sclass == "pending"} { append class " purpleshade" } elseif {$sclass == "pending-unschedule" || $sclass == "pending-skip"} { append class " strike purpleshade" } elseif {[string match "*pending*" $sclass]} { append class " orangeshade" } if {$end > $dayend + 1} { # Push event into tomorrow. if {$s ne "0"} { $s setorigstart $start } lappend tomorrow [list $s $($dayend + 1) $end \ $service $event $sclass] set newpos [set p [secstopx 86400 $hourpx $usedhours]] append name "..." } else { set newpos [set p [\ secstopx $($end - $daystart) $hourpx $usedhours]] if {$start == $daystart && $s ne "0" && [$s get _origstart] > 0} { set name "..$name" set start [$s get _origstart] $s setorigstart 0 } } # Calculate width incr p -$pxpos # Account for padding incr p -$pad if {$p < 8} { # Event too narrow, force to 8 pixels. set padadj $(8 - $p) set p 8 } else { set padadj 0 } puts -nonewline "
" if {$debug} { puts -nonewline [format "@%d s=%d w=%dpx @%dpx /=%d" \ $pxpos $($end - $start) $p $newpos $padadj] } puts -nonewline "$name
" set pxpos $newpos } proc render_timeline {usedhours} { global debug events width pad hmap padadj puts "
\n" set tothours [lsum $usedhours] if {!$tothours} { puts "No schedule data found." return } # calculate pixels per hour set hourpx [expr {int($width / $tothours)}] if {$debug} { puts "USEDHOURS: $usedhours
\n" puts "HOURPX: $hourpx (tothours: $tothours)
\n" } # Show the hour bar. puts "
" puts "
 
" # Account for element padding and margin set px $($hourpx - $pad) for {set i 0} {$i < 25} {incr i} { if {[lindex $usedhours $i] ne "1"} continue puts -nonewline \ "
[\ format "%02dh" $i]
" } puts "
\n" # To store events which overflow into tomorrow. set tomorrow {} # Midnight today. set day [midnight] set gday [clock scan [clock format $day -format {%Y %m %d %T}] \ -format {%Y %m %d %T} -gmt 1] set elength [llength $events] set eindex 0 set start 0 while {$start < $day} { pop_event } for {set i 0} {$i < 8} {incr i} { # To store things that need to move to the next row. set rows {} if {$i % 2} { set class "odd" } else { set class "even" } set eclass "blueshade" set dayend [set daystart $day] incr dayend 86399 # Row 1 puts "
" puts "
" puts "
[clock format $gday \ -format {%a %d/%m/%Y} -gmt 1]
" set pxpos [set padadj 0] if {[llength $tomorrow]} { set dummy {} foreach row $tomorrow { lassign $row s xstart xend xs xe xsclass showevent $s $eclass rows dummy \ pxpos $xstart $xend $usedhours \ $daystart $dayend $hourpx \ $xs $xe $xsclass } set tomorrow {} } while {$start >= $daystart && $start <= $dayend} { if {$slotid ne "-1"} { set tab "TBL_RESERVATION" if {$sclass eq "pending"} { set tab "pending" } set s [rsv slot $tab $slotid] } else { set s "0" } if {[dict exists $hmap $hsvc]} { set service $hmap($hsvc) } else { set service 0 } showevent $s $eclass rows tomorrow pxpos \ $start $end $usedhours \ $daystart $dayend $hourpx \ $service $eid $sclass pop_event } # Close row showpad 86400 $hourpx pxpos $usedhours puts "
" # Output other rows if necessary while {[llength $rows]} { set nrows {} puts "
" set pxpos [set padadj 0] foreach row $rows { lassign $row s xstart xend xs xe xsclass showevent $s $eclass nrows tomorrow \ pxpos $xstart $xend $usedhours \ $daystart $dayend $hourpx \ $xs $xe $xsclass } showpad 86400 $hourpx pxpos $usedhours puts "
" set rows $nrows set eclass "pinkshade" } incr day 86400 incr gday 86400 # Close ct_day puts "
" } puts "\n
\n" } ###################################################################### # Compressed Day Schedule Visualisation set usedhours [lrepeat 24 0] # Determine which hours are used. foreach e $events { lassign $e start end set shour [clock format $start -format "%H"] set ehour [clock format $end -format "%H"] if {$ehour < $shour} { incr ehour 24 } for {set i $shour} {$i <= $ehour} {incr i} { set index $i if {$i > 23} { incr index -24 } lset usedhours $index 1 } } # To show 24 hours #set usedhours [lrepeat 24 1] puts "

Schedule

" render_timeline $usedhours puts "
" puts {

Key:

Scheduled event
Conflict
Pending change
Pending schedule
Pending unschedule
} source assets.jim footer