#!/usr/bin/wish4.2 -f # graphbal - Graph running balance # # Written by Arlindo L. Oliveira (aml@inesc.pt) # # Copyright (C) 1996 Arlindo L. Oliveira (aml@inesc.pt) # # $Id: graphbal,v 1.1.1.1 1999/12/18 02:06:47 curt Exp $ set data(0,0) " " set data(0,1) " " set cnt 1 while {[gets stdin line] >= 1} { set data($cnt,0) [lindex $line 0] set data($cnt,1) [lindex $line 1] if {$data($cnt,0) == $data([expr $cnt-1],0)} { set data([expr $cnt-1],1) $data($cnt,1) } else { incr cnt } } proc graphData {graph row col} { global data return $data($row,$col) } proc graphCols {canvas} { return 1 } proc graphRows {canvas} { global cnt return [expr $cnt-1] } # # createColumnGraph # rows : number of data rows 1 ... rows # cols : number of data cols 1 ... cols # data(0,i) contains data labels # data(i,0) contains abcissa labels # set barColors(1) "blue" set barColors(2) "green" set barColors(3) "red" set barColors(4) "yellow" set barColors(5) "brown" proc graphColor {i} { global barColors return $barColors($i) } proc defGraphMargin {} { return 60 } proc defGraphHeight {} { return 480 } proc defGraphWidth {} { return 640 } proc defGraphWinHeight {} { return [expr [defGraphHeight]+2*[defGraphMargin]] } proc defGraphWinWidth {} { return [expr [defGraphWidth]+[defGraphMargin]+[defGraphMargin]] } proc cutZero {st} { if {[string range $st 0 0] == 0} { return [string range $st 1 2] } else { return $st } } set months(01) Jan set months(02) Feb set months(03) Mar set months(04) Apr set months(05) May set months(06) Jun set months(07) Jul set months(08) Aug set months(09) Sep set months(10) Oct set months(11) Nov set months(12) Dec proc month {date} { global months return $months([string range $date 4 5]) } proc daysBetween {first last} { set y1 [string range $first 0 3] set m1 [cutZero [string range $first 4 5]] set d1 [cutZero [string range $first 6 7]] set y2 [string range $last 0 3] set m2 [cutZero [string range $last 4 5]] set d2 [cutZero [string range $last 6 7]] return [expr 365*($y2-$y1) + 30*($m2-$m1) + $d2-$d1] } proc normalize {value} { global logten set logten 0 while {$value >= 10} { set value [expr $value/10] incr logten } return $value } proc createColumnGraph {graphName {canv 0}} { global graphCnt canvas logten set cols [graphCols $graphName] set rows [graphRows $graphName] wm withdraw . if {$canv == 0} { toplevel .graph$graphCnt set canvas [canvas .graph$graphCnt.graph -width [defGraphWinWidth] \ -height [defGraphWinHeight] -bg white] button .graph$graphCnt.dismiss -text dismiss \ -command {destroy .} button .graph$graphCnt.print -text Print \ -command { toplevel .m message .m.msg -font 12x24 -text "Printing to file bal.ps" pack .m.msg wm geometry .m +300+300 after 2000 {destroy .m} $canvas postscript -file bal.ps -pagewidth 19c } } pack $canvas pack .graph$graphCnt.dismiss -fill x pack .graph$graphCnt.print -fill x # # Width of each bar # set gw [defGraphWidth] set gh [defGraphHeight] set gm [defGraphMargin] $canvas create rectangle $gm $gm [expr $gm+$gw] [expr $gm+$gh] \ -fill gray80 -outline gray80 set max 0 set min 0 for {set j 1} {$j <= $cols} {incr j} { for {set i 1} {$i <= $rows} {incr i} { set x [graphData graphName $i $j] if {$x < $min} {set min $x} if {$x > $max} {set max $x} } } set max_min_diff 1.0 if {$max > [expr $min+1]} {set max_min_diff [expr $max-$min]} # # Auto-scaling # set dy [normalize [expr $max_min_diff/10]] # 5 dy=10 # 2 dy=5 # 1 dy=2 # 1<=dy --> dy=1 if { $dy > 5 } { set dy 10 } else { if { $dy > 2 } { set dy 5 } else { if { $dy > 1 } { set dy 2 } else { set dy 1 } } } set dy [expr $dy*pow(10,$logten)] set mintick [expr int($min/$dy)] if { $mintick < 0 } { set mintick [expr $mintick-1] } set maxtick [expr int($max/$dy+1)] if { $maxtick < 0 } { set mintick [expr $maxtick-1] } set min [expr $dy*$mintick] set max [expr $dy*($maxtick+0.3)] set max_min_diff [expr $max-$min] set yscale [expr $gh/($max_min_diff)] set zero [expr $gh+$gm+$min/($max_min_diff)*$gh] set nlevels [expr $rows/8] set ndays [daysBetween [graphData $graphName 1 0] \ [graphData $graphName $rows 0]] if {$ndays != 0} { set xscale [expr $gw/1.0/$ndays] } else { set xscale [expr $gw/1.0] } # # Draw axes # $canvas create line $gm $zero [expr $gm+$gw] $zero $canvas create line $gm [expr $gm+$gh] $gm $gm -arrow last for {set i $mintick} {$i <= $maxtick} {incr i} { set val [expr $i*$dy] if {$val <= $max && $val >= $min} { $canvas create text [expr $gm-8] [expr $zero-$val*$yscale] \ -text $val -anchor e $canvas create line $gm [expr $zero-$val*$yscale] \ [expr $gm-5] [expr $zero-$val*$yscale] } } # # Draw a tic marking the final balance for period graphed. # set finbal [graphData $graphName $rows 1] $canvas create line $gm [expr $zero-$finbal*$yscale] \ [expr $gm-5] [expr $zero-$finbal*$yscale] -fill red set prevmt [month [graphData $graphName 1 0]] for {set i 2} {$i <= $rows} {incr i} { set x1 [daysBetween [graphData $graphName 1 0] \ [graphData $graphName [expr $i-1] 0]] set x2 [daysBetween [graphData $graphName 1 0] \ [graphData $graphName $i 0]] if {[graphData $graphName $i 1] > 0} { set color red } else { set color orange } $canvas create polygon \ [expr $gm+$x1*$xscale] \ [expr $zero-[graphData $graphName [expr $i-1] 1]*$yscale] \ [expr $gm+$x2*$xscale] \ [expr $zero-[graphData $graphName $i 1]*$yscale] \ [expr $gm+$x2*$xscale] \ $zero \ [expr $gm+$x1*$xscale] \ $zero \ -fill $color set mt [month [graphData $graphName $i 0]] if {$mt != $prevmt} { $canvas create text [expr $gm+$x2*$xscale+2] [expr $gm+$gh+10] \ -anchor w -text $mt $canvas create line [expr $gm+$x2*$xscale] [expr $gm+$gh+10] \ [expr $gm+$x2*$xscale] $zero set prevmt $mt } } } set graphCnt 0 createColumnGraph lixo 0