summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorschneefux <schneefux+commit@schneefux.xyz>2018-06-17 14:08:43 +0200
committerschneefux <schneefux+commit@schneefux.xyz>2018-12-13 17:09:21 +0100
commit059e3abd9995919fc2756496579c34972f9e8db5 (patch)
treec394d93c6e3b267112b4e2d59f8e652c582a9310 /src
parent77befbd2142397f4e26a03d5fecc170d4e2db566 (diff)
downloadbrokentalents-059e3abd9995919fc2756496579c34972f9e8db5.tar.gz
brokentalents-059e3abd9995919fc2756496579c34972f9e8db5.zip
ReportTable: Advantage per Level -> Max Win Rate, fix 5v5/3v3 table, add filters
Diffstat (limited to 'src')
-rw-r--r--src/ReportService.js3
-rw-r--r--src/ReportTable.vue59
-rw-r--r--src/RouterParamMixin.js30
-rw-r--r--src/WinPickScatter.vue5
4 files changed, 84 insertions, 13 deletions
diff --git a/src/ReportService.js b/src/ReportService.js
index 8bd9514..3a94671 100644
--- a/src/ReportService.js
+++ b/src/ReportService.js
@@ -2,7 +2,7 @@ import * as maps from './maps/maps';
import * as metadata from '../data/2d73896c/metadata.json';
const POPULAR_THRESHOLD = 1.0; // percent
-const PICKS_THRESHOLD = 200; // picks
+const PICKS_THRESHOLD = 300; // picks
const report = require('../data/2d73896c/report.json')
.filter((entry) => entry.Actor != undefined); // bad data from API downtime
@@ -66,6 +66,7 @@ for(let mode of modes) {
return Object.assign({}, entry, {
TalentWinrateBase: intercept,
TalentWinrateScaling: slope, // to 1 = max level
+ TalentWinrateMax: intercept + slope,
TalentWinrateLevelScaling: slope / maps.getMaxLevel(entry),
TotalPicks: sum_weights || entry.Count, // NoTalent has no weights
TotalWinner: sum_y / sum_weights || entry.Winner,
diff --git a/src/ReportTable.vue b/src/ReportTable.vue
index 4cbc280..8a0d617 100644
--- a/src/ReportTable.vue
+++ b/src/ReportTable.vue
@@ -1,9 +1,38 @@
<template>
<section>
+ <b-field>
+ <p class="control">
+ <b-dropdown v-model="filterRarity">
+ <button class="button" slot="trigger">
+ <span>{{ filterRarity || 'All' }} Talents</span>
+ <b-icon icon="menu-down"></b-icon>
+ </button>
+
+ <b-dropdown-item value="">All Talents</b-dropdown-item>
+ <b-dropdown-item v-for="rarity in RARITIES" :key="rarity" :value="rarity">{{ rarity }} Talents</b-dropdown-item>
+ </b-dropdown>
+ </p>
+
+ <b-input placeholder="Search…" type="search" icon="magnify" v-model="filterName"></b-input>
+
+ </b-field>
+
+ <b-field>
+ <div class="control">
+ <b-switch v-model="filterLowPickrate">Include entries without enough data</b-switch>
+ </div>
+ </b-field>
+
<b-table :data="report"
:default-sort="['TotalPicks', 'desc']"
:default-sort-directon="'desc'"
:paginated="true">
+ <template slot-scope="props" slot="header">
+ <b-tooltip :active="!!props.column.meta" :label="props.column.meta || ''" position="is-bottom" dashed>
+ {{ props.column.label }}
+ </b-tooltip>
+ </template>
+
<template slot-scope="props">
<b-table-column field="Actor" label="Hero" sortable>
<!-- desktop, table view -->
@@ -39,24 +68,25 @@
</div>
</b-table-column>
- <b-table-column field="Winner" label="Level 1 Win Rate" sortable numeric>
- <template v-if="isNaN(props.row.TalentWinrateBase) || props.row.SampleTooSmall">
- {{ (100 * props.row.Winner).toFixed(2) }}%
+ <b-table-column field="TalentWinrateBase" label="Level 1 Win Rate" meta="Estimated." :visible="hasTalents" sortable numeric>
+ <template v-if="isNaN(props.row.TalentWinrateBase)">
+ {{ (100 * props.row.Winner).toFixed(2) }}% <!-- No Talent -->
</template>
<template v-else>
{{ (100 * props.row.TalentWinrateBase).toFixed(2) }}%
</template>
</b-table-column>
- <b-table-column field="TalentWinrateScaling" label="Win Rate Advantage" sortable numeric>
- <template v-if="isNaN(props.row.TalentWinrateScaling) || props.row.SampleTooSmall">
- <span class="mdi mdi-gauge-empty mdi-18px" title="Not enough data"></span>
- </template>
- <template v-else>
- {{ (props.row.TalentWinrateScaling > 0? '+' : '') + (100 * props.row.TalentWinrateScaling / getLevelBuckets()).toFixed(2) }}% <small>for {{ getLevelsPerBucket(props.row) + (getLevelsPerBucket(props.row) > 1? ' Levels' : ' Level') }}</small>
+ <b-table-column field="TalentWinrateMax" label="Max Level Win Rate" meta="Estimated." :visible="hasTalents" sortable numeric>
+ <template v-if="!isNaN(props.row.TalentWinrateMax)">
+ {{ (100 * props.row.TalentWinrateMax).toFixed(2) }}%
</template>
</b-table-column>
+ <b-table-column field="Winner" label="Win Rate" :visible="!hasTalents" sortable numeric>
+ {{ (100 * props.row.Winner).toFixed(2) }}%
+ </b-table-column>
+
<b-table-column field="TotalPicks" label="Pick Rate" sortable numeric>
{{ (100 * playersPerMatch * props.row.TotalPicks / totalPicks).toFixed(2) }}%
</b-table-column>
@@ -76,6 +106,7 @@ export default Vue.component('report-table', {
mixins: [ RouterParamMixin ],
data: function() {
return {
+ RARITIES: maps.RARITIES,
getTalentName: maps.getTalentName,
getTalentRarityIndex: maps.getTalentRarityIndex,
getHero: maps.getHero,
@@ -85,7 +116,15 @@ export default Vue.component('report-table', {
},
computed: {
report: function() {
- return ReportService.getReport(this.selectedMode);
+ const giveTrue = (x) => true;
+ const filters = [
+ this.filterRarity != ''? (entry) => maps.getTalentRarity(entry.Talent) == this.filterRarity : giveTrue,
+ this.filterName != ''? (entry) => maps.getHero(entry.Actor).includes(this.filterName) || maps.getTalentName(entry.Talent).includes(this.filterName) : giveTrue,
+ !this.filterLowPickrate? (entry) => !entry.SampleTooSmall : giveTrue,
+ ];
+ const and = (a, b) => a && b;
+ return ReportService.getReport(this.selectedMode)
+ .filter((entry) => filters.map((filter) => filter(entry)).reduce(and, true));
},
totalPicks: function() {
return ReportService.getTotalPicks(this.selectedMode);
diff --git a/src/RouterParamMixin.js b/src/RouterParamMixin.js
index 073da35..0c5dbc3 100644
--- a/src/RouterParamMixin.js
+++ b/src/RouterParamMixin.js
@@ -20,5 +20,35 @@ export default {
this.$router.push({ query });
},
},
+ filterRarity: {
+ get: function() {
+ return this.$route.query.rarity || '';
+ },
+ set: function(value) {
+ this.$ga.event('Rarity', 'update', value);
+ const query = Object.assign({}, this.$route.query, { rarity: value });
+ this.$router.push({ query });
+ },
+ },
+ filterName: {
+ get: function() {
+ return this.$route.query.search || '';
+ },
+ set: function(value) {
+ this.$ga.event('Search', 'update', value);
+ const query = Object.assign({}, this.$route.query, { search: value });
+ this.$router.push({ query });
+ },
+ },
+ filterLowPickrate: {
+ get: function() {
+ return this.$route.query.lowPickrate == true;
+ },
+ set: function(value) {
+ this.$ga.event('LowPickrate', 'update', value);
+ const query = Object.assign({}, this.$route.query, { lowPickrate: value });
+ this.$router.push({ query });
+ },
+ },
},
};
diff --git a/src/WinPickScatter.vue b/src/WinPickScatter.vue
index 7c2f906..97acfbc 100644
--- a/src/WinPickScatter.vue
+++ b/src/WinPickScatter.vue
@@ -22,13 +22,14 @@ export default Vue.component('win-pick-scatter', {
selectedMode() {
this.refresh();
},
- selectedActor() {
+ filterLowPickrate() {
this.refresh();
},
},
methods: {
refresh() {
- const data = ReportService.getReport(this.selectedMode);
+ const data = ReportService.getReport(this.selectedMode)
+ .filter((entry) => !this.filterLowPickrate? !entry.SampleTooSmall : true);
const total = ReportService.getTotalPicks(this.selectedMode);
const dataWithRarity = (rarity) => data.filter((entry) => maps.getTalentRarity(entry.Talent) == rarity);