#coding=utf-8 require "aio/core" class Aio::Module::SpecialStyle::Compare < Aio::Module::SpecialStyle include Aio::Module include Aio::Ui::Verbose # 用于传递已经分析好的现有的device attr_accessor :device_manager # 用于传递由XML,Json生成并已经解析的Hash值 attr_accessor :input_benchmark def initialize super({ :author => "Elin", :description => "此模块用于解析两个Hash值的不同点,并发出警告", }) end def parse # 将device_manager 中的按照{device_name => useful} 形式重新编排 # cmds_useful为深度克隆信息,对本体无影响 device_warning = {} total = device_manager.devices_number print_good "总共 #{total} 台设备进行比较" device_manager.each_devices_with_index do |device_name, device_klass, i| device_warning[device_name] = Aio::Base::Toolkit::DeepClone.clone(device_klass.cmds_useful) # 进度条 progress_bar(total, i+1, device_name) end @compare_hash = Aio::Module::Compare.new clear_line clear_other_info(device_warning, input_benchmark) compare(device_warning, input_benchmark) end # 只留下要比较的两个数据有共同命令的交集,其他的命令就丢弃 # 因为即使是保留了,产生的也是大量的垃圾信息 def clear_other_info(device_warning, input_benchmark) device_arr = {} input_arr = {} # 获得命令信息 device_warning.each_pair { |k, v| device_arr[k] = v.keys } input_benchmark.each_pair { |k, v| input_arr[k] = v.keys } # 删除 device_warning 中多余的命令信息 device_warning.each_pair do |name, hash| hash.delete_if do |k, v| next true unless input_arr.has_key?(name) input_arr[name].include?(k) ? false : true end end # 删除 input_benchmark 中多余的命令信息 input_benchmark.each_pair do |name, hash| hash.delete_if do |k, v| next true unless device_arr.has_key?(name) device_arr[name].include?(k) ? false : true end end end def compare(cm1, cm2, opts={}) # NOTE 待加PASS @config_compare = Aio::Config::Warning::Compare cm1_arr = [] cm2_arr = [] Aio::Base::Toolkit::Hash.flat(cm1, Aio::Base::Toolkit::Chain.new, cm1_arr) Aio::Base::Toolkit::Hash.flat(cm2, Aio::Base::Toolkit::Chain.new, cm2_arr) cp = find_diff(cm1_arr, cm2_arr) diff = { cm1: [], cm2: []} # NOTE 还需要加入config_compare # diff = { # cm1: [ [device_name, cmd, str], .. ], # cm2: [ [device_name, cmd, str], .. ] # } cp[:cm1].each do |e| # 加入cmd cmd = e[1] diff[:cm1] << [e.first, cmd, e.last] end cp[:cm2].each do |e| diff[e.first] ||= {} # 加入cmd cmd = e[1] diff[:cm2] << [e.first, cmd, e.last] end diff end def find_diff(cm1, cm2) res = {} res[:cm1] = [] res[:cm2] = [] # res 为相同的内容 total = cm1.size cm1.each_with_index do |link_1, i| cm2.each do |link_2| # 如果长度不一致,就下一个 if link_1.size != link_2.size next else name_1 = long_name(link_1) name_2 = long_name(link_2) if name_1 == name_2 res[:cm1] << link_1 res[:cm2] << link_2 # 找到了相同的就跳出小循环 break end end end # 进度条 progress_bar(total, i+1, '') end clear_line # 获得不同的内容 res[:cm1] = cm1 - res[:cm1] res[:cm2] = cm2 - res[:cm2] res end # 将一个数组转化成一长串字符作为比较方式 def long_name(arr) res = '' arr.each { |x| res += x.to_s } res end end