Stats module and example merged in.
authortjkopena@cs.drexel.edu
Fri, 29 Aug 2008 13:22:09 -0400
changeset 3570 44b0bc6817c6
parent 3567 728eb3f583b3
child 3571 05f0716c9c36
Stats module and example merged in.
examples/stats/README
examples/stats/data.db
examples/stats/wifi-default.data
examples/stats/wifi-default.eps
examples/stats/wifi-example-apps.cc
examples/stats/wifi-example-apps.h
examples/stats/wifi-example-db.sh
examples/stats/wifi-example-sim.cc
examples/stats/wifi-example.gnuplot
examples/stats/wscript
examples/wscript
src/contrib/stats/basic-data-calculators.h
src/contrib/stats/data-calculator.cc
src/contrib/stats/data-calculator.h
src/contrib/stats/data-collector.cc
src/contrib/stats/data-collector.h
src/contrib/stats/data-output-interface.cc
src/contrib/stats/data-output-interface.h
src/contrib/stats/omnet-data-output.cc
src/contrib/stats/omnet-data-output.h
src/contrib/stats/packet-data-calculators.cc
src/contrib/stats/packet-data-calculators.h
src/contrib/stats/sqlite-data-output.cc
src/contrib/stats/sqlite-data-output.h
src/contrib/stats/time-data-calculators.cc
src/contrib/stats/time-data-calculators.h
src/contrib/stats/wscript
src/contrib/wscript
src/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/stats/README	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,16 @@
+
+			  ns-3 stats example
+
+The example script wifi-example-db.sh in this directly will run
+through the entire process of running a simple experiment.  It assumes
+sqlite3 is installed as it uses the sqlite3 data output format of the
+statistics package.  It also assumes it is being run from the
+examples/stats/ subdirectory of the ns-3 package, together with its
+gnuplot script.  When the script completes successfully, a graph will
+be have been produced in examples/stats/wifi-default.eps demonstrating
+output from this example.
+
+More information on the statistics package and this example is
+available online on the ns-3 wiki at:
+
+http://www.nsnam.org/wiki/index.php/Statistical_Framework_for_Network_Simulation
Binary file examples/stats/data.db has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/stats/wifi-default.data	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,20 @@
+25   0.0
+50   0.0
+75   0.0
+100   0.0
+125   0.0
+145   3.6
+147   6.8
+150   5.0
+152   12.6
+155   20.4
+157   31.6
+160   46.4
+162   58.8
+165   71.6
+167   81.0
+170   96.4
+172   99.4
+175   100.0
+177   100.0
+180   99.4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/stats/wifi-default.eps	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,643 @@
+%!PS-Adobe-2.0
+%%Title: wifi-default.eps
+%%Creator: gnuplot 4.2 patchlevel 0
+%%CreationDate: Fri Aug 29 13:16:08 2008
+%%DocumentFonts: (atend)
+%%BoundingBox: 50 50 554 525
+%%Orientation: Portrait
+%%Pages: (atend)
+%%EndComments
+%%BeginProlog
+/gnudict 256 dict def
+gnudict begin
+%
+% The following 6 true/false flags may be edited by hand if required
+% The unit line width may also be changed
+%
+/Color false def
+/Blacktext false def
+/Solid false def
+/Dashlength 1 def
+/Landscape false def
+/Level1 false def
+/Rounded false def
+/TransparentPatterns false def
+/gnulinewidth 10.000 def
+/userlinewidth gnulinewidth def
+%
+/vshift -46 def
+/dl1 {
+  10.0 Dashlength mul mul
+  Rounded { currentlinewidth 0.75 mul sub dup 0 le { pop 0.01 } if } if
+} def
+/dl2 {
+  10.0 Dashlength mul mul
+  Rounded { currentlinewidth 0.75 mul add } if
+} def
+/hpt_ 31.5 def
+/vpt_ 31.5 def
+/hpt hpt_ def
+/vpt vpt_ def
+Level1 {} {
+/SDict 10 dict def
+systemdict /pdfmark known not {
+  userdict /pdfmark systemdict /cleartomark get put
+} if
+SDict begin [
+  /Title (wifi-default.eps)
+  /Subject (gnuplot plot)
+  /Creator (gnuplot 4.2 patchlevel 0)
+  /Author (Joe Kopena,,,,)
+%  /Producer (gnuplot)
+%  /Keywords ()
+  /CreationDate (Fri Aug 29 13:16:08 2008)
+  /DOCINFO pdfmark
+end
+} ifelse
+%
+% Gnuplot Prolog Version 4.2 (August 2006)
+%
+/M {moveto} bind def
+/L {lineto} bind def
+/R {rmoveto} bind def
+/V {rlineto} bind def
+/N {newpath moveto} bind def
+/Z {closepath} bind def
+/C {setrgbcolor} bind def
+/f {rlineto fill} bind def
+/vpt2 vpt 2 mul def
+/hpt2 hpt 2 mul def
+/Lshow {currentpoint stroke M 0 vshift R 
+	Blacktext {gsave 0 setgray show grestore} {show} ifelse} def
+/Rshow {currentpoint stroke M dup stringwidth pop neg vshift R
+	Blacktext {gsave 0 setgray show grestore} {show} ifelse} def
+/Cshow {currentpoint stroke M dup stringwidth pop -2 div vshift R 
+	Blacktext {gsave 0 setgray show grestore} {show} ifelse} def
+/UP {dup vpt_ mul /vpt exch def hpt_ mul /hpt exch def
+  /hpt2 hpt 2 mul def /vpt2 vpt 2 mul def} def
+/DL {Color {setrgbcolor Solid {pop []} if 0 setdash}
+ {pop pop pop 0 setgray Solid {pop []} if 0 setdash} ifelse} def
+/BL {stroke userlinewidth 2 mul setlinewidth
+	Rounded {1 setlinejoin 1 setlinecap} if} def
+/AL {stroke userlinewidth 2 div setlinewidth
+	Rounded {1 setlinejoin 1 setlinecap} if} def
+/UL {dup gnulinewidth mul /userlinewidth exch def
+	dup 1 lt {pop 1} if 10 mul /udl exch def} def
+/PL {stroke userlinewidth setlinewidth
+	Rounded {1 setlinejoin 1 setlinecap} if} def
+% Default Line colors
+/LCw {1 1 1} def
+/LCb {0 0 0} def
+/LCa {0 0 0} def
+/LC0 {1 0 0} def
+/LC1 {0 1 0} def
+/LC2 {0 0 1} def
+/LC3 {1 0 1} def
+/LC4 {0 1 1} def
+/LC5 {1 1 0} def
+/LC6 {0 0 0} def
+/LC7 {1 0.3 0} def
+/LC8 {0.5 0.5 0.5} def
+% Default Line Types
+/LTw {PL [] 1 setgray} def
+/LTb {BL [] LCb DL} def
+/LTa {AL [1 udl mul 2 udl mul] 0 setdash LCa setrgbcolor} def
+/LT0 {PL [] LC0 DL} def
+/LT1 {PL [4 dl1 2 dl2] LC1 DL} def
+/LT2 {PL [2 dl1 3 dl2] LC2 DL} def
+/LT3 {PL [1 dl1 1.5 dl2] LC3 DL} def
+/LT4 {PL [6 dl1 2 dl2 1 dl1 2 dl2] LC4 DL} def
+/LT5 {PL [3 dl1 3 dl2 1 dl1 3 dl2] LC5 DL} def
+/LT6 {PL [2 dl1 2 dl2 2 dl1 6 dl2] LC6 DL} def
+/LT7 {PL [1 dl1 2 dl2 6 dl1 2 dl2 1 dl1 2 dl2] LC7 DL} def
+/LT8 {PL [2 dl1 2 dl2 2 dl1 2 dl2 2 dl1 2 dl2 2 dl1 4 dl2] LC8 DL} def
+/Pnt {stroke [] 0 setdash gsave 1 setlinecap M 0 0 V stroke grestore} def
+/Dia {stroke [] 0 setdash 2 copy vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V closepath stroke
+  Pnt} def
+/Pls {stroke [] 0 setdash vpt sub M 0 vpt2 V
+  currentpoint stroke M
+  hpt neg vpt neg R hpt2 0 V stroke
+ } def
+/Box {stroke [] 0 setdash 2 copy exch hpt sub exch vpt add M
+  0 vpt2 neg V hpt2 0 V 0 vpt2 V
+  hpt2 neg 0 V closepath stroke
+  Pnt} def
+/Crs {stroke [] 0 setdash exch hpt sub exch vpt add M
+  hpt2 vpt2 neg V currentpoint stroke M
+  hpt2 neg 0 R hpt2 vpt2 V stroke} def
+/TriU {stroke [] 0 setdash 2 copy vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V closepath stroke
+  Pnt} def
+/Star {2 copy Pls Crs} def
+/BoxF {stroke [] 0 setdash exch hpt sub exch vpt add M
+  0 vpt2 neg V hpt2 0 V 0 vpt2 V
+  hpt2 neg 0 V closepath fill} def
+/TriUF {stroke [] 0 setdash vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V closepath fill} def
+/TriD {stroke [] 0 setdash 2 copy vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V closepath stroke
+  Pnt} def
+/TriDF {stroke [] 0 setdash vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V closepath fill} def
+/DiaF {stroke [] 0 setdash vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V closepath fill} def
+/Pent {stroke [] 0 setdash 2 copy gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  closepath stroke grestore Pnt} def
+/PentF {stroke [] 0 setdash gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  closepath fill grestore} def
+/Circle {stroke [] 0 setdash 2 copy
+  hpt 0 360 arc stroke Pnt} def
+/CircleF {stroke [] 0 setdash hpt 0 360 arc fill} def
+/C0 {BL [] 0 setdash 2 copy moveto vpt 90 450 arc} bind def
+/C1 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 90 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C2 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 90 180 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C3 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 180 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C4 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 180 270 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C5 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 90 arc
+	2 copy moveto
+	2 copy vpt 180 270 arc closepath fill
+	vpt 0 360 arc} bind def
+/C6 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 90 270 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C7 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 270 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C8 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 270 360 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C9 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 270 450 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C10 {BL [] 0 setdash 2 copy 2 copy moveto vpt 270 360 arc closepath fill
+	2 copy moveto
+	2 copy vpt 90 180 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C11 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 180 arc closepath fill
+	2 copy moveto
+	2 copy vpt 270 360 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C12 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 180 360 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C13 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 0 90 arc closepath fill
+	2 copy moveto
+	2 copy vpt 180 360 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/C14 {BL [] 0 setdash 2 copy moveto
+	2 copy vpt 90 360 arc closepath fill
+	vpt 0 360 arc} bind def
+/C15 {BL [] 0 setdash 2 copy vpt 0 360 arc closepath fill
+	vpt 0 360 arc closepath} bind def
+/Rec {newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto
+	neg 0 rlineto closepath} bind def
+/Square {dup Rec} bind def
+/Bsquare {vpt sub exch vpt sub exch vpt2 Square} bind def
+/S0 {BL [] 0 setdash 2 copy moveto 0 vpt rlineto BL Bsquare} bind def
+/S1 {BL [] 0 setdash 2 copy vpt Square fill Bsquare} bind def
+/S2 {BL [] 0 setdash 2 copy exch vpt sub exch vpt Square fill Bsquare} bind def
+/S3 {BL [] 0 setdash 2 copy exch vpt sub exch vpt2 vpt Rec fill Bsquare} bind def
+/S4 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def
+/S5 {BL [] 0 setdash 2 copy 2 copy vpt Square fill
+	exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def
+/S6 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill Bsquare} bind def
+/S7 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill
+	2 copy vpt Square fill Bsquare} bind def
+/S8 {BL [] 0 setdash 2 copy vpt sub vpt Square fill Bsquare} bind def
+/S9 {BL [] 0 setdash 2 copy vpt sub vpt vpt2 Rec fill Bsquare} bind def
+/S10 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt Square fill
+	Bsquare} bind def
+/S11 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt2 vpt Rec fill
+	Bsquare} bind def
+/S12 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill Bsquare} bind def
+/S13 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill
+	2 copy vpt Square fill Bsquare} bind def
+/S14 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill
+	2 copy exch vpt sub exch vpt Square fill Bsquare} bind def
+/S15 {BL [] 0 setdash 2 copy Bsquare fill Bsquare} bind def
+/D0 {gsave translate 45 rotate 0 0 S0 stroke grestore} bind def
+/D1 {gsave translate 45 rotate 0 0 S1 stroke grestore} bind def
+/D2 {gsave translate 45 rotate 0 0 S2 stroke grestore} bind def
+/D3 {gsave translate 45 rotate 0 0 S3 stroke grestore} bind def
+/D4 {gsave translate 45 rotate 0 0 S4 stroke grestore} bind def
+/D5 {gsave translate 45 rotate 0 0 S5 stroke grestore} bind def
+/D6 {gsave translate 45 rotate 0 0 S6 stroke grestore} bind def
+/D7 {gsave translate 45 rotate 0 0 S7 stroke grestore} bind def
+/D8 {gsave translate 45 rotate 0 0 S8 stroke grestore} bind def
+/D9 {gsave translate 45 rotate 0 0 S9 stroke grestore} bind def
+/D10 {gsave translate 45 rotate 0 0 S10 stroke grestore} bind def
+/D11 {gsave translate 45 rotate 0 0 S11 stroke grestore} bind def
+/D12 {gsave translate 45 rotate 0 0 S12 stroke grestore} bind def
+/D13 {gsave translate 45 rotate 0 0 S13 stroke grestore} bind def
+/D14 {gsave translate 45 rotate 0 0 S14 stroke grestore} bind def
+/D15 {gsave translate 45 rotate 0 0 S15 stroke grestore} bind def
+/DiaE {stroke [] 0 setdash vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V closepath stroke} def
+/BoxE {stroke [] 0 setdash exch hpt sub exch vpt add M
+  0 vpt2 neg V hpt2 0 V 0 vpt2 V
+  hpt2 neg 0 V closepath stroke} def
+/TriUE {stroke [] 0 setdash vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V closepath stroke} def
+/TriDE {stroke [] 0 setdash vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V closepath stroke} def
+/PentE {stroke [] 0 setdash gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  closepath stroke grestore} def
+/CircE {stroke [] 0 setdash 
+  hpt 0 360 arc stroke} def
+/Opaque {gsave closepath 1 setgray fill grestore 0 setgray closepath} def
+/DiaW {stroke [] 0 setdash vpt add M
+  hpt neg vpt neg V hpt vpt neg V
+  hpt vpt V hpt neg vpt V Opaque stroke} def
+/BoxW {stroke [] 0 setdash exch hpt sub exch vpt add M
+  0 vpt2 neg V hpt2 0 V 0 vpt2 V
+  hpt2 neg 0 V Opaque stroke} def
+/TriUW {stroke [] 0 setdash vpt 1.12 mul add M
+  hpt neg vpt -1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt 1.62 mul V Opaque stroke} def
+/TriDW {stroke [] 0 setdash vpt 1.12 mul sub M
+  hpt neg vpt 1.62 mul V
+  hpt 2 mul 0 V
+  hpt neg vpt -1.62 mul V Opaque stroke} def
+/PentW {stroke [] 0 setdash gsave
+  translate 0 hpt M 4 {72 rotate 0 hpt L} repeat
+  Opaque stroke grestore} def
+/CircW {stroke [] 0 setdash 
+  hpt 0 360 arc Opaque stroke} def
+/BoxFill {gsave Rec 1 setgray fill grestore} def
+/Density {
+  /Fillden exch def
+  currentrgbcolor
+  /ColB exch def /ColG exch def /ColR exch def
+  /ColR ColR Fillden mul Fillden sub 1 add def
+  /ColG ColG Fillden mul Fillden sub 1 add def
+  /ColB ColB Fillden mul Fillden sub 1 add def
+  ColR ColG ColB setrgbcolor} def
+/BoxColFill {gsave Rec PolyFill} def
+/PolyFill {gsave Density fill grestore grestore} def
+/h {rlineto rlineto rlineto gsave fill grestore} bind def
+%
+% PostScript Level 1 Pattern Fill routine for rectangles
+% Usage: x y w h s a XX PatternFill
+%	x,y = lower left corner of box to be filled
+%	w,h = width and height of box
+%	  a = angle in degrees between lines and x-axis
+%	 XX = 0/1 for no/yes cross-hatch
+%
+/PatternFill {gsave /PFa [ 9 2 roll ] def
+  PFa 0 get PFa 2 get 2 div add PFa 1 get PFa 3 get 2 div add translate
+  PFa 2 get -2 div PFa 3 get -2 div PFa 2 get PFa 3 get Rec
+  gsave 1 setgray fill grestore clip
+  currentlinewidth 0.5 mul setlinewidth
+  /PFs PFa 2 get dup mul PFa 3 get dup mul add sqrt def
+  0 0 M PFa 5 get rotate PFs -2 div dup translate
+  0 1 PFs PFa 4 get div 1 add floor cvi
+	{PFa 4 get mul 0 M 0 PFs V} for
+  0 PFa 6 get ne {
+	0 1 PFs PFa 4 get div 1 add floor cvi
+	{PFa 4 get mul 0 2 1 roll M PFs 0 V} for
+ } if
+  stroke grestore} def
+%
+/languagelevel where
+ {pop languagelevel} {1} ifelse
+ 2 lt
+	{/InterpretLevel1 true def}
+	{/InterpretLevel1 Level1 def}
+ ifelse
+%
+% PostScript level 2 pattern fill definitions
+%
+/Level2PatternFill {
+/Tile8x8 {/PaintType 2 /PatternType 1 /TilingType 1 /BBox [0 0 8 8] /XStep 8 /YStep 8}
+	bind def
+/KeepColor {currentrgbcolor [/Pattern /DeviceRGB] setcolorspace} bind def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke} 
+>> matrix makepattern
+/Pat1 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke
+	0 4 M 4 8 L 8 4 L 4 0 L 0 4 L stroke}
+>> matrix makepattern
+/Pat2 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop 0 0 M 0 8 L
+	8 8 L 8 0 L 0 0 L fill}
+>> matrix makepattern
+/Pat3 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop -4 8 M 8 -4 L
+	0 12 M 12 0 L stroke}
+>> matrix makepattern
+/Pat4 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop -4 0 M 8 12 L
+	0 -4 M 12 8 L stroke}
+>> matrix makepattern
+/Pat5 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop -2 8 M 4 -4 L
+	0 12 M 8 -4 L 4 12 M 10 0 L stroke}
+>> matrix makepattern
+/Pat6 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop -2 0 M 4 12 L
+	0 -4 M 8 12 L 4 -4 M 10 8 L stroke}
+>> matrix makepattern
+/Pat7 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop 8 -2 M -4 4 L
+	12 0 M -4 8 L 12 4 M 0 10 L stroke}
+>> matrix makepattern
+/Pat8 exch def
+<< Tile8x8
+ /PaintProc {0.5 setlinewidth pop 0 -2 M 12 4 L
+	-4 0 M 12 8 L -4 4 M 8 10 L stroke}
+>> matrix makepattern
+/Pat9 exch def
+/Pattern1 {PatternBgnd KeepColor Pat1 setpattern} bind def
+/Pattern2 {PatternBgnd KeepColor Pat2 setpattern} bind def
+/Pattern3 {PatternBgnd KeepColor Pat3 setpattern} bind def
+/Pattern4 {PatternBgnd KeepColor Landscape {Pat5} {Pat4} ifelse setpattern} bind def
+/Pattern5 {PatternBgnd KeepColor Landscape {Pat4} {Pat5} ifelse setpattern} bind def
+/Pattern6 {PatternBgnd KeepColor Landscape {Pat9} {Pat6} ifelse setpattern} bind def
+/Pattern7 {PatternBgnd KeepColor Landscape {Pat8} {Pat7} ifelse setpattern} bind def
+} def
+%
+%
+%End of PostScript Level 2 code
+%
+/PatternBgnd {
+  TransparentPatterns {} {gsave 1 setgray fill grestore} ifelse
+} def
+%
+% Substitute for Level 2 pattern fill codes with
+% grayscale if Level 2 support is not selected.
+%
+/Level1PatternFill {
+/Pattern1 {0.250 Density} bind def
+/Pattern2 {0.500 Density} bind def
+/Pattern3 {0.750 Density} bind def
+/Pattern4 {0.125 Density} bind def
+/Pattern5 {0.375 Density} bind def
+/Pattern6 {0.625 Density} bind def
+/Pattern7 {0.875 Density} bind def
+} def
+%
+% Now test for support of Level 2 code
+%
+Level1 {Level1PatternFill} {Level2PatternFill} ifelse
+%
+/Symbol-Oblique /Symbol findfont [1 0 .167 1 0 0] makefont
+dup length dict begin {1 index /FID eq {pop pop} {def} ifelse} forall
+currentdict end definefont pop
+/MFshow {
+   { dup 5 get 3 ge
+     { 5 get 3 eq {gsave} {grestore} ifelse }
+     {dup dup 0 get findfont exch 1 get scalefont setfont
+     [ currentpoint ] exch dup 2 get 0 exch R dup 5 get 2 ne {dup dup 6
+     get exch 4 get {show} {stringwidth pop 0 R} ifelse }if dup 5 get 0 eq
+     {dup 3 get {2 get neg 0 exch R pop} {pop aload pop M} ifelse} {dup 5
+     get 1 eq {dup 2 get exch dup 3 get exch 6 get stringwidth pop -2 div
+     dup 0 R} {dup 6 get stringwidth pop -2 div 0 R 6 get
+     show 2 index {aload pop M neg 3 -1 roll neg R pop pop} {pop pop pop
+     pop aload pop M} ifelse }ifelse }ifelse }
+     ifelse }
+   forall} bind def
+/MFwidth {0 exch { dup 5 get 3 ge { 5 get 3 eq { 0 } { pop } ifelse }
+ {dup 3 get{dup dup 0 get findfont exch 1 get scalefont setfont
+     6 get stringwidth pop add} {pop} ifelse} ifelse} forall} bind def
+/MLshow { currentpoint stroke M
+  0 exch R
+  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def
+/MRshow { currentpoint stroke M
+  exch dup MFwidth neg 3 -1 roll R
+  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def
+/MCshow { currentpoint stroke M
+  exch dup MFwidth -2 div 3 -1 roll R
+  Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def
+/XYsave    { [( ) 1 2 true false 3 ()] } bind def
+/XYrestore { [( ) 1 2 true false 4 ()] } bind def
+end
+%%EndProlog
+%%Page: 1 1
+gnudict begin
+gsave
+50 50 translate
+0.100 0.100 scale
+0 setgray
+newpath
+(Helvetica) findfont 140 scalefont setfont
+1.000 UL
+LTb
+714 420 M
+63 0 V
+4025 0 R
+-63 0 V
+stroke
+630 420 M
+[ [(Helvetica) 140.0 0.0 true true 0 ( 0)]
+] -46.7 MRshow
+1.000 UL
+LTb
+714 1177 M
+63 0 V
+4025 0 R
+-63 0 V
+stroke
+630 1177 M
+[ [(Helvetica) 140.0 0.0 true true 0 ( 20)]
+] -46.7 MRshow
+1.000 UL
+LTb
+714 1934 M
+63 0 V
+4025 0 R
+-63 0 V
+stroke
+630 1934 M
+[ [(Helvetica) 140.0 0.0 true true 0 ( 40)]
+] -46.7 MRshow
+1.000 UL
+LTb
+714 2691 M
+63 0 V
+4025 0 R
+-63 0 V
+stroke
+630 2691 M
+[ [(Helvetica) 140.0 0.0 true true 0 ( 60)]
+] -46.7 MRshow
+1.000 UL
+LTb
+714 3448 M
+63 0 V
+4025 0 R
+-63 0 V
+stroke
+630 3448 M
+[ [(Helvetica) 140.0 0.0 true true 0 ( 80)]
+] -46.7 MRshow
+1.000 UL
+LTb
+714 4205 M
+63 0 V
+4025 0 R
+-63 0 V
+stroke
+630 4205 M
+[ [(Helvetica) 140.0 0.0 true true 0 ( 100)]
+] -46.7 MRshow
+1.000 UL
+LTb
+714 420 M
+0 63 V
+0 4101 R
+0 -63 V
+stroke
+714 280 M
+[ [(Helvetica) 140.0 0.0 true true 0 ( 0)]
+] -46.7 MCshow
+1.000 UL
+LTb
+1736 420 M
+0 63 V
+0 4101 R
+0 -63 V
+stroke
+1736 280 M
+[ [(Helvetica) 140.0 0.0 true true 0 ( 50)]
+] -46.7 MCshow
+1.000 UL
+LTb
+2758 420 M
+0 63 V
+0 4101 R
+0 -63 V
+stroke
+2758 280 M
+[ [(Helvetica) 140.0 0.0 true true 0 ( 100)]
+] -46.7 MCshow
+1.000 UL
+LTb
+3780 420 M
+0 63 V
+0 4101 R
+0 -63 V
+stroke
+3780 280 M
+[ [(Helvetica) 140.0 0.0 true true 0 ( 150)]
+] -46.7 MCshow
+1.000 UL
+LTb
+4802 420 M
+0 63 V
+0 4101 R
+0 -63 V
+stroke
+4802 280 M
+[ [(Helvetica) 140.0 0.0 true true 0 ( 200)]
+] -46.7 MCshow
+1.000 UL
+LTb
+1.000 UL
+LTb
+714 4584 N
+714 420 L
+4088 0 V
+0 4164 V
+-4088 0 V
+Z stroke
+LCb setrgbcolor
+140 2502 M
+currentpoint gsave translate 90 rotate 0 0 moveto
+[ [(Helvetica) 140.0 0.0 true true 0 (% Packet Loss --- average of 5 trials per distance)]
+] -46.7 MCshow
+grestore
+LTb
+LCb setrgbcolor
+2758 70 M
+[ [(Helvetica) 140.0 0.0 true true 0 (Distance \(m\))]
+] -46.7 MCshow
+LTb
+1.000 UP
+1.000 UL
+LTb
+1.000 UL
+LT0
+LTb
+4151 4451 M
+[ [(Helvetica) 140.0 0.0 true true 0 (WiFi Defaults)]
+] -46.7 MRshow
+LT0
+4235 4451 M
+399 0 V
+1225 420 M
+511 0 V
+511 0 V
+511 0 V
+511 0 V
+409 136 V
+41 121 V
+61 -68 V
+41 288 V
+61 295 V
+41 424 V
+61 560 V
+41 470 V
+62 484 V
+40 356 V
+62 583 V
+41 114 V
+61 22 V
+41 0 V
+61 -22 V
+stroke
+LTb
+714 4584 N
+714 420 L
+4088 0 V
+0 4164 V
+-4088 0 V
+Z stroke
+1.000 UP
+1.000 UL
+LTb
+stroke
+grestore
+end
+showpage
+%%Trailer
+%%DocumentFonts: Helvetica
+%%Pages: 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/stats/wifi-example-apps.cc	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,330 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Joe Kopena <tjkopena@cs.drexel.edu>
+ *
+ * These applications are used in the WiFi Distance Test experiment,
+ * described and implemented in test02.cc.  That file should be in the
+ * same place as this file.  The applications have two very simple
+ * jobs, they just generate and receive packets.  We could use the
+ * standard Application classes included in the NS-3 distribution.
+ * These have been written just to change the behavior a little, and
+ * provide more examples.
+ *
+ */
+
+#include <ostream>
+
+#include "ns3/core-module.h"
+#include "ns3/common-module.h"
+#include "ns3/simulator-module.h"
+#include "ns3/node-module.h"
+#include "ns3/internet-stack-module.h"
+
+#include "ns3/stats-module.h"
+
+#include "wifi-example-apps.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("WiFiDistanceApps");
+
+TypeId
+Sender::GetTypeId(void)
+{
+  static TypeId tid = TypeId ("Sender")
+    .SetParent<Application> ()
+    .AddConstructor<Sender> ()
+    .AddAttribute ("PacketSize", "The size of packets transmitted.",
+                   UintegerValue(64),
+                   MakeUintegerAccessor(&Sender::m_pktSize),
+                   MakeUintegerChecker<uint32_t>(1))
+    .AddAttribute("Destination", "Target host address.",
+                  Ipv4AddressValue("255.255.255.255"),
+                  MakeIpv4AddressAccessor(&Sender::m_destAddr),
+                  MakeIpv4AddressChecker())
+    .AddAttribute("Port", "Destination app port.",
+                  UintegerValue(1603),
+                  MakeUintegerAccessor(&Sender::m_destPort),
+                  MakeUintegerChecker<uint32_t>())
+    .AddAttribute("NumPackets", "Total number of packets to send.",
+                  UintegerValue(30),
+                  MakeUintegerAccessor(&Sender::m_numPkts),
+                  MakeUintegerChecker<uint32_t>(1))
+    .AddAttribute ("Interval", "Delay between transmissions.",
+                   RandomVariableValue(ConstantVariable(0.5)),
+                   MakeRandomVariableAccessor(&Sender::m_interval),
+                   MakeRandomVariableChecker())
+    .AddTraceSource ("Tx", "A new packet is created and is sent",
+                     MakeTraceSourceAccessor (&Sender::m_txTrace))
+    ;
+  return tid;
+}
+
+
+Sender::Sender()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_socket = 0;
+}
+
+Sender::~Sender()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+Sender::DoDispose (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  m_socket = 0;
+  // chain up
+  Application::DoDispose ();
+}
+
+void Sender::StartApplication()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  if (m_socket == 0) {
+      Ptr<SocketFactory> socketFactory = GetNode()->GetObject<SocketFactory>
+        (UdpSocketFactory::GetTypeId());
+      m_socket = socketFactory->CreateSocket ();
+      m_socket->Bind ();
+  }
+
+  m_count = 0;
+
+  Simulator::Cancel(m_sendEvent);
+  m_sendEvent = Simulator::ScheduleNow(&Sender::SendPacket, this);
+
+  // end Sender::StartApplication
+}
+
+void Sender::StopApplication()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Simulator::Cancel(m_sendEvent);
+  // end Sender::StopApplication
+}
+  
+void Sender::SendPacket()
+{
+  // NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_INFO("Sending packet at " << Simulator::Now() << " to " <<
+              m_destAddr);
+
+  Ptr<Packet> packet = Create<Packet>(m_pktSize);
+
+  TimestampTag timestamp;
+  timestamp.SetTimestamp(Simulator::Now());
+  packet->AddTag(timestamp);
+
+  // Could connect the socket since the address never changes; using SendTo
+  // here simply because all of the standard apps do not.
+  m_socket->SendTo(packet, 0, InetSocketAddress(m_destAddr, m_destPort));
+
+  // Report the event to the trace.
+  m_txTrace(packet);
+
+  if (++m_count < m_numPkts) {
+    m_sendEvent = Simulator::Schedule(Seconds(m_interval.GetValue()),
+                                      &Sender::SendPacket, this);
+  }
+
+  // end Sender::SendPacket
+}
+
+
+
+
+//----------------------------------------------------------------------
+//-- Receiver
+//------------------------------------------------------
+TypeId
+Receiver::GetTypeId(void)
+{
+  static TypeId tid = TypeId ("Receiver")
+    .SetParent<Application> ()
+    .AddConstructor<Receiver> ()
+    .AddAttribute("Port", "Listening port.",
+                  UintegerValue(1603),
+                  MakeUintegerAccessor(&Receiver::m_port),
+                  MakeUintegerChecker<uint32_t>())
+    ;
+  return tid;
+}
+
+Receiver::Receiver() :
+  m_calc(0),
+  m_delay(0)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_socket = 0;
+}
+
+Receiver::~Receiver()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+Receiver::DoDispose (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  m_socket = 0;
+  // chain up
+  Application::DoDispose ();
+}
+
+void
+Receiver::StartApplication()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  if (m_socket == 0) {
+      Ptr<SocketFactory> socketFactory = GetNode()->GetObject<SocketFactory>
+        (UdpSocketFactory::GetTypeId());
+      m_socket = socketFactory->CreateSocket();
+      InetSocketAddress local = 
+        InetSocketAddress(Ipv4Address::GetAny(), m_port);
+      m_socket->Bind(local);
+  }
+
+  m_socket->SetRecvCallback(MakeCallback(&Receiver::Receive, this));
+
+  // end Receiver::StartApplication
+}
+
+void
+Receiver::StopApplication()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  if (m_socket != 0) {
+      m_socket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket> > ());
+  }
+
+  // end Receiver::StopApplication
+}
+
+void
+Receiver::SetCounter(Ptr<CounterCalculator<> > calc)
+{
+  m_calc = calc;
+  // end Receiver::SetCounter
+}
+void
+Receiver::SetDelayTracker(Ptr<TimeMinMaxAvgTotalCalculator> delay)
+{
+  m_delay = delay;
+  // end Receiver::SetDelayTracker
+}
+
+void
+Receiver::Receive(Ptr<Socket> socket)
+{
+  // NS_LOG_FUNCTION (this << socket << packet << from);
+
+  Ptr<Packet> packet;
+  Address from;
+  while (packet = socket->RecvFrom(from)) {
+    if (InetSocketAddress::IsMatchingType (from)) {
+      InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
+      NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " << 
+                   address.GetIpv4());
+    }
+
+    TimestampTag timestamp;
+    packet->FindFirstMatchingTag(timestamp);
+    Time tx = timestamp.GetTimestamp();
+
+    if (m_delay != 0) {
+      m_delay->Update(Simulator::Now() - tx);
+    }
+
+    if (m_calc != 0) {
+      m_calc->Update();
+    }
+
+    // end receiving packets
+  }
+
+  // end Receiver::Receive
+}
+
+
+
+
+//----------------------------------------------------------------------
+//-- TimestampTag
+//------------------------------------------------------
+TypeId 
+TimestampTag::GetTypeId(void)
+{
+  static TypeId tid = TypeId ("TimestampTag")
+    .SetParent<Tag> ()
+    .AddConstructor<TimestampTag> ()
+    .AddAttribute ("Timestamp",
+                   "Some momentous point in time!",
+                   EmptyAttributeValue(),
+                   MakeTimeAccessor(&TimestampTag::GetTimestamp),
+                   MakeTimeChecker())
+    ;
+  return tid;
+}
+TypeId 
+TimestampTag::GetInstanceTypeId(void) const
+{
+  return GetTypeId ();
+}
+
+uint32_t 
+TimestampTag::GetSerializedSize (void) const
+{
+  return 8;
+}
+void 
+TimestampTag::Serialize (TagBuffer i) const
+{
+  int64_t t = m_timestamp.GetNanoSeconds();
+  i.Write((const uint8_t *)&t, 8);
+}
+void 
+TimestampTag::Deserialize (TagBuffer i)
+{
+  int64_t t;
+  i.Read((uint8_t *)&t, 8);
+  m_timestamp = NanoSeconds(t);
+}
+
+void
+TimestampTag::SetTimestamp(Time time)
+{
+  m_timestamp = time;
+}
+Time
+TimestampTag::GetTimestamp(void) const
+{
+  return m_timestamp;
+}
+
+void 
+TimestampTag::Print(std::ostream &os) const
+{
+  os << "t=" << m_timestamp;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/stats/wifi-example-apps.h	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,126 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Joe Kopena <tjkopena@cs.drexel.edu>
+ *
+ * These applications are used in the WiFi Distance Test experiment,
+ * described and implemented in test02.cc.  That file should be in the
+ * same place as this file.  The applications have two very simple
+ * jobs, they just generate and receive packets.  We could use the
+ * standard Application classes included in the NS-3 distribution.
+ * These have been written just to change the behavior a little, and
+ * provide more examples.
+ *
+ */
+
+// #define NS3_LOG_ENABLE // Now defined by Makefile
+
+#include "ns3/core-module.h"
+#include "ns3/common-module.h"
+#include "ns3/application.h"
+
+#include "ns3/stats-module.h"
+
+using namespace ns3;
+
+//----------------------------------------------------------------------
+//------------------------------------------------------
+class Sender: public Application {
+public:
+  static TypeId GetTypeId(void);
+  Sender();
+  virtual ~Sender();
+
+protected:
+  virtual void DoDispose(void);
+
+private:
+  virtual void StartApplication(void);
+  virtual void StopApplication(void);
+
+  void SendPacket();
+
+  uint32_t        m_pktSize;
+  Ipv4Address     m_destAddr;
+  uint32_t        m_destPort;
+  RandomVariable  m_interval;
+  uint32_t        m_numPkts;
+
+  Ptr<Socket>     m_socket;
+  EventId         m_sendEvent;
+
+  TracedCallback<Ptr<const Packet> > m_txTrace;
+
+  uint32_t        m_count;
+
+  // end class Sender
+};
+
+
+
+
+//------------------------------------------------------
+class Receiver: public Application {
+public:
+  static TypeId GetTypeId(void);
+  Receiver();
+  virtual ~Receiver();
+
+  void SetCounter(Ptr<CounterCalculator<> > calc);
+  void SetDelayTracker(Ptr<TimeMinMaxAvgTotalCalculator> delay);
+
+protected:
+  virtual void DoDispose(void);
+
+private:
+  virtual void StartApplication(void);
+  virtual void StopApplication(void);
+
+  void Receive(Ptr<Socket> socket);
+
+  Ptr<Socket>     m_socket;
+
+  uint32_t        m_port;
+
+  Ptr<CounterCalculator<> > m_calc;
+  Ptr<TimeMinMaxAvgTotalCalculator> m_delay;
+
+  // end class Receiver
+};
+
+
+
+
+//------------------------------------------------------
+class TimestampTag : public Tag {
+public:
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (TagBuffer i) const;
+  virtual void Deserialize (TagBuffer i);
+  
+  // these are our accessors to our tag structure
+  void SetTimestamp(Time time);
+  Time GetTimestamp(void) const;
+
+  void Print(std::ostream &os) const;
+
+private:
+  Time m_timestamp;
+
+  // end class TimestampTag
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/stats/wifi-example-db.sh	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+DISTANCES="25 50 75 100 125 145 147 150 152 155 157 160 162 165 167 170 172 175 177 180"
+TRIALS="1 2 3 4 5"
+
+echo WiFi Experiment Example
+
+pCheck=`which sqlite3`
+if [ -z "$pCheck" ]
+then
+  echo "ERROR: This script requires sqlite3 (wifi-example-sim does not)."
+  exit 255
+fi
+
+pCheck=`which gnuplot`
+if [ -z "$pCheck" ]
+then
+  echo "ERROR: This script requires gnuplot (wifi-example-sim does not)."
+  exit 255
+fi
+
+pCheck=`which sed`
+if [ -z "$pCheck" ]
+then
+  echo "ERROR: This script requires sed (wifi-example-sim does not)."
+  exit 255
+fi
+
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:bin/
+
+if [ -e ../../data.db ]
+then
+  echo "Kill data.db? (y/n)"
+  read ANS
+  if [ "$ANS" = "yes" -o "$ANS" = "y" ]
+  then
+    echo Deleting database
+    rm ../../data.db
+  fi
+fi
+
+for trial in $TRIALS
+do
+  for distance in $DISTANCES
+  do
+    echo Trial $trial, distance $distance
+    ../../waf --run "wifi-example-sim --format=db --distance=$distance --run=run-$distance-$trial"
+  done
+done
+
+#
+#Another SQL command which just collects raw numbers of frames receved.
+#
+#CMD="select Experiments.input,avg(Singletons.value) \
+#    from Singletons,Experiments \
+#    where Singletons.run = Experiments.run AND \
+#          Singletons.name='wifi-rx-frames' \
+#    group by Experiments.input \
+#    order by abs(Experiments.input) ASC;"
+
+mv ../../data.db .
+
+CMD="select exp.input,avg(100-((rx.value*100)/tx.value)) \
+    from Singletons rx, Singletons tx, Experiments exp \
+    where rx.run = tx.run AND \
+          rx.run = exp.run AND \
+          rx.name='receiver-rx-packets' AND \
+          tx.name='sender-tx-packets' \
+    group by exp.input \
+    order by abs(exp.input) ASC;"
+
+sqlite3 -noheader data.db "$CMD" > wifi-default.data
+sed -i "s/|/   /" wifi-default.data
+gnuplot wifi-example.gnuplot
+
+echo "Done; data in wifi-default.data, plot in wifi-default.eps"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/stats/wifi-example-sim.cc	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,318 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Joe Kopena <tjkopena@cs.drexel.edu>
+ *
+ * This program conducts a simple experiment: It places two nodes at a
+ * parameterized distance apart.  One node generates packets and the
+ * other node receives.  The stat framework collects data on packet
+ * loss.  Outside of this program, a control script uses that data to
+ * produce graphs presenting performance at the varying distances.
+ * This isn't a typical simulation but is a common "experiment"
+ * performed in real life and serves as an accessible exemplar for the
+ * stat framework.  It also gives some intuition on the behavior and
+ * basic reasonability of the NS-3 WiFi models.
+ *
+ * Applications used by this program are in test02-apps.h and
+ * test02-apps.cc, which should be in the same place as this file.
+ * 
+ */
+
+// #define NS3_LOG_ENABLE // Now defined by Makefile
+
+#include <sstream>
+
+#include "ns3/core-module.h"
+#include "ns3/common-module.h"
+#include "ns3/node-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/wifi-module.h"
+
+#include "ns3/stats-module.h"
+
+#include "wifi-example-apps.h"
+
+using namespace ns3;
+using namespace std;
+
+NS_LOG_COMPONENT_DEFINE ("WiFiDistanceExperiment");
+
+
+
+
+void TxCallback(Ptr<CounterCalculator<uint32_t> > datac,
+                std::string path, Ptr<const Packet> packet,
+                Mac48Address realto) {
+  NS_LOG_INFO("Sent frame to " << realto << "; counted in " <<
+              datac->GetKey());
+  datac->Update();
+  // end TxCallback
+}
+
+
+
+
+//----------------------------------------------------------------------
+//-- main
+//----------------------------------------------
+int main(int argc, char *argv[]) {
+
+  double distance = 50.0;
+  string format("omnet");
+
+  string experiment("wifi-distance-test");
+  string strategy("wifi-default");
+  string input;
+  string runID;
+
+  {
+    stringstream sstr;
+    sstr << "run-" << time(NULL);
+    runID = sstr.str();
+  }
+
+  // Set up command line parameters used to control the experiment.
+  CommandLine cmd;
+  cmd.AddValue("distance", "Distance apart to place nodes (in meters).",
+               distance);
+  cmd.AddValue("format", "Format to use for data output.",
+               format);
+  cmd.AddValue("experiment", "Identifier for experiment.",
+               experiment);
+  cmd.AddValue("strategy", "Identifier for strategy.",
+               strategy);
+  cmd.AddValue("run", "Identifier for run.",
+               runID);
+  cmd.Parse (argc, argv);
+
+  if (format != "omnet" && format != "db") {
+    NS_LOG_ERROR("Unknown output format '" << format << "'");
+    return -1;
+  }
+
+  #ifndef STATS_HAS_SQLITE3
+  if (format == "db") {
+      NS_LOG_ERROR("sqlite support not compiled in.");
+      return -1;
+  }
+  #endif
+
+  {
+  stringstream sstr("");
+  sstr << distance;
+  input = sstr.str();
+  }
+
+
+
+
+  //------------------------------------------------------------
+  //-- Create nodes and network stacks
+  //--------------------------------------------
+  NS_LOG_INFO("Creating nodes.");
+  NodeContainer nodes;
+  nodes.Create(2);
+
+  NS_LOG_INFO("Installing WiFi and Internet stack.");
+  WifiHelper wifi;
+  wifi.SetMac("ns3::AdhocWifiMac");
+  wifi.SetPhy("ns3::WifiPhy");
+  NetDeviceContainer nodeDevices = wifi.Install(nodes);
+
+  InternetStackHelper internet;
+  internet.Install(nodes);
+  Ipv4AddressHelper ipAddrs;
+  ipAddrs.SetBase("192.168.0.0", "255.255.255.0");
+  ipAddrs.Assign(nodeDevices);
+
+
+
+
+  //------------------------------------------------------------
+  //-- Setup physical layout
+  //--------------------------------------------
+  NS_LOG_INFO("Installing static mobility; distance " << distance << " .");
+  MobilityHelper mobility;
+  Ptr<ListPositionAllocator> positionAlloc =
+    CreateObject<ListPositionAllocator>();
+  positionAlloc->Add(Vector(0.0, 0.0, 0.0));
+  positionAlloc->Add(Vector(0.0, distance, 0.0));
+  mobility.SetPositionAllocator(positionAlloc);
+  mobility.Install(nodes);
+
+
+
+
+  //------------------------------------------------------------
+  //-- Create a custom traffic source and sink
+  //--------------------------------------------
+  NS_LOG_INFO ("Create traffic source & sink.");
+  Ptr<Node> appSource = NodeList::GetNode(0);  
+  Ptr<Sender> sender = CreateObject<Sender>();
+  appSource->AddApplication(sender);
+  sender->Start(Seconds(1));
+
+  Ptr<Node> appSink = NodeList::GetNode(1);  
+  Ptr<Receiver> receiver = CreateObject<Receiver>();
+  appSink->AddApplication(receiver);
+  receiver->Start(Seconds(0));
+
+  //  Config::Set("/NodeList/*/ApplicationList/*/$Sender/Destination",
+  //              Ipv4AddressValue("192.168.0.2"));
+
+
+
+
+  //------------------------------------------------------------
+  //-- Setup stats and data collection
+  //--------------------------------------------
+
+  // Create a DataCollector object to hold information about this run.
+  DataCollector data;
+  data.DescribeRun(experiment,
+                   strategy,
+                   input,
+                   runID);
+
+  // Add any information we wish to record about this run.
+  data.AddMetadata("author", "tjkopena");
+
+
+  // Create a counter to track how many frames are generated.  Updates
+  // are triggered by the trace signal generated by the WiFi MAC model
+  // object.  Here we connect the counter to the signal via the simple
+  // TxCallback() glue function defined above.
+  Ptr<CounterCalculator<uint32_t> > totalTx =
+    CreateObject<CounterCalculator<uint32_t> >();
+  totalTx->SetKey("wifi-tx-frames");
+  Config::Connect("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Tx",
+                  MakeBoundCallback(&TxCallback, totalTx));
+  data.AddDataCalculator(totalTx);
+
+  // This is similar, but creates a counter to track how many frames
+  // are received.  Instead of our own glue function, this uses a
+  // method of an adapter class to connect a counter directly to the
+  // trace signal generated by the WiFi MAC.
+  Ptr<PacketCounterCalculator> totalRx =
+    CreateObject<PacketCounterCalculator>();
+  totalRx->SetKey("wifi-rx-frames");
+  Config::Connect("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/Rx",
+                  MakeCallback(&PacketCounterCalculator::FrameUpdate,
+                                    totalRx));
+  data.AddDataCalculator(totalRx);
+
+
+
+
+  // This counter tracks how many packets---as opposed to frames---are
+  // generated.  This is connected directly to a trace signal provided
+  // by our Sender class.
+  Ptr<PacketCounterCalculator> appTx =
+    CreateObject<PacketCounterCalculator>();
+  appTx->SetKey("sender-tx-packets");
+  Config::Connect("/NodeList/0/ApplicationList/*/$Sender/Tx",
+                  MakeCallback(&PacketCounterCalculator::PacketUpdate,
+                                    appTx));
+  data.AddDataCalculator(appTx);
+
+  // Here a counter for received packets is directly manipulated by
+  // one of the custom objects in our simulation, the Receiver
+  // Application.  The Receiver object is given a pointer to the
+  // counter and calls its Update() method whenever a packet arrives.
+  Ptr<CounterCalculator<> > appRx =
+    CreateObject<CounterCalculator<> >();
+  appRx->SetKey("receiver-rx-packets");
+  receiver->SetCounter(appRx);
+  data.AddDataCalculator(appRx);
+
+
+
+
+  /**
+   * Just to show this is here...
+   Ptr<MinMaxAvgTotalCalculator<uint32_t> > test = 
+   CreateObject<MinMaxAvgTotalCalculator<uint32_t> >();
+   test->SetKey("test-dc");
+   data.AddDataCalculator(test);
+
+   test->Update(4);
+   test->Update(8);
+   test->Update(24);
+   test->Update(12);
+  **/
+
+  // This DataCalculator connects directly to the transmit trace
+  // provided by our Sender Application.  It records some basic
+  // statistics about the sizes of the packets received (min, max,
+  // avg, total # bytes), although in this scenaro they're fixed.
+  Ptr<PacketSizeMinMaxAvgTotalCalculator> appTxPkts =
+    CreateObject<PacketSizeMinMaxAvgTotalCalculator>();
+  appTxPkts->SetKey("tx-pkt-size");
+  Config::Connect("/NodeList/0/ApplicationList/*/$Sender/Tx",
+                  MakeCallback
+                    (&PacketSizeMinMaxAvgTotalCalculator::PacketUpdate,
+                    appTxPkts));
+  data.AddDataCalculator(appTxPkts);
+
+
+  // Here we directly manipulate another DataCollector tracking min,
+  // max, total, and average propagation delays.  Check out the Sender
+  // and Receiver classes to see how packets are tagged with
+  // timestamps to do this.
+  Ptr<TimeMinMaxAvgTotalCalculator> delayStat =
+    CreateObject<TimeMinMaxAvgTotalCalculator>();
+  delayStat->SetKey("delay");
+  receiver->SetDelayTracker(delayStat);
+  data.AddDataCalculator(delayStat);
+
+
+
+
+  //------------------------------------------------------------
+  //-- Run the simulation
+  //--------------------------------------------
+  NS_LOG_INFO("Run Simulation.");
+  Simulator::Run();    
+  Simulator::Destroy();
+
+
+
+
+  //------------------------------------------------------------
+  //-- Generate statistics output.
+  //--------------------------------------------
+
+  // Pick an output writer based in the requested format.
+  Ptr<DataOutputInterface> output = 0;
+  if (format == "omnet") {
+    NS_LOG_INFO("Creating omnet formatted data output.");
+    output = CreateObject<OmnetDataOutput>();
+  } else if (format == "db") {
+    #ifdef STATS_HAS_SQLITE3
+      NS_LOG_INFO("Creating sqlite formatted data output.");
+      output = CreateObject<SqliteDataOutput>();
+    #endif
+  } else {
+    NS_LOG_ERROR("Unknown output format " << format);
+  }
+
+  // Finally, have that writer interrogate the DataCollector and save
+  // the results.
+  if (output != 0)
+    output->Output(data);
+
+  // end main
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/stats/wifi-example.gnuplot	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,13 @@
+set terminal postscript portrait enhanced lw 2 "Helvetica" 14
+
+set size 1.0, 0.66
+
+#-------------------------------------------------------
+set out "wifi-default.eps"
+#set title "Packet Loss Over Distance"
+set xlabel "Distance (m)"
+set xrange [0:200]
+set ylabel "% Packet Loss --- average of 5 trials per distance"
+set yrange [0:110]
+
+plot "wifi-default.data" with lines title "WiFi Defaults"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/stats/wscript	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,6 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    obj = bld.create_ns3_program('wifi-example-sim', ['stats'])
+    obj.source = ['wifi-example-sim.cc',
+                  'wifi-example-apps.cc']
--- a/examples/wscript	Fri Aug 29 14:56:24 2008 +0100
+++ b/examples/wscript	Fri Aug 29 13:22:09 2008 -0400
@@ -76,4 +76,4 @@
                                  ['core', 'simulator', 'mobility', 'wifi'])
     obj.source = 'wifi-ap.cc'
 
-
+    bld.add_subdirs('stats')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/basic-data-calculators.h	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,189 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Drexel University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Joe Kopena (tjkopena@cs.drexel.edu)
+ */
+
+#ifndef __BASIC_DATA_CALCULATORS_H__
+#define __BASIC_DATA_CALCULATORS_H__
+
+#include "data-calculator.h"
+#include "data-output-interface.h"
+
+namespace ns3 {
+
+  //------------------------------------------------------------
+  //--------------------------------------------
+  template <typename T  = uint32_t>
+  class MinMaxAvgTotalCalculator : public DataCalculator {
+  public:
+    MinMaxAvgTotalCalculator();
+    virtual ~MinMaxAvgTotalCalculator();
+
+    void Update(const T i);
+
+    virtual void Output(DataOutputCallback &callback) const;
+
+  protected:
+    virtual void DoDispose(void);
+
+    uint32_t m_count;
+    T m_total, m_min, m_max;
+
+    // end MinMaxAvgTotalCalculator
+  };
+
+  //----------------------------------------------
+  template <typename T>
+  MinMaxAvgTotalCalculator<T>::MinMaxAvgTotalCalculator()
+  {
+    m_count = 0;
+    m_total = 0;
+    m_min = ~0;
+    m_max = 0;
+  }
+
+  template <typename T>
+  MinMaxAvgTotalCalculator<T>::~MinMaxAvgTotalCalculator()
+  {
+  }
+  template <typename T>
+  void
+  MinMaxAvgTotalCalculator<T>::DoDispose(void)
+  {
+    DataCalculator::DoDispose();
+    // MinMaxAvgTotalCalculator::DoDispose
+  }
+
+  template <typename T>
+  void
+  MinMaxAvgTotalCalculator<T>::Update(const T i)
+  {
+    if (m_enabled) {
+      m_total += i;
+
+      if (i < m_min)
+        m_min = i;
+
+      if (i > m_max)
+        m_max = i;
+
+      m_count++;
+    }
+    // end MinMaxAvgTotalCalculator::Update
+  }
+  template <typename T>
+  void
+  MinMaxAvgTotalCalculator<T>::Output(DataOutputCallback &callback) const
+  {
+    callback.OutputSingleton(m_key, "count", m_count);
+    if (m_count > 0) {
+      callback.OutputSingleton(m_key, "total", m_total);
+      callback.OutputSingleton(m_key, "average", m_total/m_count);
+      callback.OutputSingleton(m_key, "max", m_max);
+      callback.OutputSingleton(m_key, "min", m_min);
+    }
+    // end MinMaxAvgTotalCalculator::Output
+  }
+
+
+
+
+  //------------------------------------------------------------
+  //--------------------------------------------
+  template <typename T  = uint32_t>
+  class CounterCalculator : public DataCalculator {
+  public:
+    CounterCalculator();
+    virtual ~CounterCalculator();
+
+    void Update();
+    void Update(const T i);
+
+    T GetCount() const;
+
+    virtual void Output(DataOutputCallback &callback) const;
+
+  protected:
+    virtual void DoDispose(void);
+
+    T m_count;
+
+    // end CounterCalculator
+  };
+
+
+  //--------------------------------------------
+  template <typename T>
+  CounterCalculator<T>::CounterCalculator() :
+    m_count(0)
+  {
+  }
+
+  template <typename T>
+  CounterCalculator<T>::~CounterCalculator()
+  {
+  }
+  template <typename T>
+  void
+  CounterCalculator<T>::DoDispose(void)
+  {
+    DataCalculator::DoDispose();
+    // CounterCalculator::DoDispose
+  }
+
+  template <typename T>
+  void
+  CounterCalculator<T>::Update()
+  {
+    if (m_enabled) {
+      m_count++;
+    }
+    // end CounterCalculator::Update
+  }
+
+  template <typename T>
+  void
+  CounterCalculator<T>::Update(const T i)
+  {
+    if (m_enabled) {
+      m_count += i;
+    }
+    // end CounterCalculator::Update
+  }
+
+  template <typename T>
+  T
+  CounterCalculator<T>::GetCount() const
+  {
+    return m_count;
+    // end CounterCalculator::GetCount
+  }
+
+  template <typename T>
+  void
+  CounterCalculator<T>::Output(DataOutputCallback &callback) const
+  {
+    callback.OutputSingleton(m_key, "count", m_count);
+    // end CounterCalculator::Output
+  }
+
+  // end namespace ns3
+};
+
+
+#endif // __BASIC_DATA_CALCULATORS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/data-calculator.cc	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,110 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Drexel University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Joe Kopena (tjkopena@cs.drexel.edu)
+ */
+
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+
+#include "data-calculator.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE("DataCalculator");
+
+
+//--------------------------------------------------------------
+//----------------------------------------------
+DataCalculator::DataCalculator() :
+  m_enabled(true)
+{
+  NS_LOG_FUNCTION_NOARGS();
+}
+
+DataCalculator::~DataCalculator()
+{
+  NS_LOG_FUNCTION_NOARGS();
+}
+
+void
+DataCalculator::DoDispose(void)
+{
+  NS_LOG_FUNCTION_NOARGS();
+
+  Simulator::Cancel(m_startEvent);
+  Simulator::Cancel(m_stopEvent);
+
+  Object::DoDispose();
+  // DataCalculator::DoDispose
+}
+
+//----------------------------------------------
+void
+DataCalculator::SetKey(const std::string key)
+{
+  m_key = key;
+  // end DataCalculator::SetKey
+}
+
+const std::string
+DataCalculator::GetKey() const
+{
+  return m_key;
+  // end DataCalculator::GetKey
+}
+
+//----------------------------------------------
+void
+DataCalculator::Enable()
+{
+  m_enabled = true;
+  // end DataCalculator::Enable
+}
+
+void
+DataCalculator::Disable()
+{
+  m_enabled = false;
+  // end DataCalculator::Disable
+}
+
+bool
+DataCalculator::GetEnabled() const
+{
+  return m_enabled;
+  // end DataCalculator::GetEnabled
+}
+
+//----------------------------------------------
+void
+DataCalculator::Start(const Time& startTime)
+{
+
+  m_startEvent = Simulator::Schedule(startTime,
+                                     &DataCalculator::Enable, this);
+
+  // end DataCalculator::Start
+}
+
+void
+DataCalculator::Stop(const Time& stopTime)
+{
+  m_stopEvent = Simulator::Schedule(stopTime,
+                                    &DataCalculator::Disable, this);
+  // end DataCalculator::Stop
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/data-calculator.h	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,70 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Drexel University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Joe Kopena (tjkopena@cs.drexel.edu)
+ */
+
+#ifndef __DATA_CALCULATOR_H__
+#define __DATA_CALCULATOR_H__
+
+#include "ns3/object.h"
+#include "ns3/nstime.h"
+#include "ns3/simulator.h"
+
+namespace ns3 {
+
+  class DataOutputCallback;
+
+  //------------------------------------------------------------
+  //--------------------------------------------
+  class DataCalculator : public Object {
+  public:
+    DataCalculator();
+    virtual ~DataCalculator();
+
+    bool GetEnabled() const;
+    void Enable();
+    void Disable();
+
+    void SetKey(const std::string key);
+    const std::string GetKey() const;
+
+    virtual void Start(const Time& startTime);
+    virtual void Stop(const Time& stopTime);
+
+    virtual void Output(DataOutputCallback &callback) const = 0;
+
+  protected:
+    bool m_enabled;  // Descendant classes *must* check & respect m_enabled!
+
+    std::string m_key;
+
+    virtual void DoDispose(void);
+
+  private:
+    EventId m_startEvent;
+    EventId m_stopEvent;
+
+    // end class DataCalculator
+  };
+
+
+  // end namespace ns3
+};
+
+
+#endif // __DATA_CALCULATOR_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/data-collector.cc	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,131 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Drexel University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Joe Kopena (tjkopena@cs.drexel.edu)
+ */
+
+#include "ns3/object.h"
+#include "ns3/log.h"
+
+#include "data-collector.h"
+#include "data-calculator.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE("DataCollector");
+
+//--------------------------------------------------------------
+//----------------------------------------------
+DataCollector::DataCollector() {
+  NS_LOG_FUNCTION_NOARGS();
+  // end DataCollector::DataCollector
+}
+
+DataCollector::~DataCollector() {
+  NS_LOG_FUNCTION_NOARGS();
+  // end DataCollector::~DataCollector
+}
+
+void DataCollector::DoDispose() {
+  NS_LOG_FUNCTION_NOARGS();
+
+  m_calcList.clear();
+  m_metadata.clear();
+
+  Object::DoDispose();
+  // end DataCollector::DoDispose
+}
+
+void
+DataCollector::DescribeRun(std::string experiment,
+                           std::string strategy,
+                           std::string input,
+                           std::string runID,
+                           std::string description)
+{
+
+  m_experimentLabel = experiment;
+  m_strategyLabel = strategy;
+  m_inputLabel = input;
+  m_runLabel = runID;
+  m_description = description;
+
+  // end DataCollector::DescribeRun
+}
+
+void
+DataCollector::AddDataCalculator(Ptr<DataCalculator> datac)
+{
+
+  m_calcList.push_back(datac);
+
+  // end DataCollector::AddDataCalculator
+}
+
+DataCalculatorList::iterator
+DataCollector::DataCalculatorBegin()
+{
+  return m_calcList.begin();
+  // end DataCollector::DataCalculatorBegin
+}
+DataCalculatorList::iterator
+DataCollector::DataCalculatorEnd()
+{
+  return m_calcList.end();
+  // end DataCollector::DataCalculatorEnd
+}
+
+void
+DataCollector::AddMetadata(std::string key, std::string value)
+{
+  std::pair<std::string, std::string> blob(key, value);
+  m_metadata.push_back(blob);
+  // end DataCollector::AddMetadata
+}
+void
+DataCollector::AddMetadata(std::string key, uint32_t value)
+{
+  std::stringstream st;
+  st << value;
+
+  std::pair<std::string, std::string> blob(key, st.str());
+  m_metadata.push_back(blob);
+  // end DataCollector::AddMetadata
+}
+void
+DataCollector::AddMetadata(std::string key, double value)
+{
+  std::stringstream st;
+  st << value;
+
+  std::pair<std::string, std::string> blob(key, st.str());
+  m_metadata.push_back(blob);
+  // end DataCollector::AddMetadata
+}
+
+MetadataList::iterator
+DataCollector::MetadataBegin()
+{
+  return m_metadata.begin();
+  // end DataCollector::MetadataBegin
+}
+MetadataList::iterator
+DataCollector::MetadataEnd()
+{
+  return m_metadata.end();
+  // end DataCollector::MetadataEnd
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/data-collector.h	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,84 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Drexel University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Joe Kopena (tjkopena@cs.drexel.edu)
+ */
+
+#ifndef __DATA_COLLECTOR_H__
+#define __DATA_COLLECTOR_H__
+
+#include <list>
+#include <string>
+
+#include "ns3/object.h"
+
+namespace ns3 {
+
+  class DataCalculator;
+
+  //------------------------------------------------------------
+  //--------------------------------------------
+  typedef std::list<Ptr<DataCalculator> > DataCalculatorList;
+  typedef std::list<std::pair<std::string, std::string> > MetadataList;
+
+  class DataCollector : public Object {
+  public:
+    DataCollector();
+    virtual ~DataCollector();
+
+    void DescribeRun(std::string experiment,
+                     std::string strategy,
+                     std::string input,
+                     std::string runID,
+                     std::string description = "");
+
+    std::string GetExperimentLabel() const { return m_experimentLabel; }
+    std::string GetStrategyLabel() const { return m_strategyLabel; }
+    std::string GetInputLabel() const { return m_inputLabel; }
+    std::string GetRunLabel() const { return m_runLabel; }
+    std::string GetDescription() const { return m_description; }
+
+    void AddMetadata(std::string key, std::string value);
+    void AddMetadata(std::string key, double value);
+    void AddMetadata(std::string key, uint32_t value);
+    MetadataList::iterator MetadataBegin();
+    MetadataList::iterator MetadataEnd();
+
+    void AddDataCalculator(Ptr<DataCalculator> datac);
+    DataCalculatorList::iterator DataCalculatorBegin();
+    DataCalculatorList::iterator DataCalculatorEnd();
+
+  protected:
+    virtual void DoDispose();
+
+  private:
+    std::string m_experimentLabel;
+    std::string m_strategyLabel;
+    std::string m_inputLabel;
+    std::string m_runLabel;
+    std::string m_description;
+
+    MetadataList m_metadata;
+    DataCalculatorList m_calcList;
+
+    // end class DataCollector
+  };
+
+  // end namespace ns3
+};
+
+#endif // __DATA_COLLECTOR_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/data-output-interface.cc	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,47 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Drexel University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Joe Kopena (tjkopena@cs.drexel.edu)
+ */
+
+#include "ns3/log.h"
+
+#include "data-output-interface.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE("DataOutputInterface");
+
+
+//--------------------------------------------------------------
+//----------------------------------------------
+DataOutputInterface::DataOutputInterface()
+{
+  NS_LOG_FUNCTION_NOARGS();
+}
+DataOutputInterface::~DataOutputInterface()
+{
+  NS_LOG_FUNCTION_NOARGS();
+}
+void
+DataOutputInterface::DoDispose()
+{
+  NS_LOG_FUNCTION_NOARGS();
+
+  Object::DoDispose();
+  // end DataOutputInterface::DoDispose
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/data-output-interface.h	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,76 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Drexel University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Joe Kopena (tjkopena@cs.drexel.edu)
+ */
+
+#ifndef __DATA_OUTPUT_INTERFACE_H__
+#define __DATA_OUTPUT_INTERFACE_H__
+
+#include "ns3/object.h"
+#include "ns3/nstime.h"
+
+namespace ns3 {
+
+  class DataCollector;
+
+  //------------------------------------------------------------
+  //--------------------------------------------
+  class DataOutputInterface : public Object {
+  public:
+    DataOutputInterface();
+    virtual ~DataOutputInterface();
+
+    virtual void Output(DataCollector &dc) = 0;
+
+  protected:
+    virtual void DoDispose();
+
+    // end class DataOutputInterface
+  };
+
+  class DataOutputCallback {
+  public:
+    virtual ~DataOutputCallback() {}
+
+    virtual void OutputSingleton(std::string key,
+                                 std::string variable,
+                                 int val) = 0;
+
+    virtual void OutputSingleton(std::string key,
+                                 std::string variable,
+                                 uint32_t val) = 0;
+
+    virtual void OutputSingleton(std::string key,
+                                 std::string variable,
+                                 double val) = 0;
+
+    virtual void OutputSingleton(std::string key,
+                                 std::string variable,
+                                 std::string val) = 0;
+
+    virtual void OutputSingleton(std::string key,
+                                 std::string variable,
+                                 Time val) = 0;
+    // end class DataOutputCallback
+  };
+
+  // end namespace ns3
+};
+
+
+#endif // __DATA_OUTPUT_INTERFACE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/omnet-data-output.cc	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,155 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Drexel University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Joe Kopena (tjkopena@cs.drexel.edu)
+ */
+
+#include <fstream>
+
+#include "ns3/log.h"
+#include "ns3/nstime.h"
+
+#include "data-collector.h"
+#include "data-calculator.h"
+#include "omnet-data-output.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE("OmnetDataOutput");
+
+
+//--------------------------------------------------------------
+//----------------------------------------------
+OmnetDataOutput::OmnetDataOutput() :
+  m_filePrefix("data")
+{
+  NS_LOG_FUNCTION_NOARGS();
+}
+OmnetDataOutput::~OmnetDataOutput()
+{
+  NS_LOG_FUNCTION_NOARGS();
+}
+void
+OmnetDataOutput::DoDispose()
+{
+  NS_LOG_FUNCTION_NOARGS();
+
+  DataOutputInterface::DoDispose();
+  // end OmnetDataOutput::DoDispose
+}
+
+void
+OmnetDataOutput::SetFilePrefix(const std::string prefix)
+{
+  m_filePrefix = prefix;
+}
+std::string
+OmnetDataOutput::GetFilePrefix() const
+{
+  return m_filePrefix;
+}
+
+//----------------------------------------------
+void
+OmnetDataOutput::Output(DataCollector &dc)
+{
+
+  std::ofstream scalarFile;
+  std::string fn = m_filePrefix + ".sca";
+  scalarFile.open(fn.c_str(), std::ios_base::app);
+
+  scalarFile << std::endl;
+  scalarFile << "run " << dc.GetRunLabel() << std::endl;
+  scalarFile << std::endl;
+  scalarFile << "attr experiment \"" << dc.GetExperimentLabel()
+            << "\"" << std::endl;
+  scalarFile << "attr strategy \"" << dc.GetStrategyLabel()
+            << "\"" << std::endl;
+  scalarFile << "attr input \"" << dc.GetInputLabel()
+            << "\"" << std::endl;
+  scalarFile << "attr description \"" << dc.GetDescription()
+            << "\"" << std::endl;
+  scalarFile << std::endl;
+
+  for (MetadataList::iterator i = dc.MetadataBegin();
+       i != dc.MetadataEnd(); i++) {
+    std::pair<std::string, std::string> blob = (*i);
+    scalarFile << "attr \"" << blob.first << "\" \"" << blob.second << "\""
+               << std::endl;
+  }
+
+  scalarFile << std::endl;
+
+  OmnetOutputCallback callback(&scalarFile);
+
+  for (DataCalculatorList::iterator i = dc.DataCalculatorBegin();
+       i != dc.DataCalculatorEnd(); i++) {
+    (*i)->Output(callback);
+  }
+
+  scalarFile << std::endl << std::endl;
+  scalarFile.close();
+
+  // end OmnetDataOutput::Output
+}
+
+OmnetDataOutput::OmnetOutputCallback::OmnetOutputCallback
+  (std::ostream *scalar) :
+  m_scalar(scalar)
+{
+}
+
+void
+OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string key,
+                                                      std::string variable,
+                                                      int val)
+{
+  (*m_scalar) << "scalar " << key << " " << variable << " " << val << std::endl;
+  // end OmnetDataOutput::OmnetOutputCallback::OutputSingleton
+}
+void
+OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string key,
+                                                      std::string variable,
+                                                      uint32_t val)
+{
+  (*m_scalar) << "scalar " << key << " " << variable << " " << val << std::endl;
+  // end OmnetDataOutput::OmnetOutputCallback::OutputSingleton
+}
+void
+OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string key,
+                                                      std::string variable,
+                                                      double val)
+{
+  (*m_scalar) << "scalar " << key << " " << variable << " " << val << std::endl;
+  // end OmnetDataOutput::OmnetOutputCallback::OutputSingleton
+}
+void
+OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string key,
+                                                      std::string variable,
+                                                      std::string val)
+{
+  (*m_scalar) << "scalar " << key << " " << variable << " " << val << std::endl;
+  // end OmnetDataOutput::OmnetOutputCallback::OutputSingleton
+}
+void
+OmnetDataOutput::OmnetOutputCallback::OutputSingleton(std::string key,
+                                                      std::string variable,
+                                                      Time val)
+{
+  (*m_scalar) << "scalar " << key << " " << variable << " " << val << std::endl;
+  // end OmnetDataOutput::OmnetOutputCallback::OutputSingleton
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/omnet-data-output.h	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,84 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Drexel University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Joe Kopena (tjkopena@cs.drexel.edu)
+ */
+
+#ifndef __OMNET_DATA_OUTPUT_H__
+#define __OMNET_DATA_OUTPUT_H__
+
+#include "ns3/nstime.h"
+
+#include "data-output-interface.h"
+
+namespace ns3 {
+
+
+  //------------------------------------------------------------
+  //--------------------------------------------
+  class OmnetDataOutput : public DataOutputInterface {
+  public:
+    OmnetDataOutput();
+    virtual ~OmnetDataOutput();
+
+    virtual void Output(DataCollector &dc);
+
+    void SetFilePrefix(const std::string prefix);
+    std::string GetFilePrefix() const;
+
+  protected:
+    virtual void DoDispose();
+
+  private:
+    class OmnetOutputCallback : public DataOutputCallback {
+    public:
+      OmnetOutputCallback(std::ostream *scalar);
+
+      void OutputSingleton(std::string key,
+                           std::string variable,
+                           int val);
+
+      void OutputSingleton(std::string key,
+                           std::string variable,
+                           uint32_t val);
+
+      void OutputSingleton(std::string key,
+                           std::string variable,
+                           double val);
+
+      void OutputSingleton(std::string key,
+                           std::string variable,
+                           std::string val);
+
+      void OutputSingleton(std::string key,
+                           std::string variable,
+                           Time val);
+
+    private:
+      std::ostream *m_scalar;
+      // end class OmnetOutputCallback
+    };
+
+    std::string m_filePrefix;
+    // end class OmnetDataOutput
+  };
+
+  // end namespace ns3
+};
+
+
+#endif // __OMNET_DATA_OUTPUT_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/packet-data-calculators.cc	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,118 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Drexel University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Joe Kopena (tjkopena@cs.drexel.edu)
+ */
+
+#include "ns3/log.h"
+#include "ns3/packet.h"
+#include "ns3/mac48-address.h"
+
+#include "basic-data-calculators.h"
+#include "packet-data-calculators.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE("PacketDataCalculators");
+
+
+//--------------------------------------------------------------
+//----------------------------------------------
+PacketCounterCalculator::PacketCounterCalculator()
+{
+  NS_LOG_FUNCTION_NOARGS();
+}
+
+PacketCounterCalculator::~PacketCounterCalculator()
+{
+  NS_LOG_FUNCTION_NOARGS();
+}
+void
+PacketCounterCalculator::DoDispose(void)
+{
+  NS_LOG_FUNCTION_NOARGS();
+
+  CounterCalculator<uint32_t>::DoDispose();
+  // PacketCounterCalculator::DoDispose
+}
+
+void
+PacketCounterCalculator::PacketUpdate(std::string path,
+                                      Ptr<const Packet> packet)
+{
+  NS_LOG_FUNCTION_NOARGS();
+
+  CounterCalculator<uint32_t>::Update();
+
+  // PacketCounterCalculator::Update
+}
+void
+PacketCounterCalculator::FrameUpdate(std::string path,
+                                     Ptr<const Packet> packet,
+                                     Mac48Address realto)
+{
+  NS_LOG_FUNCTION_NOARGS();
+
+  CounterCalculator<uint32_t>::Update();
+
+  // PacketCounterCalculator::Update
+}
+
+
+
+
+//--------------------------------------------------------------
+//----------------------------------------------
+PacketSizeMinMaxAvgTotalCalculator::PacketSizeMinMaxAvgTotalCalculator()
+{
+  NS_LOG_FUNCTION_NOARGS();
+}
+
+PacketSizeMinMaxAvgTotalCalculator::~PacketSizeMinMaxAvgTotalCalculator()
+{
+  NS_LOG_FUNCTION_NOARGS();
+}
+void
+PacketSizeMinMaxAvgTotalCalculator::DoDispose(void)
+{
+  NS_LOG_FUNCTION_NOARGS();
+
+  MinMaxAvgTotalCalculator<uint32_t>::DoDispose();
+  // end PacketSizeMinMaxAvgTotalCalculator::DoDispose
+}
+
+void
+PacketSizeMinMaxAvgTotalCalculator::PacketUpdate(std::string path,
+                                      Ptr<const Packet> packet)
+{
+  NS_LOG_FUNCTION_NOARGS();
+
+  MinMaxAvgTotalCalculator<uint32_t>::Update(packet->GetSize());
+
+  // end PacketSizeMinMaxAvgTotalCalculator::Update
+}
+void
+PacketSizeMinMaxAvgTotalCalculator::FrameUpdate(std::string path,
+                                     Ptr<const Packet> packet,
+                                     Mac48Address realto)
+{
+  NS_LOG_FUNCTION_NOARGS();
+
+  MinMaxAvgTotalCalculator<uint32_t>::Update(packet->GetSize());
+
+  // end PacketSizeMinMaxAvgTotalCalculator::Update
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/packet-data-calculators.h	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,68 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Drexel University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Joe Kopena (tjkopena@cs.drexel.edu)
+ */
+
+#ifndef __PACKET_DATA_CALCULATORS_H__
+#define __PACKET_DATA_CALCULATORS_H__
+
+#include "ns3/packet.h"
+#include "ns3/mac48-address.h"
+
+#include "data-calculator.h"
+
+namespace ns3 {
+
+  class PacketCounterCalculator : public CounterCalculator<uint32_t> {
+  public:
+    PacketCounterCalculator();
+    virtual ~PacketCounterCalculator();
+
+    void PacketUpdate(std::string path, Ptr<const Packet> packet);
+    void FrameUpdate(std::string path, Ptr<const Packet> packet,
+                     Mac48Address realto);
+
+  protected:
+    virtual void DoDispose(void);
+
+    // end class PacketCounterCalculator
+  };
+
+
+  class PacketSizeMinMaxAvgTotalCalculator :
+    public MinMaxAvgTotalCalculator<uint32_t> {
+  public:
+    PacketSizeMinMaxAvgTotalCalculator();
+    virtual ~PacketSizeMinMaxAvgTotalCalculator();
+
+    void PacketUpdate(std::string path, Ptr<const Packet> packet);
+    void FrameUpdate(std::string path, Ptr<const Packet> packet,
+                     Mac48Address realto);
+
+  protected:
+    virtual void DoDispose(void);
+
+    // end class PacketSizeMinMaxAvgTotalCalculator
+  };
+
+
+  // end namespace ns3
+};
+
+
+#endif // __PACKET_DATA_CALCULATORS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/sqlite-data-output.cc	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,238 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Drexel University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Joe Kopena (tjkopena@cs.drexel.edu)
+ */
+
+#include <sstream>
+
+#include <sqlite3.h>
+
+#include "ns3/log.h"
+#include "ns3/nstime.h"
+
+#include "data-collector.h"
+#include "data-calculator.h"
+#include "sqlite-data-output.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE("SqliteDataOutput");
+
+
+//--------------------------------------------------------------
+//----------------------------------------------
+SqliteDataOutput::SqliteDataOutput() :
+  m_dbFile("data.db")
+{
+  NS_LOG_FUNCTION_NOARGS();
+}
+SqliteDataOutput::~SqliteDataOutput()
+{
+  NS_LOG_FUNCTION_NOARGS();
+}
+void
+SqliteDataOutput::DoDispose()
+{
+  NS_LOG_FUNCTION_NOARGS();
+
+  DataOutputInterface::DoDispose();
+  // end SqliteDataOutput::DoDispose
+}
+
+void
+SqliteDataOutput::SetDBFile(const std::string file)
+{
+  m_dbFile = file;
+}
+std::string
+SqliteDataOutput::GetDBFile() const
+{
+  return m_dbFile;
+}
+
+int
+SqliteDataOutput::Exec(std::string exe) {
+  int res;
+  char **result;
+  int nrows, ncols;
+  char *errMsg = 0;
+
+  NS_LOG_INFO("executing '" << exe << "'");
+
+  res = sqlite3_get_table(m_db,
+                          exe.c_str(),
+                          &result, &nrows, &ncols,
+                          &errMsg);
+
+  if (res != SQLITE_OK) {
+    NS_LOG_ERROR("sqlite3 error: \"" << errMsg << "\"");
+  /*
+  } else {
+    // std::cout << "nrows " << nrows << " ncols " << ncols << std::endl;
+
+    if (nrows > 0) {
+      for (int i = 0; i < ncols; i++) {
+        std::cout << "  " << result[i];
+      }
+      std::cout << std::endl;
+
+      for (int r = 1; r <= nrows; r++) {
+        for (int c = 0; c < ncols; c++) {
+          std::cout << "  " << result[(r*ncols)+c];
+        }
+        std::cout << std::endl;
+      }
+      std::cout << std::endl;
+    }
+  */
+  }
+
+  sqlite3_free_table(result);
+  return res;
+
+  // end SqliteDataOutput::Exec
+}
+
+//----------------------------------------------
+void
+SqliteDataOutput::Output(DataCollector &dc)
+{
+
+  if (sqlite3_open(m_dbFile.c_str(), &m_db)) {
+    NS_LOG_ERROR("Could not open sqlite3 database \"" << m_dbFile << "\"");
+    NS_LOG_ERROR("sqlite3 error \"" << sqlite3_errmsg(m_db) << "\"");
+    sqlite3_close(m_db);
+    // TODO: Better error reporting, management!
+    return;
+  }
+
+  std::string run = dc.GetRunLabel();
+
+  Exec("create table if not exists Experiments (run, experiment, strategy, input, description text)");
+  Exec("insert into Experiments (run,experiment,strategy,input,description) values ('" +
+       run + "', '" +
+       dc.GetExperimentLabel() + "', '" +
+       dc.GetStrategyLabel() + "', '" +
+       dc.GetInputLabel() + "', '" +
+       dc.GetDescription() + "')");
+
+  Exec("create table if not exists Metadata ( run text, key text, value)");
+
+  for (MetadataList::iterator i = dc.MetadataBegin();
+       i != dc.MetadataEnd(); i++) {
+    std::pair<std::string, std::string> blob = (*i);
+    Exec("insert into Metadata (run,key,value) values ('" +
+         run + "', '" +
+         blob.first + "', '" +
+         blob.second + "')");
+  }
+
+  SqliteOutputCallback callback(this, run);
+  for (DataCalculatorList::iterator i = dc.DataCalculatorBegin();
+       i != dc.DataCalculatorEnd(); i++) {
+    (*i)->Output(callback);
+  }
+
+  sqlite3_close(m_db);
+
+  // end SqliteDataOutput::Output
+}
+
+SqliteDataOutput::SqliteOutputCallback::SqliteOutputCallback
+  (Ptr<SqliteDataOutput> owner, std::string run) :
+    m_owner(owner),
+    m_runLabel(run)
+{
+
+  m_owner->Exec("create table if not exists Singletons ( run text, name text, variable text, value )");
+
+  // end SqliteDataOutput::SqliteOutputCallback::SqliteOutputCallback
+}
+
+void
+SqliteDataOutput::SqliteOutputCallback::OutputSingleton(std::string key,
+                                                        std::string variable,
+                                                        int val)
+{
+
+  std::stringstream sstr;
+  sstr << "insert into Singletons (run,name,variable,value) values ('" <<
+    m_runLabel << "', '" <<
+    key << "', '" <<
+    variable << "', " <<
+    val << ")";
+  m_owner->Exec(sstr.str());
+
+  // end SqliteDataOutput::SqliteOutputCallback::OutputSingleton
+}
+void
+SqliteDataOutput::SqliteOutputCallback::OutputSingleton(std::string key,
+                                                        std::string variable,
+                                                        uint32_t val)
+{
+  std::stringstream sstr;
+  sstr << "insert into Singletons (run,name,variable,value) values ('" <<
+    m_runLabel << "', '" <<
+    key << "', '" <<
+    variable << "', " <<
+    val << ")";
+  m_owner->Exec(sstr.str());
+  // end SqliteDataOutput::SqliteOutputCallback::OutputSingleton
+}
+void
+SqliteDataOutput::SqliteOutputCallback::OutputSingleton(std::string key,
+                                                        std::string variable,
+                                                        double val)
+{
+  std::stringstream sstr;
+  sstr << "insert into Singletons (run,name,variable,value) values ('" <<
+    m_runLabel << "', '" <<
+    key << "', '" <<
+    variable << "', " <<
+    val << ")";
+  m_owner->Exec(sstr.str());
+  // end SqliteDataOutput::SqliteOutputCallback::OutputSingleton
+}
+void
+SqliteDataOutput::SqliteOutputCallback::OutputSingleton(std::string key,
+                                                        std::string variable,
+                                                        std::string val)
+{
+  std::stringstream sstr;
+  sstr << "insert into Singletons (run,name,variable,value) values ('" <<
+    m_runLabel << "', '" <<
+    key << "', '" <<
+    variable << "', '" <<
+    val << "')";
+  m_owner->Exec(sstr.str());
+  // end SqliteDataOutput::SqliteOutputCallback::OutputSingleton
+}
+void
+SqliteDataOutput::SqliteOutputCallback::OutputSingleton(std::string key,
+                                                        std::string variable,
+                                                        Time val)
+{
+  std::stringstream sstr;
+  sstr << "insert into Singletons (run,name,variable,value) values ('" <<
+    m_runLabel << "', '" <<
+    key << "', '" <<
+    variable << "', " <<
+    val << ")";
+  m_owner->Exec(sstr.str());
+  // end SqliteDataOutput::SqliteOutputCallback::OutputSingleton
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/sqlite-data-output.h	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,93 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Drexel University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Joe Kopena (tjkopena@cs.drexel.edu)
+ */
+
+#ifndef __SQLITE_DATA_OUTPUT_H__
+#define __SQLITE_DATA_OUTPUT_H__
+
+#include "ns3/nstime.h"
+
+#include "data-output-interface.h"
+
+#define STATS_HAS_SQLITE3
+
+class sqlite3;
+
+namespace ns3 {
+
+  //------------------------------------------------------------
+  //--------------------------------------------
+  class SqliteDataOutput : public DataOutputInterface {
+  public:
+    SqliteDataOutput();
+    virtual ~SqliteDataOutput();
+
+    virtual void Output(DataCollector &dc);
+
+    void SetDBFile(const std::string file);
+    std::string GetDBFile() const;
+
+  protected:
+    virtual void DoDispose();
+
+  private:
+    class SqliteOutputCallback : public DataOutputCallback {
+    public:
+      SqliteOutputCallback(Ptr<SqliteDataOutput> owner, std::string run);
+
+      void OutputSingleton(std::string key,
+                           std::string variable,
+                           int val);
+
+      void OutputSingleton(std::string key,
+                           std::string variable,
+                           uint32_t val);
+
+      void OutputSingleton(std::string key,
+                           std::string variable,
+                           double val);
+
+      void OutputSingleton(std::string key,
+                           std::string variable,
+                           std::string val);
+
+      void OutputSingleton(std::string key,
+                           std::string variable,
+                           Time val);
+
+    private:
+      Ptr<SqliteDataOutput> m_owner;
+      std::string m_runLabel;
+
+      // end class SqliteOutputCallback
+    };
+
+
+    sqlite3 *m_db;
+    int Exec(std::string exe);
+
+    std::string m_dbFile;
+    // end class SqliteDataOutput
+  };
+
+  // end namespace ns3
+};
+
+
+#endif // __SQLITE_DATA_OUTPUT_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/time-data-calculators.cc	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,81 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Drexel University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Joe Kopena (tjkopena@cs.drexel.edu)
+ */
+
+#include "ns3/log.h"
+#include "ns3/nstime.h"
+
+#include "time-data-calculators.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE("TimeDataCalculators");
+
+
+//--------------------------------------------------------------
+//----------------------------------------------
+TimeMinMaxAvgTotalCalculator::TimeMinMaxAvgTotalCalculator()
+{
+  m_count = 0;
+}
+TimeMinMaxAvgTotalCalculator::~TimeMinMaxAvgTotalCalculator()
+{
+}
+void
+TimeMinMaxAvgTotalCalculator::DoDispose(void)
+{
+  DataCalculator::DoDispose();
+  // TimeMinMaxAvgTotalCalculator::DoDispose
+}
+
+void
+TimeMinMaxAvgTotalCalculator::Update(const Time i)
+{
+  if (m_enabled) {
+    if (m_count) {
+      m_total += i;
+
+      if (i < m_min)
+        m_min = i;
+
+      if (i > m_max)
+        m_max = i;
+
+    } else {
+      m_min = i;
+      m_max = i;
+      m_total = i;
+    }
+    m_count++;
+
+  }
+  // end TimeMinMaxAvgTotalCalculator::Update
+}
+void
+TimeMinMaxAvgTotalCalculator::Output(DataOutputCallback &callback) const
+{
+  callback.OutputSingleton(m_key, "count", m_count);
+  if (m_count > 0) {
+    callback.OutputSingleton(m_key, "total", m_total);
+    callback.OutputSingleton(m_key, "average", m_total/Scalar(m_count));
+    callback.OutputSingleton(m_key, "max", m_max);
+    callback.OutputSingleton(m_key, "min", m_min);
+  }
+  // end TimeMinMaxAvgTotalCalculator::Output
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/time-data-calculators.h	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,62 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Drexel University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Joe Kopena (tjkopena@cs.drexel.edu)
+ */
+
+#ifndef __TIME_DATA_CALCULATORS_H__
+#define __TIME_DATA_CALCULATORS_H__
+
+#include "ns3/nstime.h"
+
+#include "data-calculator.h"
+#include "data-output-interface.h"
+
+namespace ns3 {
+
+  //------------------------------------------------------------
+  //--------------------------------------------
+  /**
+   * Unfortunately, templating the base MinMaxAvgTotalCalculator to
+   * operate over Time values isn't straightforward.  The main issues
+   * are setting the maximum value, which can be worked around easily
+   * as it done here, and dividing to get the average, which is not as
+   * easily worked around.
+  */
+  class TimeMinMaxAvgTotalCalculator : public DataCalculator {
+  public:
+    TimeMinMaxAvgTotalCalculator();
+    virtual ~TimeMinMaxAvgTotalCalculator();
+
+    void Update(const Time i);
+
+    virtual void Output(DataOutputCallback &callback) const;
+
+  protected:
+    virtual void DoDispose(void);
+
+    uint32_t m_count;
+    Time m_total, m_min, m_max;
+
+    // end class TimeMinMaxAvgTotalCalculator
+  };
+
+  // end namespace ns3
+};
+
+
+#endif // __TIME_DATA_CALCULATORS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/stats/wscript	Fri Aug 29 13:22:09 2008 -0400
@@ -0,0 +1,36 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def configure(conf):
+   e = conf.create_library_configurator()
+   e.mandatory = False
+   e.name = 'sqlite3'
+   e.define = 'SQLITE3'
+   e.uselib = 'SQLITE3'
+   conf.env['SQLITE_STATS'] = e.run()
+
+def build(bld):
+    obj = bld.create_ns3_module('stats', ['node'])
+    obj.source = [
+        'data-calculator.cc',
+        'packet-data-calculators.cc',
+        'time-data-calculators.cc',
+        'data-output-interface.cc',
+        'omnet-data-output.cc',
+        'data-collector.cc',
+        ]
+    headers = bld.create_obj('ns3header')
+    headers.module = 'stats'
+    headers.source = [
+        'data-calculator.h',
+        'packet-data-calculators.h',
+        'time-data-calculators.h',
+        'basic-data-calculators.h',
+        'data-output-interface.h',
+        'omnet-data-output.h',
+        'data-collector.h',
+        ]
+
+    if bld.env()['SQLITE_STATS']:
+        headers.source.append('sqlite-data-output.h')
+        obj.source.append('sqlite-data-output.cc')
+        obj.uselib = 'SQLITE3'
--- a/src/contrib/wscript	Fri Aug 29 14:56:24 2008 +0100
+++ b/src/contrib/wscript	Fri Aug 29 13:22:09 2008 -0400
@@ -6,7 +6,7 @@
     check.uselib = 'GTK_CONFIG_STORE'
     check.mandatory = False
     conf.env['ENABLE_GTK_CONFIG_STORE'] = check.run()
-
+    conf.sub_config('stats')
 
 def build(bld):
     module = bld.create_ns3_module('contrib', ['simulator'])
--- a/src/wscript	Fri Aug 29 14:56:24 2008 +0100
+++ b/src/wscript	Fri Aug 29 13:22:09 2008 -0400
@@ -28,6 +28,7 @@
     'devices/wifi',
     'helper',
     'devices/bridge',
+    'contrib/stats',
     )
 
 def set_options(opt):