bzr branch
http://gegoxaren.bato24.eu/bzr/vqdr/trunk
|
32
by Gustav Hartvigsson
Added RollAndKeepFunctionToken. |
1 |
using VQDR.Expression; |
2 |
using VQDR.Common; |
|
3 |
||
4 |
public class RollAndKeepFunctionToken : FunctionToken { |
|
5 |
private const int INDEX_ROLL = 1; |
|
6 |
private const int INDEX_POOL = 1; |
|
7 |
private const int INDEX_KEEP = 2; |
|
8 |
||
9 |
private const int MAX_POOL_SIZE = 50; |
|
10 |
||
11 |
private long[] roll_values = null; // = new long[MAX_POOL_SIZE]; |
|
12 |
private bool[] valid_values = null; // = new bool[MAX_POOL_SIZE]; |
|
13 |
||
14 |
construct { |
|
15 |
mandatory_num_child = 2; |
|
16 |
optional_num_child = 1; |
|
17 |
} |
|
18 |
||
19 |
protected override void evaluate_self (VQDR.Expression.Context instance) throws GLib.Error { |
|
20 |
Token? roll; |
|
21 |
long pool_size; |
|
22 |
long keep_size; |
|
23 |
|
|
24 |
roll = get_child (INDEX_ROLL); |
|
25 |
try { |
|
26 |
get_child (INDEX_POOL).evaluate (instance); |
|
27 |
} catch (Error e) { |
|
28 |
stderr.printf ("Error: %s, Error Domain: %s\n", |
|
29 |
e.message, e.domain.to_string ()); |
|
30 |
GLib.assert_not_reached (); |
|
31 |
} |
|
32 |
pool_size = get_child (INDEX_POOL).result_value.to_int (); |
|
33 |
||
34 |
if (pool_size > MAX_POOL_SIZE) { |
|
35 |
throw new ParamError.OUT_OF_BOUNDS (@"Max value $MAX_POOL_SIZE, got $pool_size"); |
|
36 |
} |
|
37 |
||
38 |
if (pool_size < 0) { |
|
39 |
pool_size = 0; |
|
40 |
} |
|
41 |
||
42 |
{ |
|
43 |
Token? keep_child = get_child (INDEX_KEEP); |
|
44 |
if (keep_child != null) { |
|
45 |
keep_child.evaluate (instance); |
|
46 |
keep_size = keep_child.result_value.to_int (); |
|
47 |
} else { |
|
48 |
keep_size = pool_size; |
|
49 |
} |
|
50 |
} |
|
51 |
||
52 |
if (keep_size > pool_size) { |
|
53 |
keep_size = pool_size; |
|
54 |
} |
|
55 |
||
56 |
/* */ |
|
57 |
||
58 |
long roll_result; |
|
59 |
long min_keep = long.MAX; |
|
60 |
int min_keep_index = 0; |
|
61 |
|
|
62 |
if (roll_values == null || roll_values.length < pool_size) { |
|
63 |
roll_values = new long[pool_size]; |
|
64 |
valid_values = new bool[pool_size]; |
|
65 |
} |
|
66 |
||
67 |
for (int i = 0; i < pool_size; i++) { |
|
68 |
roll.evaluate (instance); |
|
69 |
roll_result = roll.result_value.raw_number; |
|
70 |
|
|
71 |
roll_values[i] = roll_result; |
|
72 |
valid_values[i] = true; |
|
73 |
||
74 |
if (i < keep_size) { |
|
75 |
// simply keep and detect the minium kept value |
|
76 |
if (min_keep > roll_result) { |
|
77 |
min_keep = roll_result; |
|
78 |
min_keep_index = i; |
|
79 |
} |
|
80 |
} else { |
|
81 |
// Chose what to do. |
|
82 |
if (roll_result >= min_keep) { |
|
83 |
// Discard the Minimum value |
|
84 |
valid_values[min_keep_index] = false; |
|
85 |
||
86 |
// Search for new Minimum value |
|
87 |
min_keep = long.MAX; |
|
88 |
min_keep_index = 0; |
|
89 |
||
90 |
for (int j = 0; j <= i; j++) { |
|
91 |
if (valid_values[j]) { |
|
92 |
if (min_keep > roll_values[j]) { |
|
93 |
min_keep = roll_values[j]; |
|
94 |
min_keep_index = j; |
|
95 |
} |
|
96 |
} |
|
97 |
} |
|
98 |
} else { |
|
99 |
valid_values[i] = false; |
|
100 |
} |
|
101 |
} |
|
102 |
} // end for loop |
|
103 |
||
104 |
StringBuilder strbldr = new StringBuilder (); |
|
105 |
strbldr.append (SYM_BEGIN); |
|
106 |
|
|
107 |
FastNumber tmp_fstnmbr; |
|
108 |
||
109 |
for (int i = 0; i < pool_size; i++) { |
|
110 |
if (strbldr.len < MAX_TOKEN_STRING_LENGTH) { |
|
111 |
//we don't start with a seperator mark. |
|
112 |
if (i > 0) { |
|
113 |
strbldr.append (SYM_SEP); |
|
114 |
} |
|
115 |
// We don't want to deal with the conertion directly. |
|
116 |
// FIXME: Convert everything to FastNumbers instead of using "raw" values? |
|
117 |
tmp_fstnmbr = FastNumber.raw (roll_values[i]); |
|
118 |
strbldr.append (tmp_fstnmbr.to_string ()); |
|
119 |
|
|
120 |
if (valid_values[i] && keep_size != pool_size) { |
|
121 |
strbldr.append (SYM_SELECTED); |
|
122 |
} |
|
123 |
} |
|
124 |
if (valid_values[i]) { |
|
125 |
tmp_fstnmbr = FastNumber.raw (roll_values[i]); |
|
126 |
result_value.add (tmp_fstnmbr); |
|
127 |
} |
|
128 |
} |
|
129 |
|
|
130 |
result_max_value = roll.result_max_value.multiply (FastNumber(keep_size)); |
|
131 |
result_min_value = roll.result_min_value.multiply (FastNumber(keep_size)); |
|
132 |
||
133 |
if (strbldr.len < MAX_TOKEN_STRING_LENGTH) { |
|
134 |
strbldr.append (SYM_END); |
|
135 |
result_string = strbldr.str; |
|
136 |
} else { |
|
137 |
result_string = SYM_TRUNK_BEGIN + result_value.to_string () + SYM_TRUNK_END; |
|
138 |
} |
|
139 |
} |
|
140 |
|
|
141 |
}
|
|
|
33
by Gustav Hartvigsson
Added sudfolders to the tests folder for future use. |
142 |
/* vim: set tabstop=2:softtabstop=2:shiftwidth=2:expandtab */ |