/vqdr/trunk

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/vqdr/trunk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
using VQDR.Expression;
using VQDR.Common;

public class RollAndKeepFunctionToken : FunctionToken {
  private const int INDEX_ROLL = 1;
  private const int INDEX_POOL = 1;
  private const int INDEX_KEEP = 2;

  private const int MAX_POOL_SIZE = 50;

  private long[] roll_values  = null; // = new long[MAX_POOL_SIZE];
  private bool[] valid_values = null; // = new bool[MAX_POOL_SIZE];

  construct {
    mandatory_num_child = 2;
    optional_num_child = 1;
  }

  protected override void evaluate_self (VQDR.Expression.Context instance) throws GLib.Error {
    Token? roll;
    long  pool_size;
    long keep_size;
    
    roll = get_child (INDEX_ROLL);
    try {
      get_child (INDEX_POOL).evaluate (instance);
    } catch (Error e) {
      stderr.printf ("Error: %s, Error Domain: %s\n",
                     e.message, e.domain.to_string ());
      GLib.assert_not_reached ();
    }
    pool_size = get_child (INDEX_POOL).result_value.to_int ();

    if (pool_size > MAX_POOL_SIZE) {
      throw new ParamError.OUT_OF_BOUNDS (@"Max value $MAX_POOL_SIZE, got $pool_size");
    }

    if (pool_size < 0) {
      pool_size = 0;
    }

    {
      Token? keep_child = get_child (INDEX_KEEP);
      if (keep_child != null) {
        keep_child.evaluate (instance);
        keep_size = keep_child.result_value.to_int ();
      } else {
        keep_size = pool_size;
      }
    }

    if (keep_size > pool_size) {
      keep_size = pool_size;
    }

    /* */

    long roll_result;
    long min_keep = long.MAX;
    int min_keep_index = 0;
    
    if (roll_values == null || roll_values.length < pool_size) {
      roll_values  = new long[pool_size];
      valid_values = new bool[pool_size];
    }

    for (int i = 0; i < pool_size; i++) {
      roll.evaluate (instance);
      roll_result = roll.result_value.raw_number;
      
      roll_values[i] = roll_result;
      valid_values[i] = true;

      if (i < keep_size) {
        // simply keep and detect the minium kept value
        if (min_keep > roll_result) {
          min_keep = roll_result;
          min_keep_index = i;
        }
      } else {
        // Chose what to do.
        if (roll_result >= min_keep) {
          // Discard the Minimum value
          valid_values[min_keep_index] = false;

          // Search for new Minimum value
          min_keep = long.MAX;
          min_keep_index = 0;

          for (int j = 0; j <= i; j++) {
            if (valid_values[j]) {
              if (min_keep > roll_values[j]) {
                min_keep = roll_values[j];
                min_keep_index = j;
              }
            }
          }
        } else {
          valid_values[i] = false;
        }
      }
    } // end for loop

    StringBuilder strbldr = new StringBuilder ();
    strbldr.append (SYM_BEGIN);
    
    FastNumber tmp_fstnmbr;

    for (int i = 0; i < pool_size; i++) {
      if (strbldr.len < MAX_TOKEN_STRING_LENGTH) {
        //we don't start with a seperator mark.
        if (i > 0) {
          strbldr.append (SYM_SEP);
        }
        // We don't want to deal with the conertion directly.
        // FIXME: Convert everything to FastNumbers instead of using "raw" values?
        tmp_fstnmbr = FastNumber.raw (roll_values[i]);
        strbldr.append (tmp_fstnmbr.to_string ());
        
        if (valid_values[i] && keep_size != pool_size) {
          strbldr.append (SYM_SELECTED);
        }
      }
      if (valid_values[i]) {
        tmp_fstnmbr = FastNumber.raw (roll_values[i]);
        result_value.add (tmp_fstnmbr);
      }
    }
    
    result_max_value = roll.result_max_value.multiply (FastNumber(keep_size));
    result_min_value = roll.result_min_value.multiply (FastNumber(keep_size));

    if (strbldr.len < MAX_TOKEN_STRING_LENGTH) {
      strbldr.append (SYM_END);
      result_string = strbldr.str;
    } else {
      result_string = SYM_TRUNK_BEGIN + result_value.to_string () + SYM_TRUNK_END;
    }
  }
  
}
/* vim: set tabstop=2:softtabstop=2:shiftwidth=2:expandtab */