From 435adcdb5684b85427005e03969e80970ab4e98c Mon Sep 17 00:00:00 2001 From: "Zhan, Jennifer" Date: Sun, 15 Nov 2020 23:18:23 +0800 Subject: [PATCH] start a separate repo for SafeCampus --- .gitignore | 5 + IDEA_SafeCampus_sep.Rproj | 13 + app.R | 1009 +++++++++++++++++++++++++++++++++++++ building_info.R | 210 ++++++++ 4 files changed, 1237 insertions(+) create mode 100644 .gitignore create mode 100644 IDEA_SafeCampus_sep.Rproj create mode 100755 app.R create mode 100644 building_info.R diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b1df7f5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.Rproj.user +.Rhistory +.RData +.Ruserdata +**/.DS_Store diff --git a/IDEA_SafeCampus_sep.Rproj b/IDEA_SafeCampus_sep.Rproj new file mode 100644 index 0000000..8e3c2eb --- /dev/null +++ b/IDEA_SafeCampus_sep.Rproj @@ -0,0 +1,13 @@ +Version: 1.0 + +RestoreWorkspace: Default +SaveWorkspace: Default +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX diff --git a/app.R b/app.R new file mode 100755 index 0000000..ac10a5f --- /dev/null +++ b/app.R @@ -0,0 +1,1009 @@ +# Data Incite SafeCampus App +# Uses Shinydashboard as a framework https://rstudio.github.io/shinydashboard/ +# Created by Jennifer Zhan, Tracy Chen, Christina van Hal, and Mia Mayerhofer + +#load the packages if they are not already loaded +packages <- c("shiny", "shinydashboard", "shinyjs", "tidyr", "ggplot2", "shinyWidgets", "tidyverse", + "viridis", "hrbrthemes", "lubridate", "repr", "leaflet", "rlist") +new.packages <- packages[!(packages %in% installed.packages()[,"Package"])] +if (length(new.packages) > 0) { + install.packages(new.packages) +} + +#loading required libraries +library(shiny) +library(shinydashboard) +library(shinyjs) +library(tidyr) +library(ggplot2) +library(shinyWidgets) +library(tidyverse) +library(viridis) +library(hrbrthemes) +library(lubridate) +library(repr) +library(leaflet) +library(rlist) +# library(shinyalert) + +#loading R script +source("building_info.R", chdir = TRUE) +# rpi_wap_raw <- readRDS("/academics/MATP-4910-F20/COVID_RPI_WiFi_Data/rpi_wap_raw.rds") +combined_wap_data <- readRDS("../COVID_RPI_WiFi_Data/combined_wap_data.rds") +rpi_wap_raw <- readRDS("../COVID_RPI_WiFi_Data/rpi_wap_raw.rds") +buildinginfo <- readRDS("../COVID_RPI_WiFi_Data/buildinginfo.rds") + +#combined_wap_data <- readRDS("../Safe_Campus_App/combined_wap_data.rds") +#rpi_wap_raw <- readRDS("../Safe_Campus_App/rpi_wap_raw.rds") + +ui <- dashboardPage(skin = "black", title = "COVID SafeCampus", + dashboardHeader(title = tags$div( + class = "title-text", + tags$style(".logo {max-width: 80%;}"), + tags$div(id = "logo_block", tags$img(class="logo", src="Rensselaer.png", id="Rensselear Polytechnic Institute Logo"), + #HTML("

COVIDSafeCampus

")) + )), + + titleWidth = "330px" + ), + dashboardSidebar( + width = 320, + sidebarMenu(id = "tabs", collapsed = TRUE, + tags$head( + tags$style(HTML(".skin-black .sidebar-menu>li.active>a {font-weight: 700;}")) + ), + menuItem("Campus WiFi Overview", tabName = "geographic", selected=TRUE), + uiOutput("geographic_side"), + menuItem('Campus WiFi Dashboard',tabName = "discrete"), + uiOutput("discrete_side"), + menuItem("Detailed WiFi Overview", tabName = "continuous"), + uiOutput("continous_ctrl"), + menuItem("About COVIDSafeCampus", tabName = "about"), + uiOutput("about_side"), + menuItem("Comments and questions?",href ="https://docs.google.com/forms/d/1H_W6vvoXqEPiNtcpMnjdHQhjrgqrS1_LR3v2X9chJhg/edit?usp=sharing") + ) + + ), + dashboardBody( + tabItem(tabName = "survey", + tags$style(HTML(".sidebar-menu a {color: #FF0000}")) + ), + style = "background-color: #FAFAFA; height: 100%; min-height: 100vh;", + shinyjs::useShinyjs(), + tags$head(tags$link(includeScript("func.js"))), + tags$head(tags$style("a{cursor:pointer;}")), + tabItems( + tabItem(tabName = "about", + uiOutput("about_body")), + #campus dashboard tab + tabItem(tabName="discrete", uiOutput("interval_ctrl"), br(), br(),tags$div(HTML("

Campus Wi-Fi Dashboard

")), + tags$style("#title_panel {font-size:30px;color:black;display:block;}"), + fluidRow(column(12,br(), div(style="text-align:center", box(width=18, title = uiOutput("title_panel"))))), + helpText(HTML("", + "Return to map")), + helpText(HTML("", + "Go to Detailed WiFi Overview")), + wellPanel(inputPanel(radioButtons("data_type_discrete", "Choose to view Wi-Fi access by users or by devices", + c("Users" = "user", "Devices" = "mac"), + selected = "user"), + dateInput('date_discrete', + label = 'Choose a date', + value = max(rpi_wap_raw$Date), + min = min(rpi_wap_raw$Date), + max = max(rpi_wap_raw$Date) + ), + checkboxGroupInput( + "buildingType_discrete", + "Select a building type", + choices = c("Academic"="academic", + "Housing" = "housing", + "Greek" = "greek", + "Other Off Campus" = "otherOffCampus", + "Other On Campus" = "otherOnCampus"), + selected = list("academic") + ), + selectInput( + "buildingStr_discrete", + "Select a building", + choices = list("All building of selected type"="all", + "Academic" = academic, + "Housing" = housing, + "Greek" = greek, + "Other Off Campus" = otherOffCampus, + "Other On Campus" = otherOnCampus), + selected = "all", + multiple = FALSE, + selectize = TRUE, + width = NULL, + size = NULL + ), + sliderInput("timeRange", "Select a time range", + min = as_datetime(hms::parse_hm("0:00")), + max = as_datetime(hms::parse_hm("23:30")), + value = c(as_datetime(hms::parse_hm("14:00:00")), + as_datetime(hms::parse_hm("16:00:00"))), + timeFormat = "%H:%M", + timezone = "GMT", + step = 30*60) + ), + fluidRow( + column(9, + br(), + fluidRow(column(12, div(uiOutput("discrete_plot3", height = "100%")))), + br(), + fluidRow(column(12, div(uiOutput("discrete_plot1", height = "100%"))))), + column(3, + br(), + fluidRow(column(12, div(uiOutput("cont_plot", height = "100%")))), + br(), + fluidRow(column(12, div(uiOutput("discrete_plot2", height = "100%"))))) + ))), + #campus wifi overview tab + tabItem(tabName="geographic", uiOutput("geographic_ctrl"), br(), br(), tags$div(HTML("

