class FeedInto::Group

Constants

GROUP

Public Class Methods

new( modules: nil, group: {}, single: {} ) click to toggle source
# File lib/feed_into.rb, line 821
def initialize( modules: nil, group: {}, single: {} )
  mdl = modules.class.eql? String
  chn = single.keys.include? :channels
  mode = :not_found

  if !mdl and !chn
    puts 'No Channel found.'
  else
    if chn
     # mode = :options
     # transfer = Marshal.load( Marshal.dump( options[:channels] ) )
     # options.delete( :channels )
    end

    @group = Marshal.load( Marshal.dump( GROUP ) )
    @group[:meta][:timestamp] = Time.now.utc.to_s
    
    if options_update( group, @group, true )
      @single = Single.new( modules: modules, options: single )
      @group = options_update( group, @group, false )
      @analyse = nil
      @merge = nil
    else
    end
  end
end

Public Instance Methods

analyse( items: nil, silent: false ) click to toggle source
# File lib/feed_into.rb, line 849
def analyse( items: nil, silent: false )
  def c_log( silent, r, score )
    if !silent
      print "(#{score[:sleep]})  "
      if r[:success] 
        if r[:result][:items].length > 0
          r[:success] ? print( r[:result][:items][ 0 ][:title] ) : ''
        else
          print r[:result][:meta][:title]
        end
      else
        print r[:cmd][:name]
        r[:messages].each { | m | puts( "- #{m}" ) }
      end
      puts
    else
    end
  end


  cmds, messages = cmds( items )

  if cmds[:valid]
    keys = cmds[:cmds]
      .map { | a | a[:cmd][:channel] }
      .to_set
      .to_a
    
    groups = keys.inject( {} ) do | hash, key |  
      hash[ key ] = cmds[:cmds].select { | cmd | cmd[:cmd][:channel].eql?( key ) } 
      hash
    end

    orders, struct = get_shuffle( groups )
    results = struct.inject( {} ) do | item, k | 
      item[ k[ 0 ] ] = {}
      item[ k[ 0 ] ][:responses] = k[ 1 ].clone
      item[ k[ 0 ] ][:status] = k[ 1 ].clone
      item
    end

    orders.each.with_index do | order, index |
      start = Time.now.to_f
      score = score( index, orders, results, @group, groups )
      cmd = groups[ order[:category] ][ order[:index ] ]

      if score[:skip]
        !silent ? puts( ">> Skip: #{order}" ) : ''
        results[ order[:category] ][:responses][ order[:index] ] = {
          cmd: cmd[:cmd],
          skip: true
        }
      else
        sleep( score[:sleep] )
        r = @single.analyse( item: cmd, trust_item: true )

        !r[:status].class.eql? Integer ? tmp = 0 : tmp = r[:status]
        results[ order[:category] ][:status][ order[:index] ] = tmp #r[:status]
        results[ order[:category] ][:responses][ order[:index] ] = r
        results[ order[:category] ][:responses][ order[:index] ][:skip] = false 

        results[ order[:category] ][:responses][ order[:index] ][:time] = Time.now.to_f - start
        c_log( silent, r, score )
      end

    end
  else
    puts 'cmds not valid.'
    messages.each { | m | puts( "- #{m}" ) }
  end


  items = results
    .map { | k, v | v[:responses].map { | a | a } }
    .flatten

  categories = items
    .map { | item | item[:cmd][:category] }
    .to_set
    .to_a

  re_grouped = categories
    .inject( {} ) { | group, category | 
      group[ category] = items.select { | a | a[:cmd][:category].eql? category }
      group
    }

  @analyse = re_grouped
  self
end
c_log( silent, r, score ) click to toggle source
# File lib/feed_into.rb, line 850
def c_log( silent, r, score )
  if !silent
    print "(#{score[:sleep]})  "
    if r[:success] 
      if r[:result][:items].length > 0
        r[:success] ? print( r[:result][:items][ 0 ][:title] ) : ''
      else
        print r[:result][:meta][:title]
      end
    else
      print r[:cmd][:name]
      r[:messages].each { | m | puts( "- #{m}" ) }
    end
    puts
  else
  end
