whats-for-dinner 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,114 @@
1
+ class CommandLineInterface
2
+
3
+ CATEGORIES = Category.get_category_list
4
+
5
+ def run
6
+ location = get_location
7
+ users = get_users
8
+ whats_for_dinner = WhatsForDinner.new(location, users)
9
+ loop do
10
+ restaurant = whats_for_dinner.ask
11
+ make_recommendation(restaurant)
12
+ break if yes?("Sound good?")
13
+ end
14
+ puts "Great! Thanks for using What's For Dinner?, powered by Yelp."
15
+ end
16
+
17
+ def get_location
18
+ puts "Hi! Where do you want to have dinner tonight?"
19
+ location = gets.strip
20
+ end
21
+
22
+ def get_users
23
+ users = []
24
+ loop do
25
+ puts "What's your name?"
26
+ name = gets.strip
27
+ puts "What are you in the mood for today?"
28
+ likes = get_preferences(gets)
29
+ puts "What don't you want to eat?"
30
+ dislikes = get_preferences(gets)
31
+ user = User.new(name, likes, dislikes)
32
+ users << user
33
+ break unless yes?("Is anyone else joining you?")
34
+ end
35
+ users
36
+ end
37
+
38
+ def make_recommendation(restaurant)
39
+ puts "How about?"
40
+ puts ""
41
+ puts restaurant.name
42
+ puts "#{restaurant.rating} star rating, #{restaurant.review_count} reviews"
43
+ puts restaurant.categories.map{|category| category.title}.join(", ")
44
+ puts ""
45
+ puts restaurant.display_address
46
+ puts restaurant.display_phone
47
+ puts ""
48
+ puts "\"#{restaurant.snippet_text}\""
49
+ puts ""
50
+ end
51
+
52
+ def get_preferences(input)
53
+ validated_categories = []
54
+ if input.strip == ""
55
+ validated_categories
56
+ else
57
+ user_categories = input
58
+ .split(/[,][ ]*/)
59
+ .select {|string| !string.include? ","}
60
+ .map {|string| string.strip}
61
+ user_categories.each do |user_category|
62
+ if CATEGORIES.map{|category| category.title.downcase}.include? user_category.downcase
63
+ validated_categories << user_category.downcase
64
+ else
65
+ suggested_categories = suggested_categories(user_category).map{|category| category.title}
66
+ formatted_categories = format_categories(suggested_categories)
67
+ puts "I'm sorry, I didn't understand \"#{user_category}\". Did you mean #{formatted_categories}?"
68
+ recover_category = gets
69
+ .split(/[,][ ]*/)
70
+ .select {|string| !string.include? ","}
71
+ .first
72
+ get_preferences(recover_category).each {|category| validated_categories << category}
73
+ end
74
+ end
75
+ validated_categories.uniq
76
+ end
77
+ end
78
+
79
+ def suggested_categories(input, categories = CATEGORIES, characters = 0)
80
+ suggestions = categories
81
+ .select {|category| category.title.downcase[0, characters] == input.downcase[0, characters]}
82
+ .compact
83
+ if suggestions.empty? || suggested_categories(input, suggestions, characters + 1).empty?
84
+ suggestions
85
+ else
86
+ suggested_categories(input, suggestions, characters + 1)
87
+ end
88
+ end
89
+
90
+ def format_categories(array, string = "")
91
+ head = "\"" + array[0].split.map{|word| word.capitalize}.join(" ") + "\""
92
+ tail = array[1..-1]
93
+ if tail.empty?
94
+ string == ""? head : string + ", or " + head
95
+ else
96
+ string = string == ""? head : string + ", " + head
97
+ format_categories(tail, string)
98
+ end
99
+ end
100
+
101
+ def yes?(prompt)
102
+ puts prompt
103
+ case gets.strip.downcase
104
+ when "yes"
105
+ true
106
+ when "no"
107
+ false
108
+ else
109
+ puts "I'm sorry, I didn't understand you. Please say \"Yes\" or \"No\"."
110
+ yes?(prompt)
111
+ end
112
+ end
113
+
114
+ end
@@ -0,0 +1,33 @@
1
+ class Restaurant
2
+ attr_accessor :id, :is_claimed, :is_closed, :name, :image_url, :url, :mobile_url, :phone, :display_phone, :review_count, :categories, :distance, :rating, :rating_img_url, :rating_img_url_small, :rating_img_url_large, :snippet_text, :snippet_image_url, :address, :display_address, :city, :state_code, :postal_code, :country_code, :cross_streets, :neighborhoods, :latitude, :longitude, :menu_provider, :menu_date_updated, :reservation_url, :eat24_url
3
+
4
+ @@all = []
5
+
6
+ def initialize(restaurant)
7
+ location = restaurant.location
8
+ coordinate = location.coordinate
9
+ [restaurant, location, coordinate].each do |instance|
10
+ instance.instance_variables.each do |variable|
11
+ instance_has = instance.instance_variable_defined?(variable)
12
+ self_has = self.instance_variables.find(variable)
13
+ if instance_has && self_has
14
+ if variable.to_s == "@categories"
15
+ categories = instance.categories
16
+ .map {|category| Category.find_by_title(category[0])}
17
+ .compact
18
+ @categories = categories
19
+ categories.each {|category| category.restaurants << self}
20
+ else
21
+ self.instance_variable_set(variable, instance.instance_variable_get(variable))
22
+ end
23
+ end
24
+ end
25
+ end
26
+ @@all << self
27
+ end
28
+
29
+ def self.all
30
+ @@all
31
+ end
32
+
33
+ end
@@ -0,0 +1,17 @@
1
+ class User
2
+ attr_accessor :name, :likes, :dislikes
3
+
4
+ @@all = []
5
+
6
+ def initialize(name, likes, dislikes)
7
+ @name = name
8
+ @likes = likes.map {|title| Category.find_by_title(title)}
9
+ @dislikes = dislikes.map {|title| Category.find_by_title(title)}
10
+ @@all << self
11
+ end
12
+
13
+ def self.all
14
+ @@all
15
+ end
16
+
17
+ end
@@ -0,0 +1,51 @@
1
+ class WhatsForDinner
2
+ attr_accessor :location, :users, :yelp_client, :categories, :preferred_categories, :restaurants
3
+
4
+ def initialize(location, users)
5
+ @location = location
6
+ @users = users
7
+ @yelp_client = YelpClient.new
8
+ @categories = Category.all
9
+ @preferred_categories = []
10
+ @restaurants = []
11
+ end
12
+
13
+ def ask
14
+ if self.restaurants.empty?
15
+ category_filters = get_category_filters
16
+ self.categories = self.categories - self.preferred_categories
17
+ params = {category_filter: category_filters}
18
+ results = yelp_client.search(location, params)
19
+ self.restaurants = results.map{|result| Restaurant.new(result)}
20
+ if self.restaurants.empty?
21
+ ask
22
+ else
23
+ recommendation = self.restaurants.first
24
+ self.restaurants = self.restaurants[1..-1]
25
+ recommendation
26
+ end
27
+ else
28
+ recommendation = self.restaurants.first
29
+ self.restaurants = self.restaurants[1..-1]
30
+ recommendation
31
+ end
32
+ end
33
+
34
+ def get_category_filters
35
+ categories_with_votes = self.categories.map{|category| [category, 0]}.to_h
36
+ users.each do |user|
37
+ user.likes.each do |category|
38
+ categories_with_votes[category] += 1 if categories_with_votes.has_key?(category)
39
+ end
40
+ user.dislikes.each do |category|
41
+ categories_with_votes[category] -= 100 if categories_with_votes.has_key?(category)
42
+ end
43
+ end
44
+ max_votes = categories_with_votes.values.max
45
+ self.preferred_categories = categories_with_votes
46
+ .select {|category, votes| votes == max_votes}
47
+ .keys
48
+ self.preferred_categories.map {|category| category.filter}.join(",")
49
+ end
50
+
51
+ end
@@ -0,0 +1,18 @@
1
+ class YelpClient
2
+ attr_accessor :client
3
+
4
+ def initialize
5
+ @client = Yelp::Client.new
6
+ client.configure do |config|
7
+ config.consumer_key = "iet5BTns6urx8_MPMSN9lg"
8
+ config.consumer_secret = "LUwtv6MjjikYbt7BrHUxJV6oJ0E"
9
+ config.token = "K3EIm60p2YqhX5H5DOyZoqfFJua3TGCS"
10
+ config.token_secret = "oVvc-K6pQR31nGvujojMjty07hY"
11
+ end
12
+ end
13
+
14
+ def search(location, params = {}, locale = {})
15
+ client.search(location, params, locale).businesses
16
+ end
17
+
18
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: whats-for-dinner
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Adam Fraser
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A simple gem to help groups find restaurants that optimize their collective
14
+ preferences.
15
+ email: adam.fraser@gmail.com
16
+ executables:
17
+ - whats-for-dinner
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - bin/whats-for-dinner
22
+ - lib/category.rb
23
+ - lib/category_list.rb
24
+ - lib/command_line_interface.rb
25
+ - lib/restaurant.rb
26
+ - lib/user.rb
27
+ - lib/whats_for_dinner.rb
28
+ - lib/yelp_client.rb
29
+ homepage: https://github.com/adamgfraser/whats-for-dinner
30
+ licenses:
31
+ - None
32
+ metadata: {}
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubyforge_project:
49
+ rubygems_version: 2.4.5.1
50
+ signing_key:
51
+ specification_version: 4
52
+ summary: What's For Dinner?
53
+ test_files: []