Module: Octo::Trends

Includes:
Counter::Helper
Included in:
CategoryTrend, ProductTrend, TagTrend
Defined in:
lib/octocore/trends.rb

Constant Summary collapse

DEFAULT_COUNT =
10

Constants included from Counter::Helper

Counter::Helper::METHOD_PREFIX

Instance Method Summary collapse

Methods included from Counter::Helper

counter_text, #generate_aggregators, #get_duration_for_counter_type, #get_fromtype_for_totype, #get_typecounters, #max_type, #method_names_type_counter, #string_to_const_val, #type_counters_method_names

Instance Method Details

#aggregate!(ts = Time.now.floor) ⇒ Object

Override the aggregate! defined in counter class as the calculations

for trending are a little different


40
41
42
# File 'lib/octocore/trends.rb', line 40

def aggregate!(ts = Time.now.floor)
  aggregate_and_create(Octo::Counter::TYPE_MINUTE, ts)
end

#aggregate_and_create(oftype, ts = Time.now.floor) ⇒ Object

Aggregates and creates trends for all the enterprises for a specific

trend type at a specific timestamp

Parameters:

  • oftype (Fixnum)

    The type of trend to be calculated

  • ts (Time) (defaults to: Time.now.floor)

    The time at which trend needs to be calculated



32
33
34
35
36
# File 'lib/octocore/trends.rb', line 32

def aggregate_and_create(oftype, ts = Time.now.floor)
  Octo::Enterprise.each do |enterprise|
    calculate(enterprise.id, oftype, ts)
  end
end

#calculate(enterprise_id, trend_type, ts = Time.now.floor) ⇒ Object

Performs the actual trend calculation

Parameters:

  • enterprise_id (String)

    The enterprise ID for whom trend needs to be found

  • trend_type (Fixnum)

    The trend type to be calculates

  • ts (Time) (defaults to: Time.now.floor)

    The Timestamp at which trend needs to be calculated.



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/octocore/trends.rb', line 48

def calculate(enterprise_id, trend_type, ts = Time.now.floor)
    args = {
      enterprise_id: enterprise_id,
      ts: ts,
      type: trend_type
    }

    klass = @trend_for.constantize
    hitsResult = klass.public_send(:where, args)
    trends = hitsResult.map { |h| counter2trend(h) }

    # group trends as per the time of their happening and rank them on their
    # score
    grouped_trends = trends.group_by { |x| x.ts }
    grouped_trends.each do |_ts, trendlist|
      sorted_trendlist = trendlist.sort_by { |x| x.score }
      sorted_trendlist.each_with_index do |trend, index|
        trend.rank = index
        trend.type = trend_type
        trend.save!
      end
    end
end

Gets the trend of a type at a time

Parameters:

  • enterprise_id (String)

    The ID of enterprise for whom trend to fetch

  • type (Fixnum)

    The type of trend to fetch

  • opts (Hash) (defaults to: {})

    The options to be provided for finding trends



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/octocore/trends.rb', line 90

def get_trending(enterprise_id, type, opts={})
  ts = opts.fetch(:ts, Time.now.floor)
  args = {
    enterprise_id: enterprise_id,
    ts: opts.fetch(:ts, Time.now.floor),
    type: type
  }
  res = where(args).limit(opts.fetch(:limit, DEFAULT_COUNT))
  enterprise = Octo::Enterprise.find_by_id(enterprise_id)
  if res.count == 0 and enterprise.fakedata?
    Octo.logger.info 'Beginning to fake data'
    res = []
    if ts.class == Range
      ts_begin = ts.begin
      ts_end = ts.end
      ts_begin.to(ts_end, 1.day).each do |_ts|
        3.times do |rank|
          items = @trend_class.constantize.send(:where, {enterprise_id: enterprise_id}).first(10)
          if items.count > 0
            uid = items.shuffle.pop.unique_id
            _args = args.merge( ts: _ts, rank: rank, score: rank+1, uid: uid )
            res << self.new(_args).save!
          end
        end
      end
    elsif ts.class == Time
      3.times do |rank|
        uid = 0
        items = @trend_class.constantize.send(:where, {enterprise_id: enterprise_id}).first(10)
        if items.count > 0
          uid = items.shuffle.pop.unique_id
          _args = args.merge( rank: rank, score: rank+1, uid: uid )
          res << self.new(_args).save!
        end
      end
    end
  end
  res.map do |r|
    clazz = @trend_class.constantize
    clazz.public_send(:recreate_from, r)
  end
end

#trend_class(klass) ⇒ Object

Define the class which would be returned while fetching trending objects



82
83
84
# File 'lib/octocore/trends.rb', line 82

def trend_class(klass)
  @trend_class = klass
end

#trend_for(klass) ⇒ Object

Define the class for which trends shall be found



73
74
75
76
77
78
79
# File 'lib/octocore/trends.rb', line 73

def trend_for(klass)
  unless klass.constantize.ancestors.include?Cequel::Record
    raise ArgumentError, "Class #{ klass } does not represent a DB Model"
  else
    @trend_for = klass
  end
end

#trendableObject

Define the columns needed for Trends



13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/octocore/trends.rb', line 13

def trendable
  key :type, :int
  key :ts, :timestamp
  key :rank, :int

  column :score, :float
  column :uid, :text

  generate_aggregators { |ts, method|
    trendtype = method_names_type_counter(method)
    aggregate_and_create trendtype, ts
  }

end