206 lines
8.4 KiB
Ruby
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 |