2011-06-22 20:33:57 +02:00
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
import datetime
from collections import defaultdict
import operator
from helpers import *
import sys
import db
def getUser ( ) :
while 1 :
2018-08-19 16:38:45 +02:00
string = input ( ' user? ' )
2011-06-22 20:33:57 +02:00
session = Session ( )
user = search_user ( string , session )
session . close ( )
if not isinstance ( user , list ) :
return user . name
i = 0
if len ( user ) == 0 :
2018-08-19 16:38:45 +02:00
print ( ' no matching string ' )
2011-06-22 20:33:57 +02:00
if len ( user ) == 1 :
2018-08-19 16:38:45 +02:00
print ( ' antar: ' , user [ 0 ] . name , ' \n ' )
2011-06-22 20:33:57 +02:00
return user [ 0 ] . name
if len ( user ) > 10 :
continue
for u in user :
2018-08-19 16:38:45 +02:00
print ( i , u . name )
2011-06-22 20:33:57 +02:00
i + = 1
try :
2018-08-19 16:38:45 +02:00
n = int ( input ( ' enter number: ' ) )
2011-06-22 20:33:57 +02:00
except :
2018-08-19 16:38:45 +02:00
print ( ' invalid input, restarting ' )
2011-06-22 20:33:57 +02:00
continue
if ( n > - 1 ) and ( n < i ) :
return user [ n ] . name
def getProduct ( ) :
while 1 :
2018-08-19 16:38:45 +02:00
string = input ( ' product? ' )
2011-06-22 20:33:57 +02:00
session = Session ( )
product = search_product ( string , session )
session . close ( )
if not isinstance ( product , list ) :
return product . name
i = 0
if len ( product ) == 0 :
2018-08-19 16:38:45 +02:00
print ( ' no matching string ' )
2011-06-22 20:33:57 +02:00
if len ( product ) == 1 :
2018-08-19 16:38:45 +02:00
print ( ' antar: ' , product [ 0 ] . name , ' \n ' )
2011-06-22 20:33:57 +02:00
return product [ 0 ] . name
if len ( product ) > 10 :
continue
for u in product :
2018-08-19 16:38:45 +02:00
print ( i , u . name )
2011-06-22 20:33:57 +02:00
i + = 1
try :
2018-08-19 16:38:45 +02:00
n = int ( input ( ' enter number: ' ) )
2011-06-22 20:33:57 +02:00
except :
2018-08-19 16:38:45 +02:00
print ( ' invalid input, restarting ' )
2011-06-22 20:33:57 +02:00
continue
if ( n > - 1 ) and ( n < i ) :
return product [ n ] . name
class Database :
#for varer
varePersonAntall = defaultdict ( dict ) #varePersonAntall[Oreo][trygvrad] == 3
vareDatoAntall = defaultdict ( list ) #dict->array
vareUkedagAntall = defaultdict ( list )
#for personer
personVareAntall = defaultdict ( dict ) #personVareAntall[trygvrad][Oreo] == 3
personVareVerdi = defaultdict ( dict ) #personVareVerdi[trygvrad][Oreo] == 30 #[kr]
personDatoVerdi = defaultdict ( list ) #dict->array
personUkedagVerdi = defaultdict ( list )
#for global
personPosTransactions = { } # personPosTransactions[trygvrad] == 100 #trygvrad har lagt 100kr i boksen
personNegTransactions = { } # personNegTransactions[trygvrad» == 70 #trygvrad har tatt 70kr fra boksen
globalVareAntall = { } #globalVareAntall[Oreo] == 3
globalVareVerdi = { } #globalVareVerdi[Oreo] == 30 #[kr]
globalPersonAntall = { } #globalPersonAntall[trygvrad] == 3
globalPersonForbruk = { } #globalPersonVerdi == 30 #[kr]
globalUkedagForbruk = [ ]
globalDatoVarer = [ ]
globalDatoForbruk = [ ]
pengebeholdning = [ ]
class InputLine :
def __init__ ( self , u , p , t ) :
self . inputUser = u
self . inputProduct = p
self . inputType = t
def getDateDb ( date , inp ) :
try :
year = inp . partition ( ' - ' )
month = year [ 2 ] . partition ( ' - ' )
return datetime . datetime ( int ( year [ 0 ] ) , int ( month [ 0 ] ) , int ( month [ 2 ] ) )
except :
2018-08-19 16:38:45 +02:00
print ( ' invalid date, setting date to date found in db ' )
print ( date )
2011-06-22 20:33:57 +02:00
return date
def dateToDateNumDb ( date , startDate ) :
deltaDays = date - startDate
return int ( deltaDays . days ) , date . weekday ( )
def getInputType ( ) :
inp = 0
while not ( inp == ' 1 ' or inp == ' 2 ' or inp == ' 3 ' or inp == ' 4 ' ) :
2018-08-19 16:38:45 +02:00
print ( ' type 1 for user-statistics ' )
print ( ' type 2 for product-statistics ' )
print ( ' type 3 for global-statistics ' )
print ( ' type 4 to enter loop-mode ' )
inp = input ( ' ' )
2011-06-22 20:33:57 +02:00
return int ( inp )
def getProducts ( products ) :
product = [ ]
products = products . partition ( ' ¤ ' )
product . append ( products [ 0 ] )
while ( products [ 1 ] == ' ¤ ' ) :
products = products [ 2 ] . partition ( ' ¤ ' )
product . append ( products [ 0 ] )
return product
def getDateFile ( date , inp ) :
try :
year = inp . partition ( ' - ' )
month = year [ 2 ] . partition ( ' - ' )
return datetime . date ( int ( year [ 0 ] ) , int ( month [ 0 ] ) , int ( month [ 2 ] ) )
except :
2018-08-19 16:38:45 +02:00
print ( ' invalid date, setting date to date found on file file ' )
print ( date )
2011-06-22 20:33:57 +02:00
return datetime . date ( int ( date . partition ( ' - ' ) [ 0 ] ) , int ( date . partition ( ' - ' ) [ 2 ] . partition ( ' - ' ) [ 0 ] ) , int ( date . partition ( ' - ' ) [ 2 ] . partition ( ' - ' ) [ 2 ] ) )
def dateToDateNumFile ( date , startDate ) :
year = date . partition ( ' - ' )
month = year [ 2 ] . partition ( ' - ' )
day = datetime . date ( int ( year [ 0 ] ) , int ( month [ 0 ] ) , int ( month [ 2 ] ) )
deltaDays = day - startDate
return int ( deltaDays . days ) , day . weekday ( )
def clearDatabase ( database ) :
database . varePersonAntall . clear ( )
database . vareDatoAntall . clear ( )
database . vareUkedagAntall . clear ( )
database . personVareAntall . clear ( )
database . personVareVerdi . clear ( )
database . personDatoVerdi . clear ( )
database . personUkedagVerdi . clear ( )
database . personPosTransactions . clear ( )
database . personNegTransactions . clear ( )
database . globalVareAntall . clear ( )
database . globalVareVerdi . clear ( )
database . globalPersonAntall . clear ( )
database . globalPersonForbruk . clear ( )
return ( database )
def addLineToDatabase ( database , inputLine ) :
if abs ( inputLine . price ) > 90000 :
return database
#fyller inn for varer
if ( not inputLine . product == ' ' ) and ( ( inputLine . inputProduct == ' ' ) or ( inputLine . inputProduct == inputLine . product ) ) :
database . varePersonAntall [ inputLine . product ] [ inputLine . user ] = database . varePersonAntall [ inputLine . product ] . setdefault ( inputLine . user , 0 ) + 1
if inputLine . product not in database . vareDatoAntall :
database . vareDatoAntall [ inputLine . product ] = [ 0 ] * ( inputLine . numberOfDays + 1 )
database . vareDatoAntall [ inputLine . product ] [ inputLine . dateNum ] + = 1
if inputLine . product not in database . vareUkedagAntall :
database . vareUkedagAntall [ inputLine . product ] = [ 0 ] * 7
database . vareUkedagAntall [ inputLine . product ] [ inputLine . weekday ] + = 1
#fyller inn for personer
if ( inputLine . inputUser == ' ' ) or ( inputLine . inputUser == inputLine . user ) :
if not inputLine . product == ' ' :
database . personVareAntall [ inputLine . user ] [ inputLine . product ] = database . personVareAntall [ inputLine . user ] . setdefault ( inputLine . product , 0 ) + 1
database . personVareVerdi [ inputLine . user ] [ inputLine . product ] = database . personVareVerdi [ inputLine . user ] . setdefault ( inputLine . product , 0 ) + inputLine . price
if inputLine . user not in database . personDatoVerdi :
database . personDatoVerdi [ inputLine . user ] = [ 0 ] * ( inputLine . numberOfDays + 1 )
database . personDatoVerdi [ inputLine . user ] [ inputLine . dateNum ] + = inputLine . price
if inputLine . user not in database . personUkedagVerdi :
database . personUkedagVerdi [ inputLine . user ] = [ 0 ] * 7
database . personUkedagVerdi [ inputLine . user ] [ inputLine . weekday ] + = inputLine . price
#fyller inn delt statistikk (genereres uansett)
if ( inputLine . product == ' ' ) :
if ( inputLine . price > 0 ) :
database . personPosTransactions [ inputLine . user ] = database . personPosTransactions . setdefault ( inputLine . user , 0 ) + inputLine . price
else :
database . personNegTransactions [ inputLine . user ] = database . personNegTransactions . setdefault ( inputLine . user , 0 ) + inputLine . price
elif not ( inputLine . inputType == 1 ) :
database . globalVareAntall [ inputLine . product ] = database . globalVareAntall . setdefault ( inputLine . product , 0 ) + 1
database . globalVareVerdi [ inputLine . product ] = database . globalVareVerdi . setdefault ( inputLine . product , 0 ) + inputLine . price
#fyller inn for global statistikk
if ( inputLine . inputType == 3 ) or ( inputLine . inputType == 4 ) :
database . pengebeholdning [ inputLine . dateNum ] + = inputLine . price
if not ( inputLine . product == ' ' ) :
database . globalPersonAntall [ inputLine . user ] = database . globalPersonAntall . setdefault ( inputLine . user , 0 ) + 1
database . globalPersonForbruk [ inputLine . user ] = database . globalPersonForbruk . setdefault ( inputLine . user , 0 ) + inputLine . price
database . globalDatoVarer [ inputLine . dateNum ] + = 1
database . globalDatoForbruk [ inputLine . dateNum ] + = inputLine . price
database . globalUkedagForbruk [ inputLine . weekday ] + = inputLine . price
return database
def buildDatabaseFromDb ( inputType , inputProduct , inputUser ) :
2018-08-19 16:38:45 +02:00
sdate = input ( ' enter start date (yyyy-mm-dd)? ' )
edate = input ( ' enter end date (yyyy-mm-dd)? ' )
print ( ' building database... ' )
2011-06-22 20:33:57 +02:00
session = Session ( )
transaction_list = session . query ( Transaction ) . all ( )
inputLine = InputLine ( inputUser , inputProduct , inputType )
startDate = getDateDb ( transaction_list [ 0 ] . time , sdate )
endDate = getDateDb ( transaction_list [ - 1 ] . time , edate )
inputLine . numberOfDays = ( endDate - startDate ) . days
database = Database ( )
database = clearDatabase ( database )
if ( inputType == 3 ) or ( inputType == 4 ) :
database . globalDatoVarer = [ 0 ] * ( inputLine . numberOfDays + 1 )
database . globalDatoForbruk = [ 0 ] * ( inputLine . numberOfDays + 1 )
database . globalUkedagForbruk = [ 0 ] * 7
database . pengebeholdning = [ 0 ] * ( inputLine . numberOfDays + 1 )
2018-08-19 16:38:45 +02:00
print ( ' wait for it.... ' )
2011-06-22 20:33:57 +02:00
for transaction in transaction_list :
if transaction . purchase :
2018-08-19 16:38:45 +02:00
products = [ ent . product . name for ent in transaction . purchase . entries ]
2011-06-22 20:33:57 +02:00
else :
products = [ ]
products . append ( ' ' )
inputLine . dateNum , inputLine . weekday = dateToDateNumDb ( transaction . time , startDate )
if inputLine . dateNum < 0 or inputLine . dateNum > ( inputLine . numberOfDays ) :
continue
inputLine . user = transaction . user . name
inputLine . price = transaction . amount
for inputLine . product in products :
database = addLineToDatabase ( database , inputLine )
inputLine . price = 0 ;
2018-08-19 16:38:45 +02:00
print ( ' saving as default.dibblerlog... ' , end = ' ' )
2011-06-22 20:33:57 +02:00
f = open ( ' default.dibblerlog ' , ' w ' )
line_format = ' %s | %s | %s | %s | %s | %s \n '
transaction_list = session . query ( Transaction ) . all ( )
for transaction in transaction_list :
if transaction . purchase :
2018-08-19 16:38:45 +02:00
products = ' ¤ ' . join ( [ ent . product . name for ent in transaction . purchase . entries ] )
2011-06-22 20:33:57 +02:00
description = ' '
else :
products = ' '
description = transaction . description
line = line_format % ( ' purchase ' , transaction . time , products , transaction . user . name , transaction . amount , transaction . description )
f . write ( line . encode ( ' utf8 ' ) )
session . close ( )
f . close
#bygg database.pengebeholdning
if ( inputType == 3 ) or ( inputType == 4 ) :
for i in range ( inputLine . numberOfDays + 1 ) :
if i > 0 :
database . pengebeholdning [ i ] + = database . pengebeholdning [ i - 1 ]
#bygg dateLine
day = datetime . timedelta ( days = 1 )
dateLine = [ ]
dateLine . append ( startDate )
for n in range ( inputLine . numberOfDays ) :
dateLine . append ( startDate + n * day )
2018-08-19 16:38:45 +02:00
print ( ' done ' )
2011-06-22 20:33:57 +02:00
return database , dateLine
def buildDatabaseFromFile ( inputFile , inputType , inputProduct , inputUser ) :
2018-08-19 16:38:45 +02:00
sdate = input ( ' enter start date (yyyy-mm-dd)? ' )
edate = input ( ' enter end date (yyyy-mm-dd)? ' )
2011-06-22 20:33:57 +02:00
f = open ( inputFile )
try :
fileLines = f . readlines ( )
finally :
f . close ( )
inputLine = InputLine ( inputUser , inputProduct , inputType )
startDate = getDateFile ( fileLines [ 0 ] . partition ( ' | ' ) [ 2 ] . partition ( ' ' ) [ 0 ] , sdate )
endDate = getDateFile ( fileLines [ - 1 ] . partition ( ' | ' ) [ 2 ] . partition ( ' ' ) [ 0 ] , edate )
inputLine . numberOfDays = ( endDate - startDate ) . days
database = Database ( )
database = clearDatabase ( database )
if ( inputType == 3 ) or ( inputType == 4 ) :
database . globalDatoVarer = [ 0 ] * ( inputLine . numberOfDays + 1 )
database . globalDatoForbruk = [ 0 ] * ( inputLine . numberOfDays + 1 )
database . globalUkedagForbruk = [ 0 ] * 7
database . pengebeholdning = [ 0 ] * ( inputLine . numberOfDays + 1 )
for linje in fileLines :
if not ( linje [ 0 ] == ' # ' ) and not ( linje == ' \n ' ) :
#henter dateNum, products, user, price
restDel = linje . partition ( ' | ' )
restDel = restDel [ 2 ] . partition ( ' ' )
inputLine . dateNum , inputLine . weekday = dateToDateNumFile ( restDel [ 0 ] , startDate )
if inputLine . dateNum < 0 or inputLine . dateNum > ( inputLine . numberOfDays ) :
continue
restDel = restDel [ 2 ] . partition ( ' | ' )
restDel = restDel [ 2 ] . partition ( ' | ' )
products = restDel [ 0 ]
restDel = restDel [ 2 ] . partition ( ' | ' )
inputLine . user = restDel [ 0 ]
inputLine . price = int ( restDel [ 2 ] . partition ( ' | ' ) [ 0 ] )
for inputLine . product in getProducts ( products ) :
database = addLineToDatabase ( database , inputLine )
inputLine . price = 0 ;
#bygg database.pengebeholdning
if ( inputType == 3 ) or ( inputType == 4 ) :
for i in range ( inputLine . numberOfDays + 1 ) :
if i > 0 :
database . pengebeholdning [ i ] + = database . pengebeholdning [ i - 1 ]
#bygg dateLine
day = datetime . timedelta ( days = 1 )
dateLine = [ ]
dateLine . append ( startDate )
for n in range ( inputLine . numberOfDays ) :
dateLine . append ( startDate + n * day )
return database , dateLine
def printTopDict ( dictionary , n , k ) :
i = 0
for key in sorted ( dictionary , key = dictionary . get , reverse = k ) :
2018-08-19 16:38:45 +02:00
print ( key , ' : ' , dictionary [ key ] )
2011-06-22 20:33:57 +02:00
if i < n :
i + = 1
else :
break
def printTopDict2 ( dictionary , dictionary2 , n ) :
2018-08-19 16:38:45 +02:00
print ( ' ' )
print ( ' product : price[kr] ( number ) ' )
2011-06-22 20:33:57 +02:00
i = 0
for key in sorted ( dictionary , key = dictionary . get , reverse = True ) :
2018-08-19 16:38:45 +02:00
print ( key , ' : ' , dictionary [ key ] , ' ( ' , dictionary2 [ key ] , ' ) ' )
2011-06-22 20:33:57 +02:00
if i < n :
i + = 1
else :
break
def printWeekdays ( week , days ) :
if week == [ ] or days == 0 :
return
2018-08-19 16:38:45 +02:00
print ( ' mon: ' , ' %.2f ' % ( week [ 0 ] * 7.0 / days ) , ' tue: ' , ' %.2f ' % ( week [ 1 ] * 7.0 / days ) , ' wen: ' , ' %.2f ' % ( week [ 2 ] * 7.0 / days ) , ' thu: ' , ' %.2f ' % ( week [ 3 ] * 7.0 / days ) , ' fri: ' , ' %.2f ' % ( week [ 4 ] * 7.0 / days ) , ' sat: ' , ' %.2f ' % ( week [ 5 ] * 7.0 / days ) , ' sun: ' , ' %.2f ' % ( week [ 6 ] * 7.0 / days ) )
print ( ' forbruk per dag (snitt): ' , ' %.2f ' % ( sum ( week ) * 1.0 / days ) )
print ( ' ' )
2011-06-22 20:33:57 +02:00
def printBalance ( database , user ) :
forbruk = 0
if ( user in database . personVareVerdi ) :
2018-08-19 16:38:45 +02:00
forbruk = sum ( [ i for i in list ( database . personVareVerdi [ user ] . values ( ) ) ] )
print ( ' totalt kjøpt for: ' , forbruk , end = ' ' )
2011-06-22 20:33:57 +02:00
if ( user in database . personNegTransactions ) :
2018-08-19 16:38:45 +02:00
print ( ' kr, totalt lagt til: ' , - database . personNegTransactions [ user ] , end = ' ' )
2011-06-22 20:33:57 +02:00
forbruk = - database . personNegTransactions [ user ] - forbruk
if ( user in database . personPosTransactions ) :
2018-08-19 16:38:45 +02:00
print ( ' kr, totalt tatt fra boks: ' , database . personPosTransactions [ user ] , end = ' ' )
2011-06-22 20:33:57 +02:00
forbruk = forbruk - database . personPosTransactions [ user ]
2018-08-19 16:38:45 +02:00
print ( ' balanse: ' , forbruk , ' kr ' , end = ' ' )
print ( ' ' )
2011-06-22 20:33:57 +02:00
def printUser ( database , dateLine , user , n ) :
printTopDict2 ( database . personVareVerdi [ user ] , database . personVareAntall [ user ] , n )
2018-08-19 16:38:45 +02:00
print ( ' \n forbruk per ukedag [kr/dag], ' , end = ' ' )
2011-06-22 20:33:57 +02:00
printWeekdays ( database . personUkedagVerdi [ user ] , len ( dateLine ) )
printBalance ( database , user )
def printProduct ( database , dateLine , product , n ) :
printTopDict ( database . varePersonAntall [ product ] , n , 1 )
2018-08-19 16:38:45 +02:00
print ( ' \n forbruk per ukedag [antall/dag], ' , end = ' ' )
2011-06-22 20:33:57 +02:00
printWeekdays ( database . vareUkedagAntall [ product ] , len ( dateLine ) )
2018-08-19 16:38:45 +02:00
print ( ' Det er solgt: ' , database . globalVareAntall [ product ] , product , ' til en verdi av: ' , database . globalVareVerdi [ product ] , ' kr ' )
2011-06-22 20:33:57 +02:00
def printGlobal ( database , dateLine , n ) :
2018-08-19 16:38:45 +02:00
print ( ' \n mest lagt til: ' )
2011-06-22 20:33:57 +02:00
printTopDict ( database . personNegTransactions , n , 0 )
2018-08-19 16:38:45 +02:00
print ( ' \n mest tatt fra: ' )
2011-06-22 20:33:57 +02:00
printTopDict ( database . personPosTransactions , n , 1 )
2018-08-19 16:38:45 +02:00
print ( ' \n størst forbruk: ' )
2011-06-22 20:33:57 +02:00
printTopDict ( database . globalPersonForbruk , n , 1 )
printTopDict2 ( database . globalVareVerdi , database . globalVareAntall , n )
2018-08-19 16:38:45 +02:00
print ( ' \n forbruk per ukedag [kr/dag], ' , end = ' ' )
2011-06-22 20:33:57 +02:00
printWeekdays ( database . globalUkedagForbruk , len ( dateLine ) )
2018-08-19 16:38:45 +02:00
print ( ' Det er solgt varer til en verdi av: ' , sum ( database . globalDatoForbruk ) , ' kr, det er lagt til ' , - sum ( [ i for i in list ( database . personNegTransactions . values ( ) ) ] ) , ' og tatt fra ' , sum ( [ i for i in list ( database . personPosTransactions . values ( ) ) ] ) , end = ' ' )
print ( ' balansen blir: ' , database . pengebeholdning [ len ( dateLine ) - 1 ] , ' der negative verdier representerer at brukere har kreditt tilgjengelig ' )
2011-06-22 20:33:57 +02:00
def alt4menuTextOnly ( database , dateLine ) :
n = 10
while 1 :
2018-08-19 16:38:45 +02:00
print ( ' \n 1: user-statistics, 2: product-statistics, 3:global-statistics, n: adjust amount of data shown q:quit ' )
inp = input ( ' ' )
2011-06-22 20:33:57 +02:00
if inp == ' q ' :
break
elif inp == ' 1 ' :
try :
printUser ( database , dateLine , getUser ( ) , n )
except :
2018-08-19 16:38:45 +02:00
print ( ' \n \n Something is not right, (last date prior to first date?) ' )
2011-06-22 20:33:57 +02:00
elif inp == ' 2 ' :
try :
printProduct ( database , dateLine , getProduct ( ) , n )
except :
2018-08-19 16:38:45 +02:00
print ( ' \n \n Something is not right, (last date prior to first date?) ' )
2011-06-22 20:33:57 +02:00
elif inp == ' 3 ' :
try :
printGlobal ( database , dateLine , n )
except :
2018-08-19 16:38:45 +02:00
print ( ' \n \n Something is not right, (last date prior to first date?) ' )
2011-06-22 20:33:57 +02:00
elif inp == ' n ' :
2018-08-19 16:38:45 +02:00
n = int ( input ( ' set number to show ' ) ) ;
2011-06-22 20:33:57 +02:00
def statisticsTextOnly ( ) :
inputType = 4
product = ' '
user = ' '
2018-08-19 16:38:45 +02:00
print ( ' \n 0: from file, 1: from database, q:quit ' )
inp = input ( ' ' )
2011-06-22 20:33:57 +02:00
if inp == ' 1 ' :
database , dateLine = buildDatabaseFromDb ( inputType , product , user )
elif inp == ' 0 ' or inp == ' ' :
database , dateLine = buildDatabaseFromFile ( ' default.dibblerlog ' , inputType , product , user )
if not inp == ' q ' :
alt4menuTextOnly ( database , dateLine )