end
categories( analyse ) click to toggle source
# File lib/feed_into.rb, line 1072
def categories( analyse )
  results = {}
   analyse.keys.each do | key |
    a = {
      status: {
        success: nil,
        error: nil,
        skip: nil,
        total: nil
      },
      errors: nil,
      time: nil
    }
    
    a[:status][:success] = analyse[ key ]
      .reject { | a | a[:skip] }
      .select { | a | a[:success].eql? true }
      .length

    a[:status][:error] = analyse[ key ]
      .reject { | a | a[:skip] }
      .select { | a | a[:success].eql? false }
      .length
    
    a[:status][:skip] = analyse[ key ]
      .select { | a | a[:skip] }
      .length

    a[:status][:total] = [ :success, :error, :skip ]
      .map { | key | a[:status][ key ] }
      .sum
    
    a[:errors] = analyse[ key ]
      .reject { | a | a[:skip] }
      .select { | a | a[:success].eql? false }
      .map { | a | { name: a[:cmd][:name], url: a[:cmd][:url] } }
    
    a[:time] = analyse[ key ]
      .reject { | a | a[:skip] }
      .map { | a | a[:time] }
      .sum
      .round( 8 )

    results[ key ] = a
  end
  results
end
channels( analyse ) click to toggle source
# File lib/feed_into.rb, line 1121
def channels( analyse )
  results = {}
  
  channels = analyse
    .map { | category |
      category[ 1 ]
        .map { | a | a[:cmd][:channel] }
    }
    .flatten
    .to_set
    .to_a
  
  channels.each do | channel |
    a = {
      status: {
        success: nil,
        error: nil,
        skip: nil,
        total: nil
      },
      errors: nil,
      time: nil
    }
    
    cmds = analyse
      .map { | category |
        category[ 1 ]
          .select { | a | a[:cmd][:channel].eql? channel }
      }
      .flatten
              
    a[:status][:success] = cmds
      .reject { | a | a[:skip] }
      .select { | a | a[:success] }
      .length
    
    a[:status][:error] = cmds
      .reject { | a | a[:skip] }
      .select { | a | !a[:success] }
      .length
    
    a[:status][:skip] = cmds
      .select { | a | a[:skip] }
      .length
    
    a[:status][:total] = [ :success, :error, :skip ]
      .map { | key | a[:status][ key ] }
      .sum
    
    a[:time] = cmds
      .map { | a | a.keys.include?( :time ) ?  a[:time] : 0 }
      .sum
      .round( 8 )
    
    a[:errors] = cmds
      .reject { | a | a[:skip] }
      .select { | a | !a[:success] }
      .map { | a | { name: a[:cmd][:name], url: a[:cmd][:url] } }
      
    results[ channel ] = a
  end
  
  return results
end
merge() click to toggle source
# File lib/feed_into.rb, line 941
def merge
  def valid?( item ) 
    result = false

    if [ Hash, ActiveSupport::HashWithIndifferentAccess ].include? item.class
      one = [ :title, :time, :url ]
        .map { | key | item.keys.include? key }
        .all?

      if one
        if [ Hash, ActiveSupport::HashWithIndifferentAccess ].include? item[:time].class
          if item[:time].keys.include? :stamp
            result = true
          end
        end
      end
    end

    return result
  end


  messages = []
  result = @analyse.inject( {} ) do | categories, d |
    all = d[ 1 ].inject( [] ) do | category, response |
      if response[:skip]
      else
        if response[:success]
          response[:result][:items].each do | item |
            if valid?( item )
              itm = {
                title: item[:title],
                timestamp: item[:time][:stamp],
                url: item[:url]
              }
    
              category.push( itm )
            else
              messages.push( '- One or more key(s) in Item are not available.' )
            end
          end
        end
      end
      category
    end

    all = all.sort_by { | a | -a[:timestamp] }
    categories[ d[ 0 ].to_sym ] = all.clone
    categories
  end

  messages.each { | message | puts( message ) }

  @merge = result
  self
