|
|
source("funs/scraper.R") |
|
|
source("funs/map_helpers.R") |
|
|
source("funs/plot_weather_jma.R") |
|
|
|
|
|
server <- function(input, output, session) { |
|
|
selected_station <- reactiveVal(NULL) |
|
|
station_data <- reactiveVal(NULL) |
|
|
prev_dates <- reactiveVal(NULL) |
|
|
url_initialized <- reactiveVal(FALSE) |
|
|
|
|
|
|
|
|
style_change_trigger <- reactiveVal(0) |
|
|
map_initialized <- reactiveVal(FALSE) |
|
|
stations_before_id <- reactiveVal(NULL) |
|
|
current_raster_layers <- reactiveVal(character(0)) |
|
|
|
|
|
|
|
|
parse_url_params <- function(query_string) { |
|
|
if (is.null(query_string) || query_string == "" || query_string == "?") { |
|
|
return(list()) |
|
|
} |
|
|
|
|
|
qs <- sub("^\\?", "", query_string) |
|
|
if (qs == "") { |
|
|
return(list()) |
|
|
} |
|
|
|
|
|
pairs <- strsplit(qs, "&")[[1]] |
|
|
params <- list() |
|
|
for (pair in pairs) { |
|
|
kv <- strsplit(pair, "=")[[1]] |
|
|
if (length(kv) == 2) { |
|
|
params[[kv[1]]] <- URLdecode(kv[2]) |
|
|
} |
|
|
} |
|
|
params |
|
|
} |
|
|
|
|
|
|
|
|
broadcast_state <- function(view_override = NULL) { |
|
|
st <- selected_station() |
|
|
|
|
|
station_id <- if (!is.null(st) && nrow(st) > 0) as.character(st$ID[[1]]) else NULL |
|
|
station_name <- if (!is.null(st) && nrow(st) > 0) as.character(st$DisplayName[[1]]) else NULL |
|
|
prefecture <- if (!is.null(st) && nrow(st) > 0 && !is.na(st$PrecName[[1]])) as.character(st$PrecName[[1]]) else NULL |
|
|
resolution <- input$data_resolution |
|
|
|
|
|
|
|
|
main_tab <- input$main_nav |
|
|
view <- if (!is.null(view_override)) { |
|
|
view_override |
|
|
} else if (!is.null(main_tab)) { |
|
|
if (main_tab == "Map View") { |
|
|
"map" |
|
|
} else if (main_tab == "Station Info") { |
|
|
"station-info" |
|
|
} else if (main_tab == "Dashboard") { |
|
|
subtab <- input$dashboard_subtabs |
|
|
if (!is.null(subtab) && subtab == "Data") { |
|
|
"dashboard-data" |
|
|
} else { |
|
|
"dashboard-plots" |
|
|
} |
|
|
} else { |
|
|
"map" |
|
|
} |
|
|
} else { |
|
|
"map" |
|
|
} |
|
|
|
|
|
start_date <- if (!is.null(input$date_range)) as.character(input$date_range[1]) else NULL |
|
|
end_date <- if (!is.null(input$date_range)) as.character(input$date_range[2]) else NULL |
|
|
|
|
|
session$sendCustomMessage("updateParentURL", list( |
|
|
station = station_id, |
|
|
stationName = station_name, |
|
|
prefecture = prefecture, |
|
|
resolution = resolution, |
|
|
view = view, |
|
|
start = start_date, |
|
|
end = end_date |
|
|
)) |
|
|
} |
|
|
|
|
|
|
|
|
observe({ |
|
|
req(!url_initialized()) |
|
|
|
|
|
query <- session$clientData$url_search |
|
|
params <- parse_url_params(query) |
|
|
|
|
|
if (length(params) == 0) { |
|
|
url_initialized(TRUE) |
|
|
return() |
|
|
} |
|
|
|
|
|
|
|
|
if (!is.null(params$resolution) && params$resolution %in% c("10 Minutes", "Hourly", "Daily", "Monthly")) { |
|
|
updateRadioButtons(session, "data_resolution", selected = params$resolution) |
|
|
} |
|
|
|
|
|
|
|
|
if (!is.null(params$start) && !is.null(params$end)) { |
|
|
start_date <- tryCatch(as.Date(params$start), error = function(e) NULL) |
|
|
end_date <- tryCatch(as.Date(params$end), error = function(e) NULL) |
|
|
if (!is.null(start_date) && !is.null(end_date)) { |
|
|
updateDateRangeInput(session, "date_range", start = start_date, end = end_date) |
|
|
prev_dates(c(start_date, end_date)) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (!is.null(params$station)) { |
|
|
station_id <- params$station |
|
|
|
|
|
st <- stations %>% |
|
|
filter(ID == station_id | DisplayName == station_id) %>% |
|
|
head(1) |
|
|
if (nrow(st) > 0) { |
|
|
selected_station(st) |
|
|
updateSelectizeInput(session, "station_selector", selected = st$DisplayName) |
|
|
|
|
|
shinyjs::delay(500, { |
|
|
start_download(st) |
|
|
}) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (!is.null(params$view)) { |
|
|
view <- params$view |
|
|
shinyjs::delay(600, { |
|
|
if (view == "map") { |
|
|
session$sendCustomMessage("switchTab", list(tabId = "Map View")) |
|
|
} else if (view == "station-info") { |
|
|
session$sendCustomMessage("switchTab", list(tabId = "Station Info")) |
|
|
} else if (view %in% c("dashboard-plots", "dashboard-data")) { |
|
|
session$sendCustomMessage("switchTab", list(tabId = "Dashboard")) |
|
|
if (view == "dashboard-data") { |
|
|
shinyjs::delay(800, { |
|
|
|
|
|
|
|
|
shinyjs::runjs("$('a[data-value=\"Data\"]').tab('show');") |
|
|
}) |
|
|
} |
|
|
} |
|
|
}) |
|
|
} |
|
|
|
|
|
url_initialized(TRUE) |
|
|
}) |
|
|
|
|
|
|
|
|
generate_label <- function(name, id, type, start, end, vars) { |
|
|
paste0( |
|
|
"<div style='font-size:14px; min-width: 200px;'>", |
|
|
"<b>", htmltools::htmlEscape(name), "</b> (", id, ")<br>", |
|
|
"Type: ", type, "<br>", |
|
|
"Period: ", start, " - ", end, "<br>", |
|
|
"<div style='margin-top:5px; font-size:12px; color:#555;'>", |
|
|
"Vars: ", substring(vars, 1, 50), "...", |
|
|
"</div>", |
|
|
"</div>" |
|
|
) |
|
|
} |
|
|
|
|
|
add_resolution_period <- function(df, resolution) { |
|
|
df %>% |
|
|
mutate( |
|
|
ResolutionStart = case_when( |
|
|
resolution == "Daily" ~ Start_Daily, |
|
|
resolution == "Hourly" ~ Start_Hourly, |
|
|
resolution == "10 Minutes" ~ Start_10min, |
|
|
resolution == "Monthly" ~ Start_Monthly, |
|
|
TRUE ~ NA_real_ |
|
|
), |
|
|
ResolutionEnd = case_when( |
|
|
resolution == "Daily" ~ End_Daily, |
|
|
resolution == "Hourly" ~ End_Hourly, |
|
|
resolution == "10 Minutes" ~ End_10min, |
|
|
resolution == "Monthly" ~ End_Monthly, |
|
|
TRUE ~ NA_real_ |
|
|
) |
|
|
) |
|
|
} |
|
|
|
|
|
get_resolution_period <- function(st, resolution) { |
|
|
start_val <- switch(resolution, |
|
|
"Daily" = st$Start_Daily, |
|
|
"Hourly" = st$Start_Hourly, |
|
|
"10 Minutes" = st$Start_10min, |
|
|
"Monthly" = st$Start_Monthly, |
|
|
NA_real_ |
|
|
) |
|
|
end_val <- switch(resolution, |
|
|
"Daily" = st$End_Daily, |
|
|
"Hourly" = st$End_Hourly, |
|
|
"10 Minutes" = st$End_10min, |
|
|
"Monthly" = st$End_Monthly, |
|
|
NA_real_ |
|
|
) |
|
|
list(start = start_val, end = end_val) |
|
|
} |
|
|
|
|
|
format_period_labels <- function(start, end, current_year = NULL) { |
|
|
start_label <- ifelse(is.na(start), "Unknown", start) |
|
|
if (is.null(current_year)) { |
|
|
end_label <- ifelse(is.na(end), "Present", end) |
|
|
} else { |
|
|
end_label <- ifelse(is.na(end) | end == current_year, "Present", end) |
|
|
} |
|
|
list(start = start_label, end = end_label) |
|
|
} |
|
|
|
|
|
filtered_stations <- reactive({ |
|
|
res <- stations |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!is.null(input$date_range) && !is.null(input$data_resolution)) { |
|
|
start_yr <- as.numeric(format(input$date_range[1], "%Y")) |
|
|
end_yr <- as.numeric(format(input$date_range[2], "%Y")) |
|
|
resolution <- input$data_resolution |
|
|
|
|
|
|
|
|
res <- res %>% |
|
|
add_resolution_period(resolution) %>% |
|
|
|
|
|
filter( |
|
|
!is.na(ResolutionStart) & |
|
|
ResolutionStart <= end_yr & |
|
|
(is.na(ResolutionEnd) | ResolutionEnd >= start_yr) |
|
|
) %>% |
|
|
select(-ResolutionStart, -ResolutionEnd) |
|
|
} |
|
|
|
|
|
res |
|
|
}) |
|
|
|
|
|
|
|
|
output$visible_count <- renderText({ |
|
|
count <- nrow(filtered_stations()) |
|
|
sprintf("Visible Stations: %d", count) |
|
|
}) |
|
|
|
|
|
|
|
|
observe({ |
|
|
|
|
|
|
|
|
|
|
|
df <- filtered_stations() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
updateSelectizeInput(session, "station_selector", |
|
|
choices = c("All", sort(df$DisplayName)), |
|
|
server = TRUE |
|
|
) |
|
|
}) |
|
|
|
|
|
output$map <- renderMaplibre({ |
|
|
maplibre( |
|
|
style = "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json", |
|
|
center = c(138, 36), |
|
|
zoom = 4 |
|
|
) %>% |
|
|
add_navigation_control(show_compass = FALSE, visualize_pitch = FALSE, position = "top-left") |
|
|
}) |
|
|
|
|
|
|
|
|
observe({ |
|
|
req(!map_initialized()) |
|
|
req(input$map_zoom) |
|
|
|
|
|
|
|
|
map_initialized(TRUE) |
|
|
}) |
|
|
|
|
|
|
|
|
observeEvent(input$zoom_home, { |
|
|
df <- filtered_stations() |
|
|
req(df) |
|
|
if (nrow(df) > 0) { |
|
|
|
|
|
lons <- range(df$Lon, na.rm = TRUE) |
|
|
lats <- range(df$Lat, na.rm = TRUE) |
|
|
|
|
|
|
|
|
if (nrow(df) == 1) { |
|
|
maplibre_proxy("map") %>% |
|
|
fly_to(center = c(df$Lon[1], df$Lat[1]), zoom = 12) |
|
|
} else { |
|
|
maplibre_proxy("map") %>% |
|
|
fit_bounds(c(lons[1], lats[1], lons[2], lats[2]), animate = TRUE) |
|
|
} |
|
|
} |
|
|
}) |
|
|
|
|
|
|
|
|
observeEvent(input$main_nav, { |
|
|
if (input$main_nav == "Map View") { |
|
|
|
|
|
shinyjs::runjs(" |
|
|
setTimeout(function() { |
|
|
var map = document.getElementById('map'); |
|
|
if (map && map.__mapgl) { |
|
|
map.__mapgl.resize(); |
|
|
} |
|
|
}, 200); |
|
|
") |
|
|
} |
|
|
}) |
|
|
|
|
|
|
|
|
observeEvent(input$basemap, { |
|
|
proxy <- maplibre_proxy("map") |
|
|
|
|
|
|
|
|
old_layers <- isolate(current_raster_layers()) |
|
|
if (length(old_layers) > 0) { |
|
|
for (layer_id in old_layers) { |
|
|
proxy %>% clear_layer(layer_id) |
|
|
} |
|
|
current_raster_layers(character(0)) |
|
|
} |
|
|
|
|
|
if (input$basemap %in% c("carto_positron", "carto_voyager")) { |
|
|
|
|
|
style_url <- switch(input$basemap, |
|
|
"carto_positron" = "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json", |
|
|
"carto_voyager" = "https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json" |
|
|
) |
|
|
|
|
|
proxy %>% |
|
|
set_style(style_url) |
|
|
|
|
|
|
|
|
stations_before_id("watername_ocean") |
|
|
style_change_trigger(isolate(style_change_trigger()) + 1) |
|
|
} else if (input$basemap == "esri_imagery") { |
|
|
|
|
|
proxy %>% |
|
|
set_style("https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json") |
|
|
|
|
|
stations_before_id("watername_ocean") |
|
|
|
|
|
current_session <- shiny::getDefaultReactiveDomain() |
|
|
selected_basemap <- input$basemap |
|
|
|
|
|
later::later(function() { |
|
|
shiny::withReactiveDomain(current_session, { |
|
|
|
|
|
current_basemap <- isolate(input$basemap) |
|
|
if (current_basemap != selected_basemap) { |
|
|
return() |
|
|
} |
|
|
|
|
|
unique_suffix <- as.numeric(Sys.time()) * 1000 |
|
|
source_id <- paste0("esri_imagery_source_", unique_suffix) |
|
|
layer_id <- paste0("esri_imagery_layer_", unique_suffix) |
|
|
|
|
|
esri_url <- "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}" |
|
|
|
|
|
maplibre_proxy("map") %>% |
|
|
add_raster_source(id = source_id, tiles = c(esri_url), tileSize = 256) %>% |
|
|
add_layer( |
|
|
id = layer_id, |
|
|
type = "raster", |
|
|
source = source_id, |
|
|
paint = list("raster-opacity" = 1), |
|
|
before_id = "watername_ocean" |
|
|
) |
|
|
|
|
|
current_raster_layers(c(layer_id)) |
|
|
style_change_trigger(isolate(style_change_trigger()) + 1) |
|
|
}) |
|
|
}, delay = 0.5) |
|
|
} else { |
|
|
|
|
|
tile_url <- if (input$basemap %in% c("osm", "osm_gray")) { |
|
|
"https://tile.openstreetmap.org/{z}/{x}/{y}.png" |
|
|
} else { |
|
|
"https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}" |
|
|
} |
|
|
|
|
|
attribution_text <- if (input$basemap %in% c("osm", "osm_gray")) { |
|
|
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' |
|
|
} else { |
|
|
"Tiles © Esri" |
|
|
} |
|
|
|
|
|
paint_props <- list("raster-opacity" = 1) |
|
|
if (input$basemap == "osm_gray") { |
|
|
paint_props[["raster-saturation"]] <- -0.9 |
|
|
paint_props[["raster-contrast"]] <- 0.3 |
|
|
} |
|
|
|
|
|
|
|
|
blank_style <- list( |
|
|
version = 8, |
|
|
sources = list(), |
|
|
layers = list(), |
|
|
metadata = list(timestamp = as.numeric(Sys.time())) |
|
|
) |
|
|
json_blank <- jsonlite::toJSON(blank_style, auto_unbox = TRUE) |
|
|
blank_uri <- paste0("data:application/json,", URLencode(as.character(json_blank), reserved = TRUE)) |
|
|
|
|
|
proxy %>% |
|
|
set_style(blank_uri) |
|
|
|
|
|
current_session <- shiny::getDefaultReactiveDomain() |
|
|
selected_basemap <- input$basemap |
|
|
|
|
|
later::later(function() { |
|
|
shiny::withReactiveDomain(current_session, { |
|
|
current_basemap <- isolate(input$basemap) |
|
|
if (current_basemap != selected_basemap) { |
|
|
return() |
|
|
} |
|
|
|
|
|
unique_suffix <- as.numeric(Sys.time()) * 1000 |
|
|
source_id <- paste0("raster_source_", unique_suffix) |
|
|
layer_id <- paste0("raster_layer_", unique_suffix) |
|
|
|
|
|
maplibre_proxy("map") %>% |
|
|
add_raster_source(id = source_id, tiles = c(tile_url), tileSize = 256, attribution = attribution_text) %>% |
|
|
add_layer( |
|
|
id = layer_id, |
|
|
type = "raster", |
|
|
source = source_id, |
|
|
paint = paint_props |
|
|
) |
|
|
|
|
|
stations_before_id(NULL) |
|
|
current_raster_layers(c(layer_id)) |
|
|
style_change_trigger(isolate(style_change_trigger()) + 1) |
|
|
}) |
|
|
}, delay = 0.5) |
|
|
} |
|
|
}) |
|
|
|
|
|
|
|
|
observeEvent(input$show_labels, |
|
|
{ |
|
|
visibility <- if (input$show_labels) "visible" else "none" |
|
|
|
|
|
label_layers <- c( |
|
|
"place_villages", "place_town", "place_country_2", "place_country_1", |
|
|
"place_state", "place_continent", |
|
|
"place_city_r6", "place_city_r5", "place_city_dot_r7", "place_city_dot_r4", |
|
|
"place_city_dot_r2", "place_city_dot_z7", |
|
|
"place_capital_dot_z7", "place_capital", |
|
|
"roadname_minor", "roadname_sec", "roadname_pri", "roadname_major", |
|
|
"motorway_name", |
|
|
"watername_ocean", "watername_sea", "watername_lake", "watername_lake_line", |
|
|
"poi_stadium", "poi_park", "poi_zoo", |
|
|
"airport_label", |
|
|
"country-label", "state-label", "settlement-major-label", "settlement-minor-label", |
|
|
"settlement-subdivision-label", "road-label", "waterway-label", "natural-point-label", |
|
|
"poi-label", "airport-label" |
|
|
) |
|
|
|
|
|
proxy <- maplibre_proxy("map") |
|
|
|
|
|
for (layer_id in label_layers) { |
|
|
tryCatch( |
|
|
{ |
|
|
proxy <- proxy %>% set_layout_property(layer_id, "visibility", visibility) |
|
|
}, |
|
|
error = function(e) { |
|
|
|
|
|
} |
|
|
) |
|
|
} |
|
|
}, |
|
|
ignoreInit = TRUE |
|
|
) |
|
|
|
|
|
|
|
|
observe({ |
|
|
|
|
|
req(map_initialized()) |
|
|
|
|
|
|
|
|
style_change_trigger() |
|
|
|
|
|
|
|
|
current_year <- as.numeric(format(Sys.Date(), "%Y")) |
|
|
resolution <- input$data_resolution |
|
|
|
|
|
|
|
|
data <- filtered_stations() %>% |
|
|
add_resolution_period(resolution) %>% |
|
|
mutate( |
|
|
station_label = DisplayName, |
|
|
station_type_label = ifelse(station_type == "a", "AMeDAS", "Manned station"), |
|
|
period_start_label = ifelse(is.na(ResolutionStart), "Unknown", ResolutionStart), |
|
|
period_end_label = ifelse(is.na(ResolutionEnd) | ResolutionEnd == current_year, "Present", ResolutionEnd), |
|
|
period_label = ifelse(is.na(ResolutionStart), "Unknown", paste0(ResolutionStart, " - ", period_end_label)), |
|
|
hover_content = generate_label(DisplayName, ID, station_type_label, period_start_label, period_end_label, ObservedVariables) |
|
|
) |
|
|
|
|
|
if (nrow(data) > 0) { |
|
|
|
|
|
map_data <- st_as_sf(data, coords = c("Lon", "Lat"), crs = 4326) |
|
|
|
|
|
maplibre_proxy("map") %>% |
|
|
clear_layer("stations") %>% |
|
|
add_circle_layer( |
|
|
id = "stations", |
|
|
source = map_data, |
|
|
circle_color = "navy", |
|
|
circle_radius = 6, |
|
|
circle_stroke_color = "#00000000", |
|
|
circle_stroke_width = 0, |
|
|
circle_opacity = 0.7, |
|
|
tooltip = "hover_content", |
|
|
before_id = stations_before_id() |
|
|
) |
|
|
} else { |
|
|
maplibre_proxy("map") %>% clear_layer("stations") |
|
|
} |
|
|
|
|
|
|
|
|
st <- isolate(selected_station()) |
|
|
if (!is.null(st)) { |
|
|
|
|
|
period <- get_resolution_period(st, resolution) |
|
|
period_labels <- format_period_labels(period$start, period$end, current_year) |
|
|
lbl <- generate_label( |
|
|
st$DisplayName, st$ID, |
|
|
ifelse(st$station_type == "a", "AMeDAS", "Manned station"), |
|
|
period_labels$start, period_labels$end, |
|
|
st$ObservedVariables |
|
|
) |
|
|
highlight_selected_station(maplibre_proxy("map"), st$Lon, st$Lat, lbl) |
|
|
} |
|
|
}) |
|
|
|
|
|
|
|
|
observeEvent(input$map_feature_click, { |
|
|
click <- input$map_feature_click |
|
|
|
|
|
|
|
|
if (!is.null(click) && (isTRUE(click$layer_id == "stations") || isTRUE(click$layer == "stations"))) { |
|
|
|
|
|
props <- click$properties |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
id_val <- props$ID |
|
|
|
|
|
if (!is.null(id_val)) { |
|
|
|
|
|
closest <- stations %>% |
|
|
filter(ID == id_val) %>% |
|
|
head(1) |
|
|
|
|
|
selected_station(closest) |
|
|
|
|
|
|
|
|
current_year <- as.numeric(format(Sys.Date(), "%Y")) |
|
|
period <- get_resolution_period(closest, input$data_resolution) |
|
|
period_labels <- format_period_labels(period$start, period$end, current_year = current_year) |
|
|
lbl <- generate_label( |
|
|
closest$DisplayName, closest$ID, |
|
|
ifelse(closest$station_type == "a", "AMeDAS", "Manned station"), |
|
|
period_labels$start, period_labels$end, |
|
|
closest$ObservedVariables |
|
|
) |
|
|
highlight_selected_station(maplibre_proxy("map"), closest$Lon, closest$Lat, lbl) |
|
|
|
|
|
|
|
|
updateSelectizeInput(session, "station_selector", selected = closest$DisplayName) |
|
|
|
|
|
|
|
|
start_download(closest) |
|
|
|
|
|
|
|
|
broadcast_state() |
|
|
} |
|
|
} |
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
check_and_limit_dates <- function(start, end, resolution, anchor = "end") { |
|
|
limit_days <- Inf |
|
|
limit_msg <- "" |
|
|
|
|
|
if (resolution %in% c("Hourly", "10 Minutes")) { |
|
|
limit_days <- 93 |
|
|
limit_msg <- "3 months" |
|
|
} else if (resolution == "Daily") { |
|
|
limit_days <- 366 |
|
|
limit_msg <- "1 year" |
|
|
} else if (resolution == "Monthly") { |
|
|
limit_days <- 1826 |
|
|
limit_msg <- "5 years" |
|
|
} |
|
|
|
|
|
diff <- as.numeric(end - start) |
|
|
if (diff > limit_days) { |
|
|
new_start <- start |
|
|
new_end <- end |
|
|
|
|
|
if (anchor == "start") { |
|
|
|
|
|
new_end <- start + limit_days |
|
|
} else { |
|
|
|
|
|
new_start <- end - limit_days |
|
|
} |
|
|
return(list(start = new_start, end = new_end, limited = TRUE, msg = limit_msg)) |
|
|
} |
|
|
return(list(start = start, end = end, limited = FALSE)) |
|
|
} |
|
|
|
|
|
|
|
|
observeEvent(input$data_resolution, { |
|
|
st <- selected_station() |
|
|
req(st) |
|
|
req(input$date_range) |
|
|
|
|
|
start <- as.Date(input$date_range[1]) |
|
|
end <- as.Date(input$date_range[2]) |
|
|
|
|
|
|
|
|
res_val <- input$data_resolution |
|
|
|
|
|
if (res_val == "Monthly") { |
|
|
|
|
|
new_start <- end - 365 * 3 |
|
|
res <- list(start = new_start, end = end, limited = TRUE, msg = "3 years") |
|
|
} else { |
|
|
res <- check_and_limit_dates(start, end, res_val, anchor = "end") |
|
|
} |
|
|
|
|
|
if (res$limited) { |
|
|
updateDateRangeInput(session, "date_range", start = res$start, end = res$end) |
|
|
showNotification(paste0("Range adjusted to ", res$msg, " for ", input$data_resolution, " resolution."), type = "warning") |
|
|
|
|
|
prev_dates(c(res$start, res$end)) |
|
|
} |
|
|
|
|
|
|
|
|
start_download(st, override_start = res$start, override_end = res$end) |
|
|
}) |
|
|
|
|
|
|
|
|
observeEvent(input$date_range, { |
|
|
st <- selected_station() |
|
|
req(input$date_range) |
|
|
|
|
|
current_dates <- input$date_range |
|
|
current_start <- as.Date(current_dates[1]) |
|
|
current_end <- as.Date(current_dates[2]) |
|
|
|
|
|
last_dates <- prev_dates() |
|
|
|
|
|
|
|
|
anchor <- "end" |
|
|
|
|
|
if (!is.null(last_dates)) { |
|
|
last_start <- as.Date(last_dates[1]) |
|
|
last_end <- as.Date(last_dates[2]) |
|
|
|
|
|
|
|
|
if (current_start != last_start) { |
|
|
anchor <- "start" |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
res <- check_and_limit_dates(current_start, current_end, input$data_resolution, anchor = anchor) |
|
|
|
|
|
if (res$limited) { |
|
|
|
|
|
updateDateRangeInput(session, "date_range", start = res$start, end = res$end) |
|
|
showNotification(paste0("Limit exceeded. Adjusted to ", res$msg, "."), type = "warning") |
|
|
prev_dates(c(res$start, res$end)) |
|
|
|
|
|
|
|
|
if (!is.null(st)) { |
|
|
start_download(st, override_start = res$start, override_end = res$end) |
|
|
} |
|
|
} else { |
|
|
|
|
|
prev_dates(current_dates) |
|
|
|
|
|
if (!is.null(st)) { |
|
|
|
|
|
if (tab_down_trigger_check(current_dates, last_dates)) { |
|
|
start_download(st, override_start = current_start, override_end = current_end) |
|
|
} |
|
|
} |
|
|
} |
|
|
}) |
|
|
|
|
|
|
|
|
tab_down_trigger_check <- function(curr, last) { |
|
|
if (is.null(last)) { |
|
|
return(TRUE) |
|
|
} |
|
|
if (curr[1] != last[1] || curr[2] != last[2]) { |
|
|
return(TRUE) |
|
|
} |
|
|
return(FALSE) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fetch_stage <- reactiveVal(0) |
|
|
fetch_queue <- reactiveVal(list()) |
|
|
fetch_queue_idx <- reactiveVal(0) |
|
|
parsed_data_list <- reactiveVal(list()) |
|
|
fetch_current_token <- reactiveVal(NULL) |
|
|
final_data_path <- reactiveVal(NULL) |
|
|
|
|
|
reset_fetch <- function() { |
|
|
fetch_stage(0) |
|
|
fetch_current_token(as.numeric(Sys.time())) |
|
|
|
|
|
session$sendCustomMessage("unfreezeUI", list()) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
observeEvent(input$cancel_loading, { |
|
|
reset_fetch() |
|
|
showNotification("Loading cancelled by user.", type = "warning") |
|
|
}) |
|
|
|
|
|
start_download <- function(st, override_start = NULL, override_end = NULL) { |
|
|
req(input$date_range) |
|
|
|
|
|
|
|
|
station_data(NULL) |
|
|
|
|
|
if (!is.null(override_start)) { |
|
|
start_date <- as.Date(override_start) |
|
|
} else { |
|
|
start_date <- as.Date(input$date_range[1]) |
|
|
} |
|
|
|
|
|
if (!is.null(override_end)) { |
|
|
end_date <- as.Date(override_end) |
|
|
} else { |
|
|
end_date <- as.Date(input$date_range[2]) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
msg <- paste0("Initializing fetch for ", st$DisplayName, "...") |
|
|
session$sendCustomMessage("freezeUI", list(text = msg, station = st$DisplayName)) |
|
|
|
|
|
|
|
|
resolution <- input$data_resolution |
|
|
|
|
|
if (resolution %in% c("Daily", "Monthly")) { |
|
|
|
|
|
seq_start <- as.Date(format(start_date, format = "%Y-%m-01")) |
|
|
seq_end <- as.Date(format(end_date, format = "%Y-%m-01")) |
|
|
|
|
|
|
|
|
current_month_start <- as.Date(format(Sys.Date(), "%Y-%m-01")) |
|
|
if (seq_end > current_month_start) { |
|
|
seq_end <- current_month_start |
|
|
} |
|
|
|
|
|
dates <- seq(seq_start, seq_end, by = "month") |
|
|
|
|
|
if (length(dates) == 0) { |
|
|
showNotification("Invalid date range.", type = "error") |
|
|
reset_fetch() |
|
|
return() |
|
|
} |
|
|
|
|
|
|
|
|
q <- list() |
|
|
for (i in seq_along(dates)) { |
|
|
d <- dates[i] |
|
|
yr <- as.numeric(format(d, format = "%Y")) |
|
|
mo <- as.numeric(format(d, format = "%m")) |
|
|
q[[length(q) + 1]] <- list(year = yr, month = mo, day = NULL) |
|
|
} |
|
|
} else { |
|
|
|
|
|
|
|
|
today <- Sys.Date() |
|
|
if (end_date > today) { |
|
|
end_date <- today |
|
|
} |
|
|
|
|
|
dates <- seq(start_date, end_date, by = "day") |
|
|
|
|
|
if (length(dates) == 0) { |
|
|
showNotification("Invalid date range.", type = "error") |
|
|
reset_fetch() |
|
|
return() |
|
|
} |
|
|
|
|
|
|
|
|
q <- list() |
|
|
for (i in seq_along(dates)) { |
|
|
d <- as.Date(dates[i], origin = "1970-01-01") |
|
|
yr <- as.numeric(format(d, format = "%Y")) |
|
|
mo <- as.numeric(format(d, format = "%m")) |
|
|
dy <- as.numeric(format(d, format = "%d")) |
|
|
q[[length(q) + 1]] <- list(year = yr, month = mo, day = dy) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
fetch_queue(q) |
|
|
fetch_queue_idx(1) |
|
|
parsed_data_list(list()) |
|
|
fetch_current_token(as.numeric(Sys.time())) |
|
|
|
|
|
fetch_stage(2) |
|
|
} |
|
|
|
|
|
|
|
|
observe({ |
|
|
req(fetch_stage() == 2) |
|
|
idx <- fetch_queue_idx() |
|
|
q <- fetch_queue() |
|
|
|
|
|
if (idx > length(q)) { |
|
|
fetch_stage(6) |
|
|
} else { |
|
|
|
|
|
item <- q[[idx]] |
|
|
if (is.null(item$day)) { |
|
|
msg <- paste0( |
|
|
"Fetching data for ", item$year, "-", sprintf("%02d", item$month), |
|
|
" (", idx, "/", length(q), ")..." |
|
|
) |
|
|
} else { |
|
|
msg <- paste0( |
|
|
"Fetching data for ", item$year, "-", sprintf("%02d", item$month), "-", sprintf("%02d", item$day), |
|
|
" (", idx, "/", length(q), ")..." |
|
|
) |
|
|
} |
|
|
session$sendCustomMessage("freezeUI", list(text = msg)) |
|
|
fetch_stage(4) |
|
|
} |
|
|
}) |
|
|
|
|
|
|
|
|
observe({ |
|
|
req(fetch_stage() == 4) |
|
|
token <- fetch_current_token() |
|
|
|
|
|
later::later(function() { |
|
|
if (!identical(isolate(fetch_current_token()), token)) { |
|
|
return() |
|
|
} |
|
|
|
|
|
isolate({ |
|
|
idx <- fetch_queue_idx() |
|
|
q <- fetch_queue() |
|
|
item <- q[[idx]] |
|
|
st <- selected_station() |
|
|
|
|
|
|
|
|
df <- tryCatch( |
|
|
get_jma_data( |
|
|
block_no = st$ID, |
|
|
year = item$year, |
|
|
month = item$month, |
|
|
day = item$day, |
|
|
prec_no = st$prec_no, |
|
|
type = paste0(st$station_type, "1"), |
|
|
resolution = input$data_resolution |
|
|
), |
|
|
error = function(e) NULL |
|
|
) |
|
|
|
|
|
if (!is.null(df)) { |
|
|
if ("Day" %in% names(df)) { |
|
|
df <- df %>% |
|
|
mutate(Date = as.Date(sprintf("%04d-%02d-%02d", Year, Month, Day))) |
|
|
} |
|
|
plist <- parsed_data_list() |
|
|
plist[[length(plist) + 1]] <- df |
|
|
parsed_data_list(plist) |
|
|
} |
|
|
|
|
|
fetch_queue_idx(idx + 1) |
|
|
fetch_stage(2) |
|
|
}) |
|
|
}, 0.5) |
|
|
fetch_stage(-1) |
|
|
}) |
|
|
|
|
|
|
|
|
observe({ |
|
|
req(fetch_stage() == 6) |
|
|
token <- fetch_current_token() |
|
|
msg <- "Merging data..." |
|
|
session$sendCustomMessage("freezeUI", list(text = msg)) |
|
|
|
|
|
later::later(function() { |
|
|
if (!identical(isolate(fetch_current_token()), token)) { |
|
|
return() |
|
|
} |
|
|
|
|
|
isolate({ |
|
|
plist <- parsed_data_list() |
|
|
|
|
|
if (length(plist) == 0) { |
|
|
showNotification("No data found for the selected range.", type = "warning", session = session) |
|
|
reset_fetch() |
|
|
return() |
|
|
} |
|
|
|
|
|
|
|
|
final_df <- bind_rows(plist) |
|
|
|
|
|
|
|
|
start_date <- input$date_range[1] |
|
|
end_date <- input$date_range[2] |
|
|
|
|
|
if ("Date" %in% names(final_df)) { |
|
|
final_df <- final_df %>% |
|
|
filter(Date >= start_date & Date <= end_date) %>% |
|
|
select(-Date) |
|
|
} |
|
|
|
|
|
if (nrow(final_df) == 0) { |
|
|
showNotification("No data in exact range.", type = "warning", session = session) |
|
|
reset_fetch() |
|
|
return() |
|
|
} |
|
|
|
|
|
|
|
|
tmp <- tempfile(fileext = ".xlsx") |
|
|
write_xlsx(final_df, path = tmp) |
|
|
final_data_path(tmp) |
|
|
|
|
|
|
|
|
station_data(final_df) |
|
|
|
|
|
|
|
|
reset_fetch() |
|
|
|
|
|
|
|
|
if (is.null(input$main_nav) || input$main_nav != "Dashboard") { |
|
|
session$sendCustomMessage("switchTab", list(tabId = "Dashboard")) |
|
|
} |
|
|
showNotification(paste("Successfully loaded", nrow(final_df), "rows."), type = "message", session = session) |
|
|
}) |
|
|
}, 0.1) |
|
|
fetch_stage(-1) |
|
|
}) |
|
|
|
|
|
|
|
|
output$station_ready <- reactive({ |
|
|
!is.null(station_data()) |
|
|
}) |
|
|
outputOptions(output, "station_ready", suspendWhenHidden = FALSE) |
|
|
|
|
|
|
|
|
output$station_info_header <- renderUI({ |
|
|
st <- selected_station() |
|
|
if (is.null(st)) { |
|
|
return(NULL) |
|
|
} |
|
|
|
|
|
|
|
|
res_label <- input$data_resolution |
|
|
res_class <- if (res_label == "Hourly") "bg-primary" else "bg-success" |
|
|
|
|
|
|
|
|
df <- station_data() |
|
|
if (is.null(df) || nrow(df) == 0) { |
|
|
dates_text <- "No data loaded" |
|
|
} else { |
|
|
|
|
|
if ("Date" %in% names(df)) { |
|
|
d_range <- range(df$Date, na.rm = TRUE) |
|
|
dates_text <- paste(d_range[1], "to", d_range[2]) |
|
|
} else if ("Year" %in% names(df) && "Month" %in% names(df) && "Day" %in% names(df)) { |
|
|
|
|
|
|
|
|
start_d <- as.Date(paste(df$Year[1], df$Month[1], df$Day[1], sep = "-")) |
|
|
n <- nrow(df) |
|
|
end_d <- as.Date(paste(df$Year[n], df$Month[n], df$Day[n], sep = "-")) |
|
|
dates_text <- paste(start_d, "to", end_d) |
|
|
} else { |
|
|
dates_text <- "Loaded" |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
card( |
|
|
style = "margin-bottom: 20px; border-left: 5px solid #007bff;", |
|
|
card_body( |
|
|
padding = 15, |
|
|
layout_columns( |
|
|
fill = FALSE, |
|
|
|
|
|
div( |
|
|
strong("Station"), br(), |
|
|
span(st$DisplayName, style = "font-size: 1.1rem;"), br(), |
|
|
tags$small(class = "text-muted", paste("ID:", st$ID)) |
|
|
), |
|
|
|
|
|
div( |
|
|
strong("Location"), br(), |
|
|
span(paste0(st$Lat, "°N, ", st$Lon, "°E")), br(), |
|
|
tags$small(class = "text-muted", st$PrecLabel) |
|
|
), |
|
|
|
|
|
div( |
|
|
strong("Technical"), br(), |
|
|
span(paste0(st$Elevation, " m")), br(), |
|
|
span(class = paste("badge", res_class), res_label) |
|
|
), |
|
|
|
|
|
div( |
|
|
strong("Data Selection"), br(), |
|
|
span(dates_text) |
|
|
), |
|
|
|
|
|
div( |
|
|
class = "d-flex align-items-center justify-content-end", |
|
|
downloadButton( |
|
|
"downloadData", |
|
|
label = "Export Excel", |
|
|
class = "btn-sm btn-primary", |
|
|
icon = icon("file-excel") |
|
|
) |
|
|
) |
|
|
) |
|
|
) |
|
|
) |
|
|
}) |
|
|
|
|
|
|
|
|
output$downloadData <- downloadHandler( |
|
|
filename = function() { |
|
|
req(selected_station()) |
|
|
st <- selected_station() |
|
|
res <- if (!is.null(input$data_resolution)) tolower(input$data_resolution) else "data" |
|
|
sprintf("jma_%s_%s_%s.xlsx", st$ID, res, format(Sys.Date(), "%Y%m%d")) |
|
|
}, |
|
|
content = function(file) { |
|
|
req(final_data_path()) |
|
|
file.copy(final_data_path(), file) |
|
|
} |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
output$jma_plots_container <- renderUI({ |
|
|
df <- station_data() |
|
|
req(df) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plot_list <- tagList() |
|
|
|
|
|
|
|
|
has_temp <- any(c("Temperature", "Temp_Mean", "Temp_Max", "Temp_Min") %in% names(df) & !all(is.na(df[[if ("Temperature" %in% names(df)) "Temperature" else "Temp_Mean"]]))) |
|
|
if (has_temp) { |
|
|
plot_list <- tagList(plot_list, div(class = "col-12 col-lg-6", plotlyOutput("plot_temp", height = "350px"))) |
|
|
} |
|
|
|
|
|
|
|
|
if ("Precipitation" %in% names(df) && !all(is.na(df$Precipitation))) { |
|
|
plot_list <- tagList(plot_list, div(class = "col-12 col-lg-6", plotlyOutput("plot_precip", height = "300px"))) |
|
|
} |
|
|
|
|
|
|
|
|
if ("Wind_Speed" %in% names(df) && !all(is.na(df$Wind_Speed))) { |
|
|
plot_list <- tagList(plot_list, div(class = "col-12 col-lg-6", plotlyOutput("plot_wind", height = "350px"))) |
|
|
} |
|
|
|
|
|
|
|
|
if ("Humidity" %in% names(df) && !all(is.na(df$Humidity))) { |
|
|
plot_list <- tagList(plot_list, div(class = "col-12 col-lg-6", plotlyOutput("plot_humidity", height = "350px"))) |
|
|
} |
|
|
|
|
|
|
|
|
if ("Pressure" %in% names(df) && !all(is.na(df$Pressure))) { |
|
|
plot_list <- tagList(plot_list, div(class = "col-12 col-lg-6", plotlyOutput("plot_pressure", height = "300px"))) |
|
|
} |
|
|
|
|
|
|
|
|
has_sun <- any(c("Sunshine_Hours", "Sunshine_Minutes") %in% names(df) & !all(is.na(df[[if ("Sunshine_Hours" %in% names(df)) "Sunshine_Hours" else "Sunshine_Minutes"]]))) |
|
|
if (has_sun) { |
|
|
plot_list <- tagList(plot_list, div(class = "col-12 col-lg-6", plotlyOutput("plot_sunshine", height = "300px"))) |
|
|
} |
|
|
|
|
|
|
|
|
if ("Solar_Radiation" %in% names(df) && !all(is.na(df$Solar_Radiation))) { |
|
|
plot_list <- tagList(plot_list, div(class = "col-12 col-lg-6", plotlyOutput("plot_solar", height = "300px"))) |
|
|
} |
|
|
|
|
|
|
|
|
has_snow <- any(c("Snow_Depth", "Snowfall") %in% names(df) & !all(is.na(df[[if ("Snow_Depth" %in% names(df)) "Snow_Depth" else "Snowfall"]]))) |
|
|
if (has_snow) { |
|
|
plot_list <- tagList(plot_list, div(class = "col-12 col-lg-6", plotlyOutput("plot_snow", height = "300px"))) |
|
|
} |
|
|
|
|
|
if (length(plot_list) == 0) { |
|
|
return(div(class = "alert alert-warning", "No plottable weather data found for this period.")) |
|
|
} |
|
|
|
|
|
|
|
|
div( |
|
|
class = "row g-3", |
|
|
style = "padding: 10px;", |
|
|
plot_list |
|
|
) |
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get_plot_df <- reactive({ |
|
|
df <- station_data() |
|
|
req(df) |
|
|
res <- input$data_resolution |
|
|
|
|
|
if (res == "Monthly") { |
|
|
df$DateTime <- as.Date(paste(df$Year, df$Month, "01", sep = "-")) |
|
|
} else if (res == "Daily") { |
|
|
df$DateTime <- as.Date(paste(df$Year, df$Month, df$Day, sep = "-")) |
|
|
} else if (res == "Hourly") { |
|
|
df$DateTime <- as.POSIXct(paste0(df$Year, "-", df$Month, "-", df$Day, " ", df$Hour, ":00"), format = "%Y-%m-%d %H:%M") |
|
|
} else { |
|
|
df$DateTime <- as.POSIXct(paste0(df$Year, "-", df$Month, "-", df$Day, " ", df$Time), format = "%Y-%m-%d %H:%M") |
|
|
} |
|
|
df |
|
|
}) |
|
|
|
|
|
output$plot_temp <- renderPlotly({ |
|
|
df <- get_plot_df() |
|
|
create_temperature_plot_jma(df, input$data_resolution) |
|
|
}) |
|
|
|
|
|
output$plot_precip <- renderPlotly({ |
|
|
df <- get_plot_df() |
|
|
create_precipitation_plot_jma(df, input$data_resolution) |
|
|
}) |
|
|
|
|
|
output$plot_wind <- renderPlotly({ |
|
|
df <- get_plot_df() |
|
|
resolution <- input$data_resolution |
|
|
if (resolution == "Hourly") { |
|
|
create_wind_rose_jma(df, resolution) |
|
|
} else { |
|
|
create_wind_plot_jma(df, resolution) |
|
|
} |
|
|
}) |
|
|
|
|
|
output$plot_humidity <- renderPlotly({ |
|
|
df <- get_plot_df() |
|
|
create_humidity_plot_jma(df, input$data_resolution) |
|
|
}) |
|
|
|
|
|
output$plot_pressure <- renderPlotly({ |
|
|
df <- get_plot_df() |
|
|
create_pressure_plot_jma(df, input$data_resolution) |
|
|
}) |
|
|
|
|
|
output$plot_sunshine <- renderPlotly({ |
|
|
df <- get_plot_df() |
|
|
create_sunshine_plot_jma(df, input$data_resolution) |
|
|
}) |
|
|
|
|
|
output$plot_solar <- renderPlotly({ |
|
|
df <- get_plot_df() |
|
|
create_solar_plot_jma(df, input$data_resolution) |
|
|
}) |
|
|
|
|
|
output$plot_snow <- renderPlotly({ |
|
|
df <- get_plot_df() |
|
|
create_snow_plot_jma(df, input$data_resolution) |
|
|
}) |
|
|
|
|
|
|
|
|
output$daily_data <- DT::renderDataTable({ |
|
|
req(station_data()) |
|
|
df <- station_data() |
|
|
|
|
|
|
|
|
col_map <- c( |
|
|
"Year" = "Year", |
|
|
"Month" = "Month", |
|
|
"Day" = "Day", |
|
|
"Hour" = "Hour", |
|
|
"Time" = "Time", |
|
|
"Pressure" = "Pressure [hPa]", |
|
|
"Pressure_Sea_Level" = "Sea Level Pressure [hPa]", |
|
|
"Precipitation" = "Precipitation [mm]", |
|
|
"Precipitation_Max_1h" = "Max 1h Precipitation [mm]", |
|
|
"Precipitation_Max_10min" = "Max 10m Precipitation [mm]", |
|
|
"Temp_Mean" = "Mean Temperature [°C]", |
|
|
"Temp_Max" = "Max Temperature [°C]", |
|
|
"Temp_Min" = "Min Temperature [°C]", |
|
|
"Temperature" = "Temperature [°C]", |
|
|
"Humidity" = "Humidity [%]", |
|
|
"Humidity_Min" = "Min Humidity [%]", |
|
|
"Wind_Speed" = "Wind Speed [m/s]", |
|
|
"Wind_Speed_Max" = "Max Wind Speed [m/s]", |
|
|
"Wind_Gust_Speed" = "Max Gust Speed [m/s]", |
|
|
"Wind_Direction" = "Wind Direction", |
|
|
"Wind_Direction_Deg" = "Wind Direction [Deg]", |
|
|
"Sunshine_Hours" = "Sunshine Duration [h]", |
|
|
"Sunshine_Minutes" = "Sunshine Duration [min]", |
|
|
"Solar_Radiation" = "Solar Radiation [MJ/m²]", |
|
|
"Snowfall" = "Snowfall [cm]", |
|
|
"Snow_Depth" = "Snow Depth [cm]", |
|
|
"Snow_Days" = "Snow Days", |
|
|
"Fog_Days" = "Fog Days", |
|
|
"Thunder_Days" = "Thunder Days", |
|
|
"Dew_Point" = "Dew Point [°C]", |
|
|
"Vapor_Pressure" = "Vapor Pressure [hPa]", |
|
|
"Cloud_Cover" = "Cloud Cover [1/10]", |
|
|
"Visibility" = "Visibility [km]" |
|
|
) |
|
|
|
|
|
|
|
|
current_names <- names(df) |
|
|
for (i in seq_along(current_names)) { |
|
|
cn <- current_names[i] |
|
|
if (cn %in% names(col_map)) { |
|
|
current_names[i] <- col_map[[cn]] |
|
|
} |
|
|
} |
|
|
names(df) <- current_names |
|
|
|
|
|
DT::datatable(df, options = list(pageLength = 15, scrollX = TRUE)) |
|
|
}) |
|
|
|
|
|
|
|
|
observeEvent(input$station_selector, { |
|
|
if (input$station_selector != "All") { |
|
|
closest <- stations %>% |
|
|
filter(DisplayName == input$station_selector) %>% |
|
|
head(1) |
|
|
if (nrow(closest) > 0) { |
|
|
selected_station(closest) |
|
|
|
|
|
|
|
|
period <- get_resolution_period(closest, input$data_resolution) |
|
|
period_labels <- format_period_labels(period$start, period$end, current_year = as.numeric(format(Sys.Date(), "%Y"))) |
|
|
lbl <- generate_label( |
|
|
closest$DisplayName, closest$ID, |
|
|
ifelse(closest$station_type == "a", "AMeDAS", "Manned station"), |
|
|
period_labels$start, period_labels$end, |
|
|
closest$ObservedVariables |
|
|
) |
|
|
highlight_selected_station(maplibre_proxy("map"), closest$Lon, closest$Lat, lbl) |
|
|
|
|
|
|
|
|
start_download(closest) |
|
|
} |
|
|
} |
|
|
}) |
|
|
|
|
|
|
|
|
output$station_info_table <- DT::renderDataTable({ |
|
|
df <- filtered_stations() |
|
|
req(df) |
|
|
|
|
|
|
|
|
res <- input$data_resolution |
|
|
|
|
|
|
|
|
start_col <- switch(res, |
|
|
"Daily" = "Start_Daily", |
|
|
"Hourly" = "Start_Hourly", |
|
|
"10 Minutes" = "Start_10min", |
|
|
"Monthly" = "Start_Monthly" |
|
|
) |
|
|
end_col <- switch(res, |
|
|
"Daily" = "End_Daily", |
|
|
"Hourly" = "End_Hourly", |
|
|
"10 Minutes" = "End_10min", |
|
|
"Monthly" = "End_Monthly" |
|
|
) |
|
|
|
|
|
df_display <- df %>% |
|
|
select( |
|
|
ID, |
|
|
Name = DisplayName, |
|
|
Prefecture = PrecLabel, |
|
|
Lat, |
|
|
Lon, |
|
|
Elevation, |
|
|
Variables = ObservedVariables, |
|
|
!!sym(start_col), |
|
|
!!sym(end_col) |
|
|
) |
|
|
|
|
|
DT::datatable(df_display, |
|
|
selection = "none", |
|
|
rownames = FALSE, |
|
|
callback = DT::JS(" |
|
|
table.on('dblclick', 'tr', function() { |
|
|
var rowData = table.row(this).data(); |
|
|
if (rowData !== undefined && rowData !== null) { |
|
|
var stationId = rowData[0]; |
|
|
Shiny.setInputValue('station_info_table_dblclick', stationId, {priority: 'event'}); |
|
|
} |
|
|
}); |
|
|
"), |
|
|
options = list( |
|
|
pageLength = 20, |
|
|
scrollX = TRUE, |
|
|
searching = TRUE |
|
|
) |
|
|
) |
|
|
}) |
|
|
|
|
|
|
|
|
observeEvent(input$station_info_table_dblclick, { |
|
|
id_val <- input$station_info_table_dblclick |
|
|
req(id_val) |
|
|
|
|
|
closest <- stations %>% |
|
|
filter(ID == id_val) %>% |
|
|
head(1) |
|
|
|
|
|
req(nrow(closest) > 0) |
|
|
|
|
|
selected_station(closest) |
|
|
|
|
|
|
|
|
period <- get_resolution_period(closest, input$data_resolution) |
|
|
period_labels <- format_period_labels(period$start, period$end, current_year = as.numeric(format(Sys.Date(), "%Y"))) |
|
|
lbl <- generate_label( |
|
|
closest$DisplayName, closest$ID, |
|
|
ifelse(closest$station_type == "a", "AMeDAS", "Manned station"), |
|
|
period_labels$start, period_labels$end, |
|
|
closest$ObservedVariables |
|
|
) |
|
|
highlight_selected_station(maplibre_proxy("map"), closest$Lon, closest$Lat, lbl) |
|
|
|
|
|
|
|
|
start_download(closest) |
|
|
|
|
|
|
|
|
broadcast_state() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
observeEvent(input$main_nav, |
|
|
{ |
|
|
req(url_initialized()) |
|
|
broadcast_state() |
|
|
}, |
|
|
ignoreInit = TRUE |
|
|
) |
|
|
|
|
|
|
|
|
observeEvent(input$dashboard_subtabs, |
|
|
{ |
|
|
req(url_initialized()) |
|
|
broadcast_state() |
|
|
}, |
|
|
ignoreInit = TRUE |
|
|
) |
|
|
|
|
|
|
|
|
observeEvent(input$data_resolution, |
|
|
{ |
|
|
req(url_initialized()) |
|
|
broadcast_state() |
|
|
}, |
|
|
ignoreInit = TRUE |
|
|
) |
|
|
|
|
|
|
|
|
observeEvent(input$date_range, |
|
|
{ |
|
|
req(url_initialized()) |
|
|
broadcast_state() |
|
|
}, |
|
|
ignoreInit = TRUE |
|
|
) |
|
|
} |
|
|
|