diff options
author | emkael <emkael@tlen.pl> | 2021-01-20 00:20:38 +0100 |
---|---|---|
committer | emkael <emkael@tlen.pl> | 2021-01-20 00:20:38 +0100 |
commit | 14065d53b981a8f75ae5c1ea6e2642614f093c89 (patch) | |
tree | 5edd20bd65546badf8f36c78dd540f54fa21d2fe | |
parent | 80f000b76807fec6980340eac595cc6f4b7b0183 (diff) |
Scatter charts and tooltip fixes
-rw-r--r-- | result/index.html | 10 | ||||
-rw-r--r-- | result/krafcik.css | 18 | ||||
-rw-r--r-- | result/krafcik.js | 156 |
3 files changed, 123 insertions, 61 deletions
diff --git a/result/index.html b/result/index.html index 4a8009c..e136110 100644 --- a/result/index.html +++ b/result/index.html @@ -17,7 +17,7 @@ <main class="container"> - <h1>Polski Krafcik <span class="lead">2012-2020</span></h1> + <h1>Polski Krafcik <span class="lead">2012-2020 <small>(R.I.P.)</small></span></h1> <form id="filters"> @@ -73,6 +73,14 @@ </div> </div> + <div class="card"> + <div class="card-body"> + Browary o co najmniej 10.000 ocen. Piwa o co najmniej 15 ocenach, o określonym ABV i dodane w 2020 lub wcześniej.<br /> + Liczba ocen przeliczana per miesiąc od czasu dodania; dla piw nieprodukowanych: max. 12 miesięcy.<br /> + Dane pobrane z Untappd <time id="compile-date" datetime="2021-01-10">19 stycznia 2021</time>.<br /> + </div> + </div> + </main><!-- /.container --> <template id="brewery-template"> diff --git a/result/krafcik.css b/result/krafcik.css index 55a8a98..53de009 100644 --- a/result/krafcik.css +++ b/result/krafcik.css @@ -30,15 +30,15 @@ html, body { } #brewery-filter label img { - width: 30px; + width: 50px; } #chart-tooltip { position: absolute; background: rgba(255, 255, 200, 0.75); + border: solid 1px black; padding: 0.5em; font-size: 0.7em; - border: solid 1px black; pointer-events: none; } @@ -56,18 +56,20 @@ html, body { } #chart-tooltip dl { - display: flex; + display: grid; + width: 100%; + grid-column-gap: 1em; + grid-template-columns: 1fr min-content; margin: 0; + padding: 0 0.5em 0 0; } -#chart-tooltip dt { - width: 80%; +#chart-tooltip dt, +#chart-tooltip dd { + margin: 0; white-space: nowrap; } #chart-tooltip dd { - margin: 0; - width: 20%; - min-width: 30px; text-align: right; } diff --git a/result/krafcik.js b/result/krafcik.js index cdb0b9e..d0b70a7 100644 --- a/result/krafcik.js +++ b/result/krafcik.js @@ -5,27 +5,40 @@ $(document).ready(function() { $.getJSON('breweries.json'), $.getJSON('styles.json') ).done(function(beerData, breweryData, styleData) { + var compileDate = Date.parse($('time#compile-date').attr('datetime')); var beers = beerData[0]; $.each(beers, function(idx, beer) { + var addedDate = new Date(); + addedDate.setYear(beer.added.year); + addedDate.setMonth(beer.added.month-1); + addedDate.setDate(beer.added.day); + var dateDiff = Math.ceil((compileDate - addedDate.getTime()) / (1000 * 60 * 60 * 24 * 30)); + if (!beer.in_production) { + dateDiff = Math.min(dateDiff, 12); + } + beer.ratings.adjusted = beer.ratings.count / dateDiff; beer['scatter-data'] = [ { x: beer.abv, - y: beer.ratings + y: beer.ratings.adjusted, + ref: beer }, { x: beer.abv, - y: beer.average + y: beer.ratings.average, + reef: beer }, { - x: beer.ratings, - y: beer.average + x: beer.ratings.adjusted, + y: beer.ratings.average, + ref: beer } ]; }); - var minYear = Math.min.apply(null, beers.map(b => b.year)); - var maxYear = Math.max.apply(null, beers.map(b => b.year)); - var minMonth = Math.min.apply(null, beers.filter(b => (b.year == minYear)).map(b => b.month)); - var maxMonth = Math.min.apply(null, beers.filter(b => (b.year == maxYear)).map(b => b.month)); + var minYear = Math.min.apply(null, beers.map(b => b.added.year)); + var maxYear = Math.max.apply(null, beers.map(b => b.added.year)); + var minMonth = Math.min.apply(null, beers.filter(b => (b.added.year == minYear)).map(b => b.added.month)); + var maxMonth = Math.max.apply(null, beers.filter(b => (b.added.year == maxYear)).map(b => b.added.month)); var fullYears = maxYear - minYear - 1; var dateCount = fullYears * 12 + (12 - minMonth + 1) + maxMonth; var dateMapping = []; @@ -114,11 +127,65 @@ $(document).ready(function() { return { borderColor: style.colour, backgroundColor: Color(style.colour).alpha(0.5).rgbString(), + label: style.name, data: [] }; }) }; } + + var displayTooltip = function(chart, tooltip, data, contentFunction) { + var container = $('#chart-tooltip'); + if (!container.length) { + container = $('<div id="chart-tooltip"></div>'); + $('body').append(container); + } + if (tooltip.body) { + var positionY = chart.canvas.offsetTop; + var positionX = chart.canvas.offsetLeft; + container.html(contentFunction(tooltip, data)).show(); + container.css({ + 'top': Math.min( + positionY + tooltip.caretY, + $('body').height() - container.outerHeight() + ), + 'left': Math.min( + positionX + tooltip.caretX, + $('body').width() - container.outerWidth() + ) + }).addClass(chart.canvas.id).show(); + } else { + container.html('').removeAttr('class').hide(); + } + }; + var scatterTooltip = function(tooltip, data) { + var content = $('<div>'); + var datasets = data.datasets; + $.each(tooltip.dataPoints, function(d, dataPoint) { + var beer = datasets[dataPoint.datasetIndex].data[dataPoint.index].ref; + content.append( + $('<div>').append($('<strong>').text(beer.name)), + $('<div>').append($('<span>').text(breweries[beer.brewery].name)), + $('<div>').append($('<em>').text(beer.style.join(' - '))), + $('<dl>').append( + $('<dt>').text('ABV'), + $('<dd>').text(`${beer.abv}%`), + $('<dt>').text('L. ocen'), + $('<dd>').text(beer.ratings.count), + $('<dt>').text('Śr. ocen'), + $('<dd>').text(beer.ratings.average), + $('<dt>').text('Dodane'), + $('<dd>').text([ + `0${beer.added.day}`.slice(-2), + `0${beer.added.month}`.slice(-2), + beer.added.year + ].join('-')) + ) + ); + }); + return content; + }; + var stylesChart; $('a#styles-tab').on('shown.bs.tab', function() { if (!stylesChart) { @@ -129,8 +196,8 @@ $(document).ready(function() { labels: styleNames, datasets: [{ data: styleCounts, - backgroundColor: styleColours, - borderColor: '#000000', + backgroundColor: styleColours.map(c => Color(c).alpha(0.5).rgbString()), + borderColor: styleColours, borderWidth: 1 }] }, @@ -148,20 +215,15 @@ $(document).ready(function() { tooltips: { enabled: false, custom: function(tooltip) { - var container = $('#chart-tooltip'); - if (!container.length) { - container = $('<div id="chart-tooltip"></div>'); - $('body').append(container); - } - if (tooltip.body) { + displayTooltip(this._chart, tooltip, this._data, function(tooltip, data) { var content = $('<ul>'); $.each(styles[tooltip.dataPoints[0].index].styleTree, function(style, substyles) { var getItem = function(style, substyle) { - var count = substyleCounts[substyle ? (style + ' - ' + substyle) : style]; + var count = substyleCounts[substyle ? (`${style} - ${substyle}`) : style]; if (count) { var term = $('<dt>'); var value = $('<dd>'); - var item = $('<li>').append($('<dl>').append(term).append(value)); + var item = $('<li>').append($('<dl>').append(term, value)); term.html(substyle || style); value.html(count); return item; @@ -179,28 +241,14 @@ $(document).ready(function() { } }); if (nonZero) { - content.append($('<li>').append(style).append(sublist)); + content.append($('<li>').append(style, sublist)); } } else { content.append(getItem(style)); } }); - var positionY = this._chart.canvas.offsetTop; - var positionX = this._chart.canvas.offsetLeft; - container.html(content).show(); - container.css({ - 'top': Math.min( - positionY + tooltip.caretY, - $('body').height() - container.outerHeight() - ), - 'left': Math.min( - positionX + tooltip.caretX, - $('body').width() - container.outerWidth() - ) - }).show(); - } else { - container.html('').hide(); - } + return content; + }); } } } @@ -210,22 +258,20 @@ $(document).ready(function() { var ratingAxis = { type: 'logarithmic', ticks: { - min: 15, - max: Math.ceil(Math.max.apply(null, beers.map(b => b.ratings)) / 1000) * 1000, - callback: value => value.toLocaleString() + min: 0, + callback: value => value.toLocaleString(), + autoSkipPadding: 20 } }; var averageAxis = { ticks: { - min: Math.floor(Math.min.apply(null, beers.map(b => b.average)) * 2) * 0.5, + min: Math.floor(Math.min.apply(null, beers.map(b => b.ratings.average)) * 2) * 0.5, max: 5 } }; var abvAxis = { ticks: { - beginAtZero: true, - min: 0, - max: Math.ceil(Math.max.apply(null, beers.map(b => b.abv)) * 2) * 0.5 + min: 0 } }; var abvRatingsChart; @@ -240,7 +286,6 @@ $(document).ready(function() { yAxes: [ratingAxis] } } - }); } }); @@ -269,6 +314,12 @@ $(document).ready(function() { scales: { xAxes: [ratingAxis], yAxes: [averageAxis] + }, + tooltips: { + enabled: false, + custom: function(tooltip) { + displayTooltip(this._chart, tooltip, this._data, scatterTooltip); + } } } }); @@ -279,7 +330,7 @@ $(document).ready(function() { var dates = $('#date-filter input[name="date"]').val().split(',').map(d => dateMapping[parseInt(d)]); var breweries = $('#brewery-filter input:checked').map(function(i, input) { return input.value; }).toArray(); return beers.filter(function(beer) { - var added = beer.year + '-' + ('0' + beer.month).slice(-2); + var added = beer.added.year + '-' + `0${beer.added.month}`.slice(-2); return (breweries.indexOf(beer.brewery) > -1) && (added >= dates[0] && added <= dates[1]); }); @@ -288,8 +339,8 @@ $(document).ready(function() { var updateCharts = function() { var filtered = getFilteredBeers(beers); var bySubstyle = {}; - for (var style in substyleCounts) { - substyleCounts[style] = 0; + for (var s in substyleCounts) { + substyleCounts[s] = 0; } for (var beer in filtered) { var style = filtered[beer].style.join(' - '); @@ -311,8 +362,8 @@ $(document).ready(function() { var substyle = styleSubstyles[s][ss]; if (substyleCounts[substyle]) { styleCounts[s] += substyleCounts[substyle]; - for (var i = 0; i < 3; i++) { - scatterChartData[i].datasets[s].data = scatterChartData[i].datasets[s].data.concat(bySubstyle[substyle].map(d => d[i])); + for (var j = 0; j < 3; j++) { + scatterChartData[j].datasets[s].data = scatterChartData[j].datasets[s].data.concat(bySubstyle[substyle].map(d => d[j])); } } } @@ -337,12 +388,13 @@ $(document).ready(function() { changeTimeout = setTimeout(updateCharts, 500); }); - $('a#styles-tab').trigger('shown.bs.tab'); + var pageHash = location.hash.replace('#', '') || 'styles'; + $(`a#${pageHash}-tab`).click().trigger('shown.bs.tab'); updateCharts(); }); $('#tab-menu a').on('click', function (e) { - e.preventDefault() - $(this).tab('show') - }) + e.preventDefault(); + $(this).tab('show'); + }); }); |