whats-for-dinner 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []