inst/shiny/server.R

library(flightscanner)
library(dplyr)
library(leaflet)
library(tidyr)
library(lubridate)
library(shiny)

data("airports", package = "flightscanner")

shinyServer(function(input, output, session) {
  output$ui_date <- renderUI({
    dateInput("date3", "Arr. Date", 
              min = input$date2,
              value = input$date2 + 7, 
              format = "mm/dd/yy") 
  })
  
  
  dataset <- eventReactive(
    input$goButton, {
      withProgress({
        setProgress(message = "Working Really Hard...")
        
        Date <- switch(input$trip_type, "1" = list(input$date1, NULL),
                       "2" = list(input$date2, input$date3))
        resp.post <- apiCreateSession(orig = input$from, dest = input$to,
                                      startDate = Date[[1]], returnDate = Date[[2]])
        resp.get <- apiPollSession(resp.post)
        flightGet(resp.get)
      })
    })
  
  
  output$ui <- renderUI({
    price <- bind_rows(dataset()$price$PricingOptions)$Price
    airline <- unique(dataset()$carriers$Code)
    duration <- dataset()$legs$Duration / 60  # minutes to hours
    layover <- bind_rows(dataset()$legs$Stops)$Layover / 60  # minutes to hours
    if (length(layover) == 0) layover <- c(0, Inf)
    
    wellPanel(
      sliderInput("Price", label = "Price", 
                  min = min(price), max = max(price), value = max(price),
                  round = 2L, ticks = FALSE, pre = "$")
      ,
      tabsetPanel(
        tabPanel("Airlines Includes",
                 selectInput("Airline_In", label = "",
                             choices = airline, selected = airline, multiple = TRUE)),
        tabPanel("Airlines Excludes",
                 selectInput("Airline_Ex", label = "",
                             choices = airline, multiple = TRUE))
      )
      ,
      sliderInput("Duration", label = "Duration",
                  min = floor(min(duration)), max = ceiling(max(duration)),
                  value = ceiling(max(duration)),
                  step = 0.5, ticks = FALSE, post = "h")
      ,
      radioButtons("Stops", label = "Stops",
                   choices = list("Any number of stops" = Inf, "Nonstop only" = 0,
                                  "1 stop or fewer" = 1, "2 stops or fewer" = 2))
      ,
      sliderInput("Layover", label = "Layover",
                  min = floor(min(layover)), max = ceiling(max(layover)),
                  value = c(floor(min(layover)), ceiling(max(layover))),
                  step = 0.5, ticks = FALSE, post = "h")
      ,
      tabsetPanel(
        tabPanel("Outbound",
                 br(),
                 sliderInput("Leave_Dep_Time", label = "Departure", step = 0.5, ticks = FALSE,
                             min = 0, max = 24, value = c(0, 24)),
                 sliderInput("Leave_Arr_Time", label = "Arrival", step = 0.5, ticks = FALSE,
                             min = 0, max = 24, value = c(0, 24))
        ),
        tabPanel("Inbound",
                 br(),
                 sliderInput("Back_Dep_Time", label = "Departure", step = 0.5, ticks = FALSE,
                             min = 0, max = 24, value = c(0, 24)),
                 sliderInput("Back_Arr_Time", label = "Arrival", step = 0.5, ticks = FALSE,
                             min = 0, max = 24, value = c(0, 24))
        )
      ))
  })
  
  output$map <- leaflet::renderLeaflet({
    from_data <- airports %>% filter(IATA != "")%>% 
      filter(IATA == toupper(input$from)) 
    to_data <- airports %>% filter(IATA != "")%>% 
      filter(IATA == toupper(input$to)) 
    leaflet::leaflet() %>%
      leaflet::addTiles() %>%
      leaflet::addMarkers(data = from_data, ~ Longitude, ~ Latitude, popup = ~ Name) %>%
      leaflet::addMarkers(data = to_data, ~ Longitude, ~ Latitude, popup = ~ Name)
  })
  
  output$Search_res <- renderText({
    t <- dataset()
    if (!is.list(t)) {
      "Error happened: Check the input information and try again!"
    } else {
      "Search succeeded! Click Flight Tab For More Details:)"
    }
  })
  
  #output$value <- renderPrint({c(input$date1, input$date2, input$date3)})
  
  output$table <- renderDataTable({
    data <- dataset()
    
    # 用来debug
    # cat("DURATION:", input$Duration, "\tPRICE: ", input$Price, "\n")
    # cat("STOPS: ", input$Stops, "\tLAYOVER: ", input$Layover, "\n")
    # cat("AIRLINE: In: ", input$`Airline_In`, "\tEx: ", input$`Airline_Ex`, "\n")
    # cat("TIME: ", input$Leave_Dep_Time, "\t", input$Leave_Arr_Time, "\t",
    #     input$Back_Dep_Time, "\t", input$Back_Arr_Time, "\n")
    # rename dictionary
    vars <- c(Outbound.Dept.Time = "OutboundLegDepartureTime", 
              Outbound.Arrv.Time = "OutboundLegArrivalTime", 
              Outbound.Duration.hrs = "OutboundLegDuration",
              Outbound.No.Stops = "OutboundLegNo.Stops",
              Inbound.Dept.Time = "InboundLegDepartureTime", 
              Inbound.Arrv.Time = "InboundLegArrivalTime", 
              Inbound.Duration.hrs = "InboundLegDuration", 
              Inbound.No.Stops = "InboundLegNo.Stops")
    
    temp <- flightFilter(data,
                         max_price = input$Price,
                         max_duration = input$Duration * 60,
                         max_stops = as.numeric(input$Stops),
                         layover = input$Layover * 60,
                         # carrier_include = input$`Airline_In`,  # has problem
                         # carrier_exclude = input$`Airline_Ex`,
                         out_departure = input$Leave_Dep_Time * 60,
                         out_arrival = input$Leave_Arr_Time * 60,
                         in_departure = input$Back_Dep_Time * 60,
                         in_arrival = input$Back_Arr_Time * 60
    ) %>%
      select(-ends_with("LegId"), -ends_with("LegSegments"), -ends_with("LegStops")) %>% 
      rename(., !!vars) %>% 
      mutate(Outbound.Duration.hrs = round(Outbound.Duration.hrs/60, 1)) %>% {
        if (input$trip_type==1) . else 
          mutate(., Inbound.Duration.hrs = round(Inbound.Duration.hrs/60, 1)) %>%
          rename("Outbound\nDept.Time" = "Outbound.Dept.Time",
                 "Outbound\nArr.Time" = "Outbound.Arrv.Time",
                 "Outbound\nDuration" = "Outbound.Duration.hrs",
                 "Outbound\nNo.Stops" = "Outbound.No.Stops",
                 "Inbound\nDept.Time" = "Inbound.Dept.Time",
                 "Inbound\nArr.Time" = "Inbound.Arrv.Time",
                 "Inbound\nDuration" = "Inbound.Duration.hrs",
                 "Inbound\nNo.Stops" = "Inbound.No.Stops")
      } %>% {
        if (input$trip_type==2) . else select(., -starts_with("Inbound")) %>%
          rename("Outbound\nDept.Time" = "Outbound.Dept.Time",
                 "Outbound\nArr.Time" = "Outbound.Arrv.Time",
                 "Outbound\nDuration" = "Outbound.Duration.hrs",
                 "Outbound\nNo.Stops" = "Outbound.No.Stops")
      }
    
    
    # For debug
    # print(flightFilter(data) %>% nrow)
    # print(temp %>% nrow)
    
    temp %>% tidyr::unnest(PricingOptions) %>% 
      mutate(Link = sprintf('<a href="%s" target="_blank" class="btn btn-primary">Book</a>', LinkURL)) %>% {
      if (nrow(.) == 0) . else select(., Price, everything(), -AgentId, -LinkURL)
    }
  }, escape = FALSE, options = list(pageLength = 20))
  
  output$IATAtable <- renderDataTable({
    airports %>% filter(IATA != "") %>% select(Name, City, Country, IATA, Latitude, Longitude)
  }, options = list(pageLength = 20))
})
MinZhang95/flightscanner documentation built on July 1, 2019, 9:36 p.m.