1 module tagion.script.TagionCurrency;
2 
3 import std.format;
4 import std.traits : isNumeric;
5 
6 //import std.algorithm.searching : canFind;
7 import std.exception : assumeWontThrow;
8 
9 //import std.range : only;
10 //import std.array : join;
11 //import std.conv : to;
12 
13 //import tagion.hibon.HiBONRecord : HiBONRecord, label, recordType;
14 import tagion.script.Currency;
15 
16 @safe
17 TagionCurrency TGN(T)(T x) pure if (isNumeric!T) {
18     return TagionCurrency(cast(double) x);
19 }
20 
21 alias TagionCurrency = Currency!("TGN", 1_000_000_000, 1_000_000_000);
22 @safe ///
23 unittest {
24     //import std.stdio;
25     import std.exception : assertThrown;
26 
27     // Checks for illegal opBinary operators
28     static foreach (op; ["*", "/"]) {
29         {
30             enum code = format(
31                         q{
32                         static assert(!__traits(compiles, 10.TGN %s 12.TGN));
33                     }, op);
34             mixin(code);
35         }
36     }
37     // Checks for illegal opBinaryRight operators
38     static foreach (op; ["/", "%"]) {
39         {
40             enum code = format(
41                         q{
42                         static assert(!__traits(compiles, 4 %s 12.TGN));
43                     }, op);
44             mixin(code);
45         }
46     }
47 
48     // Check for illegal opOpAssign operators
49     static foreach (op; ["*=", "/="]) {
50         {
51             enum code = format!q{
52                 static assert(!__traits(compiles,
53                 ()
54                 {
55                     TagionCurrency x;
56                     x %s x;
57                 }));
58             }(op);
59             mixin(code);
60         }
61     }
62 
63     { // test of opEqual, opBinary, opBinaryRight, opUnary, opCmp
64         const x = 11.TGN;
65         const y = 31.TGN;
66         assert(x == 11 * TagionCurrency.BASE_UNIT);
67         assert(x + y == 42.TGN);
68         const z = x.opBinary!"+"(31 * TagionCurrency.BASE_UNIT);
69         assert(x + (31 * TagionCurrency.BASE_UNIT) == 42.TGN);
70         assert(x * 4 == 44.TGN);
71         assert(x / 4 == 2.75.TGN);
72         assert(y - x == 20.TGN);
73         assert(x - y == -20.TGN); // Check opUnary
74         assert(y - x * 2 == 9.TGN);
75         assert((x + 0.1.TGN) % 0.25.TGN == 0.1.TGN);
76         // check opBinaryRight
77         assert(4 * x == 44.TGN);
78         assert(4 * TagionCurrency.BASE_UNIT + x == 15.TGN);
79         assert(4 * TagionCurrency.BASE_UNIT - x == -7.TGN);
80         // test opCmp
81         assert(x < y);
82         assert(!(x > y));
83         const x_same = 11 * TagionCurrency.BASE_UNIT;
84         assert(x >= x_same);
85         assert(x <= x_same);
86         assert(x - y < -11 * TagionCurrency.BASE_UNIT);
87         assert(y - x > 11 * TagionCurrency.BASE_UNIT);
88     }
89 
90     { // test opOpAssign
91         auto x = 11.TGN;
92         auto y = 31.TGN;
93         y += x;
94         assert(y == 11.TGN + 31.TGN);
95         y -= 2 * x;
96         assert(y == 31.TGN - 11.TGN);
97         x += 5 * TagionCurrency.BASE_UNIT;
98         assert(x == 11.TGN + 5.TGN);
99         x -= 5 * TagionCurrency.BASE_UNIT;
100         assert(x == 11.TGN);
101         x *= 5;
102         assert(x == 5 * 11.TGN);
103         x /= 5;
104         assert(x == 11.TGN);
105         x += 0.1.TGN;
106         x %= 0.25.TGN;
107         assert(x == 0.1.TGN);
108 
109     }
110 
111     { // Check over and underflow
112         import tagion.script.ScriptException : ScriptException;
113 
114         const very_rich = (TagionCurrency.UNIT_MAX / TagionCurrency.BASE_UNIT - 1).TGN;
115         assertThrown!ScriptException(very_rich + 2.TGN);
116         const very_poor = (-TagionCurrency.UNIT_MAX / TagionCurrency.BASE_UNIT + 1).TGN;
117         assertThrown!ScriptException(very_poor - 2.TGN);
118 
119     }
120 
121     { // Check casting to double
122         import std.math : isClose;
123 
124         const x = 5.465.TGN;
125         const x_double = cast(double) x;
126         assert(isClose(x_double, 5.465, 1e-9));
127         const x_back_tgn = x_double.TGN;
128         assert(x_back_tgn == 5.465);
129     }
130 
131 
132     {
133         const x = 1_000_000_000.TGN;
134         const y = 1_000_000_000.TGN;
135 
136         import std.exception;
137         assertThrown([x,y].totalAmount);
138     }
139 }
140 
141 @safe 
142 unittest {
143     // subtract tagioncurrency value from bignumber
144     import tagion.hibon.BigNumber;
145 
146 
147     BigNumber some_big_number = BigNumber(1000);
148     TagionCurrency to_subtract = 10.TGN;
149 
150     auto t = some_big_number - to_subtract.axios;
151     // writefln("SOME BIG NUMBER: %s", t);
152 
153 
154 
155 
156 
157 
158 
159 
160 }