end
overview( channels ) click to toggle source
# File lib/feed_into.rb, line 1187
def overview( channels ) 
  results = { time: {}, all: {} }
  results[:time][:now] = Time.now.utc.to_s
  z = channels
    .keys
    .map { | key | channels[ key ][:time] }
    .sum
    .round( 0 )
  
  results[:time][:analyse] = 
    Time.at( z ).utc.strftime( "%Mm %Ss" )
  
  [ :success, :error, :skip, :total ].each do | key | 
    results[:all][ key ] = channels
      .map { | k, v | v[:status][ key ] }
      .sum
  end
  return results
end
status( silent: false ) click to toggle source
# File lib/feed_into.rb, line 1071
def status( silent: false )
  def categories( analyse )
    results = {}
     analyse.keys.each do | key |
      a = {
        status: {
          success: nil,
          error: nil,
          skip: nil,
          total: nil
        },
        errors: nil,
        time: nil
      }
      
      a[:status][:success] = analyse[ key ]
        .reject { | a | a[:skip] }
        .select { | a | a[:success].eql? true }
        .length

      a[:status][:error] = analyse[ key ]
        .reject { | a | a[:skip] }
        .select { | a | a[:success].eql? false }
        .length
      
      a[:status][:skip] = analyse[ key ]
        .select { | a | a[:skip] }
        .length

      a[:status][:total] = [ :success, :error, :skip ]
        .map { | key | a[:status][ key ] }
        .sum
      
      a[:errors] = analyse[ key ]
        .reject { | a | a[:skip] }
        .select { | a | a[:success].eql? false }
        .map { | a | { name: a[:cmd][:name], url: a[:cmd][:url] } }
      
      a[:time] = analyse[ key ]
        .reject { | a | a[:skip] }
        .map { | a | a[:time] }
        .sum
        .round( 8 )
  
      results[ key ] = a
    end
    results
  end
  
  
  def channels( analyse )
    results = {}
    
    channels = analyse
      .map { | category |
        category[ 1 ]
          .map { | a | a[:cmd][:channel] }
      }
      .flatten
      .to_set
      .to_a
    
    channels.each do | channel |
      a = {
        status: {
          success: nil,
          error: nil,
          skip: nil,
          total: nil
        },
        errors: nil,
        time: nil
      }
      
      cmds = analyse
        .map { | category |
          category[ 1 ]
            .select { | a | a[:cmd][:channel].eql? channel }
        }
        .flatten
                
      a[:status][:success] = cmds
        .reject { | a | a[:skip] }
        .select { | a | a[:success] }
        .length
      
      a[:status][:error] = cmds
        .reject { | a | a[:skip] }
        .select { | a | !a[:success] }
        .length
      
      a[:status][:skip] = cmds
        .select { | a | a[:skip] }
        .length
      
      a[:status][:total] = [ :success, :error, :skip ]
        .map { | key | a[:status][ key ] }
        .sum
      
      a[:time] = cmds
        .map { | a | a.keys.include?( :time ) ?  a[:time] : 0 }
        .sum
        .round( 8 )
      
      a[:errors] = cmds
        .reject { | a | a[:skip] }
        .select { | a | !a[:success] }
        .map { | a | { name: a[:cmd][:name], url: a[:cmd][:url] } }
        
      results[ channel ] = a
    end
    
    return results
  end
  
  
  def overview( channels ) 
    results = { time: {}, all: {} }
    results[:time][:now] = Time.now.utc.to_s
    z = channels
      .keys
      .map { | key | channels[ key ][:time] }
      .sum
      .round( 0 )
    
    results[:time][:analyse] = 
      Time.at( z ).utc.strftime( "%Mm %Ss" )
    
    [ :success, :error, :skip, :total ].each do | key | 
      results[:all][ key ] = channels
        .map { | k, v | v[:status][ key ] }
        .sum
    end
    return results
  end
  
  
  if @analyse.nil?
    !silent ? puts( 'Data is not analysed, use .analyse() before.' ) : ''
  else
    
    messages = {
      overview: {},
      channels: {},
      categories: {}
    }

    messages[:categories] = categories( @analyse )
    messages[:channels] = channels( @analyse )
    messages[:overview] = overview( messages[:channels] )
  end

  return messages
