UNPKG

crushyourfoes

Version:

A LotRO combat log parser

647 lines (559 loc) 22.4 kB
(function(exports){ exports.VERSION = "1.0.2"; exports.GetReport = function(player, opponent, log) { var myDPS = exports.GetTotalDPS(player, opponent, log); // watch out, these parameters are transposed var myEvades = exports.ParseEvades(opponent, player, log); var myBlocks = exports.ParseBlocks(opponent, player, log); var myParries = exports.ParseParries(opponent, player, log); var myResists = exports.ParseResists(opponent, player, log); // then flip back var myAttacks = exports.NumberOfAttacks(player, opponent, log); var myPartialAttacks = exports.PartialAttacks(player, log); var bigHitOut = exports.FindBiggestHit(player, opponent, log); var myCrits = exports.FindCrits(player, opponent, log); var myDevCrits = exports.FindDevCrits(player, opponent, log); var theirDPS = exports.GetTotalDPS(opponent, player, log); // watch out, these parameters are transposed var theirEvades = exports.ParseEvades(player, opponent, log); var theirBlocks = exports.ParseBlocks(player, opponent, log); var theirParries = exports.ParseParries(player, opponent, log); var theirResists = exports.ParseResists(player, opponent, log); // then flip back var theirAttacks = exports.NumberOfAttacks(opponent, player, log); var theirPartialAttacks = exports.PartialAttacks(opponent, log); var bigHitIn = exports.FindBiggestHit(opponent, player, log); var theirCrits = exports.FindCrits(opponent, player, log); var theirDevCrits = exports.FindDevCrits(opponent, player, log); var myTotalAvoidances = myEvades + myBlocks + myParries; var theirTotalAvoidances = theirEvades + theirBlocks + theirParries; var mySuccessfulAttacks = myAttacks - theirEvades - theirBlocks - theirParries - theirResists; var theirSuccessfulAttacks = theirAttacks - myEvades - myBlocks - myParries - myResists; // avoids div by zero var myDPA = (myAttacks > 0 && myDPS > 0) ? exports.DamagePerAttack(myAttacks, myDPS) : 0; var myDPATaken = (theirAttacks > 0 && theirDPS > 0) ? exports.DamagePerAttack(theirAttacks, theirDPS) : 0; var theirAvoidResist = (mySuccessfulAttacks > 0) ? 100 - exports.CalculatePercentage(myAttacks, mySuccessfulAttacks) : 0; var myAvoidResist = (theirSuccessfulAttacks > 0) ? 100 - exports.CalculatePercentage(theirAttacks, theirSuccessfulAttacks) : 0; var myCritPct = (mySuccessfulAttacks > 0 && myCrits > 0) ? exports.CalculatePercentage(mySuccessfulAttacks, myCrits) : 0; var theirCritPct = (theirSuccessfulAttacks > 0 && theirCrits > 0) ? exports.CalculatePercentage(theirSuccessfulAttacks, theirCrits) : 0; var myDevCritPct = (mySuccessfulAttacks > 0 && myDevCrits > 0) ? exports.CalculatePercentage(mySuccessfulAttacks, myDevCrits) : 0; var theirDevCritPct = (theirSuccessfulAttacks > 0 && theirDevCrits > 0) ? exports.CalculatePercentage(theirSuccessfulAttacks, theirDevCrits) : 0; var myBiggestHitOut = bigHitOut[0]; var myBiggestHitIn = bigHitIn[0]; var bigCombatLogOut = bigHitOut[1]; var bigCombatLogIn = bigHitIn[1]; var myKBs = exports.MyKillingBlows(log); var myKills = exports.WhoDied(log); var report = "CRUSH YOUR FOES!"; report +="\n===============\n"; report += "\nYour total damage done was " + myDPS; report += "\nTotal damage done to you was " + theirDPS; report += "\nYour average damage per attack was " + myDPA; report += "\nAverage damage you took per attack was " + myDPATaken; report += "\nThe largest hit you landed was for " + myBiggestHitOut; report += "\nThe largest hit you took was for " + myBiggestHitIn; report += "\nYour total number of attempted attacks was " + myAttacks; report += "\nTotal number of attempted attacks against you was " + theirAttacks; report += "\nYour number of successful attacks was " + mySuccessfulAttacks; report += "\nNumber of successful attacks against you was " + theirSuccessfulAttacks; report += "\nYour combined avoidance/resistance was " + myAvoidResist.toFixed(2) + "%"; report += "\nOpponents' combined avoidance/resistance was " + theirAvoidResist.toFixed(2) + "%"; report += "\nYour critical percentage was " + myCritPct.toFixed(2) + "%"; report += "\nOpponents' critical percentage was " + theirCritPct.toFixed(2) + "%"; report += "\nYour devastating critical percentage was " + myDevCritPct.toFixed(2) + "%"; report += "\nOpponents' devastating critical percentage was " + theirDevCritPct.toFixed(2) + "%"; report += "\n\nDetails of your biggest incoming attack:"; report += "\n\t" + bigCombatLogIn; report += "\nDetails of your biggest outgoing attack:"; report += "\n\t" + bigCombatLogOut; if (myKills.length > 0) { report +="\n\nYou killed the following: "; mobs = {}; myKills.forEach(function(line) { if (mobs.hasOwnProperty(line)) { mobs[line]++; } else { mobs[line] = 0; } }); for (var who in mobs) { if (mobs[who] > 1) { report += "\n\t" + mobs[who] + " x " + who.replace("The","").trim(); } else { report += "\n\t" + who; } } } else { report += "\n\nYou killed nothing."; } return report; } // GetReport /***************************************************************************** ** Parsing functions *****************************************************************************/ exports.GetNames = function(log) { var names = []; log.forEach(function(line) { var bInter = / interrupted /.exec(line); var bDefeated = / defeated /.exec(line); var bSuccumbed = / succumbed /.exec(line); var bHeader = /^#/.exec(line); var bLeft = /^Left /.exec(line); var bJoin = /^Joined /.exec(line); var bYou = /^You /.exec(line); var bYour = /^Your /.exec(line); var bBlow = /^blow /.exec(line); var bLoot = / contents /.exec(line); var bLoot2 = / acquired /.exec(line); var bCure = / cure /.exec(line); var bChat = /^\[/.exec(line); // mobs and bosses var bThe = /^The /.exec(line); var bBob = /^Bob and Weave /.exec(line); var bNothing = /^Nothing/.exec(line); var bIncreased = /^Increased (Morale|Power)/.exec(line); var bInspiration = /^.* Inspiration/.exec(line); var bConviction = /^Conviction/.exec(line); var bLendPower = /^Lend Power/.exec(line); var bMischievous = /^Mischievous (Glee|Delight)/.exec(line); var bIgnore; if (bLeft || bJoin || bDefeated || bInter || bHeader || bBlow || bYou || bSuccumbed || bLoot || bLoot2 || bYour || bCure || bChat || bThe || bBob || bNothing || bIncreased || bInspiration || bConviction || bLendPower || bMischievous) { bIgnore = true; } else { bIgnore = false; } if (! bIgnore) { var reName = /^(.*) (applied|scored|has)/.exec(line); if (reName) { var name = reName[1]; // console.log("[%s] indexof %d length %d", name, names.indexOf(name), names.length); if (names.indexOf(name) === -1) { names.push(name); } } } }); names = names.sort(); return names; } //FIXME: bigHit fails on 20140607_1 Llygad The Blade exports.GetTotalDPS = function(t1, t2, log) { var totalDPS = 0; log.forEach(function(line) { var bDPS = / for /.exec(line); var bGamble = /\(/.exec(line); var bTier = /Tier/.exec(line); if (t2 === "ALL") { if (bDPS) { // console.log("bDPS: " + line); if (line.indexOf(t1) === 0) { // console.log("t1: " + line); if (bGamble) { var rePoints = /for ([\d|,]+) /.exec(line); var points = parseInt(rePoints[1].replace(",","")); // console.log("%d - %s", points, line); totalDPS += points; } else if (bTier) { //FIXME: use case Combat_20140510_1.txt console.log('!!them bTier: ' + line); } else { var rePoints = /(\d+)/.exec(line.replace(",","")); var points = parseInt(rePoints[1]); totalDPS += points; // console.log('else point %d - %s', points, line); } // if bTier } else { // console.log("miss: " + line); } // if indexOf t1 } else { // console.log("miss: " + line); } // if bDPS } else if (t1 === "ALL") { if (bDPS) { if (line.indexOf(t2) !== 0) { // console.log("t2: " + line); if (bGamble) { var rePoints = /for ([\d|,]+) /.exec(line); var points = parseInt(rePoints[1].replace(",","")); // console.log("%d - %s", points, line); totalDPS += points; } else if (bTier) { var rePoints = /Tier \d+ Damage.* for (\d+)/.exec(line); // console.log('!!you bTier: ' + line); if (rePoints) { // console.dir(damage); var points = parseInt(rePoints[1].replace(",","")); totalDPS += points; } } else { var rePoints = /(\d+)/.exec(line.replace(",","")); var points = parseInt(rePoints[1]); totalDPS += points; // console.log('else point %d - %s', points, line); } // if bTier } else { // console.log("miss: " + line); } // if indexOf t2 } else { // console.log("miss: " + line); } // if bDPS } else { // specific targets if (bDPS) { if (line.indexOf(t1) === 0 && line.indexOf(t2) !== -1) { // console.log("specific target: " + line); if (bGamble) { var rePoints = /for ([\d|,]+) /.exec(line); var points = parseInt(rePoints[1].replace(",","")); // console.log("%d - %s", points, line); totalDPS += points; } else if (bTier) { console.log('!!spec bTier: ' + line); } else { var rePoints = /(\d+)/.exec(line.replace(",","")); var points = parseInt(rePoints[1]); totalDPS += points; // console.log('else point %d - %s', points, line); } // if bTier } else { // console.log("miss: " + line); } // if indexOf t1 and indexOf t2 } else { // console.log("miss: " + line); } // if bDPS } // if t2 == ALL }); // console.log('t1: %s t2: %s', t1, t2); return totalDPS; } exports.FindBiggestHit = function(t1, t2, lines) { //FIXME: Combat_20140606_1.txt biggest incoming attack was shootyman var hitData = []; var bigHit = 0; var bigLog = ""; var strBigHit = ""; lines.forEach(function(line) { var bDPS = / for /.exec(line); var bGamble = /\(/.exec(line); var bTier = /Tier/.exec(line); if (t2 === "ALL") { if (bDPS) { // console.log("bDPS: " + line); if (line.indexOf(t1) === 0) { // console.log("t1: " + line); if (bGamble) { var rePoints = /for ([\d|,]+) /.exec(line); var points = parseInt(rePoints[1].replace(",","")); if (points > bigHit) { bigHit = points; strBigHit = points; bigLog = line; } } else if (bTier) { console.log('!!bh their bTier: ' + line); } else { var rePoints = /(\d+)/.exec(line.replace(",","")); var points = parseInt(rePoints[1]); if (points > bigHit) { bigHit = points; strBigHit = points; bigLog = line; } } // if bTier } else { // console.log("miss: " + line); } // if indexOf t1 } else { // console.log("miss: " + line); } // if bDPS } else if (t1 === "ALL") { if (bDPS) { if (line.indexOf(t2) !== 0) { // console.log("t2: " + line); if (bGamble) { var rePoints = /for ([\d|,]+) /.exec(line); var points = parseInt(rePoints[1].replace(",","")); if (points > bigHit) { bigHit = points; strBigHit = points; bigLog = line; } } else if (bTier) { var rePoints = /Tier \d+ Damage.* for (\d+)/.exec(line); var points = parseInt(rePoints[1].replace(",","")); if (points > bigHit) { bigHit = points; strBigHit = points; bigLog = line; } // console.log('!!bh you bTier: ' + line); } else { var rePoints = /(\d+)/.exec(line.replace(",","")); var points = parseInt(rePoints[1]); if (points > bigHit) { bigHit = points; strBigHit = points; bigLog = line; } } // if bTier } else { // console.log("miss: " + line); } // if indexOf t2 } else { // console.log("miss: " + line); } // if bDPS } else { // specific targets if (bDPS) { if (line.indexOf(t1) === 0 && line.indexOf(t2) !== -1) { // console.log("specific target: " + line); if (bGamble) { var rePoints = /for ([\d|,]+) /.exec(line); var points = parseInt(rePoints[1].replace(",","")); if (points > bigHit) { bigHit = points; strBigHit = points; bigLog = line; } } else if (bTier) { console.log('!!bh spec bTier: ' + line); } else { var rePoints = /(\d+)/.exec(line.replace(",","")); var points = parseInt(rePoints[1]); if (points > bigHit) { bigHit = points; strBigHit = points; bigLog = line; } } // if bTier } else { // console.log("miss: " + line); } // if indexOf t1 and indexOf t2 } else { // console.log("miss: " + line); } // if bDPS } // if t2 == ALL }); hitData.push(strBigHit); hitData.push(bigLog); return hitData; } exports.ParseEvades = function(t1, t2, lines) { var evades = 0; lines.forEach(function(line) { var bTried = / tried /.exec(line); if (t1 === "ALL") { if (line.indexOf(t2) !== 0 && line.indexOf(" evaded ") !== -1 && line.indexOf(" partially " ) === -1) { evades++; // console.log("your evades: " + line); } } else if (t2 === "ALL") { if (line.indexOf(t1) === 0 && line.indexOf(" evaded ") !== -1 && line.indexOf(" partially " ) === -1) { evades++; // console.log("their: " + line); } } else { if (line.indexOf(t1) === 0 && line.indexOf(" evaded ") !== -1 && line.indexOf(" partially " ) === -1 && line.indexOf(t2) !== -1) { evades++; } } }); return evades; } exports.ParseBlocks = function(t1, t2, lines) { var blocks = 0; lines.forEach(function(line) { var bTried = / tried /.exec(line); if (t1 === "ALL") { if (line.indexOf(t2) !== 0 && line.indexOf(" blocked ") !== -1 && line.indexOf(" partially " ) === -1) { blocks++; // console.log("their: " + line); } } else if (t2 === "ALL") { if (line.indexOf(t1) === 0 && line.indexOf(" blocked ") !== -1 && line.indexOf(" partially " ) === -1) { blocks++; // console.log("yours: " + line); } } else { if (line.indexOf(t1) === 0 && line.indexOf(" blocked ") !== -1 && line.indexOf(" partially " ) === -1 && line.indexOf(t2) !== -1) blocks++; } }); return blocks; } exports.ParseParries = function(t1, t2, lines) { var parries = 0; lines.forEach(function(line) { var bTried = / tried /.exec(line); if (t1 === "ALL") { if (line.indexOf(t2) !== 0 && line.indexOf(" parried ") !== -1 && line.indexOf(" partially " ) === -1) { parries++; // console.log("their: " + line); } } else if (t2 === "ALL") { if (line.indexOf(t1) === 0 && line.indexOf(" parried ") !== -1 && line.indexOf(" partially " ) === -1) { parries++; // console.log("yours: " + line); } } else { if (line.indexOf(t1) === 0 && line.indexOf(" parried ") !== -1 && line.indexOf(" partially " ) === -1 && line.indexOf(t2) !== -1) parries++; } }); return parries; } exports.DamagePerAttack = function(attacks, totalDamage) { return Math.round(totalDamage/attacks); // return (totalDamage/attacks).toFixed(2); } exports.NumberOfAttacks = function(t1, t2, lines) { var attacks = 0; lines.forEach(function(line) { if (t1 === "ALL") { if (line.indexOf(t2) !== 0 && (line.indexOf(" for ") !== -1 || line.indexOf(" tried ") !== -1) && (line.indexOf(" benefit ") === -1 || line.indexOf(" heal ") === -1)) { // exclude buffs attacks++; // console.log('their attacks: ' + line); } } else if (t2 === "ALL") { if (line.indexOf(t1) === 0 && (line.indexOf(" for ") !== -1 || line.indexOf(" tried ") !== -1)) { attacks++; } // console.log("your attacks: " + line); } else { if (line.indexOf(t1) === 0 && line.indexOf(t2) !== -1 && (line.indexOf(" for ") !== -1 || line.indexOf(" tried ") !== -1)) attacks++; } }); return attacks; } exports.PartialAttacks = function(str, lines) { var attacks = 0; // pretty certain is broken... shows everyone's partial hits lines.forEach(function(line) { if (line.indexOf(str) !== -1 && line.indexOf(" partially ") !== -1) { attacks++; // console.log('partial: ' + line); } }); return attacks; } exports.ParseResists = function(t1, t2, lines) { var resists = 0; lines.forEach(function(line) { var bTried = / tried /.exec(line); // not used! if (t1 === "ALL") { if (line.indexOf(t2) !== 0 && line.indexOf(" resisted ") !== -1) { resists++; // console.log('yours: ' + line); } } else if (t2 === "ALL") { if (line.indexOf(t1) === 0 && line.indexOf(" resisted ") !== -1) { resists++; // console.log('theirs: ' + line); } } else { if (line.indexOf(t1) === 0 && line.indexOf(" resisted ") !== -1 && line.indexOf(t2) !== -1) { resists++; console.log('specific: ' + line); } } // t1 == ALL }); return resists; } exports.MyKillingBlows = function(lines) { var kills = 0; lines.forEach(function(line) { if (/Your mighty blow/.exec(line)) { kills++; // console.log('killed:' + line); } }); return kills; } exports.WhoDied = function(lines) { var names = []; lines.forEach(function(line) { var bKilled = /^Your mighty blow defeated (.*)\.$/.exec(line); if (bKilled) { names.push(bKilled[1].replace("the","The")); // console.dir(bKilled); } }); return names; } exports.FindCrits = function(t1, t2, lines) { var crits = 0; lines.forEach(function(line) { if (t1 === "ALL") { if (line.indexOf(" applied ") === -1 && (line.indexOf(" critical ") !== -1 || line.indexOf(" devastating ") !== -1) && line.indexOf(t2) !== 0) { crits++; // console.log('theirs: t1 %s t2 %s - ', t1,t2,line); } } else if (t2 === "ALL") { if (line.indexOf(" applied ") === -1 && (line.indexOf(" critical ") !== -1 || line.indexOf(" devastating ") !== -1) && line.indexOf(t1) === 0) { crits++; // console.log('yours: t1 %s t2 %s - ', t1,t2,line); } } else { if (line.indexOf(" applied ") === -1 && (line.indexOf(" critical ") !== -1 || line.indexOf(" devastating ") !== -1) && line.indexOf(t1) === 0 && line.indexOf(t2) !== -1) { crits++; } } }); return crits; } exports.FindDevCrits = function(t1, t2, lines) { var crits = 0; lines.forEach(function(line) { if (t1 === "ALL") { if (line.indexOf(" applied ") === -1 && line.indexOf(" devastating ") !== -1 && line.indexOf(t2) !== 0) { crits++; // console.log('theirs: t1 %s t2 %s - ', t1,t2,line); } } else if (t2 === "ALL") { if (line.indexOf(" applied ") === -1 && line.indexOf(" devastating ") !== -1 && line.indexOf(t1) === 0) { crits++; // console.log('yours: t1 %s t2 %s - ', t1,t2,line); } } else { if (line.indexOf(" applied ") === -1 && line.indexOf(" devastating ") !== -1 && line.indexOf(t1) === 0 && line.indexOf(t2) !== -1) { crits++; } } }); return crits; } exports.CalculatePercentage = function(a, e) { var factor = 100; var percentage = e / a * factor.toFixed(2); return percentage; } console.log("CRUSHYOURFOES v%s is loaded", exports.VERSION); })(typeof exports === "undefined" ? this['CYF'] = {} : exports);