List of commits:
Subject Hash Author Date (UTC)
large refactoring step after colloquium 864aef32ba2419bd43709a3239273275d3f9946e mcehlert 2014-01-09 22:23:24
inital commit - pre colloquium state dcee4d4045615b761cc54b957be7134f0e12384d Mathias Ehlert 2013-11-22 13:49:56
Initial commit a90174ca714e3b82a7100875f411a5e84a90352b Mathias Ehlert 2013-11-22 13:48:45
Commit 864aef32ba2419bd43709a3239273275d3f9946e - large refactoring step after colloquium
Author: mcehlert
Author date (UTC): 2014-01-09 22:23
Committer name: mcehlert
Committer date (UTC): 2014-01-09 22:23
Parent(s): dcee4d4045615b761cc54b957be7134f0e12384d
Signing key:
Tree: 6c32f23bd0d01d1b967b36c4f7ad0cf2fb3ed70e
File Lines added Lines deleted
README.md 0 4
app.rb 9 124
color_helper.rb 25 0
config.rb 79 0
index.rb 5 0
metric_routes.rb 21 0
node.rb 0 86
node_routes.rb 53 0
public/css/application.css 2 0
public/js/graph.js 4 4
run.rb 19 0
score_routes.rb 18 0
statistics_routes.rb 17 0
storage.rb 155 0
views/.metric_details.erb.swp 0 0
views/graph.erb 0 1
views/layout.erb 10 4
views/metric_details.erb 28 26
views/node_details.erb 66 86
views/score_details.erb 47 0
views/statistics.erb 105 0
File README.md deleted (index 04e9bf5..0000000)
1 coria-frontend
2 ==============
3
4 Sinatra Frontend for Connectivity Risk Analyser
File app.rb changed (mode: 100644) (index f68e488..cd6b8e3)
1 1 require 'rubygems' require 'rubygems'
2 2 require 'sinatra' require 'sinatra'
3 require 'redis'
4 require 'json'
5 require 'will_paginate'
6 require 'will_paginate/array'
7 require './node'
8 3
9 # bind to publicly accessable IP
10 set :bind, '0.0.0.0'
11
12 rdb = Redis.new
13 #CSS class names for alert levels from "ok" to "bad"
14
15 #HTML color codes from green to red in 0x11-steps
16 COLORS = ['#FF0000','#FF1100','#FF2200','#FF3300','#FF4400',
17 '#FF5500','#FF6600','#FF7700','#FF8800','#FF9900',
18 '#FFAA00','#FFBB00','#FFCC00','#FFDD00','#FFEE00',
19 '#FFFF00','#EEFF00','#DDFF00','#CCFF00','#BBFF00',
20 '#AAFF00','#99FF00','#88FF00','#77FF00','#66FF00',
21 '#55FF00','#44FF00','#33FF00','#22FF00','#11FF00',
22 '#00FF00'].reverse
23
24 # max number of nodes for display in metric listings
25 MAX_LIST = 20
26
27 # max number of neighbors for graphical representation with d3.js
28 MAX_GRAPH_NEIGHBORS = 300
29
30
31 # INDEX / ROOT PATH
32 get '/' do
33 rdb = Redis.new
34 @title = 'CoRiA'
35 erb :index
36 end
37
38 # NODE DETAILS
39 get '/node/:asn' do
40 rdb = Redis.new
41 @asn = params[:asn]
42 return status 404 unless Node.all_nodes.include?(@asn)
43 @title = 'Node Details'
44 @node = Node.get(params[:asn])
45 erb :node_details
46 end
47
48 # NODE SEARCH
49 post('/node') do
50 if Node.all_nodes.include?(params[:node_id].to_s)
51 redirect '/node/'+params[:node_id]
52 else
53 redirect '/'
54 end
55 end
56
57
58 # METRIC DETAILS
59 get '/metric/:metric/' do
60 @metric = params[:metric]
61
62 if Node.metric_names.keys.include?(@metric)
63 redis_key = @metric+'_normalized'
64 elsif Node.score_names.keys.include?(@metric)
65 redis_key = @metric
66 else
67 return status 404
68 end
4 require './config'
5 require './storage'
69 6
70 @metric_name = Node.metric_names[@metric] || Node.score_names[@metric]
71
72 @title = @metric_name+' Ranking'
73
74 rdb = Redis.new
75 @nodes = rdb.zrevrange(redis_key, 0, -1, {withscores: true}).paginate(:page => params[:page])
76
77 erb :metric_details
78
79 end
80
81 get '/nodes' do
82 content_type :json
83 return Node.all_nodes.to_json
84 end
85
86
87 #NODE NEIGHBORHOOD AJAX ENDPOINT FOR DISPLAY VIA d3.js
88 #color notes by unified risk score value
89 get '/node/neighbors/:id' do
90 content_type :json
91
92 @node = Node.get(params[:id])
93
94 #build response
95 response = {}
96
97 response[:nodes] = []
98 response[:links] = []
99
100 response[:nodes] << {:name => @node.data[:id], :size_multiplier => @node.data[:degree_normalized], :color => COLORS[(@node.data[:unified_risk_score]*COLORS.length).ceil]}
101
102 limited_neighbors = @node.data[:neighbors][0..MAX_GRAPH_NEIGHBORS]
103 i = 1
104 limited_neighbors.each do |node_id|
105 neighbor = Node.get(node_id)
106 color = COLORS[(neighbor.data[:unified_risk_score]*COLORS.length).ceil]
107 size_multiplier = neighbor.data[:degree_normalized]
108
109 response[:nodes] << {:name => neighbor.data[:id], :size_multiplier => size_multiplier, :color => color}
110 response[:links] << {:source => 0, :target => i}
111 i += 1
112 end
113
114 return response.to_json
115 end
7 # bind to all accessable interfaces
8 set :bind, '0.0.0.0'
116 9
117 get '/metric/:metric/histogram.json' do
118 content_type :json
119 10
120 metric = params[:metric]
11 require './index'
121 12
122 if Node.metric_names.keys.include?(metric)
123 redis_key = metric+'_normalized'
124 elsif Node.score_names.keys.include?(metric)
125 redis_key = metric
126 else
127 return status 404
128 end
13 require './node_routes'
129 14
130 values = rdb.zrevrange(redis_key, 0, -1, {withscores: true}).map{|score| score[1]}
15 require './metric_routes'
131 16
132 return values.to_json
17 require './score_routes'
133 18
134 end
19 require './statistics_routes'
File color_helper.rb added (mode: 100644) (index 0000000..9eca682)
1 require './config'
2 class ColorHelper
3
4 def self.color_class_by_value(value)
5 return self.get_color_from_array(value,CONFIG.color_classes)
6 end
7
8 def self.color_code_by_value(value)
9 return self.get_color_from_array(value,CONFIG.color_codes)
10 end
11
12
13 def self.get_color_from_array(value, list)
14 if value >= 1.0
15 return list[-1]
16 end
17
18 if value <= 0.0
19 return list[0]
20 end
21
22 return list[((value-0.001)*list.length).floor.to_i]
23 end
24
25 end
File config.rb added (mode: 100644) (index 0000000..dca71f9)
1 require 'redis'
2 require 'ostruct'
3
4
5 CONFIG = OpenStruct.new
6
7 CONFIG.node_index_key = 'all_nodes'
8 CONFIG.metric_index_key = 'all_metrics'
9 CONFIG.score_index_key = 'all_scores'
10
11 CONFIG.node_neighbors_prefix = 'node_neighbors:'
12 CONFIG.node_prefix = 'node_metrics:'
13 CONFIG.metric_prefix = 'metric:'
14 CONFIG.score_prefix = 'score:'
15 CONFIG.statistics_prefix = 'statistics:'
16
17 CONFIG.normalization_suffix = '_normalized'
18
19 CONFIG.statistical_indicators = { 'min' => "Minimum",
20 'max' => "Maximum",
21 'average' => "Average Value" ,
22 'median' => "Mean Value",
23 'standard_deviation' => "Standard Deviation"}
24
25 CONFIG.redis = Redis.new
26
27 #automatic retrieval and naive naming of available metrics from Redis
28 CONFIG.metric_names = CONFIG.redis.smembers(CONFIG.metric_index_key).inject({}) do |h,metric|
29 h[metric] = metric.split('_').map(&:capitalize).join(' ')
30 h
31 end
32
33
34 #CONFIG.metric_names = {
35 # 'clustering_coefficient' => "Clustering Coefficient",
36 # 'corrected_clustering_coefficient' => "Clustering Coefficient (Corrected)",
37 # 'degree' => "Node Degree",
38 # 'average_neighbor_degree' => "Average Neighbor Degree",
39 # 'corrected_average_neighbor_degree' => "Average Neighbor Degree (Corrected)",
40 # 'iterated_average_neighbor_degree' => "Iterated Average Neighbor Degree",
41 # 'corrected_iterated_average_neighbor_degree' => "Iterated Average Neighbor Degree (Corrected)",
42 # 'betweenness_centrality' => "Betweenness Centrality",
43 # 'eccentricity' => "Eccentricity",
44 # 'average_shortest_path_length' => "Average Shortest Path Length"
45 #}
46
47
48 #automatic retrieval and naive naming of available scores from Redis
49 CONFIG.score_names = CONFIG.redis.smembers(CONFIG.score_index_key).inject({}) do |h,score|
50 h[score] = score.split('_').map(&:capitalize).join(' ')
51 h
52 end
53
54
55 # scores have to be readable in redis
56 #CONFIG.score_names = {
57 # 'unified_risk_score' => "Unified Risk Score (URS)",
58 # 'advanced_unified_risk_score' => "Advanced URS"
59 #}
60
61
62 # css classes for status indication ordered from "good" to "bad"
63 CONFIG.color_classes = ['success','info', 'warning', 'danger']
64
65 #HTML color codes from green to red in 0x11-steps
66 CONFIG.color_codes = ['#FF0000','#FF1100','#FF2200','#FF3300','#FF4400',
67 '#FF5500','#FF6600','#FF7700','#FF8800','#FF9900',
68 '#FFAA00','#FFBB00','#FFCC00','#FFDD00','#FFEE00',
69 '#FFFF00','#EEFF00','#DDFF00','#CCFF00','#BBFF00',
70 '#AAFF00','#99FF00','#88FF00','#77FF00','#66FF00',
71 '#55FF00','#44FF00','#33FF00','#22FF00','#11FF00',
72 '#00FF00'].reverse
73
74 #can be metric or score
75 CONFIG.node_coloring_field = 'unified_risk_score'
76
77 # max number of neighbors for graphical representation with d3.js
78 CONFIG.max_graph_neighbors = 150
79 CONFIG.nodes_per_page = 25
File index.rb added (mode: 100644) (index 0000000..a0f1048)
1 #index.rb
2 get '/' do
3 @title = 'Connection Risk Analysis'
4 erb :index
5 end
File metric_routes.rb added (mode: 100644) (index 0000000..1a41081)
1 #metric_routes.rb
2 # METRIC DETAILS
3 get '/metric/:metric/' do
4 @metric = params[:metric]
5
6 return status 404 unless CONFIG.metric_names.keys.include?(@metric)
7
8 @metric_name = CONFIG.metric_names[@metric] || "Unknown"
9
10 @title = @metric_name+' Ranking'
11
12 @nodes = Storage.get_metric_nodes(params[:metric],params[:page])
13
14 erb :metric_details
15
16 end
17
18 get '/metric/:metric/histogram.json' do
19 content_type :json
20 return Storage.get_all_metric_values_normalized(params[:metric]).to_json
21 end
File node.rb deleted (index 33505d4..0000000)
1 class Node
2 @@redis = Redis.new
3
4 COLOR_TYPES = ['success','info', 'warning', 'danger']
5
6 attr_reader :data, :neighbors, :asn
7
8 # metrics have to be readable from redis as well as their respective *_normalized values
9 @@metric_names = {
10 'clustering_coefficient' => "Clustering Coefficient",
11 'corrected_clustering_coefficient' => "Clustering Coefficient (Corrected)",
12 'degree' => "Node Degree",
13 'average_neighbor_degree' => "Average Neighbor Degree",
14 'corrected_average_neighbor_degree' => "Average Neighbor Degree (Corrected)",
15 'iterated_average_neighbor_degree' => "Iterated Average Neighbor Degree",
16 'corrected_iterated_average_neighbor_degree' => "Iterated Average Neighbor Degree (Corrected)",
17 'betweenness_centrality' => "Betweenness Centrality",
18 'eccentricity' => "Eccentricity",
19 'average_shortest_path_length' => "Average Shortest Path Length"
20 }
21
22 # scores have to be readable in redis
23 @@score_names = {
24 'unified_risk_score' => "Unified Risk Score (URS)",
25 'advanced_unified_risk_score' => "Advanced URS"
26 }
27
28
29 # class methods for control flow
30 def self.all_nodes
31 @@all_nodes = @@redis.smembers("all_nodes") unless defined? @@all_nodes
32 return @@all_nodes
33 end
34
35 def self.metric_names
36 @@metric_names
37 end
38
39 def self.score_names
40 @@score_names
41 end
42
43
44 # find node by id
45 def self.get(id)
46 params = {}
47 params[:id] = id
48
49 #get all available values for the node from redis and store in variable
50 @@redis.hgetall('node_metrics:'+id.to_s).each do |metric, value|
51 params[metric.to_sym] = value.to_f
52 end
53
54 # fetch neighbors of node
55 params[:neighbors] = @@redis.smembers('node_neighbors:'+params[:id])
56
57 #instantiate new node with obtained params from redis
58 node = Node.new(params)
59 return node
60 end
61
62 def initialize(params)
63 @data = params
64 end
65
66 #helper to get an HTML colorcode for a percentage value parameter
67 def self.color_type_by_value(value)
68 if value > 1
69 return COLOR_TYPES[-1]
70 end
71
72 if value == 0
73 return COLOR_TYPES[0]
74 end
75
76 index = ((value-0.001)*COLOR_TYPES.length).floor.to_i
77 return COLOR_TYPES[index]
78 end
79
80 # instance helper to get HTML colorcode for a specific metric value of a node
81 def color_type(metric)
82 value = self.data[metric.to_sym].to_f
83 return Node.color_type_by_value(value)
84 end
85
86 end
File node_routes.rb added (mode: 100644) (index 0000000..e1a9fec)
1 #node_routes.rb
2
3 # NODE DETAILS
4
5 # NODE SEARCH
6 post('/node') do
7 node_id = params[:node_id]
8 if Storage.all_nodes.include?(node_id)
9 redirect '/node/'+node_id
10 else
11 redirect '/'
12 end
13 end
14
15 get '/node/:id/' do
16 id = params[:id]
17 return status 404 unless Storage.all_nodes.include?(id)
18
19 @title = 'Node Details'
20 @node = Storage.get_node(id)
21 erb :node_details
22 end
23
24 #NODE NEIGHBORHOOD AJAX ENDPOINT FOR DISPLAY VIA d3.js
25 #color notes by unified risk score value
26 get '/node/:id/neighbors.json' do
27 content_type :json
28
29 id = params[:id].to_s
30
31 node = Storage.get_node(id)
32
33 #build response for d3.js utilization
34 response = {}
35 response[:nodes] = []
36 response[:links] = []
37
38 color_code = node.scores.fetch(CONFIG.node_coloring_field,{}).fetch(:color_code, nil) || node.metrics.fetch(CONFIG.node_coloring_field,{}).fetch(:color_code, nil)
39
40 response[:nodes] << {:name => node.id, :color_code => color_code}
41
42 neighbors = node.neighbors[0..CONFIG.max_graph_neighbors]
43
44 neighbors.each_with_index do |node_id, i|
45 neighbor = Storage.get_node(node_id)
46 color_code = neighbor.scores.fetch(CONFIG.node_coloring_field,{}).fetch(:color_code, nil) || neighbor.metrics.fetch(CONFIG.node_coloring_field,{}).fetch(:color_code, nil)
47
48 response[:nodes] << {:name => neighbor.id, :color_code => color_code}
49 response[:links] << {:source => 0, :target => i+1}
50 end
51
52 return response.to_json
53 end
File public/css/application.css changed (mode: 100644) (index 3d5861c..7281515)
... ... h1 {
10 10 padding-top: 60px; padding-top: 60px;
11 11 } }
12 12
13 /*
13 14 #graph { #graph {
14 15 background-color: #3c3c3c; background-color: #3c3c3c;
15 16 -moz-border-radius: 6px; -moz-border-radius: 6px;
16 17 border-radius: 6px; border-radius: 6px;
17 18 } }
19 */
18 20
19 21 .progress { .progress {
20 22 margin-bottom: 0px; margin-bottom: 0px;
File public/js/graph.js changed (mode: 100644) (index 54baf9d..0efd5a3)
1 1 $(function() { $(function() {
2 2
3 var width = 800,
4 height = 800
3 var width = 720,
4 height = 720
5 5
6 6 var svg = d3.select("#graph").append("svg").attr("width", width).attr("height", height) var svg = d3.select("#graph").append("svg").attr("width", width).attr("height", height)
7 7
8 8 var fisheye = d3.fisheye.circular() var fisheye = d3.fisheye.circular()
9 9 .radius(120); .radius(120);
10 10
11 d3.json("/node/neighbors/"+node_id, function(error, json) {
11 d3.json("/node/"+node_id+"/neighbors.json", function(error, json) {
12 12 if (error) return console.warn(error); if (error) return console.warn(error);
13 13
14 14 var n = json.nodes.length; var n = json.nodes.length;
 
... ... $(function() {
51 51 .attr("cy", function(d) { return d.y; }) .attr("cy", function(d) { return d.y; })
52 52 .attr("r", 4) .attr("r", 4)
53 53 .attr("fill", "#2a9fd6") .attr("fill", "#2a9fd6")
54 .attr("stroke", function(d) {return d.color;})
54 .attr("stroke", function(d) {return d.color_code;})
55 55 .attr("stroke-width",3); .attr("stroke-width",3);
56 56
57 57 node.append("text") node.append("text")
File run.rb added (mode: 100644) (index 0000000..6ecd1cc)
1 require 'rubygems'
2 require 'sinatra'
3
4 require './config'
5 require './storage'
6 # bind to publicly accessable IP
7 set :bind, '0.0.0.0'
8
9
10 # INDEX / ROOT PATH
11 require './index'
12
13 require './node_routes'
14
15 require './metric_routes'
16
17 require './score_routes'
18
19 require './statistics_routes'
File score_routes.rb added (mode: 100644) (index 0000000..c0946e5)
1 #score_routes.rb
2 get '/score/:score/' do
3 @score = params[:score]
4
5 return status 404 unless CONFIG.score_names.keys.include?(@score)
6
7 @score_name = CONFIG.score_names[@score]
8 @title = @score_name+' Ranking'
9
10 @nodes = Storage.get_score_nodes(params[:score],params[:page])
11
12 erb :score_details
13 end
14
15 get '/score/:score/histogram.json' do
16 content_type :json
17 return Storage.get_all_score_values(params[:score]).to_json
18 end
File statistics_routes.rb added (mode: 100644) (index 0000000..f981916)
1 #statistics_routes.rb
2 get '/statistics/' do
3 @title = "Dataset Statistics"
4
5 #get statistics for all absolute metrics
6 @data_metrics_absolute = Storage.get_absolute_metric_statistics
7
8 #normalized
9 @data_metrics_normalized = Storage.get_normalized_metric_statistics
10
11 #scores
12 @data_scores = Storage.get_score_statistics
13
14 @data_correlations = Storage.get_metric_correlations
15
16 erb :statistics
17 end
File storage.rb added (mode: 100644) (index 0000000..5939518)
1 require 'ostruct'
2 require 'redis'
3 require 'json'
4 require 'will_paginate'
5 require 'will_paginate/array'
6
7 require './color_helper'
8
9
10
11 module Storage
12 @@rdb = Redis.new
13
14
15 def self.all_nodes
16 @@all_nodes = JSON.parse(@@rdb.smembers(CONFIG.node_index_key)[0]) unless defined? @@all_nodes
17 return @@all_nodes.map{|id| id.to_s}
18 end
19
20 def self.metric_names
21 @@metric_names = JSON.parse(@@rdb.smembers(CONFIG.metric_index_key)[0]) unless defined? @@metric_names
22 return @@metric_names
23 end
24
25 def self.score_names
26 @@score_names = JSON.parse(@@rdb.smembers(CONFIG.score_index_key)[0]) unless defined? @@score_names
27 return @@score_names
28 end
29
30
31
32 def self.get_node(nodeid)
33 node = OpenStruct.new
34 node.id = nodeid
35 node.metrics = {}
36 node.scores = {}
37
38 #get raw data from redis
39 all_values = @@rdb.hgetall(CONFIG.node_prefix+nodeid.to_s)
40
41 #build structured data
42 CONFIG.metric_names.each do |metric,name|
43 node.metrics[metric] = {}
44 node.metrics[metric][:name] = name
45 node.metrics[metric][:absolute] = all_values[metric].to_f
46 node.metrics[metric][:normalized] = all_values[metric+CONFIG.normalization_suffix].to_f
47 node.metrics[metric][:color_class] = ColorHelper.color_class_by_value(all_values[metric+CONFIG.normalization_suffix].to_f)
48 node.metrics[metric][:color_code] = ColorHelper.color_code_by_value(all_values[metric+CONFIG.normalization_suffix].to_f)
49 end
50 CONFIG.score_names.each do |score,name|
51 node.scores[score] = {}
52 node.scores[score][:name] = name
53 node.scores[score][:absolute] = all_values[score].to_f
54 node.scores[score][:color_class] = ColorHelper.color_class_by_value(all_values[score].to_f)
55 node.scores[score][:color_code] = ColorHelper.color_code_by_value(all_values[score].to_f)
56 end
57
58 node.neighbors = JSON.parse(@@rdb.smembers(CONFIG.node_neighbors_prefix+nodeid.to_s)[0])
59
60 return node
61 end
62
63
64
65 def self.get_metric_nodes(metric_name, page=1)
66 nodes = {}
67 @@rdb.zrevrange(CONFIG.metric_prefix+metric_name, 0, -1, {withscores: true}).each do |value|
68 nodes[value[0]] = {:id => value[0]}
69 nodes[value[0]][:absolute] = value[1].to_f
70 end
71
72 @@rdb.zrevrange(CONFIG.metric_prefix+metric_name+CONFIG.normalization_suffix, 0, -1, {withscores: true}).each do |value|
73 nodes[value[0]][:normalized] = value[1].to_f
74 nodes[value[0]][:color_class] = ColorHelper.color_class_by_value(value[1].to_f)
75 end
76 return nodes.to_a.paginate(:page => page, :per_page => CONFIG.nodes_per_page)
77 end
78
79 def self.get_all_metric_values_normalized(metric_name)
80 return @@rdb.zrevrange(CONFIG.metric_prefix+metric_name+CONFIG.normalization_suffix, 0, -1, {withscores: true}).map{|score| score[1]}
81 end
82
83
84 def self.get_score_nodes(score_name, page=1)
85 nodes = {}
86 @@rdb.zrevrange(CONFIG.score_prefix+score_name, 0, -1, {withscores: true}).each do |value|
87 nodes[value[0]] = {:id => value[0]}
88 nodes[value[0]][:absolute] = value[1].to_f
89 nodes[value[0]][:color_class] = ColorHelper.color_class_by_value(value[1].to_f)
90 end
91 return nodes.to_a.paginate(:page => page, :per_page => CONFIG.nodes_per_page)
92 end
93
94 def self.get_all_score_values(score_name)
95 return @@rdb.zrevrange(CONFIG.score_prefix+score_name, 0, -1, {withscores: true}).map{|score| score[1]}
96 end
97
98 def self.get_absolute_metric_statistics
99 data_metrics_absolute = {}
100 CONFIG.metric_names.each do |metric,mname|
101 metric_data = {}
102 CONFIG.statistical_indicators.each do |indicator,iname|
103 value = @@rdb.hget(CONFIG.statistics_prefix+metric, indicator)
104 metric_data[indicator] = value
105 end
106 metric_data['display_name'] = mname
107 data_metrics_absolute[metric] = metric_data
108 end
109 return data_metrics_absolute
110 end
111
112 def self.get_normalized_metric_statistics
113 data_metrics_normalized = {}
114 CONFIG.metric_names.each do |metric,mname|
115 metric_data = {}
116 CONFIG.statistical_indicators.each do |indicator,iname|
117 value = @@rdb.hget(CONFIG.statistics_prefix+metric+CONFIG.normalization_suffix, indicator)
118 metric_data[indicator] = value
119 end
120 metric_data['display_name'] = mname
121 data_metrics_normalized[metric] = metric_data
122 end
123 return data_metrics_normalized
124 end
125
126 def self.get_score_statistics
127 data_scores = {}
128 CONFIG.score_names.each do |score,sname|
129 score_data = {}
130 CONFIG.statistical_indicators.each do |indicator,iname|
131 value = @@rdb.hget(CONFIG.statistics_prefix+score, indicator)
132 score_data[indicator] = value
133 end
134 score_data['display_name'] = sname
135 data_scores[score] = score_data
136 end
137 return data_scores
138 end
139
140 def self.get_metric_correlations
141 correlation_data = {}
142 CONFIG.metric_names.each do |metric1,m1name|
143 correlation_data[metric1] = {:from => m1name, :correlation => {}}
144 CONFIG.metric_names.each do |metric2,m2name|
145 corr = @@rdb.hget(CONFIG.statistics_prefix+'correlations:'+metric1+':'+metric2, 'correlation')
146 conf = @@rdb.hget(CONFIG.statistics_prefix+'correlations:'+metric1+':'+metric2, 'confidence')
147 color_code = ColorHelper.color_code_by_value(corr.to_f.abs)
148 correlation_data[metric1][:correlation][metric2] = {:to => m2name, :correlation => corr, :confidence => conf, :color_code => color_code}
149 end
150 end
151 return correlation_data
152 end
153
154
155 end
File views/.metric_details.erb.swp deleted (index 119053c..0000000)
File views/graph.erb deleted (index d3f5a12..0000000)
1
File views/layout.erb changed (mode: 100644) (index 00a5740..2fda8a6)
22 22 </form> </form>
23 23
24 24 </div> </div>
25 <div class="btn-group pull-right">
25
26 <div class="btn-group btn-group-lg pull-right">
27
28 <button class="btn btn-default btn-lg btn-primary" type="button" onclick="window.location.href='/statistics/'">
29 <span class="glyphicon glyphicon-eye-open"></span> Statistics
30 </button>
31
26 32 <button class="btn btn-default btn-lg btn-primary dropdown-toggle" type="button" data-toggle="dropdown"> <button class="btn btn-default btn-lg btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
27 33 <span class="glyphicon glyphicon-list-alt"></span> List By Metrics <span class="glyphicon glyphicon-list-alt"></span> List By Metrics
28 34 </button> </button>
29 35 <ul class="dropdown-menu"> <ul class="dropdown-menu">
30 <% Node.metric_names.each do |metric,name| %>
36 <% CONFIG.metric_names.each do |metric,name| %>
31 37 <li><a href="/metric/<%= metric %>/"><%= name %></a></li> <li><a href="/metric/<%= metric %>/"><%= name %></a></li>
32 38 <% end %> <% end %>
33 39 <li class="divider"> <li class="divider">
34 <% Node.score_names.each do |score,name| %>
35 <li><a href="/metric/<%= score %>/"><%= name %></a></li>
40 <% CONFIG.score_names.each do |score,name| %>
41 <li><a href="/score/<%= score %>/"><%= name %></a></li>
36 42 <% end %> <% end %>
37 43 </ul> </ul>
38 44 </div> </div>
File views/metric_details.erb changed (mode: 100644) (index 795b041..c2ac59d)
12 12 </div> </div>
13 13
14 14 <div class="row"> <div class="row">
15 <div class="metric_slider col-md-10 col-md-offset-1">
16 <% @nodes.each do |node|
17 name = node[0]
18 value = node[1].to_f
19 %>
20 <p class="metric_text text-center">
21 <a href="/node/<%= name %>"><span class="list_heading label label-default">Node <%= name %> <span class="glyphicon glyphicon-link"></span></span></a>
22 </p>
15 <table class="table table-striped">
16 <tr>
17 <th>Node</th>
18 <th>Absolute Value</th>
19 <th class="col-md-4">Value</th>
20 <th>Normalized Value</th>
23 21
24
25 <div class="metric_bar">
26 <div class="progress">
27 <div class="progress-bar progress-bar-<%= Node.color_type_by_value(value).to_s %>" role="progressbar" aria-valuenow="<%= value*100 %>" aria-valuemin="0" aria-valuemax="100" style="width: <%= value*100 %>%;">
28 <span class="sr-only"><%= value*100.round(2) %>%</span>
22 </tr>
23 <% @nodes.each do |node, data|
24 name = data[:id]
25 absolute = data[:absolute].to_f
26 normalized = data[:normalized].to_f
27 color_class = data[:color_class]
28 %>
29 <tr>
30 <td><a href="/node/<%= node %>">Node <%= node %></a></td>
31 <td><%= absolute.round(5) %></td>
32 <td>
33 <div class="metric_bar">
34 <div class="progress">
35 <div class="progress-bar progress-bar-<%= color_class %>" role="progressbar" aria-valuenow="<%= normalized*100 %>" aria-valuemin="0" aria-valuemax="100" style="width: <%= normalized*100 %>%;">
36 <span class="sr-only"><%= normalized*100 %>%</span>
37 </div>
29 38 </div> </div>
30 </div>
31 </div>
32 <div class="text-center <%= Node.color_type_by_value(value).to_s %>">
33 <p><%= (value*100).round(2) %>%</p>
34 </div>
35
39 </div>
40 </td>
41 <td><span class="<%= color_class %>"><%= (normalized*100).round(2) %>%</span></td>
42 </tr>
36 43 <% end %> <% end %>
37
38 </div>
44 </table>
39 45 </div> </div>
46
40 47 <div class="row"> <div class="row">
41 <div class="col-md-10 col-md-offset-1">
42 48 <%= will_paginate @nodes %> <%= will_paginate @nodes %>
43 49 </div> </div>
44 50 </div> </div>
45
46
47
48
File views/node_details.erb changed (mode: 100644) (index 6a315f0..bf989c9)
1 1 <div class="row"> <div class="row">
2 <h1 class="text-center">Details for Node <%= @node.data[:id] %></h1>
2 <h1 class="text-center">Details for Node <%= @node.id %></h1>
3 3 </div> </div>
4 4
5
6
7 <div id="carousel-example-generic" class="carousel slide">
8 <!-- Indicators -->
9 <ol class="carousel-indicators">
10 <li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
11 <li data-target="#carousel-example-generic" data-slide-to="1"></li>
12 <li data-target="#carousel-example-generic" data-slide-to="2"></li>
13 </ol>
14
15 <!-- Wrapper for slides -->
16 <div class="carousel-inner">
17
18 <!-- NORMALIZED -->
19 <div class="item active metric_slider col-md-8 col-md-offset-2">
20 <div class="carousel-caption">
21 <div class="alert default">
22 <strong>Normalized Node Metrics</strong>
23 </div>
24 </div>
25
26 <% Node.metric_names.each do |metric,name| %>
27 <% metric_normalized = metric+'_normalized' %>
28 <p class="metric_text text-center">
29 <a href="/metric/<%= metric %>/"><span class="list_heading label label-default"><%= name %> <span class="glyphicon glyphicon-link"></span></span></a>
30 </p>
31 <div class="metric_bar">
32 <div class="progress">
33 <div class="progress-bar progress-bar-<%= @node.color_type(metric_normalized).to_s %>" role="progressbar" aria-valuenow="<%= @node.data[metric_normalized.to_sym]*100 %>" aria-valuemin="0" aria-valuemax="100" style="width: <%= @node.data[metric_normalized.to_sym]*100 %>%;">
34 <span class="sr-only"><%= @node.data[metric_normalized.to_sym]*100 %>%</span>
5 <div class="row">
6 <h2 class="text-center">Metric Values</h2>
7 <table class="table table-hover">
8 <tr>
9 <th>Metric</th>
10 <th>Absolute Value</th>
11 <th class="col-md-4">Normalized Value</th>
12 <th>[%]</th>
13 </tr>
14 <% @node.metrics.each do |metric,data| %>
15 <tr>
16 <td><a href="/metric/<%= metric %>/"><%= data[:name] %></a></td>
17 <td><%= data[:absolute].round(5) %></td>
18 <td>
19 <div class="metric_bar">
20 <div class="progress">
21 <div class="progress-bar progress-bar-<%= data[:color_class] %>" role="progressbar" aria-valuenow="<%= data[:normalized]*100 %>" aria-valuemin="0" aria-valuemax="100" style="width:
22 <%= data[:normalized]*100 %>%;">
23 <span class="sr-only"><%= data[:normalized]*100 %>%</span>
24 </div>
35 25 </div> </div>
36 </div>
37 </div>
38 <div class="text-center <%= @node.color_type(metric_normalized).to_s %>">
39 <p><%= (@node.data[metric_normalized.to_sym]*100).round(2) %>%</p>
40 </div>
41 <% end %>
42
43 </div>
44
45 <!-- ABSOLUTE -->
46 <div class="item metric_slider col-md-8 col-md-offset-2">
47 <div class="carousel-caption">
48 <div class="alert default">
49 <strong>Absolute Node Metrics</strong>
50 </div>
51 </div>
52
53 <% Node.metric_names.each do |metric,name| %>
54 <p class="metric_text text-center"><%= name %></p>
55 <p class="lead text-center metric_value_display"><%= @node.data[metric.to_sym] %></p>
56
57 <% end %>
58
59 </div>
60
61 <!-- SCORES -->
62 <div class="item metric_slider col-md-8 col-md-offset-2">
63 <div class="carousel-caption">
64 <div class="alert default">
65 <strong>Scores</strong>
66 </div>
67 </div>
26 </div>
27 </td>
68 28
69 <% Node.score_names.each do |score,name| %>
29 <td>
30 <span class="<%= data[:color] %>">
31 <%= (data[:normalized]*100).round(2) %>%
32 </span>
33 </td>
70 34
35 </tr>
36 <% end %>
37 </table>
38 </div>
71 39
72 <p class="metric_text text-center">
73 <a href="/metric/<%= score %>/"><span class="list_heading label label-default"><%= name %> <span class="glyphicon glyphicon-link"></span></span></a>
74 </p>
75 40
76 <div class="metric_bar">
77 <div class="progress">
78 <div class="progress-bar progress-bar-<%= @node.color_type(score).to_s %>" role="progressbar" aria-valuenow="<%= @node.data[score.to_sym]*100 %>" aria-valuemin="0" aria-valuemax="100" style="width: <%= @node.data[score.to_sym]*100 %>%;">
79 <span class="sr-only"><%= @node.data[score.to_sym]*100 %>%</span>
41 <div class="row">
42 <h2 class="text-center">Score Values</h2>
43 <table class="table table-hover">
44 <tr>
45 <th>Score</th>
46 <th class="col-md-4">Value</th>
47 <th>[%]</th>
48 </tr>
49 <% @node.scores.each do |score,data| %>
50 <tr>
51 <td><a href="/metric/<%= score %>/"><%= data[:name] %></a></td>
52 <td>
53 <div class="metric_bar">
54 <div class="progress">
55 <div class="progress-bar progress-bar-<%= data[:color_class] %>" role="progressbar" aria-valuenow="<%= data[:absolute]*100 %>" aria-valuemin="0" aria-valuemax="100" style="width: <%= data[:absolute]*100 %>%;">
56 <span class="sr-only"><%= data[:absolute]*100 %>%</span>
57 </div>
80 58 </div> </div>
81 </div>
82 </div>
83 <div class="score_value text-center <%= @node.color_type(score).to_s %>">
84 <p><%= (@node.data[score.to_sym]*100).round(2) %>%</p>
85 </div>
86 <% end %>
59 </div>
60 </td>
87 61
88 </div>
89 </div>
90 </div>
91 <div class="row">
92 <h1 class="text-center">Node Neighborhood</h1>
62 <td>
63 <span class="<%= data[:color_class] %>">
64 <%= (data[:absolute]*100).round(2) %>%
65 </span>
66 </td>
67
68 </tr>
69 <% end %>
70 </table>
93 71 </div> </div>
72
94 73 <div class="row"> <div class="row">
95 <div class="col-md-8 col-md-offset-2" id="graph">
96
97 </div>
74 <h2 class="text-center">Node Neighborhood</h2>
75 <div class="col-md-10 col-md-offset-1" id="graph">
76 </div>
98 77 </div> </div>
78
99 79
100 80 <script type="text/javascript"> <script type="text/javascript">
101 var node_id=<%= @node.data[:id] %>;
81 var node_id=<%= @node.id %>;
102 82 </script> </script>
103 83 <script src="/js/fisheye.js"></script> <script src="/js/fisheye.js"></script>
104 84 <script src="/js/graph.js"></script> <script src="/js/graph.js"></script>
File views/score_details.erb added (mode: 100644) (index 0000000..f0650e6)
1 <div class="row">
2 <div class="row">
3 <h1 class="text-center"><%= @score_name %></h1>
4 </div>
5 </div>
6
7 <div class="row">
8 <div class="col-md-10 col-md-offset-1" id="metric_histogram">
9
10 </div>
11 <script src="/js/histogram.js"></script>
12 </div>
13
14 <div class="row">
15 <table class="table table-striped">
16 <tr>
17 <th>Node</th>
18 <th class="col-md-4">Value</th>
19 <th>Normalized Value</th>
20
21 </tr>
22 <% @nodes.each do |node, data|
23 name = data[:id]
24 absolute = data[:absolute].to_f
25 color_class = data[:color_class]
26 %>
27 <tr>
28 <td><a href="/node/<%= node %>">Node <%= node %></a></td>
29 <td>
30 <div class="metric_bar">
31 <div class="progress">
32 <div class="progress-bar progress-bar-<%= color_class %>" role="progressbar" aria-valuenow="<%= absolute*100 %>" aria-valuemin="0" aria-valuemax="100" style="width: <%= absolute*100 %>%;">
33 <span class="sr-only"><%= absolute*100 %>%</span>
34 </div>
35 </div>
36 </div>
37 </td>
38 <td><span class="<%= color_class %>"><%= (absolute*100).round(2) %>%</span></td>
39 </tr>
40 <% end %>
41 </table>
42 </div>
43
44 <div class="row">
45 <%= will_paginate @nodes %>
46 </div>
47 </div>
File views/statistics.erb added (mode: 100644) (index 0000000..fccdbc0)
1 <div class="row">
2 <h1 class="text-center">Statistical Information about the Dataset</h1>
3 </div>
4
5 <div class="row">
6 <h2 class="text-center">Absolute Metric Values</h2>
7 <table class="table table-hover">
8 <tr>
9 <th>Name</th>
10 <th>Minimum</th>
11 <th>Maximum</th>
12 <th>Mean</th>
13 <th>Median</th>
14 <th>Standard Deviation</th>
15 </tr>
16 <% @data_metrics_absolute.each do |metric,values| %>
17 <tr>
18 <td><a href="/metric/<%= metric%>/"><%= values['display_name'] %></a></td>
19 <td><%= values['min'].to_f.round(5) %></td>
20 <td><%= values['max'].to_f.round(5) %></td>
21 <td><%= values['average'].to_f.round(5) %></td>
22 <td><%= values['median'].to_f.round(5) %></td>
23 <td><%= values['standard_deviation'].to_f.round(5) %></td>
24 </tr>
25 <% end %>
26 </table>
27 </div>
28
29 <div class="row">
30 <h2 class="text-center">Normalized Metric Values</h2>
31 <table class="table table-hover">
32 <tr>
33 <th>Name</th>
34 <th>Minimum</th>
35 <th>Maximum</th>
36 <th>Mean</th>
37 <th>Median</th>
38 <th>Standard Deviation</th>
39 </tr>
40 <% @data_metrics_normalized.each do |metric,values| %>
41 <tr>
42 <td><a href="/metric/<%= metric%>/"><%= values['display_name'] %></a></td>
43 <td><%= values['min'].to_f.round(5) %></td>
44 <td><%= values['max'].to_f.round(5) %></td>
45 <td><%= values['average'].to_f.round(5) %></td>
46 <td><%= values['median'].to_f.round(5) %></td>
47 <td><%= values['standard_deviation'].to_f.round(5) %></td>
48 </tr>
49 <% end %>
50 </table>
51 </div>
52
53 <div class="row">
54 <h2 class="text-center">Score Values</h2>
55 <table class="table table-hover">
56 <tr>
57 <th>Name</th>
58 <th>Minimum</th>
59 <th>Maximum</th>
60 <th>Mean</th>
61 <th>Median</th>
62 <th>Standard Deviation</th>
63 </tr>
64 <% @data_scores.each do |score,values| %>
65 <tr>
66 <td><a href="/score/<%= score %>/"><%= values['display_name'] %></a></td>
67 <td><%= values['min'].to_f.round(5) %></td>
68 <td><%= values['max'].to_f.round(5) %></td>
69 <td><%= values['average'].to_f.round(5) %></td>
70 <td><%= values['median'].to_f.round(5) %></td>
71 <td><%= values['standard_deviation'].to_f.round(5) %></td>
72 </tr>
73 <% end %>
74 </table>
75 </div>
76
77 <div class="row">
78 <h2 class="text-center">Metric Pearson Correlation</h2>
79 <table class="table table-hover">
80 <tr>
81 <td>&nbsp;</td>
82 <% CONFIG.metric_names.each do |metric,name| %>
83 <td><a href="/metric/<%= metric%>/"><%= name %></a></td>
84 <% end %>
85 </tr>
86 <% CONFIG.metric_names.each do |metric1,name1| %>
87 <tr>
88 <td><a href="/metric/<%= metric1%>/"><%= name1 %></a></td>
89 <% CONFIG.metric_names.each do |metric2,name2| %>
90 <td>
91 <span class="confidence_tooltip" data-toggle="tooltip" data-placement="top" title=""
92 data-original-title="Confidence: <%= @data_correlations[metric1][:correlation][metric2][:confidence].to_f %>"
93 style="color:<%= @data_correlations[metric1][:correlation][metric2][:color_code] %>">
94 <%= @data_correlations[metric1][:correlation][metric2][:correlation].to_f.round(2) %>
95 </span>
96 </td>
97 <% end %>
98 </tr>
99 <% end %>
100 </table>
101 </div>
102
103 <script type="text/javascript">
104 $(".confidence_tooltip").tooltip();
105 </script>
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/coria/coria-backend

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/coria/coria-backend

Clone this repository using git:
git clone git://git.rocketgit.com/user/coria/coria-backend

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main