library(dplyr)
library(tidymodels)

from_byte_string = function(x) {
  xcharvec = strsplit(x, " ")[[1]]
  xhex = as.hexmode(xcharvec)
  xraw = as.raw(xhex)
  unserialize(xraw)
}


getModelFromStringSerializedDataframe <- function(str_serialized_df) {
  
  # Posortuj zawartość ramki danych poprzez zwiększenie wartości model_id i chunk_id, aby upewnić się, że
  # fragmenty ciągu są poprawnie posortowane i gotowe do deserializacji
  model_vct <- str_serialized_df %>%
    arrange(model_id, chunk_id) %>%
    pull(model_str)
  
  # Scal fragmenty
  model_vct_str <- paste( model_vct, collapse = "" )
  
  # Przekształć ciąg bajtów na obiekt języka R
  selected_model <- from_byte_string(model_vct_str)
  
  return(selected_model)
  
}


# # Aby uruchomić ten kod w RStudio musisz zdefiniować ramkę models_df z pliku
# # 04-serialize-ml-models-in-power-query.R a następnie odkomentować poniższy kod.
# num_rows <- dim(models_df)[1]
# 
# dataset <- models_df %>%
#   filter( model_id == 'model01' ) %>%
#   cbind(
#     data.frame(
#       Age = rep(37, num_rows),
#       Embarked = rep(2, num_rows),
#       Fare = rep(2, num_rows),
#       Parch = rep(2, num_rows),
#       Pclass = rep(3, num_rows),
#       Sex = rep(0, num_rows),
#       SibSp = rep(37, num_rows)
#     )
#   )


# R Visual importuje tabele przy użyciu read.csv a nie ustawia strings_as_factors = F w roli parametru.
# Oznacza to, że fragmenty są importowane jako czynniki, a niektóre z nich są obcinane.
# gdy mają " " na końcu. Długość tych fragmentów będzie wynosiła 9999 zamiast 10000.
# Po prostu przekonwertuj na znak i dodaj spację, jeśli nchar == 9999 w celu utworzenia
# deserializacji.
dataset <- dataset %>%
  mutate( model_str = as.character(model_str) ) %>%
  mutate( model_str = ifelse(nchar(model_str) == 9999, paste0(model_str, " "), model_str) )



input_tuple_df <- dataset %>% 
  select('Age', 'Embarked', 'Fare', 'Parch', 'Pclass', 'Sex', 'SibSp') %>% 
  distinct()

selected_model <- getModelFromStringSerializedDataframe(dataset)

prediction_label <- predict(selected_model, new_data = input_tuple_df, type = 'class') %>%
  mutate(.pred_class = as.character(.pred_class)) %>% 
  pull()

prediction_score <- predict(selected_model, new_data = input_tuple_df, type = 'prob') %>% 
  pull( paste0('.pred_', prediction_label) )


plot.new()
text(0.5, 0.5,
     labels = paste0('Survived = ', prediction_label, ' (prob = ', round(prediction_score, 3), ')'),
     adj = 0.5, cex = 3.5
)
