import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__),'..'))


from sys     import argv
from math    import log
from decimal import Decimal
from decimal import getcontext
from pymongo import MongoClient
from Formula import calculateSaleReturn


USERNAME      = ''
PASSWORD      = ''
SERVER_NAME   = '127.0.0.1:27017'
DATABASE_NAME = 'test'


MINIMUM_VALUE_SUPPLY  = 100
MAXIMUM_VALUE_SUPPLY  = 10**34
GROWTH_FACTOR_SUPPLY  = 1.5


MINIMUM_VALUE_RESERVE = 100
MAXIMUM_VALUE_RESERVE = 10**34
GROWTH_FACTOR_RESERVE = 1.5


MINIMUM_VALUE_RATIO   = 10
MAXIMUM_VALUE_RATIO   = 90
GROWTH_FACTOR_RATIO   = 1.25


MINIMUM_VALUE_AMOUNT  = 1
MAXIMUM_VALUE_AMOUNT  = 10**34
GROWTH_FACTOR_AMOUNT  = 1.5


TRANSACTION_SUCCESS  = 0
TRANSACTION_FAILURE  = 1
TRANSACTION_INVALID  = 2
IMPLEMENTATION_ERROR = 3


def Main():
    username      = USERNAME     
    password      = PASSWORD     
    server_name   = SERVER_NAME  
    database_name = DATABASE_NAME
    for arg in argv[1:]:
        username      = arg[len('username='     ):] if arg.startswith('username='     ) else username     
        password      = arg[len('password='     ):] if arg.startswith('password='     ) else password     
        server_name   = arg[len('server_name='  ):] if arg.startswith('server_name='  ) else server_name  
        database_name = arg[len('database_name='):] if arg.startswith('database_name=') else database_name
    if username and password:
        uri = 'mongodb://{}:{}@{}/{}'.format(username,password,server_name,database_name)
    else:
        uri = 'mongodb://{}/{}'.format(server_name,database_name)
    getcontext().prec = 80 # 78 digits for a maximum of 2^256-1, and 2 more digits for after the decimal point
    TestAll(MongoClient(uri).get_database(database_name).get_collection('sale'))


def TestAll(collection):
    range_supply  = [int(MINIMUM_VALUE_SUPPLY *GROWTH_FACTOR_SUPPLY **n) for n in range(int(log(MAXIMUM_VALUE_SUPPLY ,GROWTH_FACTOR_SUPPLY ))+1)]
    range_reserve = [int(MINIMUM_VALUE_RESERVE*GROWTH_FACTOR_RESERVE**n) for n in range(int(log(MAXIMUM_VALUE_RESERVE,GROWTH_FACTOR_RESERVE))+1)]
    range_ratio   = [int(MINIMUM_VALUE_RATIO  *GROWTH_FACTOR_RATIO  **n) for n in range(int(log(MAXIMUM_VALUE_RATIO  ,GROWTH_FACTOR_RATIO  ))+1)]
    range_amount  = [int(MINIMUM_VALUE_AMOUNT *GROWTH_FACTOR_AMOUNT **n) for n in range(int(log(MAXIMUM_VALUE_AMOUNT ,GROWTH_FACTOR_AMOUNT ))+1)]
    for             supply  in range_supply :
        for         reserve in range_reserve:
            for     ratio   in range_ratio  :
                for amount  in range_amount :
                    if amount <= supply:
                        fixed,real = Test(supply,reserve,ratio,amount)
                        if real < 0:
                            status = TRANSACTION_INVALID
                            loss = {'absolute':0,'relative':0}
                        elif fixed < 0:
                            status = TRANSACTION_FAILURE
                            loss = {'absolute':0,'relative':0}
                        elif real < fixed:
                            status = IMPLEMENTATION_ERROR
                            loss = {'absolute':0,'relative':0}
                        else: # 0 <= fixed <= real
                            status = TRANSACTION_SUCCESS
                            loss = {'absolute':float(real-fixed),'relative':1-float(fixed/real)}
                        entry = {
                            'supply' :'{}'    .format(supply ),
                            'reserve':'{}'    .format(reserve),
                            'ratio'  :'{}'    .format(ratio  ),
                            'amount' :'{}'    .format(amount ),
                            'fixed'  :'{}'    .format(fixed  ),
                            'real'   :'{:.2f}'.format(real   ),
                            'status' :status,
                            'loss'   :loss  ,
                        }
                        id = collection.insert(entry)
                        print ', '.join('{}: {}'.format(key,entry[key]) for key in ['supply','reserve','ratio','amount','fixed','real','status','loss'])


def Test(supply,reserve,ratio,amount):
    try:
        fixed = calculateSaleReturn(supply,reserve,ratio,amount)
    except Exception:
        fixed = -1
    try:
        real = Decimal(reserve)*(1-(1-Decimal(amount)/Decimal(supply))**(100/Decimal(ratio)))
    except Exception:
        real = -1
    return fixed,real


Main()

@@ -1841,28 +1841,37 @@
 e_supply  = 
-%5Bint
+GenerateRange
 (MINIMUM_VAL
@@ -1884,58 +1884,9 @@
 PLY 
-*GROWTH_FACTOR_SUPPLY **n) for n in range(int(log(
+,
 MAXI
@@ -1925,21 +1925,16 @@
 SUPPLY )
-)+1)%5D
 %0A    ran
@@ -1946,20 +1946,29 @@
 serve = 
-%5Bint
+GenerateRange
 (MINIMUM
@@ -1985,58 +1985,9 @@
 ERVE
-*GROWTH_FACTOR_RESERVE**n) for n in range(int(log(
+,
 MAXI
@@ -2026,21 +2026,16 @@
 RESERVE)
-)+1)%5D
 %0A    ran
@@ -2043,28 +2043,37 @@
 e_ratio   = 
-%5Bint
+GenerateRange
 (MINIMUM_VAL
@@ -2086,58 +2086,9 @@
 IO  
-*GROWTH_FACTOR_RATIO  **n) for n in range(int(log(
+,
 MAXI
@@ -2127,21 +2127,16 @@
 RATIO  )
-)+1)%5D
 %0A    ran
@@ -2152,12 +2152,21 @@
   = 
-%5Bint
+GenerateRange
 (MIN
@@ -2187,58 +2187,9 @@
 UNT 
-*GROWTH_FACTOR_AMOUNT **n) for n in range(int(log(
+,
 MAXI
@@ -2232,13 +2232,8 @@
 NT )
-)+1)%5D
 %0A   
@@ -4277,15 +4277,204 @@
 ,real%0A%0A%0A
+def GenerateRange(minimumValue,maximumValue,growthFactor):%0A    return %5Bint(minimumValue*growthFactor**n) for n in range(int(log(float(maximumValue)/float(minimumValue),growthFactor))+1)%5D%0A%0A%0A
 Main()%0A

Update TestSale.py