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 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 ("" +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