Wi-Fi Access Point Usage across Campus

+

The color of each bubble represents whether there is a high or low maximum number of users or devices relative to the other buildings on campus.
+ The diameter of each bubble represents the maximum number of users or devices during the specified time period.
+ The user can click on each bubble to view the building name, the maximum number of users or devices, and the average number of users or devices.
+ If you would like to differentiate the bubbles for each building only by color, select the same size option.

")), + wellPanel(inputPanel(radioButtons("datatype", "Choose to view Wi-Fi access by users or devices", + c("Users" = "user", "Devices" = "mac"), selected="user"), + dateInput('day', label = 'Choose a day', value = sort(unique(rpi_wap_raw$Date))[length(unique(rpi_wap_raw$Date))-1], + min = min(rpi_wap_raw$Date), max = max(rpi_wap_raw$Date)), + checkboxGroupInput("buildingtype", "Select a building type", + choices = c("Academic"="academic", "Housing" = "housing","Greek" = "greek", + "Other Off Campus" = "otherOffCampus", + "Other On Campus" = "otherOnCampus"), + selected = list("academic", "housing", "greek", "otherOnCampus")), + sliderInput("time", "Select a time period", + min = as_datetime(hms::parse_hm("0:00")), + max = as_datetime(hms::parse_hm("23:30")), + value = c(as_datetime(hms::parse_hm("14:00:00")), + as_datetime(hms::parse_hm("16:00:00"))), + timeFormat = "%H:%M", + timezone = "GMT", + step = 30*60), + radioButtons("size", "Select how you would like to view the size of the bubbles", + choices = c("Actual size" = "actual", "Same size" = "same"), + selected = "actual")), + leafletOutput("bubblemap", width = "100%", height = 700)) + ), + #continuous tab + tabItem(tabName="continuous", + tags$style("#title_panel_cont {font-size:30px;color:black;display:block;}"), + fluidRow( + column(12,br(), br(), br(), div(style="text-align:center", box(width=18, title = uiOutput("title_panel_cont")))) + ), + helpText(HTML("", + "Return to campus map view")), + helpText( HTML("", + "Go to Campus WiFi Dashboard")), + wellPanel(inputPanel(dateInput('date', + label = 'Choose a date', + value = sort(unique(rpi_wap_raw$Date))[length(unique(rpi_wap_raw$Date))-1], + min = min(rpi_wap_raw$Date), + max = max(rpi_wap_raw$Date) + ), + radioButtons("data_type_continous", "Choose to view Wi-Fi access by USERS or by DEVICES", + c("Users" = "user", "Devices" = "mac"), + selected = "user"), + checkboxGroupInput( + "buildingType", + "Select a builiding type", + choices = c("Academic"="academic", + "Housing" = "housing", + "Greek" = "greek", + "Other Off Campus" = "otherOffCampus", + "Other On Campus" = "otherOnCampus"), + selected = list("academic") + ), + selectInput( + "buildingStr", + "Select a building from above building type", + choices = list("Building from above building type"="all", + "Academic" = academic, + "Housing" = housing, + "Greek" = greek, + "Other Off Campus" = otherOffCampus, + "Other On Campus" = otherOnCampus), + selected = "all", + multiple = FALSE, + selectize = TRUE, + width = NULL, + size = NULL + ), + selectInput( + "threshold", + "Ignore the Max User(or Device) counts during a day below", + choices = list("0" = 0, + "1" = 1, + "2" = 2, + "3" = 3, + "4" = 4, + "5" = 5, + "6" = 6, + "7" = 7, + "8" = 8, + "9" = 9, + "10" = 10), + selected = 5 + ) + )), + fluidRow( + tags$style("#continous_table {margin-top:10px; margin-right:10px}"), + tags$style("#continuous_ui {margin-top:10px}"), + column(8,div(uiOutput("continuous_ui"))), + column(3, div(DT::dataTableOutput("continous_table")))) + ) + ), + tags$script(HTML(' + $(document).ready(function() { + $(\'head\').append(\'\'); + $(\'head\').append(\'\'); + //all related pages should be linked below + + $("header").find("nav").append(\'

COVIDSafeCampus
\'); + // $(".sidebar-toggle").insertAfter(".tab-content"); + }) + ')), + + + ) +) + + +# Define server logic +server <- function(input, output, session) { + + output$about_body <- renderUI({ + tags$div( + HTML(" +

About COVIDSafeCampus

+
+

COVID Safe Campus is an app that reveals the usage of Wi-Fi access points and aggregations of wireless users on the campus network at Rensselaer Polytechnic Institute, Troy, New York.

+
+
+

Campus WiFi Overview

