class Eco::API::UseCases::DefaultCases::AbstractPolicyGroupAbilities < Eco::API::Common::Loaders::UseCase name "abstract-policygroup-abilities" type :export attr_reader :session, :people, :options def main(people, session, options, usecase) options[:end_get] = false @session = session; @options = options; @people = people generate_csv! end private def file @file ||= options.dig(:output, :file) || "suggested_abilities.csv" end def generate_csv! policy_groups.each_with_object({}) do |group, data| data[group.id] ||= {} data[group.id][:name] = group.name data[group.id][:suggested] = group_suggestions(group.id) data[group.id][:percents] = group_abilities(group.id) end.yield_self do |data| abilities_list = Eco::API::Organization::PresetsFactory.abilities CSV.open(file, "w") do |csv| csv << ["Type", "UserGroup", "ID", *abilities_list] # Dump the final suggestions data.each do |id, meta| csv << ["Suggested", meta[:name], id, *meta[:suggested].values_at(*abilities_list)] end # Dump the percentaged levels of each ability data.each do |id, meta| analysis = meta[:percents].values_at(*abilities_list).each_with_object([]) do |levels, values| values << levels.map do |level, percentil| "#{level ? level : "null"} => #{percentil}" end.join("\n") end csv << ["Analysis", meta[:name], id, *analysis] end end puts "Generated file #{file}" end end def policy_groups @policy_groups ||= session.policy_groups end # Suggests 1 final set of abilities for a usergroup def group_suggestions(id) group_abilities(id).each_with_object({}) do |(key, levels), set| data = levels.to_a.sort_by(&:last).reverse.first set[key] = data ? data.shift : nil end end # Cleans up each ability's levels by: # 1. cutting at some minimum threshold percentage # 2. directly selecting those greater than 70% def group_abilities(id) @group_abilities ||= {} @group_abilities[id] ||= ability_levels_percent(id).each_with_object({}) do |(ability, levels), out| outstanding = nil levels.select do |level, percentil| outstanding ||= level if percentil >= 75 percentil > 15 end.yield_self do |filtered| out[ability] = outstanding ? filtered.slice(outstanding) : filtered end end end # With given the percentages of sets of abilities # it abstracts the percentage of each level of each ability def ability_levels_percent(id) @ability_levels_percent ||= {} @ability_levels_percent[id] ||= Eco::API::Organization::PresetsFactory.abilities.each_with_object({}) do |key, out| out[key] ||= {} ability_sets_percent(id).each_with_object(out[key]) do |(set, percentil), levels| levels[set[key]] ||= 0 levels[set[key]] = (levels[set[key]] + percentil).round(2) end end end # Give a percentage to each set of abilities def ability_sets_percent(id) @ability_sets_percent ||= {} @ability_sets_percent[id] ||= scoped_relevant_raw_data(id).yield_self do |data| # Transform ability sets counter to percentage total = data[:count] abilities = data[:abilities] data[:abilities].transform_values do |val| percent(val, total) end end end # Get rid of data simingly irrelevant def scoped_relevant_raw_data(id) sp = single_percent(id) sing = single(id); mult = multiple(id) # Scope Relevant Raw Data case when sp >= 80 sing when sp < 15 mult else # combine all_abilities = sing[:abilities].keys | mult[:abilities].keys data = {count: sing[:count] + mult[:count], abilities: {}} all_abilities.each_with_object(data) do |abilities, merged| scount = sing[:abilities][abilities] || 0 mcount = mult[:abilities][abilities] || 0 merged[:abilities][abilities] = scount + mcount end end end def single_percent(id) percent(single(id)[:count], count(id)) end def single(id) groups_abilities.dig(id, :single) || {count: 0, abilities: {}} end def multiple(id) groups_abilities.dig(id, :multiple) || {count: 0, abilities: {}} end def count(id) groups_abilities.dig(id, :count) || 0 end def groups_abilities @groups_abilities ||= people.users.each_with_object({}) do |user, groups| abilities = Eco::API::Organization::PresetsFactory.all_abilities(user.account.permissions_custom) ids = user.account.policy_group_ids category = ids.count > 1 ? :multiple : :single ids.each do |id| groups[id] ||= {count: 0} groups[id][:count] += 1 groups[id][category] ||= {count: 0, abilities: {}} groups[id][category][:count] += 1 groups[id][category][:abilities][abilities] ||= 0 groups[id][category][:abilities][abilities] += 1 end end end def percent(num, total) (100 * num.to_f / total).round(2) end end