omf_web 0.9.6 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +168 -13
- data/bin/omf-web-basic +3 -3
- data/doc/index.md +205 -0
- data/example/NOT_WORKING/brooklyn/brooklyn_server.rb +2 -2
- data/example/NOT_WORKING/frisbee/data_sources/parse_log.rb +1 -1
- data/example/NOT_WORKING/frisbee/viz_server.rb +1 -1
- data/example/NOT_WORKING/gec12/gec12_demo_server.rb +1 -1
- data/example/NOT_WORKING/gec12/visualization.rb +2 -2
- data/example/NOT_WORKING/network/network_server.rb +2 -2
- data/example/NOT_WORKING/wimax/test.rb +2 -2
- data/example/NOT_WORKING/wimax/viz_server.rb +2 -2
- data/example/bridge/auth_basic.rb +75 -0
- data/example/bridge/config.ru +101 -0
- data/example/bridge/configure/configure_widget.rb +32 -0
- data/example/bridge/data_sources/sensor-sqlite.rb +28 -6
- data/example/bridge/data_sources/test31.sq3 +0 -0
- data/example/bridge/htdocs/{js/graph → graph/js}/bridge.js +2 -2
- data/example/bridge/htdocs/{js/graph → graph/js}/event_line_chart.js +7 -6
- data/example/bridge/htdocs/{js/graph → graph/js}/event_table.js +13 -5
- data/example/bridge/htdocs/template/login.html +23 -0
- data/example/bridge/viz_server.rb +3 -5
- data/example/bridge/widgets/configure.yaml +12 -0
- data/example/bridge/widgets/login.yaml +16 -0
- data/example/bridge/{overview.yaml → widgets/overview.yaml} +7 -4
- data/example/demo/data_sources/animals.rb +1 -1
- data/example/demo/data_sources/downloads.rb +1 -1
- data/example/demo/data_sources/generator.rb +1 -1
- data/example/demo/data_sources/histogram.rb +1 -1
- data/example/demo/data_sources/mobile_network.rb +4 -3
- data/example/demo/data_sources/movies.rb +1 -1
- data/example/demo/data_sources/network.rb +4 -3
- data/example/demo/data_sources/returns.rb +1 -1
- data/example/demo/data_sources/static_network.rb +4 -3
- data/example/demo/data_sources/walk.rb +1 -1
- data/example/demo/demo_viz_server.rb +1 -1
- data/example/demo/widgets/linked_graphs_tab.yaml +1 -1
- data/example/openflow-gec15/README.md +21 -0
- data/example/openflow-gec15/code_tab.yaml +36 -0
- data/example/openflow-gec15/dashboard_tab.yaml +72 -0
- data/example/openflow-gec15/doc/screenshot.png +0 -0
- data/example/openflow-gec15/exp_source.rb +104 -0
- data/example/openflow-gec15/of_viz_server.rb +63 -0
- data/example/openflow-gec15/openflow-demo.sq3 +0 -0
- data/example/openflow-gec15/raw_tab.yaml +37 -0
- data/example/openflow-gec15/repository/of-exp.rb +12 -0
- data/example/openflow-gec15/repository/sample.md +52 -0
- data/example/openflow-gec15/repository/trema-ctl6.rb +148 -0
- data/example/simple/README.md +2 -0
- data/example/simple/data_sources/gimi31.sq3 +0 -0
- data/example/simple/data_sources/ping_source.rb +56 -0
- data/example/simple/simple_viz_server.rb +39 -0
- data/example/simple/widgets/charts_tab.yaml +38 -0
- data/lib/omf-web/config.ru +31 -3
- data/lib/omf-web/data_source_proxy.rb +29 -26
- data/lib/omf-web/rack/session_authenticator.rb +93 -0
- data/lib/omf-web/rack/tab_mapper.rb +10 -5
- data/lib/omf-web/rack/websocket_handler.rb +17 -6
- data/lib/omf-web/theme/abstract_page.rb +1 -1
- data/lib/omf-web/theme/bright/flow_renderer.rb +2 -2
- data/lib/omf-web/theme/bright/layout_renderer.rb +15 -0
- data/lib/omf-web/theme/bright/mustache_renderer.rb +29 -0
- data/lib/omf-web/theme/bright/one_column_renderer.rb +2 -2
- data/lib/omf-web/theme/bright/page.rb +33 -8
- data/lib/omf-web/theme/bright/tabbed_renderer.rb +2 -3
- data/lib/omf-web/theme/bright/two_columns_renderer.rb +3 -4
- data/lib/omf-web/version.rb +1 -1
- data/lib/omf-web/widget/code_widget.rb +0 -7
- data/lib/omf-web/widget/layout/two_columns_layout.rb +3 -2
- data/lib/omf-web/widget/mustache_widget.rb +44 -0
- data/lib/omf-web/widget.rb +14 -1
- data/lib/omf_common/lobject.rb +6 -3
- data/omf_web.gemspec +3 -1
- data/share/htdocs/graph/js/abstract_nv_chart.js +14 -4
- data/share/htdocs/graph/js/abstract_widget.js +5 -4
- data/share/htdocs/graph/js/line_chart3.js +2 -0
- data/share/htdocs/graph/js/map2.js +3 -3
- data/share/htdocs/graph/js/network2.js +51 -19
- data/share/htdocs/graph/js/scatter_plot.js +6 -2
- data/share/htdocs/graph/js/table2.js +5 -2
- data/share/htdocs/js/data_source2.js +40 -8
- data/share/htdocs/js/mustache.js +29 -0
- data/share/htdocs/theme/abstract/abstract.js +10 -3
- data/share/htdocs/vendor/mustache-0.7.0/CHANGES +21 -0
- data/share/htdocs/vendor/mustache-0.7.0/LICENSE +10 -0
- data/share/htdocs/vendor/mustache-0.7.0/README.md +374 -0
- data/share/htdocs/vendor/mustache-0.7.0/jquery.mustache.js +635 -0
- data/share/htdocs/vendor/mustache-0.7.0/mustache.js +612 -0
- data/share/htdocs/vendor/nv_d3/js/nv.d3.js +9 -1
- data/share/htdocs/vendor/raphael-2.1.0/raphael.js +5815 -0
- metadata +74 -9
- data/DESIGN_NOTES.txt +0 -56
@@ -44,6 +44,8 @@ L.provide('OML.line_chart3', ["graph/js/abstract_nv_chart", "#OML.abstract_nv_ch
|
|
44
44
|
// .showValues(opts.show_values)
|
45
45
|
// .margin(opts.margin)
|
46
46
|
// ;
|
47
|
+
|
48
|
+
this.opts.transition_duration = 0; // force no smooth transition
|
47
49
|
this._configure_xy_axis(opts, chart)
|
48
50
|
},
|
49
51
|
|
@@ -51,8 +51,8 @@ function onMapLoaded() {
|
|
51
51
|
.attr('id', map_el)
|
52
52
|
;
|
53
53
|
var node = map_layer.node();
|
54
|
-
var center = opts.
|
55
|
-
var zoom = opts.zoom;
|
54
|
+
var center = opts.map.center || [151.197189, -33.895508];
|
55
|
+
var zoom = opts.map.zoom;
|
56
56
|
if (zoom == undefined) zoom = 17;
|
57
57
|
var map = this.map = new google.maps.Map(node, {
|
58
58
|
zoom: zoom,
|
@@ -133,7 +133,7 @@ function onMapLoaded() {
|
|
133
133
|
return (typeof m === "function") ? m(d.value) : m;
|
134
134
|
}
|
135
135
|
|
136
|
-
var data = d3.entries(this.data_source.
|
136
|
+
var data = d3.entries(this.data_source.rows());
|
137
137
|
this.draw_layer.selectAll('.marker')
|
138
138
|
.data(data)
|
139
139
|
.attr("cx", x_f)
|
@@ -10,7 +10,12 @@ L.provide('OML.network2', ["graph/js/abstract_chart", "#OML.abstract_chart"], fu
|
|
10
10
|
['stroke_width', 'int', 1],
|
11
11
|
['stroke_color', 'color', 'black'],
|
12
12
|
['x', 'int', 10],
|
13
|
-
['y', 'int', 10]
|
13
|
+
['y', 'int', 10],
|
14
|
+
['label_text', 'key', {property: 'name'}],
|
15
|
+
['label_font', 'string', null],
|
16
|
+
['label_size', 'int', 16],
|
17
|
+
['label_color', 'color', 'white'],
|
18
|
+
|
14
19
|
],
|
15
20
|
links: [['key', 'key', {property: 'id'}],
|
16
21
|
['stroke_width', 'int', 2],
|
@@ -59,8 +64,8 @@ L.provide('OML.network2', ["graph/js/abstract_chart", "#OML.abstract_chart"], fu
|
|
59
64
|
ss = { name: ss };
|
60
65
|
}
|
61
66
|
var prefix = ss.name;
|
62
|
-
var sn = {}; for (var p in ss) { sn[p] = ss[p]; }; sn.name = prefix + '
|
63
|
-
var sl = {}; for (var p in ss) { sl[p] = ss[p]; }; sl.name = prefix + '
|
67
|
+
var sn = {}; for (var p in ss) { sn[p] = ss[p]; }; sn.name = prefix + '/nodes';
|
68
|
+
var sl = {}; for (var p in ss) { sl[p] = ss[p]; }; sl.name = prefix + '/links';
|
64
69
|
sources = [
|
65
70
|
{name: 'nodes', stream: sn},
|
66
71
|
{name: 'links', stream: sl},
|
@@ -204,20 +209,29 @@ L.provide('OML.network2', ["graph/js/abstract_chart", "#OML.abstract_chart"], fu
|
|
204
209
|
;
|
205
210
|
|
206
211
|
|
212
|
+
function node_f(sel) {
|
213
|
+
sel.attr("cx", function(d) { return x(nmapping.x(d)) })
|
214
|
+
.attr("cy", function(d) { return y(nmapping.y(d)) })
|
215
|
+
.attr("r", nmapping.radius)
|
216
|
+
.style("fill", nmapping.fill_color)
|
217
|
+
.style("stroke", nmapping.stroke_color)
|
218
|
+
.style("stroke-width", nmapping.stroke_width)
|
219
|
+
;
|
220
|
+
}
|
207
221
|
var node = this.graph_layer.selectAll("circle.node")
|
208
222
|
.data(ndata, function(d) {
|
209
223
|
return nmapping.key(d);
|
210
224
|
});
|
211
225
|
//.data(d3.values(ndata));
|
212
226
|
//function(d) { return d.time; }
|
213
|
-
node
|
214
|
-
|
215
|
-
|
216
|
-
.attr("
|
217
|
-
.
|
218
|
-
|
219
|
-
|
220
|
-
;
|
227
|
+
var enx = node.call(node_f);
|
228
|
+
// node.enter().append("svg:circle")
|
229
|
+
// .call(node_f)
|
230
|
+
// .attr("fixed", true)
|
231
|
+
// .transition()
|
232
|
+
// .attr("r", nmapping.radius)
|
233
|
+
// .delay(0)
|
234
|
+
// ;
|
221
235
|
var en = node.enter().append("svg:circle");
|
222
236
|
en.attr("class", "node")
|
223
237
|
.attr("cx", function(d) { return x(nmapping.x(d)) })
|
@@ -231,7 +245,25 @@ L.provide('OML.network2', ["graph/js/abstract_chart", "#OML.abstract_chart"], fu
|
|
231
245
|
.attr("r", nmapping.radius)
|
232
246
|
.delay(0)
|
233
247
|
;
|
234
|
-
this._set_node_interaction_mode(
|
248
|
+
this._set_node_interaction_mode(node);
|
249
|
+
|
250
|
+
function label_f(sel) {
|
251
|
+
sel.attr("class", "node_label")
|
252
|
+
.attr('dy', '0.4em')
|
253
|
+
.attr("x", function(d) { return x(nmapping.x(d)) })
|
254
|
+
.attr("y", function(d) { return y(nmapping.y(d)) })
|
255
|
+
.attr('text-anchor', 'middle')
|
256
|
+
.style("fill", nmapping.label_color)
|
257
|
+
.style("font-size", nmapping.label_size)
|
258
|
+
.text(function(d) { return nmapping.label_text(d); });
|
259
|
+
}
|
260
|
+
var label = this.graph_layer.selectAll("text.node_label")
|
261
|
+
.data(ndata, function(d) {
|
262
|
+
return nmapping.key(d);
|
263
|
+
});
|
264
|
+
label.call(label_f);
|
265
|
+
label.enter().append("svg:text").call(label_f);
|
266
|
+
|
235
267
|
},
|
236
268
|
|
237
269
|
_set_link_interaction_mode: function(le) {
|
@@ -267,7 +299,7 @@ L.provide('OML.network2', ["graph/js/abstract_chart", "#OML.abstract_chart"], fu
|
|
267
299
|
} else {
|
268
300
|
this._render_selected_link(id);
|
269
301
|
this._render_selected_node('_NONE_');
|
270
|
-
this._report_selected(id, 'links');
|
302
|
+
this._report_selected(id, 'links', d);
|
271
303
|
}
|
272
304
|
},
|
273
305
|
|
@@ -335,7 +367,7 @@ L.provide('OML.network2', ["graph/js/abstract_chart", "#OML.abstract_chart"], fu
|
|
335
367
|
_on_node_selected: function(d) {
|
336
368
|
var key_f = this.mapping.nodes.key;
|
337
369
|
var id = key_f(d);
|
338
|
-
var msg = {id: id, type: 'node', source: this, data_source: this.data_source.nodes};
|
370
|
+
//var msg = {id: id, type: 'node', source: this, data_source: this.data_source.nodes};
|
339
371
|
|
340
372
|
if (this.selected_node == id) {
|
341
373
|
// if same link is clicked twice, unselect it
|
@@ -344,7 +376,7 @@ L.provide('OML.network2', ["graph/js/abstract_chart", "#OML.abstract_chart"], fu
|
|
344
376
|
} else {
|
345
377
|
this._render_selected_link('_NONE_');
|
346
378
|
this._render_selected_node(id);
|
347
|
-
this._report_selected(id, 'nodes');
|
379
|
+
this._report_selected(id, 'nodes', d);
|
348
380
|
}
|
349
381
|
},
|
350
382
|
|
@@ -386,16 +418,16 @@ L.provide('OML.network2', ["graph/js/abstract_chart", "#OML.abstract_chart"], fu
|
|
386
418
|
|
387
419
|
},
|
388
420
|
|
389
|
-
_report_selected: function(selected_id, type) {
|
421
|
+
_report_selected: function(selected_id, type, datum) {
|
390
422
|
var ds = this.data_source[type];
|
391
|
-
var msg = {id: selected_id, type: type, source: this, data_source: ds};
|
423
|
+
var msg = {id: selected_id, type: type, source: this, data_source: ds, datum: datum};
|
392
424
|
OHUB.trigger("graph.selected", msg);
|
393
425
|
OHUB.trigger("graph." + ds.name + ".selected", msg);
|
394
426
|
},
|
395
427
|
|
396
|
-
_report_deselected: function(selected_id, type) {
|
428
|
+
_report_deselected: function(selected_id, type, datum) {
|
397
429
|
var ds = this.data_source[type];
|
398
|
-
var msg = {id: selected_id, type: type, source: this, data_source: ds};
|
430
|
+
var msg = {id: selected_id, type: type, source: this, data_source: ds, datum: datum};
|
399
431
|
OHUB.trigger("graph.deselected", msg);
|
400
432
|
OHUB.trigger("graph." + ds.name + ".deselected", msg);
|
401
433
|
}
|
@@ -58,8 +58,12 @@ L.provide('OML.scatter_plot', ["graph/js/abstract_chart", "#OML.abstract_chart",
|
|
58
58
|
var r_f = typeof(r_m) != 'function' ? d3.functor(r_m) : r_m;
|
59
59
|
var w_f = typeof(r_m) != 'function' ? (2 * r_m) : function(d) { return 2 * r_m(d); }
|
60
60
|
|
61
|
-
var x = function(d) {
|
62
|
-
|
61
|
+
var x = function(d) {
|
62
|
+
return x_f(x_m(d)) + ca.x - r_f(d);
|
63
|
+
};
|
64
|
+
var y = function(d) {
|
65
|
+
return ca.ty + ca.h - y_f(y_m(d)) - r_f(d);
|
66
|
+
};
|
63
67
|
var rects = this.chart_layer.selectAll("rect").data(data);
|
64
68
|
rects.transition().duration(o.transition)
|
65
69
|
.attr("x", x)
|
@@ -168,9 +168,12 @@ L.provide('OML.table2', ["graph/js/abstract_widget", "#OML.abstract_widget", '#s
|
|
168
168
|
var i = 0;
|
169
169
|
} else {
|
170
170
|
columns = _.map(schema, function(col) {
|
171
|
-
var i = 0;
|
172
171
|
return { id: col.index, name: col.title, field: col.name, width: 0, sortable: true };
|
173
|
-
|
172
|
+
});
|
173
|
+
// Remove the leading __id__ column
|
174
|
+
if (columns[0].field == '__id__') {
|
175
|
+
columns.splice(0, 1);
|
176
|
+
}
|
174
177
|
}
|
175
178
|
return columns;
|
176
179
|
},
|
@@ -161,13 +161,35 @@ OML.data_source = function(opts) {
|
|
161
161
|
});
|
162
162
|
} else {
|
163
163
|
// need to append to 'rows' as it's referenced in other closures
|
164
|
-
_.each(msg.rows, function(r) { rows.push(r) });
|
165
|
-
var chop = msg.offset - offset;
|
166
|
-
if (offset >= 0 && chop > 0) {
|
167
|
-
rows = _.rest(rows, chop);
|
164
|
+
// _.each(msg.rows, function(r) { rows.push(r) });
|
165
|
+
// var chop = msg.offset - offset;
|
166
|
+
// if (offset >= 0 && chop > 0) {
|
167
|
+
// rows = _.rest(rows, chop);
|
168
|
+
// }
|
169
|
+
switch (msg.action) {
|
170
|
+
case 'added':
|
171
|
+
_.each(msg.rows, function(r) { rows.push(r) });
|
172
|
+
break;
|
173
|
+
case 'removed':
|
174
|
+
// This could most likely be made a bit faster.
|
175
|
+
_.each(msg.rows, function(row) {
|
176
|
+
var id = row[0]; // first column is ALWAYS a unique row id
|
177
|
+
var l = rows.length;
|
178
|
+
var row_no;
|
179
|
+
for (row_no = 0; row_no < l; row_no++) {
|
180
|
+
if (rows[row_no][0] == id) break;
|
181
|
+
}
|
182
|
+
if (row_no < l) {
|
183
|
+
rows.splice(row_no, 1);
|
184
|
+
} else {
|
185
|
+
var xxx = 0; // Removing non existing row
|
186
|
+
}
|
187
|
+
});
|
188
|
+
break;
|
189
|
+
default:
|
190
|
+
throw "Unknown message action '" + msg.action + "'.";
|
168
191
|
}
|
169
192
|
}
|
170
|
-
offset = msg.offset;
|
171
193
|
|
172
194
|
update_indexes();
|
173
195
|
var evt = {data_source: data_source};
|
@@ -183,7 +205,7 @@ OML.data_source = function(opts) {
|
|
183
205
|
// Reset state
|
184
206
|
rows = [];
|
185
207
|
update_indexes();
|
186
|
-
sm = {col_name: active_slice_col_name, col_value: col_value}
|
208
|
+
var sm = {col_name: active_slice_col_name, col_value: col_value}
|
187
209
|
send_server_msg('request_slice', {slice: sm})
|
188
210
|
}
|
189
211
|
var active_slice_col_name = null;
|
@@ -269,8 +291,18 @@ OML.data_source = function(opts) {
|
|
269
291
|
var evt_name = so.event.name;
|
270
292
|
if (! evt_name)
|
271
293
|
throw "Missing event name in slice definition for data source '" + name + "'.";
|
272
|
-
OHUB.bind(evt_name, function(
|
273
|
-
|
294
|
+
OHUB.bind(evt_name, function(msg) {
|
295
|
+
var schema = msg.schema || msg.data_source.schema;
|
296
|
+
|
297
|
+
var key = so.event.key;
|
298
|
+
var col = _.find(schema, function(cd) { return cd.name == key });
|
299
|
+
if (col) {
|
300
|
+
var event = msg.datum;
|
301
|
+
var col_id = event[col.index];
|
302
|
+
if (col_id) {
|
303
|
+
set_slice_column(col_id);
|
304
|
+
}
|
305
|
+
}
|
274
306
|
})
|
275
307
|
}
|
276
308
|
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
L.provide('OML.mustache', ["vendor/mustache/mustache.js", 'vendor/bootstrap/css/bootstrap.css'], function () {
|
2
|
+
|
3
|
+
if (typeof(OML) == "undefined") OML = {};
|
4
|
+
|
5
|
+
OML['mustache'] = function(opts) {
|
6
|
+
|
7
|
+
var moustache = {
|
8
|
+
version: "0.1",
|
9
|
+
}
|
10
|
+
|
11
|
+
var template_url = opts.template;
|
12
|
+
if (! template_url) {
|
13
|
+
throw "Missing template declaration in mustache widget";
|
14
|
+
}
|
15
|
+
var context = {};
|
16
|
+
var el = $('#' + opts.base_id);
|
17
|
+
|
18
|
+
$.ajax({
|
19
|
+
url: '/resource/' + template_url,
|
20
|
+
type: 'get'
|
21
|
+
}).done(function(template) {
|
22
|
+
var html = Mustache.to_html(template, context);
|
23
|
+
el.html(html);
|
24
|
+
var i = 0;
|
25
|
+
})
|
26
|
+
|
27
|
+
return moustache;
|
28
|
+
}
|
29
|
+
})
|
@@ -2,7 +2,7 @@ L.baseURL = "/resource";
|
|
2
2
|
OML = {
|
3
3
|
data_sources: {},
|
4
4
|
widgets: {},
|
5
|
-
|
5
|
+
window_size: {width: null, height: null}
|
6
6
|
};
|
7
7
|
|
8
8
|
var OHUB = {};
|
@@ -10,6 +10,13 @@ _.extend(OHUB, Backbone.Events);
|
|
10
10
|
|
11
11
|
$(window).resize(function(x) {
|
12
12
|
var w = $(window);
|
13
|
-
|
14
|
-
|
13
|
+
var width = w.width();
|
14
|
+
var height = w.height();
|
15
|
+
var current = OML.window_size;
|
16
|
+
|
17
|
+
if (current.width != width || current.height != height) {
|
18
|
+
current.width = width; current.height = height;
|
19
|
+
OHUB.trigger('window.resize', current);
|
20
|
+
OHUB.trigger('layout.resize', {});
|
21
|
+
}
|
15
22
|
});
|
@@ -0,0 +1,21 @@
|
|
1
|
+
= 0.7.0 / 10 Sep 2012
|
2
|
+
|
3
|
+
* Rename Renderer => Writer.
|
4
|
+
* Allow partials to be loaded dynamically using a callback (thanks @TiddoLangerak
|
5
|
+
for the suggestion).
|
6
|
+
* Fixed a bug with higher-order sections that prevented them from being
|
7
|
+
passed the raw text of the section from the original template.
|
8
|
+
* More concise token format. Tokens also include start/end indices in the
|
9
|
+
original template.
|
10
|
+
* High-level API is consistent with the Writer API.
|
11
|
+
* Allow partials to be passed to the pre-compiled function (thanks @fallenice).
|
12
|
+
* Don't use eval (thanks @cweider).
|
13
|
+
|
14
|
+
= 0.6.0 / 31 Aug 2012
|
15
|
+
|
16
|
+
* Use JavaScript's definition of falsy when determining whether to render an
|
17
|
+
inverted section or not. Issue #186.
|
18
|
+
* Use Mustache.escape to escape values inside {{}}. This function may be
|
19
|
+
reassigned to alter the default escaping behavior. Issue #244.
|
20
|
+
* Fixed a bug that clashed with QUnit (thanks @kannix).
|
21
|
+
* Added volo support (thanks @guybedford).
|
@@ -0,0 +1,10 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2009 Chris Wanstrath (Ruby)
|
4
|
+
Copyright (c) 2010 Jan Lehnardt (JavaScript)
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
7
|
+
|
8
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
9
|
+
|
10
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|