SimpleOutput 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,138 @@
1
+ =begin
2
+ SimpleOutput
3
+
4
+ Copyright 2014 Austen Higgins-Cassidy
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ =end
18
+
19
+ class SimpleChartkick < SimpleOutput::SimpleOutputPlugin
20
+
21
+ require 'json'
22
+
23
+ def initialize(filename="results.html", title="Html Results Page", javascript_path="../include")
24
+ super()
25
+ @filename = filename
26
+ @chart_type = {}
27
+ chartkick_path = javascript_path + ((javascript_path[-1] == "/") ? "chartkick.js" : "/chartkick.js");
28
+ @html = "<html>\n<title>\n#{title}\n</title>\n<script src='http://www.google.com/jsapi'></script>\n
29
+ <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js'></script>
30
+ <script src='#{chartkick_path}'></script>\n<body>\n"
31
+
32
+ end
33
+
34
+ def options_callback(options)
35
+ if options.has_key?("chart_type")
36
+ @chart_type[@current_name] = options['chart_type']
37
+ end
38
+ end
39
+
40
+ #Rendering Functions functions
41
+ def write_html(content, index)
42
+ @html += content
43
+ end
44
+
45
+ def div(content, name = nil)
46
+ if name == nil
47
+ index = @chart_id
48
+ else
49
+ index = @chart_names[name]
50
+ end
51
+ self.write_html("<div>#{content}</div>\n", index)
52
+ end
53
+
54
+ def p(content, name = nil)
55
+ if name == nil
56
+ index = @chart_id
57
+ else
58
+ index = @chart_names[name]
59
+ end
60
+ self.write_html("<p>#{content}</p>\n", index)
61
+ end
62
+
63
+ def chart_div(data, type="LineChart", name=nil)
64
+ #Convert data to pairs
65
+ @chart_id = @chart_id + 1
66
+ if name != nil
67
+ self.div("<h1>#{name}</h1>")
68
+ end
69
+ self.write_html("<div id='chart-#{@chart_id}' style='height:450px;'></div>\n", @chart_id);
70
+ @js_block += "new Chartkick.#{type}('chart-#{@chart_id}'," + data.to_json + ", {'format':'string'});\n"
71
+ end
72
+
73
+ def linechart(data)
74
+ #Accepts a name:value hash {"Football" => 10, "Basketball" => 5}
75
+ #or a array of pairs [["Football", 10], ["Basketball", 5]]
76
+ #may also nest series with a hash {:name => "Trial1", :data => trial1_data},...
77
+ self.chart_div("LineChart",data)
78
+ end
79
+
80
+ def piechart(data)
81
+ #does not accept multiple series
82
+ self.chart_div("PieChart",data)
83
+ end
84
+
85
+ def columnchart(data)
86
+ self.chart_div("ColumnChart",data)
87
+ end
88
+
89
+ def barchart(data)
90
+ self.chart_div("BarChart",data)
91
+ end
92
+
93
+ def areachart(data)
94
+ self.chart_div("AreaChart", data)
95
+ end
96
+
97
+ def getMultiSeriesHashes
98
+ data_hash = {}
99
+
100
+ @x.each_pair do |(key, x_series)|
101
+ data_hash[key] = []
102
+ y_series = @y[key]
103
+ x_series.each_with_index do |x_data, index|
104
+
105
+ y_data = y_series[index]
106
+ series_key = @series_names[key][index]
107
+ data_hash[key] << {'name' => series_key}
108
+ data_hash[key].last['data'] = {}
109
+ x_data.each_with_index do |x_point, index|
110
+ y_point = y_data[index]
111
+ data_hash[key].last['data'][x_point] = y_point
112
+ end
113
+ end
114
+ end
115
+ return data_hash
116
+ end
117
+
118
+ def save
119
+ @chart_id = 0
120
+ @js_block = ""
121
+
122
+ self.getMultiSeriesHashes.each_pair do |(chart_name, chart_series)|
123
+ type = @chart_type.has_key?(chart_name) ? @chart_type[chart_name] : "LineChart"
124
+ if type == "PieChart"
125
+ chart_series = chart_series[0]['data']
126
+ end
127
+ self.chart_div(chart_series, type, chart_name)
128
+ if @annotations.has_key?(chart_name)
129
+ @annotations[chart_name].each {|content| self.p(content)}
130
+ end
131
+ end
132
+ @html += "<script>$(function (){#{@js_block}});</script></body></html>"
133
+ File.open(@filename, "w") do |file|
134
+ file.syswrite(@html)
135
+ end
136
+ end
137
+
138
+ end
@@ -0,0 +1,319 @@
1
+ =begin
2
+
3
+ SimpleOutput Module
4
+ Copyright 2014 Austen Higgins-Cassidy
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ =end
18
+
19
+
20
+
21
+
22
+ module SimpleOutput
23
+ class SimpleOutputPlugin
24
+
25
+ def initialize()
26
+ @x = {}
27
+ @y = {}
28
+ @series_names = {}
29
+ @data_id = 0
30
+ @annotations = {}
31
+ @current_name = ""
32
+ @series_id = 0
33
+ end
34
+ #Virtual Functions
35
+ def options_callback(options)
36
+ end
37
+
38
+ def set_x_callback(data, name, options)
39
+ end
40
+
41
+ def set_y_callback(data, name, options)
42
+ end
43
+
44
+ def append_callback(x,y,name,options)
45
+ end
46
+
47
+ def new_series_callback(name)
48
+ end
49
+
50
+ #CORE functions
51
+ def translate_name(name)
52
+ if name == nil
53
+ name = @current_name
54
+ end
55
+ if !@x.has_key?(name)
56
+ @x[name] = []
57
+ end
58
+ if !@y.has_key?(name)
59
+ @y[name] = []
60
+ end
61
+ return name
62
+ end
63
+
64
+ def advance_series(name=nil)
65
+ @series_id += 1
66
+ @current_name = name == nil ? "series-#{@series_id}" : name
67
+ self.new_series_callback(name)
68
+ if !@series_names.has_key?(@current_name)
69
+ @series_names[@current_name] = []
70
+ end
71
+ @annotations[@current_name] = []
72
+ @current_name
73
+ end
74
+
75
+ def append_series_name(name=nil, options={})
76
+ name = translate_name(name)
77
+ if !@series_names.has_key?(name)
78
+ @series_names[name] = []
79
+ end
80
+ if options.has_key?('series')
81
+ @series_names[name] << options['series']
82
+ else
83
+ @series_names[name] << "data-#{@data_id}"
84
+ @data_id += 1
85
+ end
86
+ end
87
+
88
+ def setXData(data, name, options={})
89
+ @x[name] = []
90
+ @x[name] << data
91
+ self.set_x_callback(data, name, options)
92
+ end
93
+
94
+ def setYData(data, name, options={})
95
+ @y[name] = []
96
+ @y[name] << data
97
+ self.set_y_callback(data, name, options)
98
+ end
99
+
100
+ def newData( x=[], y=[],name=nil, options={})
101
+ name = self.advance_series(name)
102
+ self.setXData(x, name, options)
103
+ self.setYData(y, name, options)
104
+ self.append_series_name(name,options)
105
+ self.options_callback(options)
106
+ end
107
+
108
+ #Interface Functions ===================================
109
+ def appendXY( x=[], y=[],name=nil, options={})
110
+ name = translate_name(name)
111
+ @x[name] << x
112
+ @y[name] << y
113
+ self.append_series_name(name, options)
114
+ self.options_callback(options)
115
+ self.append_callback(x,y,name,options)
116
+ end
117
+
118
+ def setXY(x=[], y=[], name=nil, options={})
119
+ self.newData(x,y,name,options)
120
+ end
121
+
122
+ def appendPoints(points =[], name=nil, options={})
123
+ x = []
124
+ y = []
125
+ points.each do |point|
126
+ x << point[0]
127
+ y << point[1]
128
+ end
129
+ self.appendXY(x,y,name,options)
130
+ end
131
+
132
+ def setPoints(points = [], name=nil, options={})
133
+ x = []
134
+ y = []
135
+ points.each do |point|
136
+ x << point[0]
137
+ y << point[1]
138
+ end
139
+ self.setXY(x,y,name, options)
140
+ end
141
+
142
+ def appendHash(hash = {}, name=nil, options={})
143
+ name = translate_name(name)
144
+ x = []
145
+ y = []
146
+ hash.each_with_index do |(key, value), index|
147
+ if key.is_a? Numeric
148
+ x << key
149
+ else
150
+ x << index
151
+ end
152
+ if value.is_a? Numeric
153
+ y << value
154
+ else
155
+ y << 0
156
+ end
157
+ end
158
+ self.appendXY(x,y,name,options)
159
+ end
160
+
161
+ def setHash(hash ={}, name=nil, options={})
162
+ x = []
163
+ y = []
164
+ hash.each_with_index do |(key, value), index|
165
+ if key.is_a? Numeric
166
+ x << key
167
+ else
168
+ x << index
169
+ end
170
+ if value.is_a? Numeric
171
+ y << value
172
+ else
173
+ y << 0
174
+ end
175
+ end
176
+ self.setXY(x,y,name,options)
177
+ end
178
+
179
+ def annotate(annotation, name=nil, options = {})
180
+ name = translate_name(name)
181
+ @annotations[name] << annotation
182
+ self.options_callback(options)
183
+ end
184
+
185
+ #Internal Helpers
186
+ def getDataAsPoints
187
+ series_data = {}
188
+ @x.each_pair do |(key, x_series)|
189
+ #For each series of data
190
+ y_series = @y[key]
191
+ series_data[key] = []
192
+
193
+ x_series.each_with_index do |x_line, index|
194
+ #For each line
195
+ series_data[key] << [] #Create an empty set
196
+ y_line = y_series[index]
197
+ x_line.each_with_index do |x_point, index|
198
+ y_point = y_line[index]
199
+ series_data[key].last << [x_point, y_point]
200
+ end
201
+ end
202
+ end
203
+ return series_data
204
+ end
205
+
206
+ def getDataAsXY
207
+ series_data = {}
208
+ @x.each_pair do |(key, x_series)|
209
+ y_series = @y[key]
210
+ series_data[key] = []
211
+ x_series.each_with_index do |x_line, index|
212
+ y_line = y_series[index]
213
+ series_data[key] << [x_line, y_line]
214
+ end
215
+ end
216
+ return series_data
217
+ end
218
+
219
+ def getSeriesHashes
220
+ data_hash = {}
221
+
222
+ @x.each_pair do |(key, x_series)|
223
+
224
+ data_hash[key] = {}
225
+ y_series = @y[key]
226
+ x_series.each_with_index do |x_data, index|
227
+
228
+ y_data = y_series[index]
229
+ series_key = @series_names[key][index]
230
+ data_hash[key][series_key] = {}
231
+ x_data.each_with_index do |x_point, index|
232
+ y_point = y_data[index]
233
+ data_hash[key][series_key][x_point] = y_point
234
+ end
235
+ end
236
+ end
237
+ return data_hash
238
+ end
239
+
240
+ #Output
241
+ def save()
242
+
243
+ end
244
+
245
+ end
246
+
247
+ class SimpleOutputEngine
248
+
249
+ def initialize()
250
+ @plugins = []
251
+ @data_id = 0
252
+ end
253
+
254
+ def addPlugin(plugin)
255
+ @plugins << plugin
256
+ end
257
+
258
+ #Accept either [[x,y],[x,y]]
259
+ #Hash [name] = y
260
+ # array [x,y ]
261
+ #Interface Functions
262
+ def appendXY( x=[], y=[],name=nil, options={})
263
+ @plugins.each {|plugin| plugin.appendXY(x,y,name, options)}
264
+ end
265
+
266
+ def appendXYarray(data=[], name=nil, options={})
267
+ @plugins.each {|plugin| plugin.appendXY(data[0],data[1],name, options)}
268
+ end
269
+
270
+ def setXYarray(data = [], name=nil, options={})
271
+ @plugins.each {|plugin| plugin.setXY(data[0],data[1], name, options)}
272
+ end
273
+
274
+ def setXY(x=[], y=[], name=nil, options={})
275
+ @plugins.each {|plugin| plugin.setXY(x,y,name, options)}
276
+ end
277
+
278
+ def appendPoints(points =[], name=nil, options={})
279
+ @plugins.each {|plugin| plugin.appendPoints(points,name, options)}
280
+ end
281
+
282
+ def setPoints(points = [], name=nil, options={})
283
+ @plugins.each {|plugin| plugin.setPoints(points,name, options)}
284
+ end
285
+
286
+ def appendHash(hash = {}, name=nil, options={})
287
+ @plugins.each {|plugin| plugin.appendHash(hash,name, options)}
288
+ end
289
+
290
+ def setHash(hash ={}, name=nil, options={})
291
+ @plugins.each {|plugin| plugin.setHash(hash,name, options)}
292
+ end
293
+
294
+ def setArray(data = [], name=nil, options={})
295
+ x = []
296
+ data.count.times {|i| x << i}
297
+ y = data
298
+ self.setXY(x,y,name,options)
299
+ end
300
+
301
+ def appendArray(data = [], name=nil, options={})
302
+ x = []
303
+ data.count.times {|i| x << i}
304
+ y = data
305
+ self.appendXY(x,y,name,options)
306
+ end
307
+
308
+ def annotate(annotation, name=nil, options={})
309
+ @plugins.each {|plugin| plugin.annotate(annotation, name, options)}
310
+ end
311
+
312
+ def save()
313
+ @plugins.each {|plugin| plugin.save()}
314
+ end
315
+
316
+ end
317
+
318
+
319
+ end