end
to_h( type: nil ) click to toggle source
# File lib/feed_into.rb, line 999
def to_h( type: nil )
  if @analyse.nil? and @merge.nil?
    puts 'No Data found, please use .analyse() before.'
    return nil
  else
    if type.nil?
      if @merge.nil?
        return @analyse
      else
        return @merge
      end
    else
      case type
        when :merge
          return @merge
        when :analyse
          return @analyse
      end
    end
  end
end
to_rss( key: Symbol, silent: false ) click to toggle source
# File lib/feed_into.rb, line 1022
def to_rss( key: Symbol, silent: false )
  result = ''

  if @merge.nil?
    !silent ? puts( 'Data is not merged in groups, use .merge() before.' ) : ''
  else
    if @merge.keys.include? key
      rss = RSS::Maker.make( 'atom' ) do | maker |
        maker.channel.author = ''
        maker.channel.updated = Time.now.to_s
        maker.channel.about = ''
        maker.channel.title = key.to_s
  
        @merge[ key ].each do | entry |
          maker.items.new_item do | item |
            item.link = entry[:url]
            item.title = entry[:title]

            d = Time.at( entry[:timestamp] ).to_datetime.to_s

            item.updated = d
          end   
        end
      end
    else
      !silent ? puts( 'Key does not exist.' ) : ''
    end
    result = rss.to_s.gsub( '<link href="', '<link rel="alternate" href="' )
  end

  return result
end
to_rss_all( silent: false ) click to toggle source
# File lib/feed_into.rb, line 1056
def to_rss_all( silent: false )
  results = {}

  if @merge.nil?
    !silent ? puts( 'Data is not merged in groups, use .merge() before.' ) : ''
  else
    @merge.keys.each do | key |
      results[ key ] = to_rss( key: key, silent: false )
    end
  end

  return results
end
valid?( item ) click to toggle source
# File lib/feed_into.rb, line 942
def valid?( item ) 
  result = false

  if [ Hash, ActiveSupport::HashWithIndifferentAccess ].include? item.class
    one = [ :title, :time, :url ]
      .map { | key | item.keys.include? key }
      .all?

    if one
      if [ Hash, ActiveSupport::HashWithIndifferentAccess ].include? item[:time].class
        if item[:time].keys.include? :stamp
          result = true
        end
      end
    end
  end

  return result
end

Private Instance Methods

cmds( cs ) click to toggle source
# File lib/feed_into.rb, line 1230
def cmds( cs )
  valid = {
    array: true,
    hash: true,
  }

  result = {
    valid: false,
    cmds: []
  }

  cmds = []
  messages = []
  if cs.class.eql? Array
    test = cs.map do | c |
      [ Hash, ActiveSupport::HashWithIndifferentAccess, String ].include? c.class
    end

    if test.all?
      cmds = cs.map do | c |
        cmd, messages = @single.cmd( c, @single.settings )
        { cmd: cmd, messages: messages }
      end
    else
      valid[:hash] = false
      messages.push( 'cmds: Not all Items are Class "Hash"' )
    end
  else
    valid[:array] = false
    messages.push( 'cmds: Input is not Class "Array"' )
  end

  result[:valid] = valid.map { | k, v | v }.all?
  result[:cmds].concat( cmds )

  return result, messages
end
get_shuffle( groups ) click to toggle source
# File lib/feed_into.rb, line 1269
def get_shuffle( groups )
  def struct( groups )
    boilerplate = groups
      .inject( {} ) { | hash, k | hash[ k[ 0 ] ] = k[ 1 ].length; hash }

    struct = boilerplate.inject( {} )  do | hash, key |
      hash[ key[ 0 ] ] = key[ 1 ].times.map { | a | nil }
      hash
    end
    
    groups = boilerplate.inject( {} )  do | hash, key |
      hash[ key[ 0 ] ] = key[ 1 ].times.map { | a | "#{key[ 0 ]}--#{a}" }
      hash
    end

    return groups, struct
  end
  

  def shuffle( struct, groups )
    results = []
    order = []

    l = struct.map { | k, v | v.length }.sum
    for round in 0..l - 1
      selections = struct
        .filter_map { | k, v | k if v.length > 0 }

      variety = selections.length
      if round == 0
        current = selections[ 0 ]
      else
        case selections.length
          when 0
            before = 0
          when 1
            before = 0
          when 2
            before = 1
          when 3
            before = 2
          when 4
            before = 3
        else
          before = 4
        end

        selections = selections
          .reject { | s | order.last( before ).include?( s ) }      
      end

      current = selections[ rand( 0..selections.length - 1 ) ]
      r_index = rand( 0..struct[ current ].length - 1 )

      index = struct[ current ][ r_index ].split( '--' ).last.to_i

      channel = groups[ current ][ index ][:cmd][:channel]

      result = { category: current, index: index, variety: variety, channel: channel }

      results.push( result )

      struct[ current ].delete_at( r_index )
      order.push( current )
    end

    return results
  end
  
  tmp, struct = struct( groups )
  orders = shuffle( tmp, groups )
  #orders.each { | order | puts( order.to_s ) }

  return orders, struct
