rufus-decision 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.txt CHANGED
@@ -2,6 +2,18 @@
2
2
  = rufus-decision CHANGELOG.txt
3
3
 
4
4
 
5
+ == rufus-decision - 1.3.0 released 2010/02/15
6
+
7
+ - removing 'require "rubygems"' from lib/ (argh)
8
+ - moving to jeweler (thanks Kenneth Kalmer)
9
+ - lib/rufus/decision/ dir
10
+
11
+
12
+ == rufus-decision - 1.2.0 released 2009/09/07
13
+
14
+ - issue 1 : made 'bounded' default and added 'unbounded' option
15
+
16
+
5
17
  == rufus-decision - 1.1 released 2009/04/25
6
18
 
7
19
  - todo #25670 : :ruby_eval settable at table initialization
data/CREDITS.txt CHANGED
@@ -3,5 +3,6 @@
3
3
 
4
4
  == Feedback
5
5
 
6
+ - ocgarlan
6
7
  - Fu Zhang
7
8
 
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+
2
+ Copyright (c) 2006-2010, John Mettraux, jmettraux@gmail.com
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in
12
+ all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+
data/README.txt CHANGED
@@ -4,16 +4,14 @@
4
4
 
5
5
  == getting it
6
6
 
7
- sudo gem install -y rufus-decision
7
+ gem install rufus-decision
8
8
 
9
- or at
10
-
11
- http://rubyforge.org/frs/?group_id=4812
12
9
 
13
10
  == intro blog post
14
11
 
15
12
  http://jmettraux.wordpress.com/2009/04/25/rufus-decision-11-ruby-decision-tables/
16
13
 
14
+
17
15
  == usage
18
16
 
19
17
  More info at http://rufus.rubyforge.org/rufus-decision/classes/Rufus/Decision/Table.html but here is a recap.
@@ -102,7 +100,7 @@ WARNING though : use at your own risk. CSV loaded from untrusted locations may c
102
100
 
103
101
  == uninstalling it
104
102
 
105
- sudo gem uninstall -y rufus-decision
103
+ gem uninstall rufus-decision
106
104
 
107
105
 
108
106
  == dependencies
@@ -124,7 +122,7 @@ irc.freenode.net #ruote
124
122
 
125
123
  == issue tracker
126
124
 
127
- http://rubyforge.org/tracker/?atid=18584&group_id=4812&func=browse
125
+ http://github.com/jmettraux/rufus-decision/issues
128
126
 
129
127
 
130
128
  == source
