]> git.xonotic.org Git - xonotic/xonstat.git/commitdiff
Change margin of the weaponCharts.
authorAnt Zucaro <azucaro@gmail.com>
Thu, 29 Oct 2015 00:47:43 +0000 (20:47 -0400)
committerAnt Zucaro <azucaro@gmail.com>
Thu, 29 Oct 2015 00:47:43 +0000 (20:47 -0400)
xonstat/static/js/weaponCharts.js

index 548a72684156f4721c430e49611d92f664968d63..3a0bf5c14fa02e721817de4801ae2780e17c1b38 100644 (file)
@@ -27,246 +27,136 @@ var weaponColors = {
   "fireball": "#33ff33"
 };
 
-// Flatten the existing weaponstats JSON requests
-// to ease indexing
-var flatten = function(weaponData) {
-  flattened = {}
-
-  // each game is a key entry...
-  weaponData.games.forEach(function(e,i) { flattened[e] = {}; });
-
-  // ... with indexes by weapon_cd
-  weaponData.weapon_stats.forEach(function(e,i) { flattened[e.game_id][e.weapon_cd] = e; });
-
-  return flattened;
-}
-
-// Calculate the Y value for a given weapon stat
-function accuracyValue(gameWeaponStats, weapon) {
-  if (gameWeaponStats[weapon] == undefined) {
-    return null;
-  }
-  var ws = gameWeaponStats[weapon];
-  var pct = ws.fired > 0 ? Math.round((ws.hit / ws.fired) * 100) : 0;
-  
-  return pct;
-}
-
-// Calculate the tooltip text for a given weapon stat
-function accuracyTooltip(weapon, pct, averages) {
-  if (pct == null) {
-    return null;
-  }
-
-  var tt = weapon + ": " + pct.toString() + "%";
-  if (averages[weapon] != undefined) {
-    return tt + " (" + averages[weapon].toString() + "% average)"; 
-  }
-
-  return tt;
-}
-
-// Draw the accuracy chart in the "accuracyChart" div id
-function drawAccuracyChart(weaponData) {
-
-  var data = new google.visualization.DataTable();
-  data.addColumn('string', 'X');
-  data.addColumn('number', 'Shotgun');
-  data.addColumn({type: 'string', role: 'tooltip'});
-  data.addColumn('number', 'MG');
-  data.addColumn({type: 'string', role: 'tooltip'});
-  data.addColumn('number', 'Vortex');
-  data.addColumn({type: 'string', role: 'tooltip'});
-  data.addColumn('number', 'Vaporizer');
-  data.addColumn({type: 'string', role: 'tooltip'});
-  data.addColumn('number', 'Arc');
-  data.addColumn({type: 'string', role: 'tooltip'});
-
-  var flattened = flatten(weaponData);
-
-  for(i in weaponData.games) {
-    var game_id = weaponData.games[i];
-    var sg = accuracyValue(flattened[game_id], "shotgun");
-    var sgTT = accuracyTooltip("shotgun", sg, weaponData.averages);
-    var mg = accuracyValue(flattened[game_id], "machinegun");
-    var mgTT = accuracyTooltip("machinegun", mg, weaponData.averages); 
-    var vortex = accuracyValue(flattened[game_id], "vortex");
-    var vortexTT = accuracyTooltip("vortex", vortex, weaponData.averages);
-    var mn = accuracyValue(flattened[game_id], "vaporizer");
-    var mnTT = accuracyTooltip("vaporizer", mn, weaponData.averages);
-    var arc = accuracyValue(flattened[game_id], "arc");
-    var arcTT = accuracyTooltip("arc", arc, weaponData.averages); 
-
-    data.addRow([game_id.toString(), sg, sgTT, mg, mgTT, vortex,
-            vortexTT, mn, mnTT, arc, arcTT]);
-  }
-
-  var options = {
-    backgroundColor: { fill: 'transparent' },
-    lineWidth: 2,
-    legend: { 
-      textStyle: { color: "#666" }
-    },
-    hAxis: {
-      title: 'Games',
-      textPosition: 'none',
-      titleTextStyle: { color: '#666' }
-    },
-    vAxis: {
-      title: 'Percentage',
-      titleTextStyle: { color: '#666' },
-      minValue: 0,
-      maxValue: 100,
-      baselineColor: '#333',
-      gridlineColor: '#333',
-      ticks: [20, 40, 60, 80, 100]
-    },
-    series: {
-      0: { color: weaponColors["shotgun"] },
-      1: { color: weaponColors["machinegun"] },
-      2: { color: weaponColors["vortex"] },
-      3: { color: weaponColors["vaporizer"] },
-      4: { color: weaponColors["arc"] }
-    }
-  };
-
-  var chart = new google.visualization.LineChart(document.getElementById('accuracyChart'));
-
-  // a click on a point sends you to that games' page
-  var accuracySelectHandler = function(e) {
-    var selection = chart.getSelection()[0];
-    if (selection != null && selection.row != null) {
-      var game_id = data.getFormattedValue(selection.row, 0);
-      window.location.href = "http://stats.xonotic.org/game/" + game_id.toString();
-    }
-  };
-  google.visualization.events.addListener(chart, 'select', accuracySelectHandler);
-
-  chart.draw(data, options);
-}
-
-// Calculate the damage Y value for a given weapon stat
-function damageValue(gameWeaponStats, weapon) {
-  if (gameWeaponStats[weapon] == undefined) {
-    return null;
-  }
-  return gameWeaponStats[weapon].actual;
-}
-
-// Calculate the damage tooltip text for a given weapon stat
-function damageTooltip(weapon, dmg) {
-  if (dmg == null) {
-    return null;
-  }
-  return weapon + ": " + dmg.toString() + " HP damage";
-}
-
-// Draw the damage chart into the "damageChart" div id
-function drawDamageChart(weaponData) {
-
-  var data = new google.visualization.DataTable();
-  data.addColumn('string', 'X');
-  data.addColumn('number', 'Shotgun');
-  data.addColumn({type: 'string', role: 'tooltip'});
-  data.addColumn('number', 'Machine Gun');
-  data.addColumn({type: 'string', role: 'tooltip'});
-  data.addColumn('number', 'Vortex');
-  data.addColumn({type: 'string', role: 'tooltip'});
-  data.addColumn('number', 'Mortar');
-  data.addColumn({type: 'string', role: 'tooltip'});
-  data.addColumn('number', 'Electro');
-  data.addColumn({type: 'string', role: 'tooltip'});
-  data.addColumn('number', 'Crylink');
-  data.addColumn({type: 'string', role: 'tooltip'});
-  data.addColumn('number', 'Hagar');
-  data.addColumn({type: 'string', role: 'tooltip'});
-  data.addColumn('number', 'Devastator');
-  data.addColumn({type: 'string', role: 'tooltip'});
-  data.addColumn('number', 'Arc');
-  data.addColumn({type: 'string', role: 'tooltip'});
-
-  var flattened = flatten(weaponData);
-
-  for(i in weaponData.games) {
-    var game_id = weaponData.games[i];
-    var sg = damageValue(flattened[game_id], "shotgun");
-    var sgTT = damageTooltip("shotgun", sg);
-    var mg = damageValue(flattened[game_id], "machinegun");
-    var mgTT = damageTooltip("machinegun", mg); 
-    var vortex = damageValue(flattened[game_id], "vortex");
-    var vortexTT = damageTooltip("vortex", vortex);
-    var mn = damageValue(flattened[game_id], "vaporizer");
-    var mnTT = damageTooltip("vaporizer", mn);
-    var mortar = damageValue(flattened[game_id], "mortar");
-    var mortarTT = damageTooltip("mortar", mortar);
-    var electro = damageValue(flattened[game_id], "electro");
-    var electroTT = damageTooltip("electro", electro); 
-    var crylink = damageValue(flattened[game_id], "crylink");
-    var crylinkTT = damageTooltip("crylink", crylink);
-    var hagar = damageValue(flattened[game_id], "hagar");
-    var hagarTT = damageTooltip("hagar", hagar);
-    var rl = damageValue(flattened[game_id], "devastator");
-    var rlTT = damageTooltip("devastator", rl); 
-    var arc = damageValue(flattened[game_id], "arc");
-    var arcTT = damageTooltip("arc", arc); 
-
-    data.addRow([
-      game_id.toString(), 
-      sg, sgTT,
-      mg, mgTT,
-      vortex, vortexTT, 
-      mortar, mortarTT,
-      electro, electroTT,
-      crylink, crylinkTT,
-      hagar, hagarTT,
-      rl, rlTT,
-      arc, arcTT
-    ]);
-  }
-
-  var options = {
-    backgroundColor: { fill: 'transparent' },
-    legend: { 
-      position: 'top', 
-      maxLines: 3,
-      textStyle: { color: "#666" }
-    },
-    vAxis: {
-      title: 'HP Damage',  
-      titleTextStyle: {color: '#666'},
-      baselineColor: '#333',
-      gridlineColor: '#333',
-    },
-    hAxis: {
-      title: 'Games',
-      textPosition: 'none',
-      titleTextStyle: { color: '#666' },
-    },
-    isStacked: true,
-    series: {
-      0: { color: weaponColors["shotgun"] },
-      1: { color: weaponColors["machinegun"] },
-      2: { color: weaponColors["vortex"] },
-      3: { color: weaponColors["mortar"] },
-      4: { color: weaponColors["electro"] },
-      5: { color: weaponColors["crylink"] },
-      6: { color: weaponColors["hagar"] },
-      7: { color: weaponColors["devastator"] },
-      8: { color: weaponColors["arc"] }
-    }
-  };
-
-  var chart = new google.visualization.ColumnChart(document.getElementById('damageChart'));
-
-  // a click on a point sends you to that game's page
-  var damageSelectHandler = function(e) {
-    var selection = chart.getSelection()[0];
-    if (selection != null && selection.row != null) {
-      var game_id = data.getFormattedValue(selection.row, 0);
-      window.location.href = "http://stats.xonotic.org/game/" + game_id.toString();
-    }
-  };
-  google.visualization.events.addListener(chart, 'select', damageSelectHandler);
+// these weapons are used in the damage chart
+var damageWeapons = new Set(["vortex", "machinegun", "shotgun",
+        "arc", "uzi", "nex", "minstanex", "rifle", "grenadelauncher", "minelayer",
+        "rocketlauncher", "hlac", "seeker", "fireball",  
+        "mortar", "electro", "crylink", "hagar", "devastator"]);
+
+// these weapons are used in the accuracy chart
+var accuracyWeapons = new Set(["vortex", "machinegun", "shotgun", "vaporizer",
+        "arc", "uzi", "nex", "minstanex", "rifle"]);
+
+// draw an accuracy chart into the given element id
+function drawAccuracyChart(id, data) {
+
+    // transform games list into a map such that games[game_id] = linear sequence
+    var games = {};
+    data.games.forEach(function(v,i){ games[v] = i; });
+
+    // for use in filtering out weapons that were not fired
+    function wasFired(e) { return e.fired != 0; }
+
+    // for use in filtering out splash-damage weapons
+    function isAccuracyWeapon(e) { return accuracyWeapons.has(e.weapon_cd); }
+
+    // transform it into something NVD3 can use
+    var accuracyData = d3.nest().key(function(d) { return d.weapon_cd; })
+        .entries(data.weapon_stats.filter(isAccuracyWeapon).filter(wasFired));
+
+    nv.addGraph(function() {
+      var chart = nv.models.lineChart()
+        .useInteractiveGuideline(false)
+        .forceY([0,1])
+        .showLegend(true)
+        .showYAxis(true)
+        .showXAxis(true)
+        .color(function(d){ return weaponColors[d.key]; })
+        .x(function(d) { return games[d.game_id] })
+        .y(function(d) { return d.fired > 0 ? d.hit/d.fired : 0; })
+      ;
+
+      chart.tooltip.contentGenerator(function(key, y, e, graph) {
+          return "<table><tr><td>" +
+              key.point.weapon_cd + ": " +
+              Math.round(key.point.y*100) + "% (" +
+              Math.round(data.averages[key.point.weapon_cd]) + "% avg)" + 
+              "</td></tr></table>";
+      });
+
+      chart.lines.dispatch.on("elementClick", function(e) { 
+          window.location.href = "http://stats.xonotic.org/game/" + e.point.game_id.toString();
+      });
+
+      chart.yAxis
+          .axisLabel('Accuracy')
+          .tickFormat(d3.format('2%'));
+
+      chart.xAxis
+          .axisLabel('Games')
+          .tickFormat(function(e) { return ''; });
+
+      d3.select("#accuracyChartSVG")
+          .datum(accuracyData)
+          .call(chart);
+
+      nv.utils.windowResize(function() { chart.update() });
+      return chart;
+    });
+};
 
-  chart.draw(data, options);
-}
+// draw an damage chart into the given element id
+function drawDamageChart(id, data) {
+    
+    // transform games list into a map such that games[game_id] = linear sequence
+    var games = {};
+    data.games.forEach(function(v,i){ games[v] = i; });
+
+    // for use in filtering out splash-damage weapons
+    function isDamageWeapon(e) { return damageWeapons.has(e.weapon_cd); }
+
+    // transform it into something NVD3 can use
+    var damageData = d3.nest().key(function(d) { return d.weapon_cd; })
+        .entries(data.weapon_stats.filter(isDamageWeapon));
+
+    nv.addGraph(function() {
+        var chart = nv.models.multiBarChart()
+          .reduceXTicks(true)   //If 'false', every single x-axis tick label will be rendered.
+          .rotateLabels(0)      //Angle to rotate x-axis labels.
+          .showControls(true)   //Allow user to switch between 'Grouped' and 'Stacked' mode.
+          .groupSpacing(0.1)    //Distance between each group of bars.
+          .showXAxis(true)
+          .stacked(true)
+          .color(function(d){ return weaponColors[d.key]; })
+          .x(function(d) { return games[d.game_id] })
+          .y(function(d) { return d.actual; })
+        ;
+
+        chart.tooltip.contentGenerator(function(key, y, e, graph) {
+
+            var txt = "<table><tr><td>" +
+                key.data.weapon_cd  + ": " + key.data.actual + " HP damage";
+
+            if (key.data.frags > 0) {
+                if(key.data.frags > 1) {
+                    txt += " (" + key.data.frags + " frags)";
+                } else {
+                    txt += " (" + key.data.frags + " frag)";
+                }
+            }
+            txt += "</td></tr></table>";
+
+            return txt;
+        });
+
+        chart.multibar.dispatch.on("elementClick", function(e) { 
+            window.location.href = "http://stats.xonotic.org/game/" + e.data.game_id.toString();
+        });
+
+        chart.xAxis
+            .axisLabel('Games')
+            .tickFormat(function(e){ return '';});
+
+        chart.yAxis
+            .axisLabel('Damage (HP)')
+            .tickFormat(d3.format(',d'));
+
+        d3.select('#damageChartSVG')
+            .datum(damageData)
+            .call(chart);
+
+        nv.utils.windowResize(chart.update);
+
+        return chart;
+    });
+};