diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..6eb8545d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +coverage +.DS_Store diff --git a/.ruby-gemset b/.ruby-gemset new file mode 100644 index 00000000..73f861e5 --- /dev/null +++ b/.ruby-gemset @@ -0,0 +1 @@ +farmar diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 00000000..276cbf9e --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.3.0 diff --git a/Rakefile b/Rakefile new file mode 100644 index 00000000..43932cd6 --- /dev/null +++ b/Rakefile @@ -0,0 +1,9 @@ +require 'rake/testtask' + + Rake::TestTask.new do |t| + t.libs = ["lib"] + t.warning = true + t.test_files = FileList['specs/*_spec.rb'] + end + + task default: :test diff --git a/far_mar.rb b/far_mar.rb new file mode 100644 index 00000000..803a49d4 --- /dev/null +++ b/far_mar.rb @@ -0,0 +1,35 @@ +# gems your project needs +require 'csv' +require 'chronic' +require 'date' + +# our namespace module +module FarMar +end + +class RepeatMethods + # DATA = "./support/vendors.csv" + + def self.all + CSV.read(self::DATA).map { |line| self.new(line) } + end + + def self.find(id) + CSV.foreach(self::DATA) do |line| + return self.new(line) if line[0].to_i == id + end + end + +end + +PRODUCT_CSV = "./support/products.csv" +MARKET_CSV = "./support/markets.csv" +VENDORS_CSV = "./support/vendors.csv" +SALE_CSV = "./support/sales.csv" +# all of our data classes that live in the module +require_relative './lib/farmar_market' +# ...require all needed classes + +require_relative "./lib/farmar_sale" +require_relative './lib/farmar_vendor' +require_relative './lib/farmar_product' diff --git a/lib/farmar_market.rb b/lib/farmar_market.rb new file mode 100644 index 00000000..7c952659 --- /dev/null +++ b/lib/farmar_market.rb @@ -0,0 +1,81 @@ + +class FarMar::Market < RepeatMethods + DATA = "./support/markets.csv" + + attr_reader :market_id, :name, :address, :city, :county, :state, :zip + + def initialize(market_info) + @market_id, @name, @address, @city, @county, @state, @zip = market_info + @market_id = @market_id.to_i + end + + # vendors: returns a collection of FarMar::Vendor instances that are associated with + # the market by the market_id field. + def vendors + vendors = CSV.read(VENDORS_CSV).select { |line| line[3].to_i == self.market_id } + vendors.collect { |v| FarMar::Vendor.new(v)} + end + + # products returns a collection of FarMar::Product instances that are associated to the + # market through the FarMar::Vendor class. + # use vendors method to find vendors, make instances of their products + def products + vendor_ids = vendors.collect { |vendor| vendor.vendor_id} + CSV.read(PRODUCT_CSV).collect do |line| + FarMar::Product.new(line) if vendor_ids.include? line[2].to_i + end + end + + # self.search(search_term) returns a collection of FarMar::Market instances + # where the market name or vendor name contain the search_term. + def self.search(search_term) + #find vendors whose names match the search term and collect their ids + vendor_matches = CSV.read(VENDORS_CSV).select do |line| + line[1].downcase.include? search_term.downcase + end + vendor_ids = vendor_matches.collect { |vendor| vendor[3]} + + #iterate through markets to see if any market names match search term + market_matches = CSV.read(MARKET_CSV).select do |line| + (line[1].downcase.include? search_term.downcase) || (vendor_ids.include? line[0]) + end + market_matches.collect { |market| FarMar::Market.new(market)} + + end + + # prefered_vendor: returns the vendor with the highest revenue + def preferred_vendor + self.vendors.max_by { |vendor| vendor.revenue} + end + + def worst_vendor + self.vendors.min_by { |vendor| vendor.revenue} + end + + #prefered_vendor(date): returns the vendor with the highest revenue for the given date + def preferred_vendor_on(date) + date = Chronic.parse(date) + #when you give a day it defaults to noon, so i caught the whole day by adding and substracting 11hours 59min + time_range = ((date - 43199)..(date + 43199)) + vendor_ids = self.vendors.collect { |vendor| vendor.vendor_id } + vendor_sales = CSV.read(SALE_CSV).select do |line| + vendor_ids.include? line[3].to_i + end + vendor_sales.collect! { |sale| FarMar::Sale.new(sale) } + vendor_sales.select { |sale| time_range.include? sale.purchase_time } + #create a hash that will assign a key to each vendor id and add amount to value + answer = {} + vendor_sales.each do |sale| + vendor = sale.vendor_id + amount = sale.amount + + if answer[vendor].nil? + answer[vendor] = amount + else + answer[vendor] += amount + end + end + answer = answer.max_by { |vendor, amount| amount} + return FarMar::Vendor.find(answer[0]) + end +end diff --git a/lib/farmar_product.rb b/lib/farmar_product.rb new file mode 100644 index 00000000..833803e5 --- /dev/null +++ b/lib/farmar_product.rb @@ -0,0 +1,41 @@ +class FarMar::Product < RepeatMethods + DATA = "./support/products.csv" + + attr_reader :product_id, :name, :vendor_id + def initialize(product_info) + @product_id, @name, @vendor_id = product_info + @product_id = @product_id.to_i + @vendor_id = @vendor_id.to_i + end + + #vendor: returns the FarMar::Vendor instance that is associated with this vendor + #using the FarMar::Product vendor_id field + def vendor + CSV.foreach(VENDORS_CSV) do |line| + return FarMar::Vendor.new(line) if line[0].to_i == vendor_id + end + end + + # sales: returns a collection of FarMar::Sale instances that are associated using + # the FarMar::Sale product_id field. + def sales + sales = CSV.read(SALE_CSV).select do |line| + line[4].to_i == self.product_id + end + sales.collect { |sale| FarMar::Sale.new(sale)} + end + + #number_of_sales: returns the number of times this product has been sold. + def number_of_sales + sales.length + end + + #self.by_vendor(vendor_id): returns all of the products with the given vendor_id + def self.by_vendor(vendor_id) + products = CSV.read(PRODUCT_CSV).select do |line| + line[2].to_i == vendor_id + end + products.collect { |product| FarMar::Product.new(product)} + end + +end diff --git a/lib/farmar_sale.rb b/lib/farmar_sale.rb new file mode 100644 index 00000000..57267e5d --- /dev/null +++ b/lib/farmar_sale.rb @@ -0,0 +1,40 @@ + +class FarMar::Sale < RepeatMethods + DATA = "./support/sales.csv" + + attr_reader :sale_id, :amount, :purchase_time, :vendor_id, :product_id + def initialize(sale_info) + @sale_id, @amount, @purchase_time, @vendor_id, @product_id = sale_info + @sale_id = @sale_id.to_i + @amount = @amount.to_i + @purchase_time = Chronic.parse(@purchase_time) + @vendor_id = @vendor_id.to_i + @product_id = @product_id.to_i + end + + # vendor: returns the FarMar::Vendor instance that is associated with this sale using the + # FarMar::Sale vendor_id field + def vendor + CSV.foreach(VENDORS_CSV) do |line| + return FarMar::Vendor.new(line) if line[0].to_i == self.vendor_id + end + end + + # product: returns the FarMar::Product instance that is associated with this sale using + # the FarMar::Sale product_id field + def product + CSV.foreach(PRODUCT_CSV) do |line| + return FarMar::Product.new(line) if line[0].to_i == self.product_id + end + end + + def self.between(beginning_time, end_time) + begin_time = Chronic.parse(beginning_time) + end_time = Chronic.parse(end_time) + time_range = (begin_time..end_time) + sales = CSV.read(SALE_CSV).select do |line| + time_range.include? Chronic.parse(line[2]) + end + sales.collect { |sale| FarMar::Sale.new(sale)} + end +end diff --git a/lib/farmar_vendor.rb b/lib/farmar_vendor.rb new file mode 100644 index 00000000..49b97999 --- /dev/null +++ b/lib/farmar_vendor.rb @@ -0,0 +1,51 @@ + +class FarMar::Vendor < RepeatMethods + DATA = "./support/vendors.csv" + + attr_reader :vendor_id, :name, :number_of_employees, :market_id + + def initialize(vendor_info) + @vendor_id, @name, @number_of_employees, @market_id = vendor_info + @vendor_id = @vendor_id.to_i + @number_of_employees = @number_of_employees.to_i + @market_id = @market_id.to_i + end + + #market: returns the FarMar::Market instance that is associated with this vendor using + #the FarMar::Vendor market_id field + def market + CSV.foreach(MARKET_CSV) do |line| + return FarMar::Market.new(line) if line[0].to_i == self.market_id + end + end + + #products: returns a collection of FarMar::Product instances that are associated by + #the FarMar::Product vendor_id field. + def products + products = CSV.read(PRODUCT_CSV).select do |line| + line[2].to_i == self.vendor_id + end + products.collect { |product| FarMar::Product.new(product)} + end + + #sales: returns a collection of FarMar::Sale instances that are associated by the vendor_id field. + def sales + sales = CSV.read(SALE_CSV).select do |line| + line[3].to_i == vendor_id + end + sales.collect { |sale| FarMar::Sale.new(sale)} + end + + #revenue: returns the the sum of all of the vendor's sales (in cents) + def revenue + all_money = sales.collect { |sale| sale.amount} + all_money.reduce(0, :+) + end + + #self.by_market(market_id): returns all of the vendors with the given market_id + def self.by_market(market_id) + vendors = CSV.read(VENDORS_CSV).select { |line| line[3].to_i == market_id } + vendors.collect { |vendor| FarMar::Vendor.new(vendor)} + end + +end diff --git a/specs/market_spec.rb b/specs/market_spec.rb new file mode 100644 index 00000000..ad9725af --- /dev/null +++ b/specs/market_spec.rb @@ -0,0 +1,90 @@ +require_relative './spec_helper' +require_relative '../far_mar' + + +describe FarMar::Market do + + it "does this exist" do + FarMar::Market.wont_be_nil + end + + it "creates an array of market instance" do + FarMar::Market.all.class.must_equal(Array) + end + + it "creates instances of market from csv file" do + classes = FarMar::Market.all.map { |market| market.class } + classes.uniq.must_equal [FarMar::Market] + end + + it "creates an instance of FarMar::Market" do + FarMar::Market.new([4, "yay", "dirt", "ryan", "claire", "five", "six"]).must_be_instance_of(FarMar::Market) + end + + describe "self.find" do + + it "should find instance of market with matching id" do + FarMar::Market.find(1).name.must_equal("People's Co-op Farmers Market") + end + + it "should return nil when it can't find a matching market id" do + FarMar::Market.find(2727272727).must_equal(nil) + end + + end + + describe ".vendors" do + let(:market_one) {FarMar::Market.find(1)} + + it "should return an array of that market's vendors" do + market_one.vendors.must_be_instance_of(Array) + end + + it "vendors should have same market_id as the market" do + market_one.market_id.must_equal(market_one.vendors[1].market_id) + end + + end + + describe "products" do + let(:market_one) {FarMar::Market.find(1)} + + it "should return array of products sold by that market" do + market_one.products.must_be_instance_of Array + end + + it 'should return instances of product' do + market_one.products[0].class.must_equal FarMar::Product + end + + end + + describe 'self.search' do + it "should return collection where search term is in market name" do + FarMar::Market.search('school').length.must_equal 3 + end + end + + describe 'preferred_vendor' do + it "should return vendor in that market with highest revenue" do + market = FarMar::Market.find(1) + market.preferred_vendor.vendor_id.must_equal(5) + end + end + + describe 'worst_vendor' do + it "should return vendor in that market with least revenue" do + market = FarMar::Market.find(1) + market.worst_vendor.vendor_id.must_equal(6) + end + end + + describe "preferred_vendor_on(date)" do + let (:market) { FarMar::Market.find(1)} + + it "returns vendor with most revenue on specific date" do + market.preferred_vendor_on("11/12/13").vendor_id.must_equal 5 + end + end + +end diff --git a/specs/product_spec.rb b/specs/product_spec.rb new file mode 100644 index 00000000..6436cd99 --- /dev/null +++ b/specs/product_spec.rb @@ -0,0 +1,80 @@ +require_relative './spec_helper' +require_relative '../far_mar' + + +describe FarMar::Product do + + it "does this exist" do + FarMar::Product.wont_be_nil + end + + it "can create instance of product class" do + FarMar::Product.new("super-toy").must_be_instance_of(FarMar::Product) + end + + describe ".all" do + let(:products) { FarMar::Product.all} + + it "can create array of all products from csv file" do + products.class.must_equal(Array) + end + + it "creates instances of product" do + all_products = products.map { |product| product.class} + all_products.uniq.must_equal [FarMar::Product] + end + end + + describe ".find" do + let(:product_eight) { FarMar::Product.find(8)} + + it "can find a product given an id" do + product_eight.name.must_equal("Shaky Honey") + end + + end +#14,Stupendous Carrots,7 + describe '.vendor' do + let(:carrot) { FarMar::Product.find(14)} + + it 'should return vendor that sells this product' do + carrot.vendor.vendor_id.must_equal(7) + end + + end + + # describe 'market' do + # let (:bike) {FarMar::Product.find(12)} + # it "should return market where that product is sold" do + # bike.market.market_id.must_equal + # + # end + # end + + describe '.sales' do + let (:toy) { FarMar::Product.find(40)} + it 'returns collection of all sales instances for this product' do + classes = toy.sales.map { |sale| sale.class} + classes.uniq.must_equal [FarMar::Sale] + end + end + + describe '.number_of_sales' do + let (:car) { FarMar::Product.find(50)} + + it "should return the number of sales for that item" do + car.number_of_sales.must_be_instance_of Fixnum + end + + end + + describe 'self.by_vendor' do + it "should return all products with given vendor_id" do + goods = FarMar::Product.by_vendor(30) + classes = goods.map { |product| product.class} + classes.uniq.must_equal [FarMar::Product] + end + end + + +end diff --git a/specs/sale_spec.rb b/specs/sale_spec.rb new file mode 100644 index 00000000..4c80f64b --- /dev/null +++ b/specs/sale_spec.rb @@ -0,0 +1,61 @@ +require_relative './spec_helper' +require_relative '../far_mar' + + +describe FarMar::Sale do + + before do + info = [3,44,"tomorrow at 5pm", 5,7] + @sale = FarMar::Sale.new(info) + end + + it "does this exist" do + FarMar::Sale.wont_be_nil + end + + it "can create instance of sale" do + @sale.must_be_instance_of(FarMar::Sale) + end + + it "creates array of all sales" do + FarMar::Sale.all.must_be_instance_of(Array) + end + + describe 'find' do + + it "can find a specific sale based on sale_id" do + FarMar::Sale.find(10).amount.must_equal(5160) + end + end + + describe 'datetime conversion with new' do + + it "should convert purchase time to datetime" do + FarMar::Sale.find(1).purchase_time.hour.must_equal(4) + end + + end + + describe '.vendor' do + it "should return vendor instance that made that sale" do + this_sale = FarMar::Sale.find(30) + this_sale.vendor.class.must_equal FarMar::Vendor + end + end + + describe '.product' do + it "should return product instance" do + this_sale = FarMar::Sale.find(30) + this_sale.product.class.must_equal FarMar::Product + end + end + + describe "self.between" do + it "should return all sales between two times" do + sales = FarMar::Sale.between("11/8/2013 at 4pm", "11/8/2013 at 8pm") + sales[0].purchase_time.class.must_equal Time + end + end + + +end diff --git a/specs/spec_helper.rb b/specs/spec_helper.rb new file mode 100644 index 00000000..7f5ad918 --- /dev/null +++ b/specs/spec_helper.rb @@ -0,0 +1,10 @@ +require 'simplecov' +SimpleCov.start +require 'minitest' +require 'minitest/spec' +require 'minitest/autorun' +require 'minitest/reporters' +require 'date' + +# give us some really nice output +Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new diff --git a/specs/vendor_spec.rb b/specs/vendor_spec.rb new file mode 100644 index 00000000..e9401e78 --- /dev/null +++ b/specs/vendor_spec.rb @@ -0,0 +1,99 @@ +require_relative './spec_helper' +require_relative '../far_mar' + + +describe FarMar::Vendor do + + it "does this exist" do + FarMar::Vendor.wont_be_nil + end + + describe "self.all" do + let(:all_vendors) { FarMar::Vendor.all} + + it "creates an array of vendor info" do + all_vendors.must_be_instance_of(Array) + end + + it "creates an array of vendor instances" do + classes = all_vendors.map { |vendor| vendor.class } + classes.uniq.must_equal [FarMar::Vendor] + end + end + + describe "self.find" do + let(:vendor_ten) {FarMar::Vendor.find(10)} + + it "should find instance of vendor given id" do + vendor_ten.name.must_equal("Kertzmann LLC") + end + + it "should return nil when it can't find vendor" do + FarMar::Vendor.find(-3).must_be_nil + end + + end + + describe ".market" do + let(:vendor_five) { FarMar::Vendor.find(5)} + + it "should return the market where the vendor sells" do + vendor_five.market.market_id.must_equal(1) + end + + end + + describe '.products' do + let(:adam) {FarMar::Vendor.find(8)} + let(:adams_products) {adam.products} + + it "should return array of products that the vendor sells" do + adams_products.must_be_instance_of Array + end + + it "should return array of instances of FarMar::Product" do + classes = adams_products.map { |product| product.class} + classes.uniq.must_equal [FarMar::Product] + end + end + + describe '.sales' do + let(:johnny_sales) {FarMar::Vendor.find(6).sales} + + it "should return array of sales instances belonging to vendor" do + classes = johnny_sales.map { |sale| sale.class} + classes.uniq.must_equal [FarMar::Sale] + end + + end + + describe '.revenue' do + let(:mark) {FarMar::Vendor.find(10)} + + it "should return sum of all vendor's sales" do + mark.revenue.class.must_equal Fixnum + end + + end + + describe 'self.by_market' do + let(:market_one_vendors) {FarMar::Vendor.by_market(2)} + + it "should array of vendors with the given market_id" do + market_one_vendors.class.must_equal Array + end + + it "should return array of vendor instances" do + classes = market_one_vendors.map { |vendor| vendor.class} + classes.uniq.must_equal [FarMar::Vendor] + end + + end + + # describe "self.most_revenue(n)" do + # it "should provide n vendors with most revenue" do + # FarMar::Vendor.most_revenue(2)[0].class.must_equal FarMar::Vendor + # end + # end + +end diff --git a/support/markets.csv b/support/markets.csv index 6a265cd0..9eff6fb4 100644 --- a/support/markets.csv +++ b/support/markets.csv @@ -497,4 +497,4 @@ 497,Nevada County Farmers Market,11078 West First Street North,Prescott,Nevada,Arkansas,71857 498,Morningside Park Farmers Market,110th Street & Manhattan Avenue,Mornignside Heights,New York,New York,10027 499,Fletcher Allen's Farmers' Market,111 Colchester Ave 204 EN3,Burlington,Chittenden,Vermont,5401 -500,Montefiore Medical Center Farmers Market_Thursday,111 E. 210th Street,Bronx,Bronx,New York,10467 \ No newline at end of file +500,Montefiore Medical Center Farmers Market_Thursday,111 E. 210th Street,Bronx,Bronx,New York,10467