'''
### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###
                   308-304 - Object-Oriented Software Design
                                 ASSIGNMENT  1
   PTesting.py ---
      Performance testing for both SpreadsheetData implementations.

   last modified: 01/26/02
                       ===============================
                             Copyright (c)  2002
                            Jean-Sébastien BOLDUC
                             (jseb@cs.mcgill.ca)

                        McGill University  (Montréal)
                       ===============================

### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###
'''

from math import sqrt, floor, ceil

from SSheetLIST import *
SSL = SpreadsheetData

from SSheetDICT import *
SSD = SpreadsheetData

# Two useful timing functions (Implementation details skipped)
#    TIC() -- Reset the internal timer to zero
#    TOC() -- Returns the elapsed time (in seconds) since the last TIC()
from time import time
__lastTime = [time()]
def TIC(t = __lastTime):
  t[0] = time()
def TOC(t = __lastTime):
  return time() - t[0]
del __lastTime

sizeIncr = 5 # size increment
maxTime = 15. # maximum response time

### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###
### FULL SYSTEMS


### TEST 1 -- LIST IMPLEMENTATION

print "TEST 1 -- FULL SYSTEM, LIST IMPLEMENTATION"

size = 10  # Initial spreadsheet dimension: size*size

while 1:
  TIC() # Start timer
  S = SSL() # Initialize
  # Fill spreadsheet (size*size cells):
  # Interested in a worst-case behaviour (filling first the top-left, then the
  # bottom-right cells would require the internal __table to be resized only
  # once -- best-case behaviour)
  for row in range(1, size+1):
    for col in range(1, size+1):
      S[CellCoordinate(row, col)] = CellData(1)
  # Access all cells:
  for row in range(1, size+1):
    for col in range(1, size+1):
      x = S[CellCoordinate(row, col)]
  deltaTime = TOC() # Stop timer
  print "%4d\t%8.4f" % (size, deltaTime)
  if deltaTime < maxTime:
    size = size+sizeIncr
  else:
    break


### TEST 2 -- DICT IMPLEMENTATION

print "\n\nTEST 2 -- FULL SYSTEM, DICT IMPLEMENTATION"

size = 10  # Initial spreadsheet dimension: size*size

while 1:
  TIC() # Start timer
  S = SSD() # Initialize
  # Fill spreadsheet (size*size cells):
  for row in range(1, size+1):
    for col in range(1, size+1):
      S[CellCoordinate(row, col)] = CellData(1)
  # Access all cells:
  for row in range(1, size+1):
    for col in range(1, size+1):
      x = S[CellCoordinate(row, col)]
  deltaTime = TOC() # Stop timer
  print "%4d\t%8.4f" % (size, deltaTime)
  if deltaTime < maxTime:
    size = size+sizeIncr
  else:
    break


### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###
### SPARSE SYSTEMS


### TEST 3 -- LIST IMPLEMENTATION

print "\n\nTEST 3 -- SPARSE SYSTEM, LIST IMPLEMENTATION"

size = 10  # Initial spreadsheet dimension: size*size

while 1:

  # nRows * nCols is approximately 10% of size * size
  nRows =  floor(sqrt(0.1*size**2))
  nCols =  ceil(sqrt(0.1*size**2))

  coords = range(1, size+1)
  
  # Build a list rowCoords with nRows evenly distributed row coordinates. We
  # want to make sure rows number 1 and number size are included in the list 
  # (this is a tricky code. The assert at the end is to check it worked as 
  # expected).
  rowCoords = []
  C = int(size/(nRows-1))
  for i in range(nRows-1):
    rowCoords.append(coords[i*C])
  rowCoords.append(coords[-1])
  assert(len(rowCoords) == nRows)
  
  # Repeat as above, but building colIndexes...
  colCoords = []
  C = int(size/(nCols-1))
  for j in range(nCols-1):
    colCoords.append(coords[j*C])
  colCoords.append(coords[-1])
  assert(len(colCoords) == nCols)
  
  TIC() # Start timer
  S = SSL() # Initialize
  # Fill spreadsheet (size*size cells):
  # Again interested in a worst-case behaviour, guaranteed by the way rowCoords
  # and colCoords are built (fills the spreadsheet from left to right, and from
  # top to bottom).
  for row in rowCoords:
    for col in colCoords:
      S[CellCoordinate(row, col)] = CellData(1)
  # Access all cells:
  for row in rowCoords:
    for col in colCoords:
      x = S[CellCoordinate(row, col)]
  deltaTime = TOC() # Stop timer
  print "%4d\t%8.4f" % (size, deltaTime)
  if deltaTime < maxTime:
    size = size+sizeIncr
  else:
    break


### TEST 4 -- DICT IMPLEMENTATION

print "\n\nTEST 4 -- SPARSE SYSTEM, DICT IMPLEMENTATION"

size = 10  # Initial spreadsheet dimension: size*size

while 1:

  # nRows * nCols is approximately 10% of size * size
  nRows =  floor(sqrt(0.1*size**2))
  nCols =  ceil(sqrt(0.1*size**2))

  coords = range(1, size+1)
  
  # Build a list rowCoords with nRows evenly distributed row coordinates.
  # Same as for list implementation.
  rowCoords = []
  C = int(size/(nRows-1))
  for i in range(nRows-1):
    rowCoords.append(coords[i*C])
  rowCoords.append(coords[-1])
  assert(len(rowCoords) == nRows)
  
  # Repeat as above, but building colIndexes...
  colCoords = []
  C = int(size/(nCols-1))
  for j in range(nCols-1):
    colCoords.append(coords[j*C])
  colCoords.append(coords[-1])
  assert(len(colCoords) == nCols)
  
  TIC() # Start timer
  S = SSD() # Initialize
  # Fill spreadsheet (size*size cells):
  for row in rowCoords:
    for col in colCoords:
      S[CellCoordinate(row, col)] = CellData(1)
  # Access all cells:
  for row in rowCoords:
    for col in colCoords:
      x = S[CellCoordinate(row, col)]
  deltaTime = TOC() # Stop timer
  print "%4d\t%8.4f" % (size, deltaTime)
  if deltaTime < maxTime:
    size = size+sizeIncr
  else:
    break
