What is Dota 2
• Multiplayer online battle arena (MOBA) is a computer game in which a player controls a single character in one of two teams. The objective is to destroy the opposing team's main structure with the assistance of periodically spawned computer-controlled units that march forward along set paths.
How To Make A Recommendation(Association Rules)
• Given the character choices so far, what do winners tend to pick?
• Association Rules (Basket Analysis)
• Rule Example: {‘Bounty’ ,…,’Jakiro’} => {‘Sven’}
My Team Mates Pick So I Should Pick
Association Rules: Measures of Interestingness
• Rule Example: {‘Bounty’ ,…,’Jakiro’} => {‘Sven’}
• Measures of Interestingness– Support
Frequency the complete set (X U Y) occursHigher Support => more frequentLow Support => could just be chanceAffected by the number of distinct items to chose from
– ConfidenceRatio between (X U Y) and (X)Reliability of rule inferenceHigh Confidence => Y more likely present with XIf Low Support then could still be chance
– LiftEquivalent to testing how frequency of full itemset (X U Y) occurs compared to how often would expect it to occur if X and Y were independentIf Lift > 1 => X and Y occur together more often than if independent (perhaps)High lift suggests some relationship between X and Y
• See http://www-users.cs.umn.edu/~kumar/dmbook/ch6.pdf for details
Item Set X (0…n items) Y (1 item)
Applying to DOTA
• Basket consists of 5 items (1 per team member)• During player draft, my team mates make picks• I want a rule that looks at previous winning
teams and suggests a pick for me given my teams selection
• Eg {RUBICK,SHADOW SHAMAN} => {SVEN}
Obtain Data
• DOTA 2 Web API– Send request via HTTP– Receive JSON file
library(RCurl) #Used to send and receive HTTP messages accross web
historyURL <- paste("https://community-dota-2.p.mashape.com/IDOTA2Match_570/GetMatchHistory/V001/?key=" ,SteamAuthKey,"&format=JSON",sep="")
matchHistory <- getURL(historyURL,header = TRUE ,httpheader = c("X-Mashape-Key" = XMashapeKey, "Accept" = "application/json") , .opts = list(ssl.verifypeer = FALSE), verbose = TRUE)
What is received (JSON){ "result":
{ "players": [ { "account_id": 75021757, "player_slot": 0, "hero_id": 45, "item_0": 50…}
, ….. ], "radiant_win": false, "duration": 1914, "start_time": 1342739723, "match_id": 27110133, "match_seq_num": 27106670, "tower_status_radiant": 4, "tower_status_dire": 1974, "barracks_status_radiant": 3, "barracks_status_dire": 63, "cluster": 131, "first_blood_time": 133, "lobby_type": 0, "human_players": 10, "leagueid": 0, "positive_votes": 0, "negative_votes": 0, "game_mode": 0 }
}
Storing the JSON Data
• Conventional Database is relational• Would have to transform considerably to store
in data base• MongoDB – NoSQL database, stores JSON (in
binary format)• Allows interrogation of JSON data• See https://www.mongodb.org/ for details
Using R to Talk to MongoDBInsert Document
library(rmongodb)
InsertMatchDataIntoMongo <- function(connection, collection, MatchDataJSON) { #inserts a match JSON file into the mongo DB #check that the connection exists if (mongo.is.connected(connection) == FALSE) {
stop("mongo is not connected") }
#convert JSON to BSON in order to insert to DB MatchDataJSON.bson <- mongo.bson.from.JSON(MatchDataJSON)
#insert data into database mongo.insert(connection,collection, MatchDataJSON.bson)
}
Using R to Talk to MongoDBRetrieve Documents
library(rmongodb)
#create query from JSON according to MongoDB Query structure query <- mongo.bson.from.JSON(
'{ "result.human_players" : 10 , "result.duration" : {"$gte" : 900} , "$or" : [ {"result.radiant_win" : true}
, {"result.radiant_win" : false} ] }')
#use fields to create a projection of the document fields <- list("result.players.hero_id"="1L"
, "result.players.player_slot"="1L“,"result.radiant_win" = "1L")
#extract data from mongo DB matches <- mongo.find.all(m,ns,query = query, fields = fields)
Dealing with JSON in R(Embedded documents => loops in loops : sapply, lapply)#functions for extracting data from matches list and removing duplicates getid <- function(players) { return(unlist(players)[["hero_id"]])
}
#create winning team basket setchooseWinners <- function(match) {
if (match[["result"]][["radiant_win"]] == TRUE) {return(sapply(match[["result"]][["players"]][1:5],getid)) } else { return(sapply(match[["result"]]
[["players"]][6:10],getid)) }}
#Create list of winners winners <- lapply(matches, chooseWinners)
Creating Association Rules in Rlibrary(arules) library(pmml)
#Convert list of vectors to transaction matrixwinners.trans <- as(winners,"transactions")
#Apply apriori algorithm using parameterswinners.rules <- apriori(winners.trans
, parameter = list(support = 0.001, confidence = 0.01))
#Write rules to CSV write(winners.rules, file = winnerfile, sep = "|")
#Write rules to PMML write.PMML(winners.rules, file = winnerfilePMML)
Making a Recommendation#recommender functionrecommendMyPick <- function(rules, picks, sortby = "lift") {
#Check that sortby is correct if (!(sortby %in% c("lift","support","confidence"))) { sortby = "lift" }
#convert picks to hero_ID p <- sapply(picks,HeroNameToID)
#ensure that picks is a charcter vector p <- as.character(p)
#subset rules to only include picks r.sub <- subset(rules, subset = lhs %ain% p)
#return rules with highest sort by myPick <- as(head(sort(r.sub, by = sortby), n = 3)
, "data.frame")
return(myPick) }
Lessons Learned/Problems
• Are my Recommendations any good?– Need more data
• Rcurl is easy once you understand the syntax and the API requirements
• MongoDB is good for storing JSON but difficult to query
• JSON data takes some wrangling• arules is straightforward once you get to the
transactions stage, but getting there can be hard work