11#!/usr/bin/python3
22
3+ import random
34import requests
45import time
56import json
910from enum import Enum
1011
1112class CurrencyFormat (Enum ):
13+ """An Enum representing different formats of Currency in coda.
14+
15+ Constants:
16+ WHOLE - represents whole coda (1 whole coda == 10^9 nanocodas)
17+ NANO - represents the atomic unit of coda
18+ """
1219 WHOLE = 1
1320 NANO = 2
1421
1522class CurrencyUnderflow (Exception ):
1623 pass
1724
1825class Currency ():
26+ """A convenience wrapper around interacting with coda currency values.
27+
28+ This class supports performing math on Currency values of differing formats.
29+ Currency instances can be added or subtracted. Currency instances can also be
30+ scaled through multiplication (either against another Currency instance or a
31+ int scalar).
32+ """
33+
1934 @classmethod
2035 def __nanocodas_from_int (_cls , n ):
2136 return n * 1000000000
@@ -32,7 +47,40 @@ def __nanocodas_from_string(_cls, s):
3247 else :
3348 raise Exception ('invalid coda currency format: %s' % s )
3449
50+ @classmethod
51+ def random (_cls , lower_bound , upper_bound ):
52+ """Generates a random Currency instance between a provided lower_bound and upper_bound
53+
54+ Arguments:
55+ lower_bound {Currency} -- A Currency instance representing the lower bound for the randomly generated value
56+ upper_bound {Currency} -- A Currency instance representing the upper bound for the randomly generated value
57+
58+ Returns:
59+ Currency - A randomly generated Currency instance between the lower_bound and upper_bound
60+ """
61+ if not (isinstance (lower_bound , Currency ) and isinstance (upper_bound , Currency )):
62+ raise Exception ('invalid call to Currency.random: lower and upper bound must be instances of Currency' )
63+ if not upper_bound .nanocodas () >= lower_bound .nanocodas ():
64+ raise Exception ('invalid call to Currency.random: upper_bound is not greater than lower_bound' )
65+ if lower_bound == upper_bound :
66+ return lower_bound
67+ bound_range = upper_bound .nanocodas () - lower_bound .nanocodas ()
68+ delta = random .randint (0 , bound_range )
69+ return lower_bound + Currency (delta , format = CurrencyFormat .NANO )
70+
3571 def __init__ (self , value , format = CurrencyFormat .WHOLE ):
72+ """Constructs a new Currency instance. Values of different CurrencyFormats may be passed in to construct the instance.
73+
74+ Arguments:
75+ value {int|float|string} - The value to construct the Currency instance from
76+ format {CurrencyFormat} - The representation format of the value
77+
78+ Return:
79+ Currency - The newly constructed Currency instance
80+
81+ In the case of format=CurrencyFormat.WHOLE, then it is interpreted as value * 10^9 nanocodas.
82+ In the case of format=CurrencyFormat.NANO, value is only allowed to be an int, as there can be no decimal point for nanocodas.
83+ """
3684 if format == CurrencyFormat .WHOLE :
3785 if isinstance (value , int ):
3886 self .__nanocodas = Currency .__nanocodas_from_int (value )
@@ -51,13 +99,23 @@ def __init__(self, value, format=CurrencyFormat.WHOLE):
5199 raise Exception ('invalid Currency format %s' % format )
52100
53101 def decimal_format (self ):
102+ """Computes the string decimal format representation of a Currency instance.
103+
104+ Return:
105+ str - The decimal format representation of the Currency instance
106+ """
54107 s = str (self .__nanocodas )
55108 if len (s ) > 9 :
56109 return s [:- 9 ] + '.' + s [- 9 :]
57110 else :
58111 return '0.' + ('0' * (9 - len (s ))) + s
59112
60113 def nanocodas (self ):
114+ """Accesses the raw nanocodas representation of a Currency instance.
115+
116+ Return:
117+ int - The nanocodas of the Currency instance represented as an integer
118+ """
61119 return self .__nanocodas
62120
63121 def __str__ (self ):
0 commit comments