+
  • This tab reveals the usage of Wi-Fi access points on the campus network at RPI.
  • +
  • Users can customize their searches using the following 4 selections:
  • +
      +
    1. View the WiFi access via user count or device count.
    2. +
    3. Select a specific date within the last 7 days.
    4. +
    5. Specify the 30 minutes interval they wish to view.
    6. +
    7. Refine their searches by only selecting specific building types.
    +
  • Based on the user's selection, the main panel will display a bubble map.
  • + +

    +

    Continuous Data Overview

    +
  • This tab provides an overview of the WiFi access on campus via WAP devices.
  • +
  • Users can customize their searches using the following 3 selections:
  • +
      +
    1. Select a specific date within the last 7 days.
    2. +
    3. Select a specific or multiple buildings.
    4. +
    5. Refine their searches by only selecting from specific building types.
    +
  • Based on the user's selection, the main panel will display a heatmap showcasing the WiFi access per WAP device.
  • +

    +

    Campus WiFi Dashboard

    +
  • This tab provides an overview of the WiFi access on campus via WAP devices in 30 minute intervals.
  • +
  • Users can customize their searches using the following 5 selections:
  • +
      +
    1. View the WiFi access via user count or MAC count.
    2. +
    3. Select a specific date within the last 7 days.
    4. +
    5. Select a specific or multiple buildings.
    6. +
    7. Refine their searches by only selecting from specific building types.
    8. +
    9. Specify the 30 minutes interval they wish to view the information.
    +
  • Based on user's selection, the main panel will display 4 plots showcasing a main heatmap displaying the WiFi access per WAP device at every 30 minutes interval, 2 aggregate bar plots showing the WiFi access per WAP device and every 30 minutes, and a plot of the WiFi access at each 30 minutes interval modeled by a polynomial function.
  • + +
    +

    DISCLAIMERS

    +

    This is a prototype app. Some of the information displayed may not be 100% accurate. Improvements to this app will continue to be made.

    + + + "), + + ) + }) + + #Map tab + output$geographic_ctrl <- renderUI({ + incoming <- reactive({ + combined_wap_data$Building <- forcats::fct_explicit_na(combined_wap_data$Building) + wap_map_data_time1 <- combined_wap_data %>% filter(time==(hms::as_hms(input$time[1])), Date==input$day, buildingType %in% input$buildingtype) + wap_map_data_time2 <- combined_wap_data %>% filter(time==(hms::as_hms(input$time[2])), Date==input$day, buildingType %in% input$buildingtype) + combined_wap_data_with_times <- left_join(wap_map_data_time1, wap_map_data_time2, by=c("Building","Date", "latitude","longitude")) + if (input$datatype == "user"){ + users <- combined_wap_data_with_times %>% select(Building, users.x, users.y) + users$max <- apply(users[,2:3],1,max) + combined_wap_data_final <- combined_wap_data_with_times %>% mutate(average_users = (users.x+users.y)/2, time = time.y-time.x) + combined_wap_data_final$max_users <- users$max + combined_wap_data_final <- combined_wap_data_final %>% select(-time.x, -time.y, -users.x, -users.y) + } + else{ + macs <- combined_wap_data_with_times %>% select(Building, macs.x, macs.y) + macs$max <- apply(macs[,2:3],1,max) + combined_wap_data_final <- combined_wap_data_with_times %>% mutate(average_macs = (macs.x+macs.y)/2, time = time.y-time.x) + combined_wap_data_final$max_macs <- macs$max + combined_wap_data_final <- combined_wap_data_final %>% select(-time.x, -time.y, -macs.x, -macs.y) + } + }) + + # default box + minLng = min(rpi_wap_raw$longitude) + minLat = min(rpi_wap_raw$latitude) + maxLng = max(rpi_wap_raw$longitude) + maxLat = max(rpi_wap_raw$latitude) + + #plot the bubble map + #observe({ + if (input$size == "actual"){ + output$bubblemap <- renderLeaflet({ + if (input$datatype == "user"){ + pal <- colorNumeric(palette, incoming()$max_users, reverse=TRUE) + m <- leaflet(incoming()) %>% addTiles() %>% + addLegend(pal = pal, values = ~max_users, group = "circles", + position = "topleft", title="Maximum Number of Users") + # only add the data if there is data to be added + if (nrow(incoming()) > 0) { + pal <- colorNumeric(palette = palette, domain = incoming()$max_users, reverse = TRUE) + m <- addCircles(m, lat = ~latitude, lng = ~longitude, radius = ~max_users/2, + color = ~pal(max_users), stroke = FALSE, fillOpacity = .7, options = list(padding = c(50,50))) + m <- addCircleMarkers(m, lat = ~latitude, lng = ~longitude, popup = ~paste0("Building: ", Building, "
    ", "Max: ", max_users," users", "
    ", "Average: ", average_users, " users", "
    ", + "Learn more about the ", "", Building,""), + options = popupOptions(closeButton = TRUE), radius = ~max_users/2, color = ~pal(max_users)) + m + } else { + m <- fitBounds(m, lng1 = minLng, lat1 = minLat, lng2 = maxLng, lat2 = maxLat) + m + } + } + else{ + pal <- colorNumeric(palette, incoming()$max_macs, reverse=TRUE) + m <- leaflet(incoming()) %>% addTiles() %>% + addLegend(pal = pal, values = ~max_macs, group = "circles", + position = "topleft", title="Maximum Number of Users") + # only add the data if there is data to be added + if (nrow(incoming()) > 0) { + pal <- colorNumeric(palette = palette, domain = incoming()$max_macs, reverse = TRUE) + m <- addCircles(m, lat = ~latitude, lng = ~longitude, radius = ~max_macs/2, + color = ~pal(max_macs), stroke = FALSE, fillOpacity = .7, options = list(padding = c(50,50))) + m <- addCircleMarkers(m, lat = ~latitude, lng = ~longitude, popup = ~paste0("Building: ", Building, "
    ", "Max: ", max_macs," devices", "
    ", "Average: ", average_macs, " devices", "
    ", + "Learn more about the ", "", Building,""), + options = popupOptions(closeButton = TRUE), radius = ~max_macs/2, color = ~pal(max_macs)) + m + } else { + m <- fitBounds(m, lng1 = minLng, lat1 = minLat, lng2 = maxLng, lat2 = maxLat) + m + } + } + m + }) + } + else{ + output$bubblemap <- renderLeaflet({ + if (input$datatype == "user"){ + pal <- colorNumeric(palette, incoming()$max_users, reverse=TRUE) + m <- leaflet(incoming()) %>% addTiles() %>% + addLegend(pal = pal, values = ~max_users, group = "circles", + position = "topleft", title="Maximum Number of Users") + # only add the data if there is data to be added + if (nrow(incoming()) > 0) { + pal <- colorNumeric(palette = palette, domain = incoming()$max_users, reverse = TRUE) + m <- addCircles(m, lat = ~latitude, lng = ~longitude, radius = 15, + color = ~pal(max_users), stroke = FALSE, fillOpacity = .7, options = list(padding = c(50,50))) + m <- addCircleMarkers(m, lat = ~latitude, lng = ~longitude, popup = ~paste0("Building: ", Building, "
    ", "Max: ", max_users," users", "
    ", "Average: ", average_users, " users", "
    ", + "Learn more about the ", "", Building,""), + options = popupOptions(closeButton = TRUE), radius = 15, color = ~pal(max_users)) + m + } else { + m <- fitBounds(m, lng1 = minLng, lat1 = minLat, lng2 = maxLng, lat2 = maxLat) + m + } + } + else{ + pal <- colorNumeric(palette, incoming()$max_macs, reverse=TRUE) + m <- leaflet(incoming()) %>% addTiles() %>% + addLegend(pal = pal, values = ~max_macs, group = "circles", + position = "topleft", title="Maximum Number of Users") + # only add the data if there is data to be added + if (nrow(incoming()) > 0) { + pal <- colorNumeric(palette = palette, domain = incoming()$max_macs, reverse = TRUE) + m <- addCircles(m, lat = ~latitude, lng = ~longitude, radius = 15, + color = ~pal(max_macs), stroke = FALSE, fillOpacity = .7, options = list(padding = c(50,50))) + m <- addCircleMarkers(m, lat = ~latitude, lng = ~longitude, popup = ~paste0("Building: ", Building, "
    ", "Max: ", max_macs," devices", "
    ", "Average: ", average_macs, " devices", "
    ", + "Learn more about the ", "", Building,""), + options = popupOptions(closeButton = TRUE), radius = 15, color = ~pal(max_macs)) + m + } else { + m <- fitBounds(m, lng1 = minLng, lat1 = minLat, lng2 = maxLng, lat2 = maxLat) + m + } + } + + }) + } + + #}) + }) + + # keep input selector in all the tabs consistently, allow user to change the input in any tab. + observe({ + # when the users change input at the Campus Overview tab + if(input$tabs=='geographic'){ + marker_info <- input$bubblemap_marker_click + abbreviation <- buildinginfo$abbrev[buildinginfo$latitude == marker_info$lat & buildinginfo$longitude == marker_info$lng] + # If user was jumping to Detailed WiFi overview tab, then input date, time should be same as map's, and marker should be clicked + if((!(input$buildingStr == abbreviation)||!(input$date == input$day)||!(input$buildingType == input$buildingtype)||!(input$data_type_continous == input$datatype)) && + !is.null(input$bubblemap_marker_click)){ + updateRadioButtons(session, "data_type", selected=input$datatype) + updateDateInput(session, "date", value = input$day) + updateCheckboxGroupInput(session, "buildingType", selected = input$buildingtype) + # If users do not select any building type, plot should show all the data; + # The dropdown should include all the buildings. + if(!is.null(input$buildingType)){ + buildingtype<-input$buildingType + buildingname<-alltype[buildingtype] + buildingname<-c("Buildings from selected building type(s)"="all",buildingname) + } + else{ + buildingname<-c("Buildings from selected building type(s)"="all",alltype) + } + updateSelectInput(session, "buildingStr",choices = buildingname,selected=abbreviation) + } + # If user was jumping to WiFi dashboard, then input date, time should be same as map's, and marker should be clicked + if((!(input$buildingStr_discrete == abbreviation)||!(input$date_discrete == input$day)||!(input$timeRange == input$time)||! + (identical(input$buildingType_discrete, input$buildingtype))||!(identical(input$data_type_discrete,input$datatype))) && !is.null(input$bubblemap_marker_click)){ + updateRadioButtons(session, "data_type_discrete", selected=input$datatype) + updateDateInput(session, "date_discrete", value = input$day) + updateCheckboxGroupInput(session, "buildingType_discrete", selected = input$buildingtype) + updateSliderInput(session, "timeRange", value=input$time, timeFormat = "%H:%M") + # If users do not select any building type, plot should show all the data; + # The dropdown should include all the buildings. + if(!is.null(input$buildingType_discrete)){ + buildingtype<-input$buildingType_discrete + buildingname<-alltype[buildingtype] + buildingname<-c("Buildings from selected building type(s)"="all",buildingname) + } + else{ + buildingname<-c("Buildings from selected building type(s)"="all",alltype) + } + updateSelectInput(session, "buildingStr_discrete",choices = buildingname,selected=abbreviation) + } + } + # when the users change input at the Detailed Wifi Overview tab + else if(input$tabs=='continuous'){ + data_type_info <- input$data_type_continous + date_info<-input$date + building_type_info<-input$buildingType + building_info<-input$buildingStr + # update the input in the Campus Wifi Overview tab consistently with the Detailed Wifi Overview tab + if(!(input$datatype == data_type_info)||!(input$day == date_info)||!(identical(input$buildingtype,building_type_info))){ + updateRadioButtons(session, "datatype", selected=data_type_info) + updateDateInput(session, "day", value = date_info) + updateCheckboxGroupInput(session, "buildingtype", selected = building_type_info) + } + # update the input in the Campus Wifi Dashboard tab consistently with the Detailed Wifi Overview tab + if(!(input$data_type_discrete == data_type_info)||!(input$date_discrete == date_info)||!(identical(input$buildingType_discrete,building_type_info))||!(input$buildingStr_discrete==building_info)){ + updateRadioButtons(session, "data_type__discrete", selected=data_type_info) + updateDateInput(session, "date_discrete", value = date_info) + updateCheckboxGroupInput(session, "buildingType_discrete", selected = building_type_info) + # If users do not select any building type, plot should show all the data; + # The dropdown should include all the buildings. + if(!is.null(input$buildingType_discrete)){ + buildingtype<-input$buildingType_discrete + buildingname<-alltype[buildingtype] + buildingname<-c("Buildings from selected building type(s)"="all",buildingname) + } + else{ + buildingname<-c("Buildings from selected building type(s)"="all",alltype) + } + updateSelectInput(session, "buildingStr_discrete",choices = buildingname,selected=building_info) + } + + } + # when the users change input at the Campus Wifi Dashboard tab + else if(input$tabs=='discrete'){ + data_type_info <- input$data_type_discrete + date_info<-input$date_discrete + building_type_info<-input$buildingType_discrete + building_info<-input$buildingStr_discrete + time_info<-input$timeRange + # update the input in the Campus Wifi Overview tab consistently with the Campus Wifi Dashboard tab + if(!(input$datatype == data_type_info)||!(input$day == date_info)||!(identical(input$buildingtype,building_type_info))||!(identical(input$time, time_info))){ + updateRadioButtons(session, "datatype", selected=data_type_info) + updateDateInput(session, "day", value = date_info) + updateCheckboxGroupInput(session, "buildingtype", selected = building_type_info) + updateSliderInput(session, "time", value=time_info, timeFormat = "%H:%M") + } + # update the input in the Detailed Wifi Overview tab consistently with the Campus Wifi Dashboard tab + if(!(input$data_type_continous == data_type_info)||!(input$date == date_info)||!(identical(input$buildingType,building_type_info))||!(input$buildingStr==building_info)){ + updateRadioButtons(session, "data_type_continous", selected=data_type_info) + updateDateInput(session, "date", value = date_info) + updateCheckboxGroupInput(session, "buildingType", selected = building_type_info) + if(!is.null(input$buildingType)){ + buildingtype<-input$buildingType + buildingname<-alltype[buildingtype] + buildingname<-c("Buildings from selected building type(s)"="all",buildingname) + } + else{ + buildingname<-c("Buildings from selected building type(s)"="all",alltype) + } + updateSelectInput(session, "buildingStr",choices = buildingname,selected=building_info) + } + } + }) + + + #campus dashboard tab + output$interval_ctrl <- renderUI({ + discrete_dat <- reactive({ + if(input$buildingStr_discrete=="all"){ + building="" + # if user does not select any building type, the plot should show all the Wap data. + if(is.null(input$buildingType_discrete)){ + rpi_wap_raw<-rpi_wap_raw %>% + # Filter by selected date + filter(Date==as_date(input$date_discrete)) + } + # if user select one or more building types, the plot should show the data of the buildings in those types. + else{ + rpi_wap_raw<-rpi_wap_raw %>% + # Filter by selected date and building + filter(Date==as_date(input$date_discrete))%>% + filter(buildingType%in%input$buildingType_discrete) %>% + filter(time>=(hms::as_hms(input$timeRange[1]))) %>% + filter(time<=(hms::as_hms(input$timeRange[2]))) + } + } + # when the user selects a specified building. + else{ + rpi_wap_raw<-rpi_wap_raw %>% + filter(Date==as_date(input$date_discrete)) %>% + filter(abbrev == input$buildingStr_discrete)%>% + filter(time>=(hms::as_hms(input$timeRange[1]))) %>% + filter(time<=(hms::as_hms(input$timeRange[2]))) + } + + }) + + # Sum the number of Wi-Fi users by device + by_device <- reactive({ + + if (input$data_type_discrete == "user") { + trimmedHitsData <- discrete_dat() %>% + dplyr::group_by(devname, Date) %>% + dplyr::summarize(total = sum(usercount)) + } else { + trimmedHitsData <- discrete_dat() %>% + dplyr::group_by(devname, Date) %>% + dplyr::summarize(total = sum(maccount)) + } + + }) + + # Sum the number of Wi-Fi users by hour + by_time <- reactive({ + if (input$data_type_discrete == "user") { + trimmedHitsData <- discrete_dat() %>% + dplyr::group_by(Date, time) %>% + dplyr::summarize(total = sum(usercount)) + } else { + trimmedHitsData <- discrete_dat() %>% + dplyr::group_by(Date, time) %>% + dplyr::summarize(total = sum(maccount)) + } + + }) + + discrete_dat_fin <- reactive({ + if (input$data_type_discrete == "user") { + all_discrete_dat <- discrete_dat() + names(all_discrete_dat)[names(all_discrete_dat) == "usercount"] <- "Count" + all_discrete_dat + } else { + all_discrete_dat <- discrete_dat() + names(all_discrete_dat)[names(all_discrete_dat) == "maccount"] <- "Count" + all_discrete_dat + } + }) + + ht <- reactiveVal(400) + ht_main <- reactiveVal(400) + + set_breaks = function(max_y) { + if (max_y <= 4){ + seq(0, max_y, by = 1) + } else if (max_y > 4 & max_y < 16){ + seq(0, max_y, by = 2) + } else { + seq(0, max_y, by = max_y %/% 4) + } + } + + # Plot the graphs for the interval view + observe({ + # Main plot for interval data + output$p1 <- renderPlot({ + max_y <- max(discrete_dat_fin()$Count) + ggplot(discrete_dat_fin(), aes(x = time, y = devname, fill = Count)) + + geom_tile() + + xlab(label = "Time of day (24-hour clock)") + + ylab(label = "WAP Device Name") + + ggtitle(paste("RPI WiFi access per WAP devices in 30 minutes interval on", input$date_discrete, + "from", hms::as_hms(input$timeRange[1]), "to", hms::as_hms(input$timeRange[2]))) + + scale_fill_distiller(palette = "Purples", direction = "horizontal", name = "Count", + breaks = set_breaks(max_y)) + theme_ipsum() + + theme(plot.title = element_text(size = 16)) + + theme(axis.title.x = element_text(size = 12)) + + theme(axis.title.y = element_text(size = 12)) + + theme(plot.margin = unit(c(1,0,1,0), "cm")) + + theme(panel.grid.major.x = element_line(colour = "black"), + panel.ontop = TRUE) + }, height=ht_main) + + output$discrete_plot1 <- renderUI({ + if(nrow(discrete_dat())==0){ + h1("There is no building under selected condition") + } + else{ + plotOutput("p1",height = "100%") + } + }) + + # Plot for Wi-Fi connection by device + output$p2 <- renderPlot({ + max_y <- max(by_device()$total) + ggplot(by_device(), aes(x=devname, y=total, fill=total)) + + geom_bar(stat="identity") + + xlab(label = "WAP Device Name") + + ylab(label = "Nunber of access per WAP device") + + ggtitle("RPI WiFi access per WAP devices") + + scale_fill_distiller(palette = "Purples", direction = "horizontal", name = "Count", breaks = set_breaks(max_y)) + theme_ipsum() + + theme_bw() + coord_flip() + + theme(plot.title = element_text(size = 16, face = "bold")) + + theme(axis.title.x = element_text(size = 12)) + + theme(axis.title.y = element_text(size = 12)) + + theme(plot.margin = unit(c(1,0,1,0), "cm")) + }, height=ht_main) + + output$discrete_plot2 <- renderUI({ + if(nrow(discrete_dat())==0){ + h1(" ") + } + else{ + plotOutput("p2",height = "100%") + } + }) + + # Plot for Wi-Fi connection by hour + output$p3 <- renderPlot({ + max_y <- max(by_time()$total) + ggplot(by_time(), aes(x=time, y=total, fill=total)) + + geom_bar(stat="identity") + + xlab(label = "Time of day (24-hour clock)") + + ylab(label = "Number of WAP device access by hour") + + ggtitle(paste("RPI WiFi access in 30 minutes interval on", input$date_discrete, + "from", hms::as_hms(input$timeRange[1]), "to", hms::as_hms(input$timeRange[2]))) + + theme_bw() + + scale_fill_distiller(palette = "Purples", direction = "horizontal", name = "Count", + breaks = set_breaks(max_y)) + + theme_ipsum() + + theme(plot.title = element_text(size = 16)) + + theme(axis.title.x = element_text(size = 12)) + + theme(axis.title.y = element_text(size = 12)) + + theme(plot.margin = unit(c(1,0,1,2.5), "cm")) + + theme(panel.grid.major.x = element_line(colour = "black"), + panel.ontop = TRUE) + }, height=ht) + + output$discrete_plot3 <- renderUI({ + if(nrow(discrete_dat())==0){ + h1(" ") + } + else{ + plotOutput("p3",height = "100%") + } + }) + + # Plot for Wi-Fi data in continuous time + output$p4 <- renderPlot({ + max_y <- max(by_time()$total) + ggplot(by_time(), aes(x=time, y = total)) + + geom_line(data = by_time(), aes(x=time, y=total), color = "#999999", size = 2) + + geom_point(data = by_time(), aes(fill=total), colour="black",pch=21, size=4) + + xlab(label = "Time of day (24-hour clock)") + + ylab(label = "Number of WAP device access by hour") + + ggtitle(paste("RPI WiFi access in 30 minutes interval \n (continuous representation)")) + + theme_bw() + + theme(plot.title = element_text(size = 16)) + + theme(axis.title.x = element_text(size = 12)) + + theme(axis.title.y = element_text(size = 12)) + + scale_colour_distiller(palette = "Purples", trans = "reverse") + + scale_fill_distiller(palette = "Purples", direction = "horizontal", name = "Count", + breaks = set_breaks(max_y)) + theme_ipsum() + + theme(plot.margin = unit(c(1,0,1,0), "cm")) + }, height=ht) + + output$cont_plot <- renderUI({ + if(nrow(discrete_dat())==0){ + h1(" ") + } + else{ + plotOutput("p4",height = "100%") + } + }) + + output$title_panel <- renderUI({ + if(input$buildingStr_discrete=="all"){ + paste("All building of", tools::toTitleCase(input$buildingType_discrete), "type on", input$date_discrete, "from", + hms::as_hms(input$timeRange[1]), "to", hms::as_hms(input$timeRange[2]), "EST") + } else{ + row<- which(buildinginfo$abbrev == input$buildingStr_discrete) + buildingname<-as.character(buildinginfo[row, 1]) + paste(buildingname, "on", input$date_discrete, "from", hms::as_hms(input$timeRange[1]), "to", hms::as_hms(input$timeRange[2]), "EST") + } + }) + + }) + + observeEvent({ + input$buildingStr_discrete + input$date_discrete + input$buildingType_discrete + input$timeRange}, { + if(nrow(dat())!=0){ + row_number<-length(unique(discrete_dat_fin()$devname)) + if (row_number > 10000) { + ht_main(10000) + } else if(row_number==1){ + ht_main(row_number*75) + } else if(row_number>1 & row_number<=3){ + ht_main(row_number*65) + }else if(row_number>3 & row_number<=10){ + ht_main(row_number*40) + } else if (row_number>10 & row_number<=20){ + # browser() + ht_main(row_number*30) + } else { + ht_main(row_number*25) + } + } + }) + + }) + + + # update input choices with only showing the buildings for the selected building types + observe({ + # If users do not select any building type, plot should show all the data; + # The dropdown should include all the buildings. + if(!is.null(input$buildingType)){ + buildingtype<-input$buildingType + buildingname<-alltype[buildingtype] + buildingname<-c("Buildings from above building type(s)"="all",buildingname) + } + else{ + buildingname<-c("Buildings from above building type(s)"="all",alltype) + } + updateSelectInput(session, "buildingStr", + choices = buildingname + ) + }) + + output$title_panel_cont = renderUI({ + if(input$buildingStr=="all"){ + if(length(input$buildingType)==1){ + paste("All building of", tools::toTitleCase(input$buildingType), "type on", input$date) + } + # if the user selects multiple building types + else{ + bulding_type=toString(input$buildingType) + paste("All building of", tools::toTitleCase(bulding_type), "type on", input$date) + } + + } else{ + row<- which(buildinginfo$abbrev == input$buildingStr) + buildingname<-buildinginfo[row, 1] + paste(buildingname, "on", input$date) + } + }) + + dat <- reactive({ + if(input$data_type_continous=="user"){ + # when the user selects the 'entire campus' + if(input$buildingStr=="all"){ + building="" + # if user does not select any building type, the plot should show all the Wap data. + if(is.null(input$buildingType)){ + rpi_wap_raw<-rpi_wap_raw %>% + # Filter by selected date and building + filter(Date==as_date(input$date))%>% + group_by(devname) %>% + mutate(max_count = max(usercount)) %>% + ungroup() %>% + filter(max_count>=input$threshold) + } + # if user select one or more building types, the plot should show the data of the buildings in those types. + else{ + rpi_wap_raw<-rpi_wap_raw %>% + # Filter by selected date and building + filter(Date==as_date(input$date))%>% + filter(buildingType%in% input$buildingType)%>% + group_by(devname) %>% + mutate(max_count = max(usercount)) %>% + ungroup() %>% + filter(max_count>=input$threshold) + } + } + # when the user selects a specified building. + else{ + rpi_wap_raw<-rpi_wap_raw %>% + # Filter by selected date, building types, and building + filter(Date==as_date(input$date)) %>% + filter(abbrev == input$buildingStr_discrete)%>% + group_by(devname) %>% + mutate(max_count = max(usercount)) %>% + ungroup() %>% + filter(max_count>=input$threshold) + } + } + + else { + # when the user selects the 'entire campus' + if(input$buildingStr=="all"){ + building="" + # if user does not select any building type, the plot should show all the Wap data. + if(is.null(input$buildingType)){ + rpi_wap_raw<-rpi_wap_raw %>% + # Filter by selected date and building + filter(Date==as_date(input$date))%>% + group_by(devname) %>% + mutate(max_count = max(maccount)) %>% + ungroup() %>% + filter(max_count>=input$threshold) + } + # if user select one or more building types, the plot should show the data of the buildings in those types. + else{ + rpi_wap_raw<-rpi_wap_raw %>% + # Filter by selected date and building + filter(Date==as_date(input$date))%>% + filter(buildingType %in% input$buildingType)%>% + group_by(devname) %>% + mutate(max_count = max(maccount)) %>% + ungroup() %>% + filter(max_count>=input$threshold) + } + } + # when the user selects a specified building. + else{ + rpi_wap_raw<-rpi_wap_raw %>% + # Filter by selected date, building types, and building + filter(Date==as_date(input$date)) %>% + filter(abbrev == input$buildingStr_discrete)%>% + group_by(devname) %>% + mutate(max_count = max(maccount)) %>% + ungroup() %>% + filter(max_count>=input$threshold) + } + } + # if(nrow(rpi_wap_raw)==0){ + # shinyalert("Oops!", "Something went wrong.", type = "error"); + # } + }) + + + plotHeight <- reactiveVal(1000) + + observe({ + output$plot2 <- renderPlot({ + #if there is data under selected condition. + if(nrow(dat())!=0){ + rpi_wap_raw<-dat() + if(input$data_type_continous=="user"){ + rpi_wap_raw %>% + # Now plot! + ggplot( aes(x=date_time, y=0.5)) + + geom_line(aes(color = usercount, size=2)) + + scale_color_gradient(low = "white", high = "darkblue") + + ylim(0,1) + + theme_bw() + + theme(axis.text.y=element_blank(), + axis.ticks.y=element_blank(), + panel.grid.major.y = element_blank(), + panel.grid.minor.y = element_blank()) + + facet_grid(rows = vars(devname), switch = "both") + + theme(panel.border = element_rect(color = "white", fill = NA, size = 1))+ + theme(strip.text.y.left = element_text(angle = 0)) + + theme(panel.grid.minor.x = element_line( size=0.5, color="black" ), + panel.grid.major.x = element_line( size=1, color="black" )) + + scale_x_datetime(date_breaks = "3 hours",date_minor_breaks="1 hour",position="top", date_labels="%H") + + theme(legend.position="right") + + theme( + panel.background = element_rect(fill = NA), + panel.ontop = TRUE)+ + labs(y="Access Point ID", x = "Time of Day(24hr clock)") + } + else { + rpi_wap_raw %>% + # Now plot! + ggplot( aes(x=date_time, y=0.5)) + + geom_line(aes(color = maccount, size=2)) + + scale_color_gradient(low = "white", high = "darkblue") + + ylim(0,1) + + theme_bw() + + theme(axis.text.y=element_blank(), + axis.ticks.y=element_blank(), + panel.grid.major.y = element_blank(), + panel.grid.minor.y = element_blank()) + + facet_grid(rows = vars(devname), switch = "both") + + theme(panel.border = element_rect(color = "white", fill = NA, size = 1))+ + theme(strip.text.y.left = element_text(angle = 0)) + + theme(panel.grid.minor.x = element_line( size=0.5, color="black" ), + panel.grid.major.x = element_line( size=1, color="black" )) + + scale_x_datetime(date_breaks = "3 hours",date_minor_breaks="1 hour",position="top", date_labels="%H") + + theme(legend.position="right") + + theme( + panel.background = element_rect(fill = NA), + panel.ontop = TRUE)+ + labs(y="Access Point ID", x = "Time of Day(24hr clock)") + } + + } + + },height = plotHeight) + output$continuous_ui<- renderUI({ + # if there is no data under selected condition. + if(nrow(dat())==0){ + h1("There is no building under selected condition") + } + else{ + plotOutput("plot2",height = "100%") + } + }) + }) + + output$continous_table <- DT::renderDataTable({ + if(input$buildingStr!="all"&input$data_type_continous=="user"){ + building_user<-paste("Total number of users in", tools::toTitleCase(input$buildingStr)) + type_user<-paste("Total number of users in", tools::toTitleCase(input$buildingType), "type") + max_building_user<-paste("Max number of users in", tools::toTitleCase(input$buildingStr)) + max_type_user<-paste("Max number of users in", tools::toTitleCase(input$buildingType), "type") + max_count<-dat()[!duplicated(dat()$devname),] + hottest_time<-dat()[dat()$usercount==dat()$max_count,] + hottest_time<-hottest_time[!duplicated(hottest_time$devname),]$date_time + print(hottest_time) + cont_table<-data.frame("Devname"=(max_count$devname),"max_building_user"=(max_count$max_count),"Hottest Time"=hottest_time) + names(cont_table)[names(cont_table) == "max_building_user"]=max_building_user + rownames(cont_table) <- NULL + print(cont_table) + cont_table + } + },options = list(searching = FALSE)) + + observeEvent({ + input$buildingStr + input$threshold + input$date + input$buildingType}, { + if(nrow(dat())!=0){ + row_number<-length(unique(dat()$devname)) + if (row_number > 10000) { + plotHeight(10000) + } else if(row_number==1){ + plotHeight(row_number*75) + } else if(row_number>1 & row_number<=3){ + plotHeight(row_number*65) + }else if(row_number>3 & row_number<=10){ + plotHeight(row_number*40) + } else if (row_number>10 & row_number<=20){ + # browser() + plotHeight(row_number*30) + } else { + plotHeight(row_number*25) + } + } + }) +} + +# Run the application +shinyApp(ui = ui, server = server) \ No newline at end of file diff --git a/building_info.R b/building_info.R new file mode 100644 index 0000000..5a8b373 --- /dev/null +++ b/building_info.R @@ -0,0 +1,210 @@ +### continuous and dashboard view ### + +# Building selector sub-lists +academic <- list( + "Amos Eaton"="amos", + "Carnegie Building"="carn", + "CBIS"="biot", + "CII"="cii", + "Cogswell Lab"="cogs", + "DCC"="dcc", + "Folsom Library"="lib", + "Greene Building"="gree", + "JEC"="jec", + "Lally Building"="lall", + "Materials Research Center"="mrc", + "Pittsburgh Building"="pitt", + "Polymer Center"="poly", + "Rensselaer Union"="unio", + "Ricketts Building"="rick", + "Sage Lab"="sage", + "Science Center"="scic", + "Troy Building"="troy", + "Voorhees Computing Center"="vcc", + "Walker Lab"="walk", + "West Hall"="west", + "Winslow Building"="wins") + +greek <- list( + "Alpha Epsilon Pi, 284 Pawling Ave"="aepi", + "Delta Phi, 311 Congress St"="cong", + "Delta Tau Delta, 133 Sunset Terrace"="delt", + "Lambda Chi Alpha, 200 Sunset Terrace" ="lxa", + "Phi Kappa Theta, 107 Sunset Terrace" ="phik", + "Phi Mu Delta, 224 Pawling Ave"="phim", + "Phi Sigma Kappa, 316/320 Congress St"="phis", + "Theta Chi, 2100 Burdett Ave"="thetc", + "Theta Xi, 1490 Sage Ave"="thetx", + "Zeta Psi, 25 Belle Ave"="zeta") + +housing <- list( + "Albright Court #71"="albr71", + "Albright Court #73"="albr73", + "Albright Court #76"="albr76", + "Albright Court #82"="albr82", + "Albright Court #84"="albr84", + "Albright Court #85"="albr85", + "Albright Court #88"="albr88", + "Albright Court #91"="albr91", + "Albright Court #94"="albr94", + "Albright Court #95"="albr95", + "Albright Court #97"="albr97", + "BARH A"="barha", + "BARH B" = "barhb", + "BARH C" = "barhc", + "BARH D" = "barhd", + "Barton Hall"="bart", + "Beman Lane #11"="bema11", + "Beman Lane #13"="bema13", + "Beman Lane #15"="bema15", + "Beman Lane #16"="bema16", + "Beman Lane #18"="bema18", + "Beman Lane #21"="bema21", + "Beman Lane #23"="bema23", + "Beman Lane #25"="bema25", + "Beman Lane #26"="bema26", + "Beman Lane #28"="bema28", + "Blitman Commons"="blit", + "Bray Hall"="bray", + "Brinsmade Terrace #11"="brin11", + "Brinsmade Terrace #13"="brin13", + "Brinsmade Terrace #16"="brin16", + "Brinsmade Terrace #21"="brin21", + "Brinsmade Terrace #23"="brin23", + "Brinsmade Terrace #26"="brin26", + "Brinsmade Terrace #32"="brin32", + "Brinsmade Terrace #34"="brin34", + "Brinsmade Terrace #35"="brin35", + "Brinsmade Terrace #41"="brin41", + "Brinsmade Terrace #43"="brin43", + "Brinsmade Terrace #46"="brin46", + "Bryckwyck Apts, Sunset Terrace"="bryc", + "Burdett Ave #2144" ="burd", + "Cary Hall"="cary", + "Chasen Building, downtown"="chas", + "City Station South"="ctys", + "City Station West"="ctyw", + "Colonie Apts Bldg A"="coloa", + "Colonie Apts Bldg B"="colob", + "Colonie Apts Bldg C"="coloc", + "Colonie Apts Bldg D"="colod", + "Colvin Circle #12"="colv12", + "Colvin Circle #14"="colv14", + "Colvin Circle #16"="colv16", + "Colvin Circle #22"="colv22", + "Colvin Circle #24"="colv24", + "Colvin Circle #26"="colv26", + "Colvin Circle #28"="colv28", + "Colvin Circle #30"="colv30", + "Colvin Circle #31"="colv31", + "Colvin Circle #34"="colv34", + "Colvin Circle #36"="colv36", + "Colvin Circle #42"="colv42", + "Colvin Circle #43"="colv43", + "Colvin Circle #44"="colv44", + "Colvin Circle #52"="colv52", + "Colvin Circle #54"="colv54", + "Colvin Circle #56"="colv56", + "Colvin Circle #62"="colv62", + "Colvin Circle #64"="colv64", + "Colvin Circle #66"="colv66", + "Crockett Hall"="croc", + "Davison Hall"="davi", + "E-Housings (Cass)"="cass", + "E-Housings (Clem)"="clem", + "E-Housings (Hear)"="hear", + "E-Housings (Hira)"="hira", + "E-Housings (Voor)"="voor", + "E-Housings (Wait)"="wait", + "Gurley Building, downtown"="gurl", + "Hall Hall"="hall", + "McGiffert, Stacwyck Apartments" ="mcgi", + "Nason Hall"="naso", + "North Hall"="nort", + "Nugent Hall"="nuge", + "Polytech Apartments"="polyt", + "Quad (Cald)"="cald", + "Quad (Buck)"="buck", + "Quad (Chur)"="chur", + "Quad (Coop)"="coop", + "Quad (Hunt)"="hunt", + "Quad (IPAC)"="ipac", + "Quad (Macd)"="macd", + "Quad (Pard)"="pard", + "Quad (Roeb)"="roeb", + "Quad (Whit)"="whit", + "Rousseau, Stacwyck Apartments"="rous", + "Sharp Hall"="shar", + "Tech Terrace Apartments"="tech", + "Thompson, Stacwyck Apartments"="thom", + "Williams, Stacwyck Apartments"="will", + "Wiltsie, Stacwyck Apartments"="wilt", + "Warren Hall"="warr") + +otherOffCampus <- list( + "90 College Ave"="coll", + "CCI, North Greenbush"="cci", + "College Ave #92, RPI Ambulance"="ambu", + "DFWI, Lake George"="dfwi", + "Jordan Road #405, Tech Park, CCI"="cci", + "Jordan Road #250, Tech Park"="techp250", + "Jordan Road #350, Tech Park"="techp350", + "Jordan Road #465, Tech Park"="techp465", + "LINAC/NES, Tibbits Ave"="linac", + "Moes, College Ave"="moes", + "Off Campus Commons, 1525 15th St"="offc", + "Old Bumstead Garage, behind Colonie Apts"="bums", + "Pahl House, corner of 15th and Peoples"="pahl", + "Peoples Ave #1002"="peop1002", + "Peoples Ave #1516"="peop1516", + "Peoples Ave #901"="peop901", + "Peoples Ave #907"="peop907", + "President's House"="pres", + "Proctors Building, downtown"="proc", + "Rensselaer at Hartford"="cap0", + "SAE, 12 Myrtle Ave off Pawling Ave"="sael", + "Service Building, Peoples Ave"="servb", + "Walthousen Lab, Schenectady"="sche", + "Watervliet Facility, 805 25th St, Watervliet"="wate") + +otherOnCampus <- list( + "87 Gym"="gym8", + "Academy Hall"="acad", + "Admissions"="admi", + "ASRC"="armo", + "ASRC auto shop"="auto", + "ASRC garage"="garg", + "College Ave #90, EMPAC resident artists" = "empar", + "Commons Dining Hall"="comm", + "East Campus Community Center"="eccc", + "ECAV arena"="ecav", + "ECAV stadium"="ecavs", + "EMPAC"="empa", + "Fitness Center"="fitn", + "H Building"="hbui", + "Heffner Alumni House"="heff", + "Houston Field House"="fiel", + "J Building, Peoples Ave"="jbui", + "RPI Playhouse, 15th St"="play", + "Robison Pool"="robi", + "Russell Sage Dining Hall"="rsdh", + "Visitor Information Center, Public Safety"="vic0", + "WRPI tower, North Greenbush" ="wrpi") + +alltype<-list("academic"=academic,"greek"=greek,"housing"=housing,"otherOffCampus"=otherOffCampus,"otherOnCampus"=otherOnCampus) + + +### campus view ### +#apinfo <- read_csv("~/IDEA-COVID-ContactTracing/wap_data/apinfo.csv", col_types = cols()) +#apinfo <- read_csv("/academics/MATP-4910-F20/IDEA-COVID-ContactTracing/wap_data/apinfo.csv", col_types = cols()) +#colnames(apinfo) <- c("devname", "Building", "Floor", "Room","latitude", "longitude") + +#buildinginfo <- as.data.frame(read_csv("~/IDEA-COVID-ContactTracing/wap_data/allBuildingInfo.csv", col_types=cols())) + +#allinfo <- left_join(apinfo, buildinginfo, by="Building") +#allinfo <- allinfo %>% select(-latitude.x,-longitude.x) +#colnames(allinfo) <- c("devname","Building","Floor","Room","longitude","latitude","buildingType","abbrev") + +#custom color palette +palette <- c("darkred", "red4", "red3", "indianred3", "salmon", "lightskyblue", "steelblue1", "royalblue1", "royalblue4", "navyblue", "midnightblue") +