data/Rakefile ADDED
@@ -0,0 +1,80 @@
1
+
2
+
3
+ require 'lib/rufus/decision/version.rb'
4
+
5
+ require 'rubygems'
6
+ require 'rake'
7
+
8
+
9
+ #
10
+ # CLEAN
11
+
12
+ require 'rake/clean'
13
+ CLEAN.include('pkg', 'tmp', 'html')
14
+ task :default => [ :clean ]
15
+
16
+
17
+ #
18
+ # GEM
19
+
20
+ require 'jeweler'
21
+
22
+ Jeweler::Tasks.new do |gem|
23
+
24
+ gem.version = Rufus::Decision::VERSION
25
+ gem.name = 'rufus-decision'
26
+ gem.summary = 'CSV based Ruby decision tables'
27
+
28
+ gem.description = %{
29
+ CSV based Ruby decision tables
30
+ }
31
+ gem.email = 'jmettraux@gmail.com'
32
+ gem.homepage = 'http://github.com/jmettraux/rufus-decision/'
33
+ gem.authors = [ 'John Mettraux' ]
34
+ gem.rubyforge_project = 'rufus'
35
+
36
+ gem.test_file = 'test/test.rb'
37
+
38
+ gem.add_dependency 'rufus-dollar'
39
+ gem.add_dependency 'rufus-treechecker'
40
+ gem.add_development_dependency 'yard'
41
+ gem.add_development_dependency 'jeweler'
42
+
43
+ # gemspec spec : http://www.rubygems.org/read/chapter/20
44
+ end
45
+ Jeweler::GemcutterTasks.new
46
+
47
+
48
+ #
49
+ # DOC
50
+
51
+ begin
52
+
53
+ require 'yard'
54
+
55
+ YARD::Rake::YardocTask.new do |doc|
56
+ doc.options = [
57
+ '-o', 'html/rufus-decision', '--title',
58
+ "rufus-decision #{Rufus::Decision::VERSION}"
59
+ ]
60
+ end
61
+
62
+ rescue LoadError
63
+
64
+ task :yard do
65
+ abort "YARD is not available : sudo gem install yard"
66
+ end
67
+ end
68
+
69
+
70
+ #
71
+ # TO THE WEB
72
+
73
+ task :upload_website => [ :clean, :yard ] do
74
+
75
+ account = 'jmettraux@rubyforge.org'
76
+ webdir = '/var/www/gforge-projects/rufus'
77
+
78
+ sh "rsync -azv -e ssh html/rufus-decision #{account}:#{webdir}/"
79
+ end
80
+
data/TODO.txt ADDED
@@ -0,0 +1,8 @@
1
+
2
+ [x] transform(h, options), :accumulate option ? NO
3
+
4
+
5
+ [ ] non csv string representation ?
6
+ [ ] dsl ?
7
+ [ ] ruote participant
8
+
@@ -0,0 +1,7 @@
1
+ data_decision = [
2
+ [ 'in:age', 'in:trait', 'out:salesperson' ],
3
+ [ '18..35', '', 'Adeslky' ],
4
+ [ '25..35', '', 'Bronco' ],
5
+ [ '36..50', '', 'Espradas' ],
6
+ [ '', 'maniac', 'Korolev' ],
7
+ ];
Binary file
Binary file
data/demo/public/in.js ADDED
@@ -0,0 +1,5 @@
1
+ data_in = [
2
+ [ 'age', 'trait', 'name' ],
3
+ [ 33, 'goofy', 'Longbow' ],
4
+ [ 45, 'maniac', 'Baumgartner' ],
5
+ ];
@@ -0,0 +1,140 @@
1
+
2
+ <html>
3
+ <head>
4
+ <title>testing a decision table</title>
5
+ <style>
6
+
7
+ /* tb rl */
8
+ /* t r b l */
9
+
10
+ body {
11
+ font-family: "Helvetica Neue Light", Helvetica, Arial, sans-serif;
12
+ font-size: 12pt;
13
+ }
14
+
15
+ #central {
16
+ }
17
+ #left_pane {
18
+ width: 100px;
19
+ float: left;
20
+ }
21
+ #right_pane {
22
+ margin-left: 10px;
23
+ float: left;
24
+ }
25
+
26
+ .table_buttons {
27
+ font-size: 70%
28
+ }
29
+
30
+ .ruse_cell {
31
+ border-top: 1px solid #dddddd;
32
+ border-left: 1px solid #dddddd;
33
+ border-right: 1px solid #F0F0F0;
34
+ border-bottom: 1px solid #F0F0F0;
35
+ margin: 0;
36
+ padding: 0;
37
+ text-align: right;
38
+ }
39
+ /*.ruse_cell:focus { // not used
40
+ background-color: #f0f0f0;
41
+ }*/
42
+ .focused {
43
+ background-color: #f0f0f0;
44
+ }
45
+ .ruse_headcell {
46
+ height: 1em;
47
+ float: left;
48
+ background: #f0f0f0 url(/images/ruse_head_bg.png) repeat top left;
49
+ }
50
+ .ruse_headcell_left {
51
+ float: left;
52
+ background: white;
53
+ height: 1em;
54
+ width: 1px;
55
+ }
56
+ .ruse_headcell_handle {
57
+ height: 1em;
58
+ width: 3px;
59
+ cursor: w-resize;
60
+ float: right;
61
+ }
62
+ </style>
63
+
64
+ <script src="js/fluo-json.js"></script>
65
+ <script src="js/ruote-sheets.js"></script>
66
+ <script src="js/request.js"></script>
67
+ </head>
68
+
69
+ <body>
70
+
71
+ <div id="central">
72
+
73
+ <div id="left_pane">
74
+ <img src="/images/arrow.png" align="right"/>
75
+ </div>
76
+
77
+ <div id="right_pane">
78
+
79
+ in : <span class="table_buttons">
80
+ <a href="#" onclick="RuoteSheets.addRow('sheet_in');">add row</a>
81
+ <a href="#" onclick="RuoteSheets.addCol('sheet_in');">add col</a>
82
+ <a href="#" onclick="RuoteSheets.deleteRow('sheet_in');">del row</a>
83
+ <a href="#" onclick="RuoteSheets.deleteCol('sheet_in');">del col</a>
84
+ <a href="#" onclick="RuoteSheets.undo('sheet_in');">undo</a>
85
+ </span>
86
+ <div id='sheet_in'></div>
87
+
88
+ <br/>
89
+
90
+ decision table : <span class="table_buttons">
91
+ <a href="#" onclick="RuoteSheets.addRow('sheet_decision');">add row</a>
92
+ <a href="#" onclick="RuoteSheets.addCol('sheet_decision');">add col</a>
93
+ <a href="#" onclick="RuoteSheets.deleteRow('sheet_decision');">del row</a>
94
+ <a href="#" onclick="RuoteSheets.deleteCol('sheet_decision');">del col</a>
95
+ <a href="#" onclick="RuoteSheets.undo('sheet_decision');">undo</a>
96
+ </span>
97
+ <div id='sheet_decision'></div>
98
+
99
+ <br/>
100
+
101
+ <input type="submit" onclick='return decide();' value='decide !'/><br />
102
+
103
+ <br/>
104
+
105
+ out :
106
+ <div id='sheet_out'></div>
107
+
108
+ </div>
109
+
110
+ </div>
111
+
112
+ <!-- some javascript -->
113
+
114
+ <script src="/in.js"></script>
115
+ <script src="/decision.js"></script>
116
+
117
+ <script>
118
+
119
+ RuoteSheets.render('sheet_in', data_in);
120
+ RuoteSheets.render('sheet_decision', data_decision);
121
+
122
+ function decide () {
123
+
124
+ var data =
125
+ '[' +
126
+ fluoToJson(RuoteSheets.toArray('sheet_in')) + ',' +
127
+ fluoToJson(RuoteSheets.toArray('sheet_decision')) +
128
+ ']';
129
+
130
+ var result = httpPost('/decision', data);
131
+ result = fluoFromJson(result);
132
+
133
+ RuoteSheets.render('sheet_out', result);
134
+ }
135
+
136
+ </script>
137
+
138
+ </body>
139
+ </html>
140
+
@@ -0,0 +1,186 @@
1
+ // Copyright (C) 2008 Google Inc.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ // ruote 'source' :
16
+ // http://github.com/jmettraux/ruote-fluo/tree/master/public/js/fluo-json.js
17
+
18
+ /**
19
+ * @param {string} json per RFC 4627
20
+ * @return {Object|Array}
21
+ * @author Mike Samuel <mikesamuel@gmail.com>
22
+ */
23
+ //var jsonParse = (function () {
24
+ var fluoFromJson = (function () {
25
+ var number
26
+ = '(?:-?\\b(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\\b)';
27
+ var oneChar = '(?:[^\\0-\\x08\\x0a-\\x1f\"\\\\]'
28
+ + '|\\\\(?:[\"/\\\\bfnrt]|u[0-9A-Fa-f]{4}))';
29
+ var string = '(?:\"' + oneChar + '*\")';
30
+
31
+ // Will match a value in a well-formed JSON file.
32
+ // If the input is not well-formed, may match strangely, but not in an unsafe
33
+ // way.
34
+ // Since this only matches value tokens, it does not match whitespace, colons,
35
+ // or commas.
36
+ var jsonToken = new RegExp(
37
+ '(?:false|true|null|[\\{\\}\\[\\]]'
38
+ + '|' + number
39
+ + '|' + string
40
+ + ')', 'g');
41
+
42
+ // Matches escape sequences in a string literal
43
+ var escapeSequence = new RegExp('\\\\(?:([^u])|u(.{4}))', 'g');
44
+
45
+ // Decodes escape sequences in object literals
46
+ var escapes = {
47
+ '"': '"',
48
+ '/': '/',
49
+ '\\': '\\',
50
+ 'b': '\b',
51
+ 'f': '\f',
52
+ 'n': '\n',
53
+ 'r': '\r',
54
+ 't': '\t'
55
+ };
56
+ function unescapeOne(_, ch, hex) {
57
+ return ch ? escapes[ch] : String.fromCharCode(parseInt(hex, 16));
58
+ }
59
+
60
+ // A non-falsy value that coerces to the empty string when used as a key.
61
+ var EMPTY_STRING = new String('');
62
+ var SLASH = '\\';
63
+
64
+ // Constructor to use based on an open token.
65
+ var firstTokenCtors = { '{': Object, '[': Array };
66
+
67
+ return function (json) {
68
+ // Split into tokens
69
+ var toks = json.match(jsonToken);
70
+ // Construct the object to return
71
+ var result;
72
+ var tok = toks[0];
73
+ if ('{' === tok) {
74
+ result = {};
75
+ } else if ('[' === tok) {
76
+ result = [];
77
+ } else {
78
+ throw new Error(tok);
79
+ }
80
+
81
+ // If undefined, the key in an object key/value record to use for the next
82
+ // value parsed.
83
+ var key;
84
+ // Loop over remaining tokens maintaining a stack of uncompleted objects and
85
+ // arrays.
86
+ var stack = [result];
87
+ for (var i = 1, n = toks.length; i < n; ++i) {
88
+ tok = toks[i];
89
+
90
+ var cont;
91
+ switch (tok.charCodeAt(0)) {
92
+ default: // sign or digit
93
+ cont = stack[0];
94
+ cont[key || cont.length] = +(tok);
95
+ key = void 0;
96
+ break;
97
+ case 0x22: // '"'
98
+ tok = tok.substring(1, tok.length - 1);
99
+ if (tok.indexOf(SLASH) !== -1) {
100
+ tok = tok.replace(escapeSequence, unescapeOne);
101
+ }
102
+ cont = stack[0];
103
+ if (!key) {
104
+ if (cont instanceof Array) {
105
+ key = cont.length;
106
+ } else {
107
+ key = tok || EMPTY_STRING; // Use as key for next value seen.
108
+ break;
109
+ }
110
+ }
111
+ cont[key] = tok;
112
+ key = void 0;
113
+ break;
114
+ case 0x5b: // '['
115
+ cont = stack[0];
116
+ stack.unshift(cont[key || cont.length] = []);
117
+ key = void 0;
118
+ break;
119
+ case 0x5d: // ']'
120
+ stack.shift();
121
+ break;
122
+ case 0x66: // 'f'
123
+ cont = stack[0];
124
+ cont[key || cont.length] = false;
125
+ key = void 0;
126
+ break;
127
+ case 0x6e: // 'n'
128
+ cont = stack[0];
129
+ cont[key || cont.length] = null;
130
+ key = void 0;
131
+ break;
132
+ case 0x74: // 't'
133
+ cont = stack[0];
134
+ cont[key || cont.length] = true;
135
+ key = void 0;
136
+ break;
137
+ case 0x7b: // '{'
138
+ cont = stack[0];
139
+ stack.unshift(cont[key || cont.length] = {});
140
+ key = void 0;
141
+ break;
142
+ case 0x7d: // '}'
143
+ stack.shift();
144
+ break;
145
+ }
146
+ }
147
+ // Fail if we've got an uncompleted object.
148
+ if (stack.length) { throw new Error(); }
149
+ return result;
150
+ };
151
+ })();
152
+
153
+
154
+ //
155
+ // the following code is ruote-fluo code, under the BSD license.
156
+ //
157
+ function fluoToJson (o, quotes) {
158
+ if (quotes != false) quotes = true;
159
+ if (o == null) return 'null';
160
+ var t = (typeof o);
161
+ if (t == 'undefined') return 'null' // really ?
162
+ if (t == 'number') return o;
163
+ if (t == 'string') {
164
+ //return quotes ? '"' + o + '"' : o;
165
+ if ( ! quotes) return o;
166
+ return '"' +
167
+ o
168
+ .replace(/"/g, '\\"')
169
+ .replace(/\r/g, '')
170
+ .replace(/\n/g, '\\n') +
171
+ '"';
172
+ // this global replace works with safari (webkit) and ffox
173
+ }
174
+ if (o.constructor.toString().indexOf(' Array()') == 8) {
175
+ var a = [];
176
+ for (var i = 0; i < o.length; i++) a.push(fluoToJson(o[i]));
177
+ return '[' + a.join(', ') + ']';
178
+ }
179
+ if (t == 'object') {
180
+ var a = [];
181
+ for (var key in o) a.push(fluoToJson(key) + ': ' + fluoToJson(o[key]));
182
+ return '{' + a.join(', ') + '}';
183
+ }
184
+ return o.toString();
185
+ }
186
+