# # ================================================================== # # This file and the page in which it appears are # Copyright (c) 1997 by hav.Software and Horace A. Vallas, Jr. # All rights reserved # # No right is granted to copy or distribute this file or any of # its # contents except as may occur in normal browsing of the # page in which it appears. # # questions to: hav@hav.com # http://www.hav.com/ # # ================================================================== # # NOTE: this graphic accepts three OPTIONAL arguments: # # expiration indicates the number of seconds till the server # cached graphic will expire. # If the expiration argument IS NOT present, # then the expiration time is calculated to be # 10 seconds after midnight. # # numtoshow number of days to show - if larger than the number # of days os data in the archive file, this will be be # set equal to the number of days of data in the archive file # default=30 # # xStep number of bits/day on the X-axis # default=10 # # ================================================================== # # NOTE: this graphic creates an IMAGE MAP named vpChartMap with one # link for each data value plotted. The links are to the # JavaNeoTrack java demo of daily hourly visitors & page-accesses ######################### Basic System Init ############################### set home ../.. # # first check that yesterday has been added to the # JavaNeoTrack and JavaNeoTrackTotals data files # if not, then add it now # set sec2 [clock scan [clock format [clock seconds] -format %D]] set sec1 [expr $sec2 - 82800] set sec1 [clock scan [clock format $sec1 -format %D]] if {$sec1 == $sec2} { set sec1 [expr $sec2 - 86400] set sec1 [clock scan [clock format $sec1 -format %D]] if {$sec1 == $sec2} { set sec1 [expr $sec2 - 90000] set sec1 [clock scan [clock format $sec1 -format %D]] } } #if {[dbfetch JavaNeoTrack [code_date $sec1] reportArray] == 0} { # load_virtual $home/neoscript/totalvis.nws # total_yesterday_visitors $sec1 $sec2 # set justAddedYesterday 1 #} else { # set justAddedYesterday 0 #} # # now initialize the imagemap for the gif # catch {filerm dat vpChartMap} set mapFP [access_data_file vpChartMap] puts $mapFP "" # now load any arguments sent with the gif request load_response ######################### Utility Procs ############################### # ====================================================================== # # getData will retrieve the data to be plotted # along with certain global values like min & max # counts, start/end dates, etc. # # data are retrieved from the JavaNeoTRack archive file # one record per day # each record has two array elements (page & visitor) # each element consists of 432 values (one for each # 200 second period of a day) proc getData {} { global gif global numToShow dataFile global pageData visData page vis global startDate endDate error global font global xStep tickSize spacer global lat rat xat global lal ral xal global lat rat xat global grid gridTLC gridBLC gridTRC gridBRC global dayKeys # some initialization # get the list of keys from the data file # ordered from newest to oldest set keys {} catch {set keys [lrange [lsort -decreasing -ascii [dbkeys $dataFile]] 0 [expr $numToShow - 1]]} set numToShow [llength $keys] ;# just incase we asked for more days than are in the archive set lastDay [expr $numToShow - 1] if {[llength $keys] == 0} { set error "Cannot access data file" return } else { set error "" if {[llength $keys] > $numToShow} { } } # for each day to be shown, sum the number of pages served # and the number of visitors. # Also, keep track of the min/max pages and visitors for # all days shown as well as the starting and ending dates # involved. set startDate [lindex $keys 0] set endDate [lindex $keys end] set i 0 foreach key $keys { dbfetch $dataFile $key repArray # calculate the daily totals for pages and visitors set dayKeys($i) $key set pageData($i) $repArray(page) set visData($i) $repArray(visitor) # test and set min/max pages and visitors as needed if {$pageData($i) > $page(max)} {set page(max) $pageData($i)} if {$pageData($i) < $page(min)} {set page(min) $pageData($i)} if {$visData($i) > $vis(max)} {set vis(max) $visData($i)} if {$visData($i) < $vis(min)} {set vis(min) $visData($i)} catch {unset repArray} incr i } # DONE! so return } ;# ***** end proc getData # ====================================================================== # # initChart will calculate the M & A factors for page and visitor counts # and then draw the chart axes, grid lines, and labels # proc initChart {} { global gif global numToShow dataFile global pageData visData page vis global startDate endDate error global font global xStep tickSize spacer global lat rat xat global lal ral xal global lat rat xat global grid gridTLC gridBLC gridTRC gridBRC # draw the axes and grid # draw the grid first drawGrid gif gridTLC gridBLC gridTRC gridBRC $tickSize $numToShow $xStep # the left Y-axis (PAGES) drawAxis gif $gridTLC(x) $gridTLC(y) $gridBLC(x) $gridBLC(y) \ page $gif(leftAxisColor) lat lal 90 # the right Y-axis (VISITORS) drawAxis gif $gridTRC(x) $gridTRC(y) $gridBRC(x) $gridBRC(y) \ vis $gif(rightAxisColor) rat ral 90 # the left axis (PAGE) drawAxis gif $gridBLC(x) $gridBLC(y) $gridBRC(x) $gridBRC(y) \ 0 $gif(xAxisColor) xat xal 0 } ;# **** end of proc initChart # ====================================================================== # # drawGrid will draw the grid on the chart space # proc drawGrid {thegif tl bl tr br tick numDays xStep} { upvar $thegif theGif upvar $tl tL upvar $bl bL upvar $tr tR upvar $br bR # the horizontal lines (3) gd line $theGif(image) $theGif(gridColor) \ [expr $tL(x) - $tick] $tL(y) [expr $tR(x) + $tick] $tR(y) gd line $theGif(image) $theGif(gridColor) \ [expr $tL(x) - $tick] [expr [expr [expr $bL(y) - $tL(y)] / 2] + $tL(y)] \ [expr $tR(x) + $tick] [expr [expr [expr $bL(y) - $tL(y)] / 2] + $tL(y)] gd line $theGif(image) $theGif(gridColor) \ [expr $bL(x) - $tick] $bL(y) [expr $bR(x) + $tick] $bR(y) # the verticle lines (one for each day) set X $tL(x) loop i 0 $numDays { gd line $theGif(image) $theGif(gridColor) \ $X $tL(y) $X [expr $bL(y) + $tick] incr X $xStep } } # ====================================================================== # # drawAxis will draw and label an X or Y axis of the chart # proc drawAxis {gifimage startX startY endX endY theData axisColor theTitle theLabel angle} { global gif global numToShow dataFile global pageData visData page vis global startDate endDate error global font global xStep tickSize spacer global lat rat xat global lal ral xal global lat rat xat global grid gridTLC gridBLC gridTRC gridBRC upvar $gifimage theGif upvar $theTitle title upvar $theLabel label # draw the axis line gd line $theGif(image) $axisColor $startX $startY $endX $endY # draw the title if {$angle} { gd textup $theGif(image) $axisColor small $title(x) $title(y) $title(text) } else { gd text $theGif(image) $axisColor small $title(x) $title(y) $title(text) } # draw the labels if {$angle} { gd text $theGif(image) $theGif(labelColor) small $label(x) \ $label(y) $label(text1) gd text $theGif(image) $theGif(labelColor) small $label(x) \ [expr $label(y) + [expr $grid(height) / 2]] $label(text2) gd text $theGif(image) $theGif(labelColor) small $label(x) \ [expr $label(y) + $grid(height)] $label(text3) } else { gd text $theGif(image) $theGif(labelColor) small $label(x) \ $label(y) $label(text1) gd text $theGif(image) $theGif(labelColor) small \ [expr $label(x) + [expr $grid(width) / 2]] $label(y) $label(text2) gd text $theGif(image) $theGif(labelColor) small \ [expr $label(x) + $grid(width)] $label(y) $label(text3) } } # ====================================================================== # # drawAxis will draw the data curves # proc drawData {theData theParms color} { global gif global numToShow dataFile global pageData visData page vis global startDate endDate error global font global xStep tickSize spacer global lat rat xat global lal ral xal global lat rat xat global grid gridTLC gridBLC gridTRC gridBRC global dayKeys mapFP upvar $theData data upvar $theParms parm set radius [expr $xStep / 2] set i $numToShow incr i -1 set xFrom $grid(x) scan [expr $gridBLC(y) - [expr $data($i) * $parm(M) + $parm(A)]] %d yFrom set altText [clock format [decode_date $dayKeys($i)] -format "%a, %b %e"] set junkLink [clock format [decode_date $dayKeys($i)] -format "%a_%b_%e"] puts $mapFP "\"$altText\"" loop i {$i -1} -1 -1 { set xTo [expr $xFrom + $xStep] scan [expr $gridBLC(y) - [expr $data($i) * $parm(M) + $parm(A)]] %d yTo set altText [clock format [decode_date $dayKeys($i)] -format "%a, %b %e"] set junkLink [clock format [decode_date $dayKeys($i)] -format "%a_%b_%e"] puts $mapFP "\"$altText\"" gd line $gif(image) $color $xFrom $yFrom $xTo $yTo gd line $gif(image) $color $xFrom [expr $yFrom - 1] $xTo [expr $yTo - 1] set xFrom $xTo set yFrom $yTo } } ############################# Global Data ################################# #set pageData set page(min) 10000 set page(max) 0 set page(M) 1.0 set page(A) 0.0 #set visData set vis(min) 10000 set vis(max) 0 set vis(M) 1.0 set vis(A) 0.0 if {[info exists response(numtoshow)]} { set numToShow $response(numtoshow) } else { set numToShow 30 } set startDate "" set endDate "" set error "" ##################### Get The Data To Be Plotted ######################## # # Note: we need the previous Global Data section to be defined before # calling getData which, in turn, must precede the following # global data definitions that need info & data from getData. set dataFile "JavaNeoTrackTotals" getData ######################### More Global Data ############################### # # note: these data must be initialized AFTER the call to getdata # because their values are determined by the data values set font(height) 12 set font(width) 6 if {[info exists response(xStep)]} { set xStep $response(xStep) } else { set xStep 10 } set tickSize 5 set spacer 10 set lat(text) "Pages" ;# SET THESE THREE BY HAND !! set rat(text) "Visitors" set xat(text) "Days" set lat(len) [llength [split $lat(text) {}]] set lat(width) $font(height) set lat(height) [expr $font(width) * $lat(len)] set lal(text1) $page(max) set lal(text3) $page(min) set lal(text2) [expr $lal(text1) - [expr [expr $lal(text1) - $lal(text3)] / 2]] set lal(len) [llength [split $lal(text1) {}]] set lal(width) [expr $font(width) * $lal(len)] set rat(len) [llength [split $rat(text) {}]] set rat(width) $font(height) set rat(height) [expr $font(width) * $rat(len)] set ral(text1) $vis(max) set ral(text3) $vis(min) set ral(text2) [expr $ral(text1) - [expr [expr $ral(text1) - $ral(text3)] / 2]] set ral(len) [llength [split $ral(text1) {}]] set ral(width) [expr $font(width) * $ral(len)] set xat(len) [llength [split $xat(text) {}]] set xat(width) [expr $font(width) * $xat(len)] set xat(height) $font(height) set xal(text3) [clock format [decode_date $startDate] -format %m/%d] set xal(text2) "" set xal(text1) [clock format [decode_date $endDate] -format %m/%d] set xal(len) 5 set xal(width) [expr $font(width) * $xal(len)] set grid(height) 75 set grid(width) [expr [expr $numToShow - 1] * $xStep] set grid(x) [expr $spacer + $font(height) + $spacer + $lal(width) + $spacer + $tickSize] set grid(y) [expr $font(height)/2 + $spacer] set gridTLC(x) $grid(x) set gridTLC(y) $grid(y) set gridBLC(x) $grid(x) set gridBLC(y) [expr $grid(y) + $grid(height)] set gridTRC(x) [expr $grid(x) + $grid(width)] set gridTRC(y) $grid(y) set gridBRC(x) [expr $grid(x) + $grid(width)] set gridBRC(y) [expr $grid(y) + $grid(height)] set lal(x) [expr $spacer + $lat(width) + $spacer] set lal(y) $spacer set lat(x) [expr $spacer] set lat(y) [expr [expr [expr $grid(height) - $lat(height)] / 2] + $grid(y) + $lat(height)] set ral(x) [expr $gridTRC(x) + $tickSize + $spacer] set ral(y) $spacer set rat(x) [expr $gridTRC(x) + $tickSize + $spacer + $ral(width) + $spacer] set rat(y) [expr [expr [expr $grid(height) - $rat(height)] / 2] + $grid(y) + $rat(height)] set xal(x) [expr $gridBLC(x) - [expr $xal(width) / 2]] set xal(y) [expr $gridBLC(y) + $spacer] set xat(x) [expr [expr [expr $grid(width) - $xat(width)] / 2] + $gridBLC(x)] set xat(y) [expr $xal(y) + $spacer] set gif(height) [expr $xat(y) + $xat(height) + $spacer] set gif(width) [expr $rat(x) + $rat(width) + $spacer] ############## Main Processing following all Initializations ################# # calculate the M & A values set page(M) [expr $grid(height).0 / [expr $page(max).0 - $page(min).0]] set page(A) [expr -1.0 * $page(M) * $page(max).0 + $grid(height).0] set vis(M) [expr $grid(height).0 / [expr $vis(max).0 - $vis(min).0]] set vis(A) [expr -1.0 * $vis(M) * $vis(max).0 + $grid(height).0] #=================== Create and draw the image set gif(image) [gd create $gif(width) $gif(height)] set gif(white) [gd color new $gif(image) 255 255 255] set gif(black) [gd color new $gif(image) 0 0 0] set gif(blue) [gd color new $gif(image) 0 0 192] set gif(red) [gd color new $gif(image) 192 0 0] set gif(gray) [gd color new $gif(image) 192 192 192] set gif(bgColor) $gif(white) set gif(gridColor) $gif(gray) set gif(leftAxisColor) $gif(blue) set gif(rightAxisColor) $gif(red) set gif(xAxisColor) $gif(black) set gif(labelColor) $gif(black) # init the chart and draw/label the grid initChart # draw the data traces drawData pageData page $gif(leftAxisColor) drawData visData vis $gif(rightAxisColor) # set the gif expiration time # if no expiration time was sent with the gif request ... i.e. ...?expiration=xx # then set the expiration to be just after midnight if {![info exists expiration]} { set now [clock seconds] set nextDay [clock scan [clock format [expr $now + 93600] -format %m/%d/%Y]] incr nextDay 30 ;# safety margin of 30 seconds set expiration [expr $nextDay - $now] } image_expire $expiration # finally close the imagemap puts $mapFP "\n" close $mapFP # now write outa and close the gif and DONE!! gd writeGIF $gif(image) $imageFile gd destroy $gif(image)