Skip to content

Instantly share code, notes, and snippets.

@Awlter
Created March 11, 2018 16:10
Show Gist options
  • Save Awlter/2dfca9d04e2b3c0bf5a09121dd02493f to your computer and use it in GitHub Desktop.
Save Awlter/2dfca9d04e2b3c0bf5a09121dd02493f to your computer and use it in GitHub Desktop.
require 'pry'
class Booker
def process
customer = Customer.new
result = Packages.new(customer).cheapest
output(result)
end
private
def output(result)
puts "OUTPUT:"
puts result[0].flight
puts result[1].flight
end
end
class Customer
CUSTOMER_TYPES = ['REWARD', 'REGULAR']
WEEK = ['MON', 'TUE', 'WED', 'TUR', 'FRI', 'SAT', 'SUN']
WEEKENDS = ['SAT', 'SUN']
attr_accessor :type, :departure_at_weekends, :return_at_weekends, :from, :to
def initialize
get_input
end
private
def get_input
type, departure_time, return_time = nil
while true do
puts "INPUT: (e.g: REWARD, 20160410SUN, 20160420WED)"
inputs = gets.chomp.split(/\,\ ?/)
type = inputs[0].upcase
departure_time = inputs[1][-3..-1].upcase
return_time = inputs[2][-3..-1].upcase
break if correct_input?(type, departure_time, return_time)
puts "Please input with the suggested format."
end
@type = type
@departure_at_weekends = WEEKENDS.include? departure_time
@return_at_weekends = WEEKENDS.include? return_time
binding.pry
# for extensions: e.g more places
@from = "XI'AN"
@to = "CHENGDU"
end
def correct_input?(type, departure_time, return_time)
(CUSTOMER_TYPES.include? type) &&
(WEEK.include? departure_time) &&
(WEEK.include? return_time)
end
end
class Packages
FLIGHTS = {
"XI'AN" => {
"CHENGDU" => [
{ number: 'GD2501', sched: '08:00'},
{ number: 'GD2606', sched: '12:25'},
{ number: 'GD8732', sched: '19:30'}
]
},
"CHENGDU" => {
"XI'AN" => [
{ number: 'GD2502', sched: '12:00'},
{ number: 'GD2607', sched: '16:25'},
{ number: 'GD8733', sched: '23:30'}
]
}
}
attr_accessor :customer, :packages
def initialize(customer)
@customer = customer
@packages = []
generate_packages
end
def cheapest
packages.min { |a, b| total_price(a) <=> total_price(b) }
end
private
def total_price(package)
package[0].price + package[1].price
end
def generate_packages
leaving_tickets = LeavingTickets.new(FLIGHTS[customer.from][customer.to], customer)
returning_tickets = ReturningTickets.new(FLIGHTS[customer.to][customer.from], customer)
binding.pry
self.packages = leaving_tickets.create_packages(returning_tickets)
end
end
class Tickets
FLIGHT_PRICES = {
'GD2501' => {
'WEEKDAYS' => { 'REGULAR' => 1100, 'REWARD' => 800 },
'WEEKENDS' => { 'REGULAR' => 900, 'REWARD' => 500 }
},
'GD2606' => {
'WEEKDAYS' => { 'REGULAR' => 1600, 'REWARD' => 1100 },
'WEEKENDS' => { 'REGULAR' => 600, 'REWARD' => 500 }
},
'GD8732' => {
'WEEKDAYS' => { 'REGULAR' => 2200, 'REWARD' => 1000 },
'WEEKENDS' => { 'REGULAR' => 1500, 'REWARD' => 400 }
},
'GD2502' => {
'WEEKDAYS' => { 'REGULAR' => 1700, 'REWARD' => 800 },
'WEEKENDS' => { 'REGULAR' => 900, 'REWARD' => 800 }
},
'GD2607' => {
'WEEKDAYS' => { 'REGULAR' => 1600, 'REWARD' => 1100 },
'WEEKENDS' => { 'REGULAR' => 600, 'REWARD' => 500 }
},
'GD8733' => {
'WEEKDAYS' => { 'REGULAR' => 1600, 'REWARD' => 1500 },
'WEEKENDS' => { 'REGULAR' => 1000, 'REWARD' => 400 }
}
}
attr_accessor :list
def initialize(flights, customer, weekends)
@list = []
enlist(flights, customer, weekends)
end
def create_packages(another)
self.list.product(another.list)
end
private
def enlist(flights, customer, weekends)
flights.each do |flight|
price = calculate_price(flight, customer.type, weekends)
ticket = Ticket.new(flight[:number], price, flight[:sched])
optimizing_add(ticket)
end
end
def optimizing_add(ticket)
if list.empty?
@list << ticket
else
index = @list.find_index {|t| t == ticket }
if index.nil?
@list << ticket
else
@list[index] = ticket if ticket.better_than?(@list[index])
end
end
end
def calculate_price(flight, type, weekends)
week = weekends ? 'WEEKENDS' : 'WEEKDAYS'
FLIGHT_PRICES[flight[:number]][week][type]
end
end
class LeavingTickets < Tickets
def initialize(flights, customer)
super(flights, customer, customer.departure_at_weekends)
end
end
class ReturningTickets < Tickets
def initialize(flights, customer)
super(flights, customer, customer.return_at_weekends)
end
end
class Ticket
attr_reader :flight, :price, :sched
def initialize(flight, price, sched)
@flight = flight
@price = price
@sched = sched
end
def ==(another)
price == another.price
end
def better_than?(another)
hour_of_self = sched.split(':')[0].to_i
hour_of_another = another.sched.split(':')[0].to_i
return true if (hour_of_self - 12).abs <= 1
return false if (hour_of_another - 12).abs <= 1
hour_of_self < hour_of_another
end
end
Booker.new.process
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment