library(dplyr)
library(caret)
library(ggplot2)
library(xgboost)
library(drat)
library(Matrix)
library(readr)
library(data.table)

training <- fread("../input/train_V2.csv")
training <- training[complete.cases(training),]

training$matchType1 <- training$matchType
training$matchType1 <- gsub(".*squad.*", "squad", training$matchType1)
training$matchType1 <- gsub(".*solo.*", "solo", training$matchType1)
training$matchType1 <- gsub(".*duo.*", "duo", training$matchType1)
training$matchType1 <- gsub(".*flare.*", "squad", training$matchType1)
training$matchType1 <- gsub(".*crash.*", "duo", training$matchType1)
training$rankPoints <- ifelse(training$rankPoints == -1, 0, training$rankPoints)
training$zombiecheater<- ifelse(training$walkDistance == 0 & training$winPlacePerc > 0, 1, 0)
training$totaldist <- training$walkDistance + training$rideDistance + training$swimDistance
training <- training[training$maxPlace > 1,]
training$healsboosts <- training$heals  + training$boosts

####winners####
solo <- training[training$matchType1 == "solo" | training$matchType1 == "other" | training$matchType1 == "crash",]
duosquad <- training[training$matchType1 == "squad" | training$matchType1 == "duo",]

rm(training)
gc()

normalized<-function(m){
  (m - min(m))/(max(m)-min(m))
}

solodf <- subset(solo, select = -c(winPlacePerc, groupId, Id, matchType, matchType1, DBNOs, revives, teamKills))
solodf <- solodf %>%
  group_by(matchId) %>%
  mutate(killplcmax = killPlace/maxPlace)
solomutate <- solodf %>%
  group_by(matchId) %>%
  mutate_all(.funs = funs(normalized, rank))
solomutate <- as.data.frame(solomutate)
solomutate <- cbind(solomutate, solo[,c("winPlacePerc")])
solomutate <- solomutate[,colSums(is.na(solomutate)) == 0]


####Solo Modeling####
set.seed(1234)
soloind <- sample(2, nrow(solomutate), replace = T, prob = c(0.8, 0.2))
trainsolo <- solomutate[soloind==1,]
testsolo <- solomutate[soloind==2,]
trainsolo <- trainsolo %>%
  ungroup()
testsolo <- testsolo %>%
  ungroup()
trainsolom <- data.matrix(select(trainsolo,-matchId, -winPlacePerc))
train_label_solo <- trainsolo$winPlacePerc
train_matrix_solo <- xgb.DMatrix(data = as.matrix(trainsolom), label = train_label_solo)
testsolom <- data.matrix(select(testsolo,-matchId, -winPlacePerc))
test_label_solo <- testsolo$winPlacePerc
test_matrix_solo <- xgb.DMatrix(data = as.matrix(testsolom), label = test_label_solo)

# Parameters
xgb_params_solo <- list("objective" = "reg:linear",
                        "eval_metric" = "mae")
watchlist_solo <- list(train = train_matrix_solo, test = test_matrix_solo)

bst_model <- xgb.train(params = xgb_params_solo,
                       data = train_matrix_solo,
                       nrounds = 1326,
                       watchlist = watchlist_solo,
                       eta = .3,
                       print_every_n = 25,
                        max_depth = 6,
                        subsample = 0.8,
                        nthread=8,
                        colsample_bytree = 0.8,
                       seed = 333)

rm(solomutate, trainsolo, testsolo, solo, solodf, train_matrix_solo, test_matrix_solo)
gc()
####Squads Modeling####

squads <- subset(duosquad, select = -c(Id, matchType, matchType1))
squads <- squads %>%
  group_by(matchId) %>%
  mutate(killplcmax = killPlace/maxPlace)
squads <- squads %>% ungroup() %>% select(-matchDuration)
squads <- squads %>%
  group_by(groupId) %>%
  mutate(groupmembers = n(),
  avgwalk = mean(walkDistance),
         maxwalk = max(walkDistance),
         avgtotaldist = sum(totaldist),
         maxtotaldist = max(totaldist),
         maxkill = max(killPlace),
         avgkill = mean(killPlace),
         avgboost = mean(boosts),
         avgheal = mean(heals),
         maxhb = max(healsboosts),
         maxxkillplc = max(killplcmax),
         meankillplc = mean(killplcmax),
         teamtotaldmg = sum(damageDealt),
         teamtotalwpns = sum(weaponsAcquired),
         teamtotalkills = sum(kills))

squads <- squads %>% 
  group_by(matchId) %>%
  mutate(norm_groupmembers = normalized(groupmembers),
    norm_maxxkillplc = normalized(maxxkillplc),
         norm_avgkillplc = normalized(maxxkillplc),
         rank_avgwalk = rank(avgwalk),
         rank_maxwalk = rank(maxwalk),
         rank_avgtotaldist = rank(avgtotaldist),
         rank_maxtotaldist = rank(maxtotaldist),
         rank_maxkill = rank(maxkill),
         rank_avgkill = rank(avgkill),
         rank_avgboost = rank(avgboost),
         rank_avgheal = rank(avgheal),
         rank_maxhb = rank(maxhb),
         rank_maxxkillplc = rank(maxxkillplc),
         rank_totaldmg = rank(teamtotaldmg),
         totaldmg = sum(damageDealt),
         totalwalk = sum(walkDistance),
         sumtotaldist = sum(totaldist),
         totalwpns = sum(weaponsAcquired),
         totalkills = sum(kills),
         avgwalkdist = mean(walkDistance),
         totalmeankillplc = mean(killplcmax),
         totalmaxxkillplc = max(killplcmax))

squads <- squads %>%
  mutate(distwpns = avgtotaldist/teamtotalwpns,
         wpndiff = teamtotalwpns/totalwpns,
         walkdiff = walkDistance/avgwalkdist,
         distdiff = avgtotaldist/sumtotaldist,
         tmkilldif = teamtotalkills/totalkills,
         killdiff = kills/avgwalkdist,
         teamkilldiff = teamtotalkills/avgtotaldist)


set.seed(1233)
squadind <- sample(2, nrow(squads), replace = T, prob = c(0.8, 0.2))
trainsquad <- squads[squadind==1,]
testsquad <- squads[squadind==2,]
trainsquad <- trainsquad %>%
  ungroup()
testsquad <- testsquad %>%
  ungroup()
trainsquadm <- data.matrix(select(trainsquad,-matchId, -winPlacePerc, -groupId))
train_label_squad <- trainsquad$winPlacePerc
train_matrix_squad <- xgb.DMatrix(data = as.matrix(trainsquadm), label = train_label_squad)
testsquadm <- data.matrix(select(testsquad,-matchId, -winPlacePerc, -groupId))
test_label_squad <- testsquad$winPlacePerc
test_matrix_squad <- xgb.DMatrix(data = as.matrix(testsquadm), label = test_label_squad)

xgb_params2 <- list("objective" = "reg:linear",
                    "eval_metric" = "mae")
watchlistsq <- list(train = train_matrix_squad, test = test_matrix_squad)

rm(duosquads, squads)
gc()

bst_modelsq <- xgb.train(params = xgb_params2,
                         data = train_matrix_squad,
                         nrounds = 1500,
                         watchlist = watchlistsq,
                         eta = .3,
                         print_every_n = 100,
                        max_depth = 6,
                        subsample = 0.8,
                        nthread=8,
                        colsample_bytree = 0.8,
                         seed = 333)

rm(trainsquad, testsquad, train_matrix_squad, test_matrix_squad)
gc()

testing <-fread("../input/test_V2.csv")
testing$matchType1 <- testing$matchType
testing$matchType1 <- gsub(".*squad.*", "squad", testing$matchType1)
testing$matchType1 <- gsub(".*solo.*", "solo", testing$matchType1)
testing$matchType1 <- gsub(".*duo.*", "duo", testing$matchType1)
testing$matchType1 <- gsub(".*flare.*", "squad", testing$matchType1)
testing$matchType1 <- gsub(".*crash.*", "duo", testing$matchType1)
testing$rankPoints <- ifelse(testing$rankPoints == -1, 0, testing$rankPoints)
testing$zombiecheater<- ifelse(testing$walkDistance == 0, 1, 0)
testing$totaldist <- testing$walkDistance + testing$rideDistance + testing$swimDistance
testing$healsboosts <- testing$heals  + testing$boosts



####winners####
solo <- testing[testing$matchType1 == "solo" | testing$matchType1 == "other" | testing$matchType1 == "crash",]
duosquad <- testing[testing$matchType1 == "squad" | testing$matchType1 == "duo",]

rm(testing)
gc()

solodf <- subset(solo, select = -c(groupId, Id, matchType, matchType1, DBNOs, revives, teamKills))
solodf <- solodf %>%
  group_by(matchId) %>%
  mutate(killplcmax = killPlace/maxPlace)
solomutate <- solodf %>%
  group_by(matchId) %>%
  mutate_all(.funs = funs(normalized, rank))
solomutate <- as.data.frame(solomutate)
solomutate <- solomutate %>% ungroup() %>% select(-matchId)
solomutate <- solomutate[,colSums(is.na(solomutate)) == 0]
rm(solodf)
gc()

