Skip to content

Commit

Permalink
Merge pull request odota#1080 from yasp-dota/match_logs
Browse files Browse the repository at this point in the history
Match logs
  • Loading branch information
howardchung authored Jun 25, 2016
2 parents 0d958f7 + c76de71 commit 967ad0b
Show file tree
Hide file tree
Showing 24 changed files with 511 additions and 155 deletions.
1 change: 0 additions & 1 deletion config.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ var defaults = {
"UI_HOST": "", //The host of the UI, redirect traffic from / and /return here
"ENABLE_RECAPTCHA": "", //set to enable the recaptcha on the Request page
"ENABLE_ADS": "", //set to turn on ads
"ENABLE_PRO_PARSING": "", // set to parse pro matches from sequential API
"ENABLE_MATCH_CACHE": "", // set to enable caching matches (Redis)
"ENABLE_PLAYER_CACHE": "", // set to enable caching players (Cassandra)
"ENABLE_INSERT_ALL_MATCHES": "", //set to enable inserting all matches
Expand Down
81 changes: 54 additions & 27 deletions java_parser/src/main/java/yasp/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import skadistats.clarity.model.s1.GameRulesStateType;
import skadistats.clarity.processor.entities.Entities;
import skadistats.clarity.processor.entities.OnEntityEntered;
import skadistats.clarity.processor.entities.OnEntityLeft;
import skadistats.clarity.processor.entities.UsesEntities;
import skadistats.clarity.processor.gameevents.CombatLog;
import skadistats.clarity.processor.gameevents.OnCombatLogEntry;
Expand Down Expand Up @@ -70,14 +71,15 @@ private class Entry {
public Integer gold_reason;
public Integer xp_reason;
public String valuename;
public Float stun_duration;
public Float slow_duration;
//public Float stun_duration;
//public Float slow_duration;
//entity fields
public Integer gold;
public Integer lh;
public Integer xp;
public Integer x;
public Integer y;
public Integer z;
public Float stuns;
public Integer hero_id;
public Integer life_state;
Expand All @@ -87,7 +89,9 @@ private class Entry {
public Integer assists;
public Integer denies;
//public Boolean hasPredictedVictory;

public Boolean entityleft;
public Integer ehandle;

public Entry() {
}

Expand Down Expand Up @@ -234,8 +238,8 @@ public void onCombatLogEntry(Context ctx, CombatLogEntry cle) {
combatLogEntry.attackerillusion = cle.isAttackerIllusion();
combatLogEntry.targetillusion = cle.isTargetIllusion();
combatLogEntry.value = cle.getValue();
combatLogEntry.stun_duration = cle.getStunDuration();
combatLogEntry.slow_duration = cle.getSlowDuration();
//combatLogEntry.stun_duration = cle.getStunDuration();
//combatLogEntry.slow_duration = cle.getSlowDuration();
//value may be out of bounds in string table, we can only get valuename if a purchase (type 11)
if (cle.getType() == DOTA_COMBATLOG_TYPES.DOTA_COMBATLOG_PURCHASE) {
combatLogEntry.valuename = cle.getValueName();
Expand All @@ -255,28 +259,12 @@ public void onCombatLogEntry(Context ctx, CombatLogEntry cle) {

@OnEntityEntered
public void onEntityEntered(Context ctx, Entity e) {
//CDOTA_NPC_Observer_Ward
//CDOTA_NPC_Observer_Ward_TrueSight
//s1 "DT_DOTA_NPC_Observer_Ward"
//s1 "DT_DOTA_NPC_Observer_Ward_TrueSight"
boolean isObserver = e.getDtClass().getDtName().equals("CDOTA_NPC_Observer_Ward");
boolean isSentry = e.getDtClass().getDtName().equals("CDOTA_NPC_Observer_Ward_TrueSight");
if (isObserver || isSentry) {
//System.err.println(e);
Entry entry = new Entry(time);
Integer x = getEntityProperty(e, "CBodyComponent.m_cellX", null);
Integer y = getEntityProperty(e, "CBodyComponent.m_cellY", null);
Integer[] pos = {x, y};
entry.type = isObserver ? "obs" : "sen";
entry.key = Arrays.toString(pos);
//System.err.println(entry.key);
Integer owner = getEntityProperty(e, "m_hOwnerEntity", null);
Entity ownerEntity = ctx.getProcessor(Entities.class).getByHandle(owner);
entry.slot = ownerEntity != null ? (Integer) getEntityProperty(ownerEntity, "m_iPlayerID", null) : null;
//2/3 radiant/dire
//entry.team = e.getProperty("m_iTeamNum");
output(entry);
}
processWardEntity(ctx, e, false);
}

@OnEntityLeft
public void onEntityLeft(Context ctx, Entity e) {
processWardEntity(ctx, e, true);
}

@UsesEntities
Expand Down Expand Up @@ -448,6 +436,45 @@ public <T> T getEntityProperty(Entity e, String property, Integer idx) {
FieldPath fp = e.getDtClass().getFieldPathForName(property);
return e.getPropertyForFieldPath(fp);
}

public void processWardEntity(Context ctx, Entity e, boolean entityLeft)
{
//CDOTA_NPC_Observer_Ward
//CDOTA_NPC_Observer_Ward_TrueSight
//s1 "DT_DOTA_NPC_Observer_Ward"
//s1 "DT_DOTA_NPC_Observer_Ward_TrueSight"
boolean isObserver = e.getDtClass().getDtName().equals("CDOTA_NPC_Observer_Ward");
boolean isSentry = e.getDtClass().getDtName().equals("CDOTA_NPC_Observer_Ward_TrueSight");
if (isObserver || isSentry) {
//System.err.println(e);
Entry entry = new Entry(time);
Integer x = getEntityProperty(e, "CBodyComponent.m_cellX", null);
Integer y = getEntityProperty(e, "CBodyComponent.m_cellY", null);
Integer z = getEntityProperty(e, "CBodyComponent.m_cellZ", null);
Integer[] pos = {x, y};
entry.x = x;
entry.y = y;
entry.z = z;
if (entityLeft)
{
entry.type = isObserver ? "obs_left" : "sen_left";
}
else
{
entry.type = isObserver ? "obs" : "sen";
}
entry.key = Arrays.toString(pos);
entry.entityleft = entityLeft;
entry.ehandle = e.getHandle();
//System.err.println(entry.key);
Integer owner = getEntityProperty(e, "m_hOwnerEntity", null);
Entity ownerEntity = ctx.getProcessor(Entities.class).getByHandle(owner);
entry.slot = ownerEntity != null ? (Integer) getEntityProperty(ownerEntity, "m_iPlayerID", null) : null;
//2/3 radiant/dire
//entry.team = e.getProperty("m_iTeamNum");
output(entry);
}
}

public void run(String[] args) throws Exception {
long tStart = System.currentTimeMillis();
Expand Down
4 changes: 0 additions & 4 deletions json/navbar_pages.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@
"benchmarks": {
"name": "Benchmarks"
},
"top": {
"name": "Top",
"hide": true
},
"distributions": {
"name": "Distributions"
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"http-proxy": "^1.13.1",
"jade": "^1.11.0",
"jquery": "^2.2.0",
"knex": "^0.10.0",
"knex": "^0.11.7",
"moment": "^2.11.2",
"multer": "^1.1.0",
"numeral": "^1.5.3",
Expand Down
1 change: 0 additions & 1 deletion processors/populate.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,4 @@ function populate(e, container)
break;
}
}

module.exports = populate;
20 changes: 10 additions & 10 deletions processors/processExpand.js
Original file line number Diff line number Diff line change
Expand Up @@ -427,25 +427,25 @@ function processExpand(entries, meta)
},
"obs": function(e)
{
//key is a JSON array of position data
e.key = JSON.parse(e.key);
e.posData = true;
expand(e);
var e2 = JSON.parse(JSON.stringify(e));
e2.posData = false;
e2.type = "obs_log";
expand(e2);
var e3 = JSON.parse(JSON.stringify(e));
//key is a JSON array of position data
e3.key = JSON.parse(e3.key);
e3.posData = true;
expand(e3);
},
"sen": function(e)
{
e.key = JSON.parse(e.key);
e.posData = true;
expand(e);
var e2 = JSON.parse(JSON.stringify(e));
e2.posData = false;
e2.type = "sen_log";
expand(e2);
}
var e3 = JSON.parse(JSON.stringify(e));
e3.key = JSON.parse(e3.key);
e3.posData = true;
expand(e3);
},
};
//define the types we want to put into each array
//null means all types
Expand Down
93 changes: 78 additions & 15 deletions processors/processReduce.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,85 @@
/**
* A processor to reduce the event stream by grouping similar events.
* NOT CURRENTLY IN PRODUCTION USE
* A processor to reduce the event stream to only logs we want to persist
**/
function processReduce(entries)
function processReduce(entries, match, meta)
{
var reduceMap = {};
//group by player_slot, type, targethero, targetillusion
for (var i = 0; i < entries.length; i++)
//for now, disable log parsing for regular matches
if (!match.doLogParse)
{
//group big categories: actions, combat log damage
var e = entries[i];
var identifier = [e.player_slot, e.type, e.key].join(":");
e.value = e.value || 1;
//var identifier = e.type;
//e.value = 1;
reduceMap[identifier] = reduceMap[identifier] ? reduceMap[identifier] + e.value : e.value || 1;
return;
}
//var fs = require('fs');
//fs.writeFileSync('./output3.json', JSON.stringify(reduceMap, null , 2));
var basicLogTypes = {
"obs": 1,
"sen": 1,
"obs_left": 1,
"sen_left": 1,
};
var result = entries.filter(function(e)
{
if (match.doLogParse)
{
if (e.type === "actions")
{
return false;
}
if (e.type === "DOTA_COMBATLOG_MODIFIER_REMOVE")
{
return false;
}
if (e.type === "DOTA_COMBATLOG_DAMAGE" || e.type === "DOTA_COMBATLOG_MODIFIER_ADD" || e.type === "DOTA_COMBATLOG_HEAL")
{
if (!e.targethero || e.targetillusion)
{
return false;
}
}
if (e.type === "interval" && e.time % 60 !== 0)
{
return false;
}
if (!e.time)
{
return false;
}
return true;
}
else
{
return (e.type in basicLogTypes);
}
}).map(function(e)
{
var e2 = Object.assign(
{}, e,
{
match_id: match.match_id,
attackername_slot: meta.hero_to_slot[e.attackername],
targetname_slot: meta.hero_to_slot[e.targetname],
sourcename_slot: meta.hero_to_slot[e.sourcename],
targetsourcename_slot: meta.hero_to_slot[e.targetname],
player1_slot: meta.slot_to_playerslot[e.player1],
player_slot: e.player_slot || meta.slot_to_playerslot[e.slot],
inflictor: translate(e.inflictor),
});
delete e2.attackername;
delete e2.targetname;
delete e2.sourcename;
delete e2.targetsourcename;
return e2;
});
/*
var count = {};
result.forEach(function(r)
{
count[r.type] = (count[r.type] || 0) + 1;
});
console.log(count);
*/
return result;
}

function translate(s)
{
return s === "dota_unknown" ? null : s;
}
module.exports = processReduce;
87 changes: 87 additions & 0 deletions routes/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,93 @@ module.exports = function(db, redis, cassandra)
});
});
*/
/*
api.get('/match_logs/:match_id', function(req, res, cb)
{
db.raw(`SELECT * FROM match_logs WHERE match_id = ? ORDER BY time ASC`, [req.params.match_id]).asCallback(function(err, result)
{
if (err)
{
return cb(err);
}
res.json(result.rows);
});
});
*/
api.get('/pro_matches', function(req, res, cb)
{
db.raw(`
SELECT match_id, start_time, duration, ma.leagueid, name
FROM matches ma
JOIN leagues le
ON ma.leagueid = le.leagueid
WHERE ma.leagueid > 0
ORDER BY match_id DESC
`).asCallback(function(err, result)
{
if (err)
{
return cb(err);
}
res.json(result.rows);
});
});
api.get('/pro_players', function(req, res, cb)
{
queries.getProPlayers(db, redis, function(err, result)
{
if (err)
{
return cb(err);
}
res.json(result);
});
});
api.get('/drafts', function(req, res, cb)
{
db.raw(`
SELECT pb.hero_id,
sum(case when ((pm.player_slot < 128) = m.radiant_win) then 1 else 0 end) wins,
sum(case when is_pick is true then 1 else 0 end) picks,
sum(case when is_pick is false then 1 else 0 end) bans
FROM picks_bans pb
LEFT JOIN matches m
ON pb.match_id = m.match_id
LEFT JOIN player_matches pm
ON pb.hero_id = pm.hero_id
AND pm.match_id = m.match_id
GROUP BY pb.hero_id;
`).asCallback(function(err, result)
{
if (err)
{
return cb(err);
}
res.json(result.rows);
});
});
api.get('/pick_order', function(req, res, cb)
{
db.raw(`SELECT hero_id, ord, count( * ) FROM picks_bans WHERE is_pick is true GROUP BY hero_id, ord;`).asCallback(function(err, result)
{
if (err)
{
return cb(err);
}
res.json(result.rows);
});
});
api.get('/leagues', function(req, res, cb)
{
db.raw(`SELECT * FROM leagues ORDER BY leagueid DESC`).asCallback(function(err, result)
{
if (err)
{
return cb(err);
}
res.json(result.rows);
});
});
api.get('/distributions', function(req, res, cb)
{
queries.getDistributions(redis, function(err, result)
Expand Down
Loading

0 comments on commit 967ad0b

Please sign in to comment.