end
score( index, orders, results, obj, groups ) click to toggle source
# File lib/feed_into.rb, line 1346
def score( index, orders, results, obj, groups )
  current = orders[ index ]

  if index == 0
    test = []
  else
    test = orders
      .first( index )
      .select { | order | order[:channel].eql? current[:channel] }
     
    test = test
      .map { | cmd | 
        if results[ cmd[:category] ][:responses][ cmd[:index] ][:skip]
          :skip
        else
          results[ cmd[:category] ][:responses][ cmd[:index] ][:status]
        end
      }
      .select { | a | !a.eql?( :skip ) }
      .last( obj[:sleep][:range] )
  end

  scores = test.map do | sr |
    if sr.nil?
      key = :other
    else
      tmp = obj[:sleep][:codes].find { | a | a[:status].eql?( sr ) }
      key = tmp[:add]
    end
    obj[:sleep][:scores][ key ][:value]
  end

  score = scores.sum
  tmp = obj[:sleep][:stages].find do | a |
    case a[:range].length
      when 1
        score >= a[:range][ 0 ]
      when 2
        score >= a[:range][ 0 ] and score <= a[:range][ 1 ]
    end
  end
  result = Marshal.load( Marshal.dump( tmp ) )

  found = obj[:sleep][:varieties]
    .find { | variety | variety[:variety].eql? current[:variety] }

  tension = !found.nil? ? found[:sleep] : 0 
  result[:sleep] = result[:sleep].to_i + tension.to_i

  result[:score] = score
  return result
end
shuffle( struct, groups ) click to toggle source
# File lib/feed_into.rb, line 1288
def shuffle( struct, groups )
  results = []
  order = []

  l = struct.map { | k, v | v.length }.sum
  for round in 0..l - 1
    selections = struct
      .filter_map { | k, v | k if v.length > 0 }

    variety = selections.length
    if round == 0
      current = selections[ 0 ]
    else
      case selections.length
        when 0
          before = 0
        when 1
          before = 0
        when 2
          before = 1
        when 3
          before = 2
        when 4
          before = 3
      else
        before = 4
      end

      selections = selections
        .reject { | s | order.last( before ).include?( s ) }      
    end

    current = selections[ rand( 0..selections.length - 1 ) ]
    r_index = rand( 0..struct[ current ].length - 1 )

    index = struct[ current ][ r_index ].split( '--' ).last.to_i

    channel = groups[ current ][ index ][:cmd][:channel]

    result = { category: current, index: index, variety: variety, channel: channel }

    results.push( result )

    struct[ current ].delete_at( r_index )
    order.push( current )
  end

  return results
end
struct( groups ) click to toggle source
# File lib/feed_into.rb, line 1270
def struct( groups )
  boilerplate = groups
    .inject( {} ) { | hash, k | hash[ k[ 0 ] ] = k[ 1 ].length; hash }

  struct = boilerplate.inject( {} )  do | hash, key |
    hash[ key[ 0 ] ] = key[ 1 ].times.map { | a | nil }
    hash
  end
  
  groups = boilerplate.inject( {} )  do | hash, key |
    hash[ key[ 0 ] ] = key[ 1 ].times.map { | a | "#{key[ 0 ]}--#{a}" }
    hash
  end
    
  return groups, struct
end