#!/bin/sh  
# \
exec oagwish "$0" "$@"

# $Log: not supported by cvs2svn $
# Revision 1.1  2006/09/25 21:58:16  shang
# first version.
#
 

set auto_path [linsert $auto_path 0 /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]
APSDebugPath

set CVSRevisionAuthor "\$Revision: 1.2 $ \$Author: shang $"

APSApplication . -name ComputeStationDownTime -version $CVSRevisionAuthor \
      -overview {This application computes station down time.}

proc SetStatus {text args} {
    global status
    set status "[clock format [clock seconds] -format %H:%M:%S] $text"
    update      
}

proc GetStationList {args} {
    global IDsectorList IDmissingList BMmissingList BMsectorList stationList 
    global RunNumber dataDir APSRun
    
    set stationFile /home/helios/oagData/flcoord/stations.sdds
    
    set tmpRoot /tmp/[APSTmpString]
    set scheduleFile $dataDir/$RunNumber/schedule.sdds
    if ![file exist $scheduleFile] {
        return -code error "$scheduleFile does not exist!"
    }
    APSAddToTmpFileList -ID stationdowntime -fileList "$tmpRoot.ID $tmpRoot.BM"
    if [catch {exec sddsprocess $stationFile $tmpRoot.ID -match=col,Beamline=ID -match=col,Sector=N,!
        exec sddsprocess $stationFile $tmpRoot.BM -match=col,Beamline=BM -match=col,Sector=N,!} result] {
        return -code error $result
    }
    set columns [exec sddsquery -col $stationFile]
    foreach col $columns {
        if [string match "Station*" $col] {
            lappend stationList [string range $col end end]
        }
    }
    set IDsectorList [join [exec sdds2stream $tmpRoot.ID -col=Sector]]
    set BMsectorList [join [exec sdds2stream $tmpRoot.BM -col=Sector]]
    
    set IDsectors [llength $IDsectorList]
    set BMsectors [llength $BMsectorList]
    set colList [exec sddsquery -col $scheduleFile]
    foreach col $colList {
        if {[regexp {ID} $col] || [regexp {BM} $col]} {
            lappend statColList $col
        }
    }
  
    foreach beam {ID BM} {
        foreach station $stationList {
            for {set index 0} {$index<[set ${beam}sectors]} {incr index} {
                set sector [lindex [set ${beam}sectorList] $index]
                set col PA:[format %02ld $sector]${beam}:$station
                if [lsearch $statColList $col]<0 {
                    lappend ${beam}missingList S[expr $index +1]$station
                }
            }
        }
      
        if {0} {
        foreach station $stationList {
            set stationStatus [exec sdds2stream $tmpRoot.$beam -col=Station$station]
            for {set index 0} {$index<[set ${beam}sectors]} {incr index} {
                set status [lindex $stationStatus $index]
                set sector [lindex [set ${beam}sectorList] $index]
                if {$status=="n"} {
                    lappend ${beam}missingList S[expr $index +1]$station
                } else {
                    set col PA:[format %02ld $sector]${beam}:$station 
                    lappend statColList PA:[format %02ld $sector]$beam:$station
                }
            }
        }
        }
        #foreach station $stationList {
        #    for {set index 0} {$index<[set ${beam}sectors]} {incr index} {
        #        set sector [lindex [set ${beam}sectorList] $index]
        #        set col PA:[format %02ld $sector]${beam}:$station
        #        if [lsearch $statColList $col]<0 {
        #            lappend ${beam}missingList S[expr $index +1]$station
        #        }
        #    }
        #}
        #set stationStatus [exec sdds2stream $tmpRoot.$beam -col=Station$station]
        # for {set index 0} {$index<[set ${beam}sectors]} {incr index} {
        #    set status [lindex $stationStatus $index]
        #    set sector [lindex [set ${beam}sectorList] $index]
        #    if {$status=="n"} {
        #        lappend ${beam}missingList S[expr $index +1]$station
        #    } else {
        #        set col PA:[format %02ld $sector]${beam}:$station
        #       if [lsearch $statColList $col]<0] {
        #           lappend ${beam}missingList S[expr $index +1]$station
        #      }
        #      #lappend statColList PA:[format %02ld $sector]$beam:$station
        #  }
        # }
    }
    
    return
    set statColList [lsort $statColList]
    set tmpRoot /tmp/[APSTmpString]
    set index 0
    set fileList ""
    foreach month {10 11 12} endDay {31 30 31} {
        for {set day 1} {$day<=$endDay} {incr day} {
            set option "-defaultType=short"
            lappend option "-par=StartDay,type=string"
            lappend option "-data=2005-$month-$day"
            lappend option "-par=StartTime,type=double"
            lappend option "-data=[clock scan "2005-$month-$day"]"
            lappend option "-col=TimeInHour,type=long"
            lappend option "-data=0,8,16,24"
            foreach col $statColList {
                lappend option "-col=$col"
                lappend option "-data=0,0,0,0"
            }
            if [catch {eval exec sddsmakedataset $option -pipe=out \
                           | sddsprocess -pipe=in $tmpRoot.$index \
                           \"-define=col,Time,TimeInHour 3600 * StartTime +\" } result] {
                return -code error $result
            }
            lappend fileList $tmpRoot.$index
            incr index
        }
    }
    #if [catch {eval exec sddscombine $fileList stationSchedule.sdds -over} result] {
    #    return -code error $result
   # }
    eval file delete -force $fileList
}

proc SetDateTimeToToday {args} {
    set hour 0
    set rootname ""
    APSStrictParseArguments {hour rootname}
    global todayMonth todayYear todayDay 
    global ${rootname}Month ${rootname}Year ${rootname}Day ${rootname}Hour
    
    APSDateBreakDown -dayVariable todayDay -yearVariable todayYear \
      -monthVariable todayMonth -twoDigitYear 0 -leadingZeros 0
    set ${rootname}Hour $hour
    set ${rootname}Month $todayMonth
    set ${rootname}Day $todayDay
    set ${rootname}Year $todayYear
}

proc MakeDateTimeFrame {widget args} {
    set parent .
    APSStrictParseArguments {parent}
    set label "Date/Time Range of Interest"
    
    global runList 
    
    APSFrame $widget -parent $parent -label $label
    set w $parent$widget.frame

    
    APSDateTimeAdjEntry .startDate -parent $w \
      -yearVariable StartYear \
      -monthVariable StartMonth \
      -dayVariable StartDay \
      -hourVariable StartHour \
      -label "Starting date/time (year, month, day, hour): " -defaultHour 0 
    APSDateTimeAdjEntry .endDate -parent $w \
      -yearVariable EndYear \
      -monthVariable EndMonth \
      -dayVariable EndDay \
      -hourVariable EndHour \
      -label "Ending date/time (year, month, day, hour):   " -defaultHour 24 
    
   # SetDateTimeToToday -rootname Start -hour 0
   # SetDateTimeToToday -rootname End  -hour 24
    SetDateTime 
}

proc SetDateTime {args} { 
    set rootname ""
    APSParseArguments {rootname}
    global RunNumber APSRun StartYear StartMonth StartDay 
    global EndYear EndMonth EndDay StartHour EndHour
    if ![string length $rootname] {
        set rootnameList {Start End}
    } else {
        set rootnameList $rootname
    }
    foreach rootname $rootnameList {
        set ${rootname}Year $APSRun($RunNumber.${rootname}Year)
        set ${rootname}Month $APSRun($RunNumber.${rootname}Month)
        set ${rootname}Day $APSRun($RunNumber.${rootname}Day) 
        set ${rootname}Hour $APSRun($RunNumber.${rootname}Hour)
    }
}

proc MakeStationSelectionWidget {args} {
    
    global IDsectorList IDmissingList BMmissingList BMsectorList stationList 
    
    set widgetList [APSTabFrame .tab -parent .userFrame -label "" \
                        -labelList {ID BM} -width 900 -height 280 \
                        -packOption "-expand yes -fill both"]
    set IDwidget [lindex $widgetList 0]
    set BMwidget [lindex $widgetList 1]
    
    foreach beam {ID BM} {
        APSSRSectorButtons .beamline -parent [set ${beam}widget] -rootname [string tolower $beam] \
            -orientation horizontal -sectorList [set ${beam}sectorList] \
            -label  "" -description "Beamline selections" \
            -itemList $stationList -packOption "-side top" \
            -itemLabelList $stationList -sectorControl 1 \
            -missingList [set ${beam}missingList] 
        APSGetVariableNameOfSRSectorButtons -sectorList [set ${beam}sectorList] \
            -itemList $stationList -rootname [string tolower $beam] \
            -arrayName ${beam}Array 
    } 
    
}
proc GetSelectedStationList {args} {
    global IDArray BMArray scheduleFile
    
    set SelectedBeamlineList ""
    foreach name [array name IDArray] {
        global $IDArray($name)
        if [set $IDArray($name)] {
            set sector [scan $name %2d]
            set station [string range $name end end]
            lappend SelectedBeamlineList PA:[format %02ld $sector]ID:$station
        }
    }
    foreach name [array name BMArray] {
        global $BMArray($name)
        if [set $BMArray($name)] {
            set sector [scan $name %2d]
            set station [string range $name end end]
            lappend SelectedBeamlineList PA:[format %02ld $sector]BM:$station
        }
    }
    
    if ![llength $SelectedBeamlineList] {
        return -code error "No beamline is selected!"
    }
    set SelectedBeamlineList [lsort $SelectedBeamlineList] 
    return $SelectedBeamlineList 
}

 
proc CalculateDownTime {args} {
    global RunNumber APSRun dataDir
    global StartYear StartMonth StartDay StartHour EndYear EndMonth EndDay EndHour 
    
    set schedule 0
    set detail 0
    APSParseArguments {schedule detail}
    
    if ![file exist $dataDir/$RunNumber] {
        SetStatus "Log data for $RunNumber is not available yet."
        return
    }
    if [catch {GetSelectedStationList} stationList] {
        SetStatus "$stationList"
        return
    }
    if !$schedule {
        foreach nm {Start End} {
            set hourList [split [set ${nm}Hour] :]
            set hours [lindex $hourList 0]
            set minutes 0
            set seconds 0
            if [llength $hourList]>1 {
                set minutes [lindex $hourList 1]
            }
            if [llength $hourList]>2 {
                set seconds [lindex $hourList 2]
            }
            if [llength $hourList]>3 {
                return -code error "Invalid ${nm} hour - [set ${nm}Hour] provided."
            }
            set ${nm}Seconds [expr $hours * 3600 + $minutes * 60 + $seconds]
        }
        
        set starttime [expr [clock scan "$StartYear-$StartMonth-$StartDay"] + $StartSeconds]
        set endtime [expr [clock scan "$EndYear-$EndMonth-$EndDay"] + $EndSeconds]
        if {$endtime<$starttime} {
            SetStatus "Invalide data range given, the end date is earlier than the start date!"
            return
        }
        if {$starttime<$APSRun($RunNumber.StartTime)} {
            SetStatus "The data before [clock format $startTime0 -format %m/%d/%y:%H] for $RunNumber is not available, reset the start time to  $APSRun($RunNumber.StartDate)."
            set starttime $APSRun($RunNumber.StartTime)
            SetDateTime -rootname Start
        } elseif {$starttime>$APSRun($RunNumber.StartTime)} {
            SetStatus "The start date is beyond the $RunNumber"
            return
        }
        if {$endtime>$APSRun($RunNumber.EndTime)} {
            SetStatus "The data after [clock format $endtime -format %m/%d/%y:%H:%M:%S] beyond $RunNumber end date, reset the end time to $APSRun($RunNumber.EndDate)."
            set endtime $APSRun($RunNumber.EndTime)
            SetDateTime -rootname End
        }
        #set startTimeStamp [clock format [format %.0f $starttime] -format %m/%d/%y:%H:%M:%S]
        #set endTimeStamp [clock format [format %.0f $endtime] -format %m/%d/%y:%H:%M:%S]
    }
    set tmpRoot /tmp/[APSTmpString]  
    APSAddToTmpFileList -ID PSSDown -fileList "$tmpRoot.sdds $tmpRoot.print"
    if !$schedule {
       SetStatus "Compute total downtime from $StartMonth/$StartDay/$StartYear to $EndMonth/$EndDay/$EndYear ..."
        if [catch {exec stationDownTime \
                       -start=time=$starttime -end=time=$endtime \
                       -station=[join $stationList ,] \
                       -dataDir=$dataDir/$RunNumber $tmpRoot.sdds} result] {
            SetStatus "$result"
            return
        }
        SetStatus "done."
        set startTimeStamp [lindex [exec sdds2stream -par=StartTimeStamp $tmpRoot.sdds] 0]
        set endTimeStamp [lindex [exec sdds2stream -par=EndTimeStamp $tmpRoot.sdds] 0]
        if [catch {exec sddsprintout $tmpRoot.sdds $tmpRoot.print  \
                       "-title=Results in hour from $startTimeStamp to $endTimeStamp" \
                       -col=Station,editlabel=%/PA:// \
                       -col=ScheduleTime,format=%10.2f \
                       -col=UserDownTime,format=%10.2f  \
                       -col=APSDownTime,format=%10.2f  \
                       -col=TotalDownTime,format=%10.2f } result] {
            APSDeleteTmpFileList -ID downtime
            SetStatus "$result"
            return
        }
    } else {
        SetStatus "Computing down time within each schedule for $RunNumber ..." 
        if [catch {exec  stationDownTime \
                       -station=[join $stationList ,] -schedule \
                       -dataDir=$dataDir/$RunNumber $tmpRoot.sdds} result] {
            SetStatus "$result"
            return
        }
        set startTimeStamp [lindex [exec sdds2stream -par=StartTimeStamp $tmpRoot.sdds] 0]
        set endTimeStamp [lindex [exec sdds2stream -par=EndTimeStamp $tmpRoot.sdds] 0]
        SetStatus "done."
        if [catch {exec sddsprintout $tmpRoot.sdds.downtime $tmpRoot.print1 \
                       "-title=Summary of station down time from $startTimeStamp to $endTimeStamp" \
                       -postPagelines=2 \
                       -col=Station,editlabel=%/PA://,format=%10s \
                       -col=ScheduledHours,format=%15.0f,label=TotalScheduledHours \
                       -col=ScheduledShifts,label=TotalScheduledShifts \
                       -col=TotalMissedShifts -col=UserMissedShifts } result] {
            SetStatus "$result"
            return
        }
        APSFileDisplayWindow .[APSUniqueName printout] -fileName $tmpRoot.print1 \
        -width 110 -printCommand "enscript -r" -sddsExportableFile $tmpRoot.sdds.downtime \
        -deleteOnClose 1 -height 30  
        if [catch {exec sddsprocess $tmpRoot.sdds -pipe=out \
                       "-filter=par,TotalDownTime,0,0,!" \
                       "-filter=col,AllDownTime,0,0,!" \
                       | sddsprintout -pipe=in  $tmpRoot.print \
                       "-title=Down time within one schedule for selected stations from $startTimeStamp to $endTimeStamp" \
                       -postPagelines=2 \
                       -par=Station,editlabel=%/PA://,format=%10s,endsline \
                       -par=TotalUserDownTime,format=%15.2f,endsline \
                       -par=TotalSRDownTime,format=%15.2f,endsline \
                       -par=TotalPSSDownTime,format=%15.2f,endsline \
                       -col=Date -col=ScheduleHour \
                       -col=UserDownTime,format=%10.2f \
                       -col=PSSDownTime,format=%10.2f \
                       -col=SRDownTime,format=%10.2f \
                        -col=AllDownTime,format=%10.2f \
                       -col=ActiveBeamTime,format=%10.2f } result] {
            SetStatus "$result"
            return
        } 
    } 
    APSFileDisplayWindow .[APSUniqueName printout] -fileName $tmpRoot.print \
        -width 110 -printCommand "enscript -r" -sddsExportableFile $tmpRoot.sdds \
        -deleteOnClose 1 -height 30  
}

proc UpdateDates {args} { 
    global APSRun StartYear StartMonth StartDay StartHour EndYear EndDay EndMonth EndHour RunNumber
    
    set dateList {StartYear StartMonth StartDay StartHour EndYear EndDay EndMonth EndHour}
    foreach date $dateList {
        set $date $APSRun(${RunNumber}.$date)
    }
}
set status "This computes the PSS station down time.\n\The defintion of down time is the time of when with scheduled beamtime, beam not active plus no-attendance;\n\nUserDownTime is the down time of when beam not active + scheduled beamtime + no_attendance + stored beam in SR + no aps fault;\n\nPSSDownTime is the down time of when beam not active + scheduled beamtime +  no_attendance + stored beam in SR + aps fault\n\nSRDownTime is the downtime of when beam not active + scheduled beamtime + no_attendance + SR is down\n\nAPSDownTime = SRDownTime + PSSDownTime\n\nTotalDownTime = UserDownTime + APSDownTime."
APSScrolledStatus .status -parent .userFrame -textVariable status -width 80 \
    -withButtons 1 -height 10
set dataDir /home/helios/oagData/sr/beamlineDownTime
set runList [exec sdds2stream -col=RunName $dataDir/APS_schedule.sdds]
set startDateList  [exec sdds2stream -col=StartDate $dataDir/APS_schedule.sdds]
set endDateList  [exec sdds2stream -col=EndDate $dataDir/APS_schedule.sdds]
 
foreach run $runList start $startDateList end $endDateList {
    set tmpList [split $start /]
    set tmpList1 [split $end /]
    set APSRun($run.StartYear) [lindex $tmpList 2]
    set APSRun($run.StartMonth) [lindex $tmpList 0]
    set APSRun($run.StartDay) [lindex $tmpList 1]
    set APSRun($run.EndYear) [lindex $tmpList1 2]
    set APSRun($run.EndMonth) [lindex $tmpList1 0]
    set APSRun($run.EndDay) [lindex $tmpList1 1]
    set APSRun($run.dir) $dataDir/$run
    set APSRun($run.StartDate) $start
    set APSRun($run.EndDate) $end
    set APSRun($run.StartTime) [clock scan $start]
    set APSRun($run.EndTime) [expr [clock scan $end] + 24 *3600]
    set APSRun($run.StartHour) 0
    set APSRun($run.EndHour) 24
    lappend comList UpdateDates
}
 
set RunNumber 2006-Run2
APSRadioButtonFrame .run -parent .userFrame -label "Run Number:" -variable RunNumber \
    -contextHelp "Select the APS run-number for computing the PSS down time at that run." \
    -buttonList $runList -valueList $runList -orientation horizontal \
    -commandList $comList

MakeDateTimeFrame .time -parent .userFrame
if [catch {GetStationList} result] {
    return -code error $result
}
    
MakeStationSelectionWidget

#APSButton .cal1 -parent .userFrame -text "Show Station DownTime" -command "CalculateDownTime" \
 #   -contextHelp "This button shows the total PSS station down time, the defintion of down time is the time of when with scheduled beamtime, shutter is closed and no-attendance;\n\three columns will be shown.\nUserDownTime is the down time when beam is ready, i.e., scheduled beamtime + beam_ready + shutter_closed + no_attendance;\nAPSDownTime is the down time when beam is not ready, i.e., scheduled beamtime + beam_not_ready + shutter_closed + no_attendance\nTotalDownTime is the sum of UserDownTime and APSDownTime."
APSButton .cal -parent .userFrame -text "Calculate DownTime" -command \
    "CalculateDownTime" -contextHelp "This button computes the downtimes from selected start time to end time for selected run number"
APSButton .cal2 -parent .userFrame -text "Calculate Downtime Within Schedules" -command "CalculateDownTime -schedule 1" -contextHelp "This button computes the downtimes within each schedule for each run, the start time and end time is obtained from the scheduled start time and end time for selected run number."
#unselect all
#foreach name [array name BeamlineArray] {
#    global $BeamlineArray($name)
#    set $BeamlineArray($name) 0
#}
