diff --git a/Gemfile b/Gemfile index c004f4ca..f2ddbc39 100644 --- a/Gemfile +++ b/Gemfile @@ -4,4 +4,6 @@ source "https://rubygems.org" gem "sinatra-activerecord" gem "sqlite3" gem "pry" +gem 'rake' gem "require_all" + diff --git a/Gemfile.lock b/Gemfile.lock index 9589226d..91e3b464 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,56 +1,58 @@ GEM remote: https://rubygems.org/ specs: - activemodel (6.0.3.1) - activesupport (= 6.0.3.1) - activerecord (6.0.3.1) - activemodel (= 6.0.3.1) - activesupport (= 6.0.3.1) - activesupport (6.0.3.1) + activemodel (6.0.3.4) + activesupport (= 6.0.3.4) + activerecord (6.0.3.4) + activemodel (= 6.0.3.4) + activesupport (= 6.0.3.4) + activesupport (6.0.3.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - coderay (1.1.1) - concurrent-ruby (1.1.6) - i18n (1.8.2) + coderay (1.1.3) + concurrent-ruby (1.1.7) + i18n (1.8.5) concurrent-ruby (~> 1.0) - method_source (0.8.2) - minitest (5.14.1) - mustermann (1.0.3) - pry (0.10.4) - coderay (~> 1.1.0) - method_source (~> 0.8.1) - slop (~> 3.4) + method_source (1.0.0) + minitest (5.14.2) + mustermann (1.1.1) + ruby2_keywords (~> 0.0.1) + pry (0.13.1) + coderay (~> 1.1) + method_source (~> 1.0) rack (2.2.3) - rack-protection (2.0.7) + rack-protection (2.1.0) rack - require_all (1.3.3) - sinatra (2.0.7) + rake (13.0.1) + require_all (3.0.0) + ruby2_keywords (0.0.2) + sinatra (2.1.0) mustermann (~> 1.0) - rack (~> 2.0) - rack-protection (= 2.0.7) + rack (~> 2.2) + rack-protection (= 2.1.0) tilt (~> 2.0) - sinatra-activerecord (2.0.12) - activerecord (>= 3.2) + sinatra-activerecord (2.0.21) + activerecord (>= 4.1) sinatra (>= 1.0) - slop (3.6.0) - sqlite3 (1.3.13) + sqlite3 (1.4.2) thread_safe (0.3.6) tilt (2.0.10) - tzinfo (1.2.7) + tzinfo (1.2.8) thread_safe (~> 0.1) - zeitwerk (2.3.0) + zeitwerk (2.4.2) PLATFORMS ruby DEPENDENCIES pry + rake require_all sinatra-activerecord sqlite3 BUNDLED WITH - 1.14.6 + 2.1.4 diff --git a/README.md b/README.md index b75f6185..934a1ea9 100644 --- a/README.md +++ b/README.md @@ -50,10 +50,117 @@ Projects need to be approved prior to launching into them, so take some time to - Present any code you would like to highlight. 7. *OPTIONAL, BUT RECOMMENDED*: Write a blog post about the project and process. + + + + + +### Option One - Data Analytics Project +1. Access a Sqlite3 Database using ActiveRecord. + +2. You should have at minimum three models including one join model. This means you must have a many-to-many relationship. +User >--- Ticket ---< Event ---< Venue ---< City + +User has_many Tickets +User has_many Events through Tickets +Ticket belongs to one user +Ticket belongs to one event +Event has_one venue +Event has_one City through Venue +Event has many tickets +Event has many users through tickets +Venue has many events +Venue belongs to one city + +3. You should seed your database using data that you collect either from a CSV, a website by scraping, or an API. +Ticket master API +API Key: QATrioQ3vEzlLyBebumHRHuNBfT39vrZ +API call format: https://app.ticketmaster.com/{package}/{version}/{resource}.json?apikey=**{API key} + -package: discovery? + -version: v2? + -resources: event, attraction, classification, venue... + +4. Your models should have methods that answer interesting questions about the data. For example, if you've collected info about movie reviews, what is the most popular movie? What movie has the most reviews? +I want to see all events in time frame in certain city +I want to see what types of events are happening within a time frame +I want to see whats happening within a price range +I want to see a record of the events I've been too +I want to see upcoming events in a similar genres to ones I've attended be +I want to see if the event I had a ticket for has been cancelled +I want to see when my favorite band is coming to my city + +5. You should provide a CLI to display the return values of your interesting methods. +? + +6. Use good OO design patterns. You should have separate classes for your models and CLI interface. + + +User CLI options + -User starts by entering location + -takes a string of city and checks if valid in database + -if no, puts out "City not found" + -if yes, store city in args hash, start next method for date + + 0. search by attraction name. + 1. search by date MM/DD/YYYY + 0-9 reserved for results + -if 0-9 puts event details with y to buy and n to go back + F. filter option menu which puts out which keys to input for another filter + D. to enter a date into the search and filter results by it + P. to enter a price into the search and filter results by it + G. to enter and filter by genre + 2.search by price + 0-9 reserved for results + F. filter option menu which puts out which keys to input for another filter + D. to enter a date into the search and filter results by it + P. to enter a price into the search and filter results by it + G. to enter and filter by genre + 3. search by genre + 0-9 reserved for results + F. filter option menu which puts out which keys to input for another filter + D. to enter a date into the search and filter results by it + P. to enter a price into the search and filter results by it + G. to enter and filter by genre + + + + + -Entering B goes back to previous page + -See all Events available by date + -see all Events available by price range + -user sees list of events, can select one with 0-9 input + -sees event, venue, price, then Y/N to purchase ticket + -Y takes them back to main page + -N goes back one level + -purchase ticket for event + -See events they have tickets for + -see events they have tickets for by date + -See events they have that are not cancelled + + + +User class + -instance variables: name + +Ticket class + -instance variables: user_id, event_id + +Event + -Location + -price range + -attraction name + -genre + + + + --- ### Common Questions: - How do I turn off my SQL logger? ```ruby # in config/environment.rb add this line: ActiveRecord::Base.logger = nil + + + ``` diff --git a/app/menu.rb b/app/menu.rb new file mode 100644 index 00000000..49c24ea6 --- /dev/null +++ b/app/menu.rb @@ -0,0 +1,118 @@ +class Menu + attr_accessor :user + + def initialize + @user = user + end + + def start_program + puts "Welcome to EventFinder!" + self.user = create_user(get_user_name, get_user_city)# add ,get_user_state the end later + pull_data_by_city_and_state(self.user.city)#add ,self.user.state + puts "Thank you, #{user.name}" + + begin_search + end + + def get_user_name + puts "Please enter your name" + user_name = STDIN.gets.chomp + user_name + end + + def get_user_city + puts "Please enter your City" + user_city = STDIN.gets.chomp + # if zip_code_valid?(user_zip.to_i) + # puts "Zip Code valid." + # else + # puts "Zip Code not valid, please try again." + # get_user_zip + # end + # user_zip.to_i + user_city + end + + def get_user_state + puts "Please enter your State" + user_state = STDIN.gets.chomp + user_state + end + + def zip_code_valid?(zip) + if zip.is_a? Integer + if zip.digits.count == 5 + true + else + false + end + else + false + end + end + + + def create_user(name, city) #add state later + User.create(name: name, city: city) + end + + def pull_data_by_city_and_state(city) #add state later + info = GetRequester.new("https://app.ticketmaster.com/discovery/v2/events.json?city=#{city}&radius=50&apikey=QATrioQ3vEzlLyBebumHRHuNBfT39vrZ").parse_json + load_event_details(info) + end + + + def load_event_details(info) + events = [] + info["_embedded"]["events"].each do |event| + new_event = Event.new + new_event.attraction_name = event["name"] + new_event.date = event["dates"]["start"]["localDate"] + new_event.venue = event["_embedded"]["venues"][0]["name"] + new_event.genre = event["classifications"][0]["subGenre"]["name"] + #new_event.event_status = event["dates"]["status"]["code"] + events << new_event + end + save_new_events(events) + end + + def save_new_events(events) + events.each do |event| + if !Event.all.select {|e|e.attraction_name == event.attraction_name && e.date == event.date} + event.save + end + Event.order(date: :asc) + #display_events(events) + end + end + + def begin_search + puts "1. Search by event name or artist name" + puts "2. Search by genre" + puts "3. Search by date" + puts "Press 'x' to exit the program" + user_input = STDIN.gets.chomp + if user_input == "1" + display_results_by_attraction_name + elsif user_input == "2" + # + elseif user_input == "3" + # + elseif user_input == "x" + exit + else + puts "Invalid entry, please try another option" + begin_search + end + end + + def display_results_by_attraction_name + puts "Please enter the event or artist you would like to see:" + user_input = STDIN.gets.chomp + #need to do trick where string can be any part of event.name, "rage" returns "Rage against the machine" + events = Event.all.select {|event|event.attraction_name == user_input} + puts events.map {|e|e.attraction_name} + end + +end + diff --git a/app/models/event.rb b/app/models/event.rb new file mode 100644 index 00000000..483415db --- /dev/null +++ b/app/models/event.rb @@ -0,0 +1,7 @@ +class Event < ActiveRecord::Base + has_many :tickets + has_many :users, through: :tickets + + + +end \ No newline at end of file diff --git a/app/models/ticket.rb b/app/models/ticket.rb new file mode 100644 index 00000000..b318a2f6 --- /dev/null +++ b/app/models/ticket.rb @@ -0,0 +1,4 @@ +class Ticket < ActiveRecord::Base + belongs_to :user + belongs_to :event +end \ No newline at end of file diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 00000000..29e7fa99 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,16 @@ +class User < ActiveRecord::Base + has_many :tickets + has_many :events, through: :tickets + + def my_tickets + Ticket.all.select {|t|t.user_id == self} + end + + def my_upcoming_events + self.my_tickets.map {|t|t.event} + end + + def buy_ticket(event) + Ticket.create(user_id: self.id, event_id: event.id) + end +end \ No newline at end of file diff --git a/bin/run.rb b/bin/run.rb index cf08c338..24e08919 100644 --- a/bin/run.rb +++ b/bin/run.rb @@ -1,5 +1,88 @@ require_relative '../config/environment' +info = GetRequester.new("https://app.ticketmaster.com/discovery/v2/events.json?city=Seattle&size=1&apikey=QATrioQ3vEzlLyBebumHRHuNBfT39vrZ").parse_json -puts "HELLO WORLD" +def search_by_city_and_state + puts "enter your location in format: city, state abbreviation" + location = gets + city = location.split(", ")[0] + state = location.split(", ")[1] + info = GetRequester.new("https://app.ticketmaster.com/discovery/v2/events.json?city=#{city}&stateCode=#{state}&apikey=QATrioQ3vEzlLyBebumHRHuNBfT39vrZ").parse_json + load_event_details(info) + event_details(info) +end + +def events_count + info = GetRequester.new("https://app.ticketmaster.com/discovery/v2/events.json?country=usa&apikey=QATrioQ3vEzlLyBebumHRHuNBfT39vrZ").parse_json + info["_embedded"]["events"].count +end + +def event_details(info) + events = [] + i = 1 + info["_embedded"]["events"].each do |event| + events << "#{i}. #{event["name"]} - #{event["dates"]["start"]["localDate"]} - #{event["_embedded"]["venues"][0]["name"]} - #{event["classifications"][0]["subGenre"]["name"]} - #{event["dates"]["status"]["code"]}" + i+=1 + end + puts events +end + +def load_event_details(info) + events = [] + info["_embedded"]["events"].each do |event| + new_event = Event.new + new_event.attraction_name = event["name"] + new_event.date = event["dates"]["start"]["localDate"] + new_event.venue = event["_embedded"]["venues"][0]["name"] + new_event.genre = event["classifications"][0]["subGenre"]["name"] + new_event.event_status = event["dates"]["status"]["code"] + events << new_event + end + save_new_events(events) +end + +def save_new_events(events) + events.each do |event| + if !Event.all.select {|e|e.attraction_name == event.attraction_name && e.date == event.date} + event.save + end + + Event.order(date: :asc) + display_events(events) + end +end + +def save_user(name, city, state) + User.create(name: name, city: city, state: state) +end + +def display_events(events) + puts events.map {|e| "#{e.name} - #{e.date} - #{e.event_status}"} +end + +def start_program + display_top_level_options + input = gets + if input == 1 + #display results by zip code + elsif input == 2 + #display results by artist name + elsif input == 3 + #display results by genre + end +end + + +def display_top_level_options + puts "Welcome to EventFinder" + puts "Please enter your zip code:" + + user_zip =STDIN.gets.chomp + + puts "1. Search by event name or artist name" + puts "2. Search by genre" + puts "3. Search by date" +end +m1 = Menu.new +m1.start_program diff --git a/config/environment.rb b/config/environment.rb index 4dbe13e5..ced65e9b 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -3,3 +3,4 @@ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'db/development.db') require_all 'lib' +require_all 'app' diff --git a/db/migrate/20201203173043_create_users.rb b/db/migrate/20201203173043_create_users.rb new file mode 100644 index 00000000..fca8d0bf --- /dev/null +++ b/db/migrate/20201203173043_create_users.rb @@ -0,0 +1,8 @@ +class CreateUsers < ActiveRecord::Migration[6.0] + def change + create_table :users do |t| + t.string :name + t.string :city + end + end +end diff --git a/db/migrate/20201203173054_create_tickets.rb b/db/migrate/20201203173054_create_tickets.rb new file mode 100644 index 00000000..905c1a12 --- /dev/null +++ b/db/migrate/20201203173054_create_tickets.rb @@ -0,0 +1,8 @@ +class CreateTickets < ActiveRecord::Migration[6.0] + def change + create_table :tickets do |t| + t.integer :user_id + t.integer :event_id + end + end +end diff --git a/db/migrate/20201203173109_create_events.rb b/db/migrate/20201203173109_create_events.rb new file mode 100644 index 00000000..5514b002 --- /dev/null +++ b/db/migrate/20201203173109_create_events.rb @@ -0,0 +1,12 @@ +class CreateEvents < ActiveRecord::Migration[6.0] + def change + create_table :events do |t| + t.string :attraction_name + t.string :date + t.string :venue + t.string :genre + t.float :price_min + t.float :price_max + end + end +end diff --git a/db/migrate/20201203192904_add_status_to_events.rb b/db/migrate/20201203192904_add_status_to_events.rb new file mode 100644 index 00000000..9a785f65 --- /dev/null +++ b/db/migrate/20201203192904_add_status_to_events.rb @@ -0,0 +1,5 @@ +class AddStatusToEvents < ActiveRecord::Migration[6.0] + def change + add_column :events, :event_status, :string + end +end diff --git a/db/migrate/20201204000105_add_state_to_users.rb b/db/migrate/20201204000105_add_state_to_users.rb new file mode 100644 index 00000000..22d5c4a5 --- /dev/null +++ b/db/migrate/20201204000105_add_state_to_users.rb @@ -0,0 +1,5 @@ +class AddStateToUsers < ActiveRecord::Migration[6.0] + def change + add_column :users, :state, :string + end +end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 00000000..463a6ab9 --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,36 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# This file is the source Rails uses to define your schema when running `rails +# db:schema:load`. When creating a new database, `rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema.define(version: 2020_12_04_000105) do + + create_table "events", force: :cascade do |t| + t.string "attraction_name" + t.string "date" + t.string "venue" + t.string "genre" + t.float "price_min" + t.float "price_max" + t.string "event_status" + end + + create_table "tickets", force: :cascade do |t| + t.integer "user_id" + t.integer "event_id" + end + + create_table "users", force: :cascade do |t| + t.string "name" + t.string "city" + t.string "state" + end + +end diff --git a/lib/get_requester.rb b/lib/get_requester.rb new file mode 100644 index 00000000..1afb4aa1 --- /dev/null +++ b/lib/get_requester.rb @@ -0,0 +1,19 @@ +require 'open-uri' +require 'net/http' +require 'json' + +class GetRequester + def initialize(url) + @url = url + end + + def get_response_body + uri = URI.parse(@url) + response = Net::HTTP.get_response(uri) + response.body + end + + def parse_json + JSON.parse(self.get_response_body) + end +end \ No newline at end of file