/vqdr/trunk

To get this branch, use:
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 */