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 }