Merge branch 'master' of git.clinicalfuture.com:arvados
[arvados.git] / apps / workbench / app / controllers / pipeline_instances_controller.rb
1 class PipelineInstancesController < ApplicationController
2   skip_before_filter :find_object_by_uuid, only: :compare
3   before_filter :find_objects_by_uuid, only: :compare
4   include PipelineInstancesHelper
5
6   def compare
7     @breadcrumb_page_name = 'compare'
8
9     @rows = []          # each is {name: S, components: [...]}
10
11     # Build a table: x=pipeline y=component
12     @objects.each_with_index do |pi, pi_index|
13       pipeline_jobs(pi).each do |component|
14         # Find a cell with the same name as this component but no
15         # entry for this pipeline
16         target_row = nil
17         @rows.each_with_index do |row, row_index|
18           if row[:name] == component[:name] and !row[:components][pi_index]
19             target_row = row
20           end
21         end
22         if !target_row
23           target_row = {name: component[:name], components: []}
24           @rows << target_row
25         end
26         target_row[:components][pi_index] = component
27       end
28     end
29
30     @rows.each do |row|
31       # Build a "normal" pseudo-component for this row by picking the
32       # most common value for each attribute. If all values are
33       # equally common, there is no "normal".
34       normal = {}              # attr => most common value
35       highscore = {}           # attr => how common "normal" is
36       score = {}               # attr => { value => how common }
37       row[:components].each do |pj|
38         pj.each do |k,v|
39           vstr = for_comparison v
40           score[k] ||= {}
41           score[k][vstr] = (score[k][vstr.to_s] || 0) + 1
42           highscore[k] ||= 0
43           if score[k][vstr] == highscore[k]
44             # tie for first place = no "normal"
45             normal.delete k
46           elsif score[k][vstr] == highscore[k] + 1
47             # more pipelines have v than anything else
48             highscore[k] = score[k][vstr]
49             normal[k] = vstr
50           end
51         end
52       end
53
54       # Add a hash in component[:is_normal]: { attr => is_the_value_normal? }
55       row[:components].each do |pj|
56         pj[:is_normal] = {}
57         pj.each do |k,v|
58           pj[:is_normal][k] = (normal.has_key?(k) && normal[k] == for_comparison(v))
59         end
60       end
61     end
62   end
63
64   protected
65   def for_comparison v
66     if v.is_a? Hash or v.is_a? Array
67       v.to_json
68     else
69       v.to_s
70     end
71   end
72
73   def find_objects_by_uuid
74     @objects = model_class.where(uuid: params[:uuids])
75   end
76
77 end