Class: DateIdeas

Inherits:
Object
  • Object
show all
Defined in:
lib/date_ideas.rb

Constant Summary collapse

ATTRIBUTES =
%w(adventure romantic athletic intellectual)

Instance Method Summary collapse

Constructor Details

#initialize(&block) ⇒ DateIdeas

Returns a new instance of DateIdeas.



5
6
7
8
# File 'lib/date_ideas.rb', line 5

def initialize(&block)
  @date_ideas = []
  instance_eval &block
end

Instance Method Details

#choose(weather, time) ⇒ Object



119
120
121
122
123
124
125
126
127
# File 'lib/date_ideas.rb', line 119

def choose(weather, time)
  keys, betas = fitted_model
  jitter = betas.inject{|sum,x| sum + x }
  outcomes = estimate_outcomes([keys, betas]).each_with_index.map {|k,i|
    [k,i]
  }.sort_by {|k| -k[0] + rand(jitter)}
  best = outcomes.first[1]
  incomplete[best]
end

#completeObject



55
56
57
# File 'lib/date_ideas.rb', line 55

def complete
  @date_ideas.reject { |idea| idea.stub? or not idea.complete? }
end

#complete_features(keys = []) ⇒ Object



111
112
113
# File 'lib/date_ideas.rb', line 111

def complete_features(keys = [])
  extract_features(complete, keys)
end

#date(name, &block) ⇒ Object



14
15
16
17
18
19
20
# File 'lib/date_ideas.rb', line 14

def date(name, &block)
  date = DateIdea.new(name)
  if block
    date.instance_eval(&block)
  end
  @date_ideas << date
end

#estimate_outcomes(model = nil) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/date_ideas.rb', line 95

def estimate_outcomes(model = nil)
  if model.nil?
    keys, betas = fitted_model
  else
    keys, betas = model
  end
  keys, features = incomplete_features(keys)
  features.map { |idea|
    val = 0
    idea[0].each_with_index { |attribute, i|
      val += betas[i] * attribute
    }
    val
  }
end

#extract_features(idea_list, keys = []) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/date_ideas.rb', line 63

def extract_features(idea_list, keys = [])
  if keys.empty?
    keys = idea_list.reduce([]) { |acc, idea|
      acc << idea.attributes.keys
    }.flatten.uniq
  end
  features = idea_list.map { |idea|
    attributes = idea.attributes.map { |key, val|
      [keys.index(key), val]
    }.sort_by {|k| k[0]}.map { |e| e[1] }
    [attributes, idea.outcome_safe]
  }
  [keys, features]
end

#fitted_model(keys = []) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/date_ideas.rb', line 78

def fitted_model(keys = [])
  dimensions, examples = complete_features(keys)
  # need regularization (elastic net?) before adding these terms
  #terms = Matrix.rows examples.map { |example|
  #  example[0] + example[0].permutation(2).to_a.map { |term| term.reduce(1) {|acc,k| acc*k } }
  #}
  terms = Matrix.rows examples.map { |example| example[0] }
  outcomes = Matrix.column_vector(examples.map { |example| example[1] })
  if (terms.t * terms).det == 0
    raise "The determinant is zero.  There's likely no useful information here."
  end
  betas = ((terms.t * terms).inv * terms.t * outcomes).t.to_a.flatten.map { |e|
    e.to_f.round(4)
  }
  [keys, betas]
end

#ideasObject



10
11
12
# File 'lib/date_ideas.rb', line 10

def ideas
  @date_ideas
end

#incompleteObject



59
60
61
# File 'lib/date_ideas.rb', line 59

def incomplete
  @date_ideas.reject { |idea| idea.stub? or idea.complete? }
end

#incomplete_features(keys = []) ⇒ Object



115
116
117
# File 'lib/date_ideas.rb', line 115

def incomplete_features(keys = [])
  extract_features(incomplete, keys)
end

#list(opts) ⇒ Object



22
23
24
25
26
27
28
29
30
# File 'lib/date_ideas.rb', line 22

def list(opts)
  if opts[:complete]
    render complete
  elsif opts[:incomplete]
    render incomplete
  else
    render
  end
end

#render(ideas = nil) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/date_ideas.rb', line 32

def render(ideas = nil)
  if nil == ideas
    ideas = @date_ideas
  end
  str = "Date ideas:\n"
  ideas.each do |f|
    if not f.complete?
      str << "  #{f.to_s}".blue
    elsif f.complete? and f.score >= 6.0
      str << "  #{f.to_s}".green
    elsif f.complete? and f.score < 6.0
      str << "  #{f.to_s}".red
    else
      raise "We should never reach this."
    end
  end
  str
end

#to_sObject



51
52
53
# File 'lib/date_ideas.rb', line 51

def to_s
  render
end