diff options
| author | schneefux <schneefux+commit@schneefux.xyz> | 2018-06-17 14:08:43 +0200 |
|---|---|---|
| committer | schneefux <schneefux+commit@schneefux.xyz> | 2018-12-13 17:09:21 +0100 |
| commit | 059e3abd9995919fc2756496579c34972f9e8db5 (patch) | |
| tree | c394d93c6e3b267112b4e2d59f8e652c582a9310 /src | |
| parent | 77befbd2142397f4e26a03d5fecc170d4e2db566 (diff) | |
| download | brokentalents-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.js | 3 | ||||
| -rw-r--r-- | src/ReportTable.vue | 59 | ||||
| -rw-r--r-- | src/RouterParamMixin.js | 30 | ||||
| -rw-r--r-- | src/WinPickScatter.vue | 5 |
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); |