####Solo Modeling####
solomutate$winPlacePerc <- predict(bst_model, data.matrix(solomutate))
solomutate$winPlacePerc <- ifelse(solomutate$winPlacePerc > 1, 1, solomutate$winPlacePerc)
solomutate$winPlacePerc <- ifelse(solomutate$winPlacePerc < 0, 0, solomutate$winPlacePerc)
solomutate$winPlacePerc <- ifelse(solomutate$maxPlace == 0, 0, solomutate$winPlacePerc)
solomutate$winPlacePerc <- ifelse(solomutate$maxPlace == 1, 1, solomutate$winPlacePerc)
sl <- solo[,1]
solofinal <- cbind(solomutate, sl)
solofinal <- solofinal[,c(55,54)]
####Squads Modeling####
rm(solomutate, solo)
gc()
squads <- duosquad
squads <- squads %>%
  group_by(matchId) %>%
  mutate(killplcmax = killPlace/maxPlace)
squads <- squads %>%
  group_by(groupId) %>%
  mutate(groupmembers = n(),
  avgwalk = mean(walkDistance),
         maxwalk = max(walkDistance),
         avgtotaldist = sum(totaldist),
         maxtotaldist = max(totaldist),
         maxkill = max(killPlace),
         avgkill = mean(killPlace),
         avgboost = mean(boosts),
         avgheal = mean(heals),
         maxhb = max(healsboosts),
         maxxkillplc = max(killplcmax),
         meankillplc = mean(killplcmax),
         teamtotaldmg = sum(damageDealt),
         teamtotalwpns = sum(weaponsAcquired),
         teamtotalkills = sum(kills))

squads <- squads %>% 
  group_by(matchId) %>%
  mutate(norm_groupmembers = normalized(groupmembers),
        norm_maxxkillplc = normalized(maxxkillplc),
         norm_avgkillplc = normalized(maxxkillplc),
         rank_avgwalk = rank(avgwalk),
         rank_maxwalk = rank(maxwalk),
         rank_avgtotaldist = rank(avgtotaldist),
         rank_maxtotaldist = rank(maxtotaldist),
         rank_maxkill = rank(maxkill),
         rank_avgkill = rank(avgkill),
         rank_avgboost = rank(avgboost),
         rank_avgheal = rank(avgheal),
         rank_maxhb = rank(maxhb),
         rank_maxxkillplc = rank(maxxkillplc),
         rank_totaldmg = rank(teamtotaldmg),
         totaldmg = sum(damageDealt),
         totalwalk = sum(walkDistance),
         sumtotaldist = sum(totaldist),
         totalwpns = sum(weaponsAcquired),
         totalkills = sum(kills),
         avgwalkdist = mean(walkDistance),
         totalmeankillplc = mean(killplcmax),
         totalmaxxkillplc = max(killplcmax))

squads <- squads %>%
  mutate(distwpns = avgtotaldist/teamtotalwpns,
         wpndiff = teamtotalwpns/totalwpns,
         walkdiff = walkDistance/avgwalkdist,
         distdiff = avgtotaldist/sumtotaldist,
         tmkilldif = teamtotalkills/totalkills,
         killdiff = kills/avgwalkdist,
         teamkilldiff = teamtotalkills/avgtotaldist)

squads <- squads %>% 
  ungroup() %>%
  select(-matchId, -groupId, -Id, -matchType, -matchType1, -matchDuration)


squads$winPlacePerc <- predict(bst_modelsq, data.matrix(squads))
squads$winPlacePerc <- ifelse(squads$winPlacePerc > 1, 1, squads$winPlacePerc)
squads$winPlacePerc <- ifelse(squads$winPlacePerc < 0, 0, squads$winPlacePerc)
squads$winPlacePerc <- ifelse(squads$maxPlace == 0, 0, squads$winPlacePerc)
squads$winPlacePerc <- ifelse(squads$maxPlace == 1, 1, squads$winPlacePerc)
squads$winPlacePerc <- ifelse(squads$maxPlace > 1 & squads$numGroups == 1, 0, squads$winPlacePerc)
squads$winPlacePerc <- ifelse(squads$numGroups == 1, 0, squads$winPlacePerc)
sq <- duosquad[,c(1:3)]
squadsfinal <- cbind(squads, sq)
squadsfinal <- squadsfinal %>%
    group_by(groupId, matchId) %>%
    mutate(winPlacePerc = mean(winPlacePerc))
squadsfinal <- squadsfinal %>% ungroup() %>% select(-groupId, -matchId)
squadsfinal <- squadsfinal[,c(73,72)]
final <- rbind(squadsfinal, solofinal)
write.csv(final, "submission.csv", row.names = FALSE)