bus/app/helpers/ruling_buses_helper.rb

206 lines
8.4 KiB
Ruby

module RulingBusesHelper
extend self
extend ActionView::Helpers::FormTagHelper
extend ActionView::Helpers::FormOptionsHelper
extend ActionView::Helpers::DateHelper
extend ActionView::Helpers::TagHelper
extend ActionView::Helpers::RenderingHelper
extend ActionView::Context
extend OrbitBasis::RenderAnywhere
extend ActionView::Helpers::UrlHelper
extend OrbitFormHelper
extend Ckeditor::Helpers::FormHelper
Setting = RulingBusSetting.first
APP_ID = Setting.app_id
APP_KEY = Setting.app_key
UpdateInterval = Setting.update_interval
Directions = I18n.available_locales.map do |locale|
[locale,I18n.with_locale(locale){I18n.t('ruling_bus.directions')}]
end.to_h
UpdateFrontInterval = Setting.update_front_interval
UpdateRouteInterval = Setting.update_route_interval
require 'httparty'
include HTTParty
base_uri 'https://ptx.transportdata.tw/MOTC/v2'
open_timeout 3
read_timeout 1
format :json
headers(
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'X-Date' => ->{ @current_timestamp = Time.now.utc.strftime('%a, %d %b %Y %T GMT') },
'Authorization' => ->{ authorization_header },
)
def authorization_header
hmac = Base64.strict_encode64(OpenSSL::HMAC.digest('sha1', APP_KEY, "x-date: #{@current_timestamp}"))
return %(hmac username="#{APP_ID}", algorithm="hmac-sha1", headers="x-date", signature="#{hmac}")
end
def self.get(url)
super(URI.encode(url))
end
def get_locale
I18n.locale.to_s=='zh_tw' ? 'Zh_tw' : 'En'
end
def bus_table
get("/Bus/EstimatedTimeOfArrival/City/Taichung/151?$top=30&$format=JSON")
end
def get_available_cities
begin
if RulingBusCity.first.nil? || RulingBusCity.first.updated_at<DateTime.now-20.minutes
response = HTTParty.get('https://ptx.transportdata.tw/MOTC/v2/Bus/api-docs/oas')
cities = response["paths"]["/v2/Bus/EstimatedTimeOfArrival/City/{City}"]["get"]["parameters"][0]["x-enum"]
RulingBusCity.first.nil? ? RulingBusCity.create(dict: cities) : RulingBusCity.first.update_attributes(dict: cities)
else
cities = RulingBusCity.first.dict
end
rescue => e
puts [e,e.backtrace]
cities = RulingBusCity.first.dict
end
I18n.locale.to_s=='zh_tw' ? cities.map{|k,v| [v,k]} : cities.map{|k,v| [k.gsub(/(?!^)[A-Z]/, ' \0'),k]}
end
def get_route_information(city,routename,locale=nil)
locale = get_locale if locale.nil?
get("/Bus/Route/City/#{city}?$format=JSON&$filter=RouteName/#{locale} eq '#{routename}'")[0]
end
def get_arrival_name(city,routename,locale=nil)
locale = get_locale if locale.nil?
info = get_route_information(city,routename,locale)
info
end
def get_stops_for_city(city,code,default_locale,locale=nil)
locale = get_locale if locale.nil?
[""] + (get("/Bus/Stop/City/#{city}?$select=StopName&$format=JSON").collect{|v| [v['StopName'][default_locale],v['StopName'][locale]]} + get("/Bus/Stop/InterCity?$select=StopName&$filter=LocationCityCode eq '#{code}'&$format=JSON").collect{|v| [v['StopName'][default_locale],v['StopName'][locale]]}).uniq.sort
end
def get_location_code(city)
get("/Bus/Station/City/#{city}?$top=1&$format=JSON")[0]["LocationCityCode"]
end
def mapping_bus_data(data,a,b,locale,no_dest)
tmp = data.group_by{|v| v['RouteName']}
bus_group = tmp.collect do |k,v|
stops = v.each_with_index.collect{|v1,i| [v1["StopName"],v1["Direction"],i]}
match_a = stops.select{|s,d,i| s[locale]==a}
match_b = no_dest ? [] : stops.select{|s,d,i| s[locale]==b}
[k[locale],match_a.collect do |s_a,d_a,i_a|
if !no_dest
mbs = match_b.collect{|s_b,d_b,i_b| i_b>i_a ? s_b : nil}.compact
mbs.length>0 ? [s_a,mbs[0],d_a] : nil
else
[s_a,{},d_a]
end
end.compact[0]
]
end.select{|v1,v2| v2}.to_h
bus_group.keys.group_by{|k| bus_group[k]}.map{|k,v| [k,v.sort]}
end
def get_bus_with_direction_from_a_to_b(city,code,a,b,default_locale,direction=nil)
locale = default_locale
no_dest = b.blank?
select_fields = "RouteName,Direction,StopSequence,StopName"
eq_sa = "(StopName/#{locale} eq '#{a}')"
eq_sb = no_dest ? " and Direction eq #{direction}" : " or (StopName/#{locale} eq '#{b}' )"
url = "/Bus/EstimatedTimeOfArrival/City/#{city}?$select=#{select_fields}&$filter=#{eq_sa}#{eq_sb}&$format=JSON&$orderby=Direction,StopSequence"
url2 = "/Bus/EstimatedTimeOfArrival/InterCity?$select=#{select_fields}&$filter=#{eq_sa}#{eq_sb}&$format=JSON&$orderby=Direction,StopSequence"
data = {bus: mapping_bus_data(self.get(url),a,b,locale,no_dest), pbus: mapping_bus_data(self.get(url2),a,b,locale,no_dest)}
end
def get_stop_time(bus_info,locale=nil)
city = bus_info.city
cache_data = bus_info.cache_data
cache_data_bus = cache_data[:bus]
cache_data_pbus = cache_data[:pbus]
locale = get_locale if locale.nil?
filters = cache_data_bus.map do |k,v|
("((StopName/#{locale} eq '#{k[0][locale]}') and Direction eq #{k[2]} and " +
'(' + v.map{|r| "RouteName/#{bus_info.locale} eq '#{r}'"}.join(' or ') + '))')
end.join(' or ')
url = "/Bus/EstimatedTimeOfArrival/City/#{city}?$select=Direction,RouteName,NextBusTime&$filter=#{filters}&$format=JSON&$orderby=RouteName/#{locale}"
begin
bus_data = JSON.parse(self.get(url).body)
rescue Errno::EHOSTUNREACH, Net::ReadTimeout, Net::OpenTimeout
return nil
end
if bus_data.class==Hash
return nil
end
if !cache_data_pbus.blank?
filters = cache_data_pbus.map do |k,v|
("((StopName/#{locale} eq '#{k[0][locale]}') and Direction eq #{k[2]} and " +
'(' + v.map{|r| "RouteName/#{bus_info.locale} eq '#{r}'"}.join(' or ') + '))')
end.join(' or ')
url2 = "/Bus/EstimatedTimeOfArrival/InterCity?$select=Direction,RouteName,NextBusTime&$filter=#{filters}&$format=JSON&$orderby=RouteName/#{locale}"
begin
pbus_data = JSON.parse(self.get(url2).body)
rescue Errno::EHOSTUNREACH, Net::ReadTimeout, Net::OpenTimeout
pbus_data = []
end
else
pbus_data = []
end
if pbus_data.class==Hash
bus_data
else
bus_data + pbus_data
end
end
def get_input_name
"ruling_bus_info"
end
def create_lang_panel(field)
tmp2 = content_tag(:div,:class => 'btn-group', :data=>{:toggle=>"buttons-radio"}) do
I18n.available_locales.collect do |key|
link_entry_ary = ["##{field}","_#{key}"]
link_entry = link_entry_ary.join
link_to(I18n.t(key),link_entry,:data=>{:toggle=>"tab"},:class=>"btn #{(key == I18n.locale ? "active" : nil)}",:for=>key)
end.join.html_safe
end
end
def multiple_lang_tag(index1,type_of_tag,field,value=nil,custom_options={},combine_element='',exteral_options={},sortable=false)
if !index1.nil?
all_field = (get_input_name + "[#{index1}][#{field}][parant]").gsub(/\[/,'_').gsub(/\]/,'')
else
all_field = (get_input_name + "[#{field}][parant]").gsub(/\[/,'_').gsub(/\]/,'')
end
tmp = (I18n.available_locales.collect do |locale|
active_flag = ((locale == I18n.locale) ? ' in active' : '')
content_tag(:div,:class => "tab-content fade#{active_flag}",:id=>"#{all_field}_#{locale}") do
value_locale = value[locale.to_s] rescue nil
if !index1.nil?
self.__send__("#{type_of_tag}_tag","#{get_input_name}[#{index1}][#{field}][#{locale}]",value_locale,custom_options)
else
self.__send__("#{type_of_tag}_tag","#{get_input_name}[#{field}][#{locale}]",value_locale,custom_options)
end
end
end.join + create_lang_panel(all_field)).html_safe + combine_element
if sortable
if exteral_options['style'].nil?
exteral_options['style'] = 'display: flex;align-items: center;flex-wrap: nowrap;'
else
exteral_options['style'] = exteral_options['style'] + 'display: flex;align-items: center;flex-wrap: nowrap;'
end
content_tag(:div,{:class => "tab-panel border"}.merge(exteral_options)) do
("<i class=\"icons-list-2\" style=\"cursor: grab;font-size: x-large;\"></i>" +content_tag(:div) do
tmp
end).html_safe
end
else
content_tag(:div,{:class => "tab-panel"}.merge(exteral_options)) do
tmp
end
end
end
end