# plumber.R #* Echo back the input #* @get / function() { message("---- hello world triggered ----") list(msg = paste0("Hello, World!")) } #* Echo back the input #* @get /iris function() { message("---- call iris data ----") list(data = janitor::clean_names(head(iris))) } #* Echo back the input #* @param msg The message to echo #* @get /echo function(msg="") { message("---- echo ----") list(msg = paste0("The message is: '", msg, "'")) } #* Return the sum of two numbers #* @param a The first number to add #* @param b The second number to add #* @post /sum function(a, b) { message("---- sum two number ----") as.numeric(a) + as.numeric(b) } #* Growth Calculation #* #* @serializer unboxedJSON #* @post /growth-calculation function(req) { # data, # init_size = 0.01, # max_doc = 120, # method = "gm" message("---- call growth function ----") data_from_user <- req$body data <- data_from_user$data init_size <- data_from_user$init_size max_doc <- data_from_user$max_doc method <- data_from_user$model_method # set maximum doc doc_vec <- 1:max_doc if (method == "gm") { print("use gm") model_res <-nls( mbw ~ asymptotic_growth*(1-(1-(init_size/asymptotic_growth)^(1/allometric_scale))*exp(-growth_rate*doc))^allometric_scale, data = data, start = list( asymptotic_growth = 40, allometric_scale = 3, growth_rate = 0.015 ) ) pred_res <- predict( model_res, list( doc = doc_vec ) ) tibble( doc = doc_vec, mbw = round(pred_res,3) ) -> growth_res } else if(method == "interp_abw") { min_doc <- min(data$doc) max_doc <- max(data$doc) growth_res <- data.frame( with(data, approx(doc, mbw, xout = seq(min_doc, max_doc, by = 1), method = "linear") ) ) %>% rename(doc = x, mbw = y) } else { initial_weight <- init_size final_doc <- max_doc adg_data <- data abw_container <- list() for (indeks in 1:nrow(adg_data)) { if (indeks == 1) { abw_container[[indeks]] <- c(initial_weight, initial_weight + cumsum(rep(adg_data$adg[indeks], adg_data$doc[indeks + 1] - adg_data$doc[indeks] - 1))) } else if(indeks == nrow(adg_data)) { initial_weight <- max(abw_container[[indeks-1]]) abw_container[[indeks]] <- c(initial_weight + cumsum(rep(adg_data$adg[indeks], final_doc - adg_data$doc[indeks] + 1))) } else { initial_weight <- max(abw_container[[indeks-1]]) abw_container[[indeks]] <- c(initial_weight + cumsum(rep(adg_data$adg[indeks], adg_data$doc[indeks + 1] - adg_data$doc[indeks]))) } } mbw_ <- unlist(abw_container) tibble( doc = 1:final_doc, mbw = mbw_ ) -> growth_res } return(growth_res) } #* One Cycle Feeding Generator #* @serializer unboxedJSON #* @post /one-cycle-generator function(req) { data_from_user <- req$body start_date <- data_from_user$start_date maximum_doc <- data_from_user$maximum_doc pond_setting <- data_from_user$pond_setting %>% janitor::clean_names() partial_harvest_setting <- data_from_user$partial_harvest_setting %>% janitor::clean_names() survival_calculation_method <- data_from_user$survival_calculation_method target_survival <- data_from_user$target_survival survival_model <- data_from_user$survival_model fi_multiplier_setting <- data_from_user$fi_multiplier_setting fr_type_setting <- data_from_user$fr_type_setting fr_coef_x <- data_from_user$fr_coef_x fr_coef_y <- data_from_user$fr_coef_y blind_feeding_start_feeding_setting <- data_from_user$blind_feeding_start_feeding_setting blind_feeding_increment_setting <- data_from_user$blind_feeding_increment_setting %>% janitor::clean_names() growth_calculation_method <- data_from_user$growth_calculation_method initial_abw <- data_from_user$initial_abw initial_growth_data <- data_from_user$initial_growth_data %>% janitor::clean_names() message("---- generate growth scenario table ----") growth_scenario_table <- growth_function_training( data = initial_growth_data, init_size = initial_abw, max_doc = maximum_doc, method = growth_calculation_method ) message("---- generate feeding for one cycle ----") result <- all_feeding_generator_function_v2( date_data = as.Date(start_date), max_doc = maximum_doc, shrimp_stock_data = pond_setting, harvest_setting = partial_harvest_setting, survival_calculation_method = survival_calculation_method, target_survival = target_survival, survival_model = survival_model, blind_feeding_day_1_setting = blind_feeding_start_feeding_setting, blind_feeding_day_2_setting = blind_feeding_increment_setting, fi_multiplier = fi_multiplier_setting, fr_calculation_method = fr_type_setting, fr_coef_x = fr_coef_x, fr_coef_y = fr_coef_y, growth_scenario_table = growth_scenario_table ) message("---- check result ----") ### blind feed table result$blind_feed_table -> blind_feed_table ### demand feeding table result$demand_feeding_table -> demand_feeding_table ### survival table result$survival_table -> survival_table ### stocking data pond_setting -> stocking_data ### partial harvest setting partial_harvest_setting ### feeding plan generation message("---- blind feeding generation ----") blind_feed_table %>% pivot_wider(names_from = type, values_from = total_feed) %>% mutate( feed_per_day_fr = blind_feeding, feed_per_day_indeks = blind_feeding ) %>% select(-blind_feeding) -> blind_feed_table message("---- demand feeding generation ----") blind_feed_table %>% bind_rows( demand_feeding_table %>% select(doc, pond_code, feed_per_day_indeks, feed_per_day_fr) ) %>% mutate(feed_type = ifelse(doc <= 30, "blind_feeding", "demand_feeding")) %>% left_join(growth_scenario_table) %>% left_join(survival_table) %>% left_join(stocking_data) %>% arrange(pond_code, doc) %>% group_by(pond_code) %>% mutate(cumulative_harvested = cumsum(harvested)) %>% ungroup() %>% mutate(biomass = mbw * population_left/1000) %>% mutate(biomass_total = biomass + (cumulative_harvested*mbw)/1000) %>% group_by(pond_code) %>% mutate( cumulative_feed_indeks = cumsum(feed_per_day_indeks), cumulative_feed_fr = cumsum(feed_per_day_fr), ) %>% ungroup() %>% mutate( fcr_indeks = cumulative_feed_indeks/biomass_total, fcr_fr = cumulative_feed_fr/biomass_total ) %>% mutate( data_type = "planning" ) -> result # variable setting ## datetime information datetime_info <- lubridate::now(tzone = "UTC") tibble( pond_code = as.character(), doc = as.numeric(), feed_index = as.numeric() ) -> feed_indeks_table for (pond_code in pond_setting$pond_code) { feed_indeks_table <- feed_indeks_table %>% bind_rows( fi_generator( total_feed_day_1 = blind_feeding_start_feeding_setting, blind_feeding_rules_table = blind_feeding_increment_setting ) %>% mutate( pond_code = pond_code ) ) } feed_indeks_table <- feed_indeks_table %>% bind_rows( demand_feeding_table %>% select(pond_code, doc, indeks_plan) %>% rename(feed_index = indeks_plan) ) %>% arrange(pond_code, doc) ## feeding_strategy_planning_datatable message("---- Save Feeding Plan for One Cycle ----") result %>% mutate( created_date = datetime_info ) %>% group_by(pond_code) %>% mutate(adg = mbw-lag(mbw)) %>% ungroup() -> result if (fr_type_setting == "FR Type 1") { result <- result %>% mutate( fr_plan = 10^(fr_coef_x-(fr_coef_y*log10(mbw))) ) } else if(fr_calculation_method == "FR Type 2") { result <- result %>% mutate( fr_plan = 10^(fr_coef_x-(fr_coef_y*log10(mbw))) * 100 ) } else { result <- result %>% mutate( fr_plan = 10^(fr_coef_x-(fr_coef_y*log10(mbw))) ) } result <- result %>% group_by(pond_code) %>% mutate(adg = round(mbw-lag(mbw), 2)) %>% ungroup() %>% mutate( carrying_capacity = biomass/pond_area, partial_biomass = population_left * harvest_percentage * mbw ) %>% left_join( feed_indeks_table ) %>% select( pond_code, doc, date, mbw, adg, fr_plan, sr_est, harvest_percentage, biomass, carrying_capacity, partial_biomass, biomass_total, population_left, feed_index, feed_per_day_fr, feed_per_day_indeks, cumulative_feed_fr, cumulative_feed_indeks, fcr_fr, fcr_indeks ) return(result) } #* One Cycle Feeding Generator #* @serializer unboxedJSON #* @post /one-week-generator function(req) { data_from_user <- req$body # Weekly pond setting ---- result_data <- data_from_user$data %>% janitor::clean_names() # date input ---- weekly_feeding_date_input <- as.Date(data_from_user$date_input) # sr setting ---- sr_method <- data_from_user$sr_method sr_model <- data_from_user$sr_model # fr setting ---- fr_method <- data_from_user$fr_method fr_x_coef <- data_from_user$fr_x_coef fr_y_coef <- data_from_user$fr_y_coef # growth method ---- growth_method <- data_from_user$growth_method feed_data_container <- tibble( pond_code = as.character(), doc_data = as.numeric(), mbw_data = as.numeric(), sr_data = as.numeric(), fi_data = as.numeric(), fr_data = as.numeric(), feed_fi = as.numeric(), feed_fr = as.numeric(), biomass_data = as.numeric(), population_data = as.numeric(), date_data = as.Date(character()) ) result_data %>% select(pond_code, stocking_actual, fi_multiplier) -> ponds_setting for (i in 1:nrow(result_data)) { pond_data <- result_data[i,] stock_data <- ponds_setting %>% filter(pond_code == pond_data$pond) %>% pull(stocking_actual) fi_mult <- ponds_setting %>% filter(pond_code == pond_data$pond) %>% pull(fi_multiplier) doc_data <- cumsum(c(pond_data$doc, rep(1, 7)))[2:8] mbw_data <- cumsum(c(pond_data$mbw_sampling, rep(pond_data$adg_target, 7)))[2:8] fi_data <- rep(pond_data$adg_target* fi_mult, 7) if (fr_method == "FR Tipe 1") { fr_data <- 10^(fr_x_coef-(fr_y_coef*log10(mbw_data))) * 100 } else if(fr_method == "FR Tipe 2") { fr_data <- 10^(fr_x_coef-(fr_y_coef*log10(mbw_data))) } else { fr_data <- 10^(fr_x_coef-(fr_y_coef*log10(mbw_data))) * 100 } if (sr_method == "Nilai SR Konstan") { message("---- Use Constant SR Model ----") sr_est <- pond_data$sr_input } else if(sr_method == "Berdasarkan Target") { message("---- Use Target Based SR ----") survival_input <- pond_data$sr_input survival_target <- pond_data$sr_target sr_est <- seq(from = survival_input, to = survival_target, length.out = 7) } else { if(model == "Model Survival Logistik") { message("---- Use Survival Logistic Model ----") sr_est <- (100 - 2.86*log2(doc_data))/100 } } feed_fi <- (stock_data * (sr_est) * doc_data * fi_data)/100000 feed_fr <- (stock_data * (sr_est) * mbw_data * fr_data)/1000 population_data <- stock_data * (sr_est) biomass <- population_data * mbw_data date_data <- seq(weekly_feeding_date_input, by = "day", length.out = 7) tibble( pond_code = pond_data$pond, doc_data = doc_data, mbw_data = mbw_data, sr_data = sr_est, fi_data = fi_data, fr_data = fr_data, feed_fi = feed_fi, feed_fr = feed_fr, fi_fr_ratio = feed_fi/feed_fr, biomass_data = biomass, population_data = population_data, date_data = date_data ) %>% bind_rows(feed_data_container) -> feed_data_container } feed_data_container <- feed_data_container %>% arrange(date_data, pond_code) return(feed_data_container) }