From 202ae0be1da9c11b674b5acf706764946c1167c6 Mon Sep 17 00:00:00 2001 From: Freeyorp Date: Fri, 29 Mar 2013 22:20:52 +1300 Subject: Compute and chart character base level --- index.html | 6 +++ js/comp/stat.js | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ js/mv.js | 32 +++++++++--- 3 files changed, 184 insertions(+), 7 deletions(-) create mode 100644 js/comp/stat.js diff --git a/index.html b/index.html index 638812a..a30cc0a 100644 --- a/index.html +++ b/index.html @@ -12,6 +12,9 @@

Experience gain instances by Character ID [?]

+
+

Experience gain instances by Character Base Level

+

Definedness of records [?]

@@ -47,5 +50,8 @@ + + + diff --git a/js/comp/stat.js b/js/comp/stat.js new file mode 100644 index 0000000..cd75646 --- /dev/null +++ b/js/comp/stat.js @@ -0,0 +1,153 @@ +/** + * Make computations about tmwAthena's stat requirements. + * + * Amongst other things, this can be used to derive a minimum base level for a stat configuration. + */ +var stat = function(){ + var stat = {}; + var statpoint = [ + 48, + 52, + 56, + 60, + 64, + 69, + 74, + 79, + 84, + 90, + 96, + 102, + 108, + 115, + 122, + 129, + 136, + 144, + 152, + 160, + 168, + 177, + 186, + 195, + 204, + 214, + 224, + 234, + 244, + 255, + 266, + 277, + 288, + 300, + 312, + 324, + 336, + 349, + 362, + 375, + 388, + 402, + 416, + 430, + 444, + 459, + 474, + 489, + 504, + 520, + 536, + 552, + 568, + 585, + 602, + 619, + 636, + 654, + 672, + 690, + 708, + 727, + 746, + 765, + 784, + 804, + 824, + 844, + 864, + 885, + 906, + 927, + 948, + 970, + 992, + 1014, + 1036, + 1059, + 1082, + 1105, + 1128, + 1152, + 1176, + 1200, + 1224, + 1249, + 1274, + 1299, + 1324, + 1350, + 1376, + 1402, + 1428, + 1455, + 1482, + 1509, + 1536, + 1564, + 1592 + ]; + /* If a character is using a certain number of status points, what is the lowest level it could be? */ + stat.minLevelForStatusPoints = function(statusPoints) { + /* + * tmwAthena status points for a level are described by the following recurrence relation: + * p(1) = 48 + * p(l) = p(l - 1) + floor((l + 14) / 4) + * For whatever reason, the server also loads a cached copy from a file of all places - db/statpoint.txt. + * If this is out of sync with the equation, fun things can happen. + * For now, naively assume that statpoint.txt is correct and shamelessly dump it here (see above). + */ + return crossfilter.bisect.left(statpoint, statusPoints, 0, statpoint.length) + 1; + }; + var statusPointInc = [0, 0] + stat.statusPointsForStat = function(v) { + if (isNaN(v)) { + throw "Invalid input"; + } + /* First, convert the absolute stat to terms of increments. */ + /* This is as simple as removing the starting value - 1 - from it. */ + /* + * The status points needed to increase from a stat with value v can be calculated as follows: + * floor((v + 9) / 10) + 1 + */ + if (statusPointInc.length > v) { + return statusPointInc[v]; + } + var i = stat.statusPointsForStat(v - 1) + Math.floor(((v - 1) + 9) / 10) + 1; + statusPointInc.push(i); + return i; + } + /* If a character has a certain arrangement of attributes, how many status points are required for this configuration? */ + stat.statusPointsForStats = function(str, agi, vit, dex, int, luk) { + return stat.statusPointsForStat(str) + + stat.statusPointsForStat(agi) + + stat.statusPointsForStat(vit) + + stat.statusPointsForStat(dex) + + stat.statusPointsForStat(int) + + stat.statusPointsForStat(luk); + }; + /* Helper function currying minLevelForStatusPoints and stat.statusPointsForStats */ + stat.minLevelForStats = function(str, agi, vit, dex, int, luk) { + return stat.minLevelForStatusPoints(stat.statusPointsForStats(str, agi, vit, dex, int, luk)); + }; + return stat; +}(); diff --git a/js/mv.js b/js/mv.js index 2b704f8..82a7d5f 100644 --- a/js/mv.js +++ b/js/mv.js @@ -111,7 +111,7 @@ var mv = {}; } d = e.match(/^(?:\d+\.\d+) PC(\d+) (?:\d+):(?:\d+),(?:\d+) STAT (\d+) (\d+) (\d+) (\d+) (\d+) (\d+) /); if (d) { - pcstat[d[1]] = { + var s = { str: parseInt(d[2]), agi: parseInt(d[3]), vit: parseInt(d[4]), @@ -119,6 +119,8 @@ var mv = {}; dex: parseInt(d[6]), luk: parseInt(d[7]) }; + s.blvl = stat.minLevelForStats(s.str, s.agi, s.vit, s.int, s.dex, s.luk); + pcstat[d[1]] = s; return; } }); @@ -128,12 +130,13 @@ var mv = {}; dateDim, dateGroup, pcDim, pcGroup, mapDim, mapGroup, - /* - * How well defined a record is. - * 0 -> Record contains undefined data - * 1 -> Record is defined, but undefined records follow and may impede validity of findings - * 2 -> Record and all succeeding records are well defined - */ + blvlDim, blvlGroup, + /* + * How well defined a record is. + * 0 -> Record contains undefined data + * 1 -> Record is defined, but undefined records follow and may impede validity of findings + * 2 -> Record and all succeeding records are well defined + */ defDim, defGroup; /* The record files are set, do everything */ function makeHeap() { @@ -148,6 +151,8 @@ var mv = {}; pcGroup = pcDim.group().reduceCount(); mapDim = cfdata.dimension(function(d) { return d.map; }); mapGroup = mapDim.group().reduce(a, s, z); + blvlDim = cfdata.dimension(function(d) { return d.pcstat ? d.pcstat.blvl : 0; }); + blvlGroup = blvlDim.group().reduceCount(); defDim = cfdata.dimension(function(d) { if (d.pcstat == undefined) { return 0; } if (d.date <= fullyDefinedCutoff) { return 1; } return 2; }); defGroup = defDim.group().reduceCount(); defDim.filterExact(2); @@ -202,6 +207,19 @@ var mv = {}; .title(function(d) { return d.key + ": " + d.value; }) .brushOn(true) ; + mv.blvlChart = dc.barChart("#blvl-chart") + .width(630) + .height(130) + .margins({left: 60, right: 18, top: 5, bottom: 30}) + .dimension(blvlDim) + .group(blvlGroup) + .gap(1) + .elasticY(true) + .x(d3.scale.linear().domain([0, blvlDim.top(1)[0].pcstat.blvl])) + .renderHorizontalGridLines(true) + .title(function(d) { return d.key + ": " + d.value; }) + .brushOn(true) + ; mv.defChart = dc.pieChart("#def-chart") .width(630) .height(130) -- cgit v1.2.3-60-g2f50