Last active
August 29, 2015 14:15
-
-
Save IlyaDonskikh/e68240899be1c23d5f4f to your computer and use it in GitHub Desktop.
Flight search
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class FlightSearch | |
include ActiveModel::Validations | |
include ActiveModel::Conversion | |
extend ActiveModel::Naming | |
attr_accessor :departure, :arrival, :date, :quotas, :return_quotas, :business_class, :with_return, :return_date, | |
:errors, :all_flights, :all_rt_flights, :adults, :childrens, :infants | |
## Validates | |
validates :departure, :arrival, :date, presence: true | |
validates_format_of :date, with: /\A[0-9]{2}\.[0-9]{2}\.[0-9]{4}\z/, message: :format | |
validate :date_range | |
## Etc. | |
def initialize(opts = {}) | |
@errors = ActiveModel::Errors.new(self) | |
self.date = (Time.now + 3.days).strftime('%d.%m.%Y') | |
self.adults = 1 | |
self.childrens = 0 | |
self.infants = 0 | |
self.business_class = false | |
opts.each do |name, value| | |
send("#{name}=", value) | |
end | |
end | |
def adults; @adults.to_i end | |
def childrens; @childrens.to_i end | |
def infants; @infants.to_i end | |
def point_downcase(type) | |
self.send(type.to_sym).to_s.mb_chars.downcase.to_s | |
end | |
def departure_downcase | |
departure.to_s.mb_chars.downcase.to_s | |
end | |
def passenger_stats | |
{ adult: adults, children: childrens, infant: infants, count: adults + childrens + infants } | |
end | |
def get_flight_point(name) | |
result = GeoSearch.new(text: name).result | |
result.first | |
end | |
def short_url | |
code = '' | |
[:departure, :arrival].each_with_index do |type_code, i| | |
item = get_flight_point(self.send(type_code)) | |
code += item[:code] | |
code += case i | |
when 0 then date.strftime('%d%m') | |
else return_date.blank? ? '' : return_date.strftime('%d%m') | |
end | |
end | |
code += 'b' if bussines_class_formatted == true | |
code += '_' + self.adults.to_s | |
code += self.childrens.to_s if childrens > 0 | |
code += self.infants.to_s if infants > 0 | |
code | |
end | |
def results | |
discount_rt_objects = quotas.to_a | |
.select { |q| !q.pair_quotas.blank? } | |
.collect { |q| q.pair_quotas } | |
.flatten.to_a | |
found_quotas = find_quotas() | |
format_quotas = format_quotas(found_quotas) | |
flights_by_format_quotas(format_quotas, discount_rt_objects) | |
end | |
private | |
def bussines_class_formatted | |
[1, '1', true, 'true'].include?(self.business_class) ? true : false | |
end | |
def find_quotas() | |
departure_name = point_downcase('departure') | |
arrival_name = point_downcase('arrival') | |
business_class = bussines_class_formatted | |
found_quotas = {} | |
%w[ow return].each do |type| | |
prefix = type == 'ow' ? '' : 'return_' | |
flight_date = self.send(prefix + 'date') | |
quotas_type = (prefix + 'quotas').to_sym | |
departure_point = type == 'ow' ? departure_name : arrival_name | |
arrival_point = type == 'ow' ? arrival_name : departure_name | |
if self.send(quotas_type) | |
found_quotas[type.to_sym] = self.send(quotas_type).select { |qt| qt.business == business_class && | |
qt.date == flight_date && qt.points('arrival').include?(arrival_point) && | |
qt.points('departure').include?(departure_point) && | |
qt.seats_available > 0 && qt.flight.status == nil } | |
end | |
end | |
found_quotas | |
end | |
def format_quotas(found_quotas) | |
data = [] | |
found_quotas[:ow].sort_by { |data| data[:price] }.each do |qt| | |
code = { flight: qt.flight, return_flight: nil, | |
date: qt.date, tag: qt.flight.number, | |
start_time: qt.start_time, end_time: qt.end_time, | |
cabin: qt.business ? 'Business' : 'Economy' } | |
if found_quotas[:return].blank? && return_date.blank? | |
data << { code: code, quota: qt, return_quota: nil } | |
elsif !found_quotas[:return].blank? | |
found_quotas[:return].sort_by { |data| data[:price] }.each do |return_qt| | |
rt_code = code.merge({ | |
return_cabin: (return_qt.business ? 'Business' : 'Economy'), | |
return_flight: return_qt.flight, | |
return_start_time: return_qt.start_time, | |
return_date: return_qt.date, | |
return_end_time: return_qt.end_time, | |
tag: qt.flight.number + '_' + return_qt.flight.number }) | |
data << { code: rt_code, quota: qt, return_quota: return_qt } | |
end | |
end | |
end | |
data.group_by { |data| data[:code] } | |
end | |
def flights_by_format_quotas(format_quotas, discount_rt_objects) | |
flights_sort = [] | |
format_quotas.each do |flight_sort| | |
flight_sort[0].merge!({ quotas: flight_sort[1].map { |fs| fs[:quota] }.uniq }) | |
flight_sort[0].merge!({ return_quotas: flight_sort[1].map { |fs| fs[:return_quota] }.uniq }) | |
passengers = passenger_stats | |
quotas = flight_sort[0][:quotas].compact | |
return_quotas = flight_sort[0][:return_quotas].compact | |
seats_available = [quotas.map { |qt| qt.seats_available }.inject{ |sum,x| sum + x }] | |
seats_available << return_quotas.map { |qt| qt.seats_available }.inject{|sum,x| sum + x } unless return_quotas.blank? | |
seats_available = seats_available.min | |
used_quotas = [] | |
passengers = Passenger.generate_list(passenger_stats, date) | |
passengers = Passenger.calc_list( | |
passengers, quotas, return_quotas, | |
discount_rt_objects, flight_sort[0][:flight], flight_sort[0][:return_flight]) | |
price = passengers.map(&:price).inject{|sum,x| sum.to_i + x.to_i } | |
flight_sort[0].merge!( { price: price } ) | |
flight_sort[0].merge!( { passengers: passengers } ) | |
flights_sort << flight_sort if flight_sort[0][:price].to_i > 0 | |
end | |
flights_sort.sort_by { |flight_sort| flight_sort[0][:price] } | |
end | |
def date_range | |
self.date = date.to_date unless date.blank? | |
self.return_date = return_date.to_date unless with_return != '1' && return_date.blank? | |
errors.add(:date, :date_rang) if date.blank? || date < DateTime.now.to_date | |
errors.add(:return_date, :date_range) if with_return == '1' && (return_date.blank? || return_date < date) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment