aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/README.md103
-rw-r--r--lib/components/status.js8
-rw-r--r--lib/components/wave_renderer.js44
-rw-r--r--lib/services/data.js39
-rw-r--r--lib/sorting_hat.js7
5 files changed, 183 insertions, 18 deletions
diff --git a/doc/README.md b/doc/README.md
index e69de29..495c624 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -0,0 +1,103 @@
+## Classes
+
+<dl>
+<dt><a href="#StatusComponent">StatusComponent</a></dt>
+<dd></dd>
+<dt><a href="#WaveRenderer">WaveRenderer</a></dt>
+<dd></dd>
+<dt><a href="#DataService">DataService</a></dt>
+<dd></dd>
+<dt><a href="#SortingHat">SortingHat</a></dt>
+<dd></dd>
+</dl>
+
+## Typedefs
+
+<dl>
+<dt><a href="#tSortingHatData">tSortingHatData</a> : <code>object</code></dt>
+<dd><p>The data structure representing the sorting hat data</p>
+</dd>
+<dt><a href="#tRunningAverages">tRunningAverages</a> : <code>object</code></dt>
+<dd><p>The running averages, including the current sum and count</p>
+</dd>
+</dl>
+
+<a name="StatusComponent"></a>
+
+## StatusComponent
+**Kind**: global class
+<a name="new_StatusComponent_new"></a>
+
+### new StatusComponent()
+The status class, renders the winner during the poll stage, and a
+message while waiting
+
+<a name="WaveRenderer"></a>
+
+## WaveRenderer
+**Kind**: global class
+<a name="new_WaveRenderer_new"></a>
+
+### new WaveRenderer()
+The wave renderer, draws some waves in a canvas to represent a set of
+cateogirzed averages
+
+<a name="DataService"></a>
+
+## DataService
+**Kind**: global class
+
+* [DataService](#DataService)
+ * [new DataService()](#new_DataService_new)
+ * [.data()](#DataService.data) ⇒
+
+<a name="new_DataService_new"></a>
+
+### new DataService()
+The main data service, connects to a socket and updates the internal
+data structure
+
+<a name="DataService.data"></a>
+
+### DataService.data() ⇒
+Returns the internal data structure, intended to be used as the data
+property in vue components
+
+**Kind**: static method of [<code>DataService</code>](#DataService)
+**Returns**: tSortingHatData
+<a name="SortingHat"></a>
+
+## SortingHat
+**Kind**: global class
+<a name="new_SortingHat_new"></a>
+
+### new SortingHat()
+The main vue application, it is composed by the other components, no real
+logic otherwise
+
+<a name="tSortingHatData"></a>
+
+## tSortingHatData : <code>object</code>
+The data structure representing the sorting hat data
+
+**Kind**: global typedef
+
+| Param | Type | Description |
+| --- | --- | --- |
+| state | <code>number</code> | the current state: 0 for waiting, 1 for polling, 2 for cool down. |
+| [winner] | <code>string</code> | the winner after polling, might be null if no winner is detected |
+| runningAverages | <code>Object.&lt;string, tRunningAverages&gt;</code> | the running averages for the different categories, used to render the waves |
+
+<a name="tRunningAverages"></a>
+
+## tRunningAverages : <code>object</code>
+The running averages, including the current sum and count
+
+**Kind**: global typedef
+
+| Param | Type | Description |
+| --- | --- | --- |
+| sum | <code>number</code> | the current total |
+| count | <code>number</code> | the number of samples |
+| average | <code>number</code> | the average (sum / count) |
+
diff --git a/lib/components/status.js b/lib/components/status.js
index 4a8b099..0f79788 100644
--- a/lib/components/status.js
+++ b/lib/components/status.js
@@ -3,7 +3,13 @@ import DataService from '../services/data';
const internals = {};
-export default Vue.component('posts', {
+/**
+ * The status class, renders the winner during the poll stage, and a
+ * message while waiting
+ *
+ * @class StatusComponent
+ */
+export default Vue.component('status', {
template: '<div class="status-widget">' +
'<transition name="fade">' +
'<div v-if="state === 0" class="waiting-message">Waiting</div>' +
diff --git a/lib/components/wave_renderer.js b/lib/components/wave_renderer.js
index c9cadc0..022f9ff 100644
--- a/lib/components/wave_renderer.js
+++ b/lib/components/wave_renderer.js
@@ -1,6 +1,8 @@
import Vue from 'vue';
import DataService from '../services/data';
+/* global window */
+
const internals = {
// Constants
@@ -26,7 +28,13 @@ const internals = {
}
};
-export default Vue.component('posts', {
+/**
+ * The wave renderer, draws some waves in a canvas to represent a set of
+ * cateogirzed averages
+ *
+ * @class WaveRenderer
+ */
+export default Vue.component('waveRenderer', {
template: '<transition name="fade">' +
'<canvas v-show="state === 1" class="wave-renderer"></canvas>' +
'</transition>',
@@ -43,21 +51,21 @@ export default Vue.component('posts', {
const keys = Object.keys(this.runningAverages);
- const averages = keys.reduce((averages, averageCategory) => {
+ const averages = keys.reduce((averagesObject, averageCategory) => {
const runningAverage = this.runningAverages[averageCategory];
- averages[averageCategory] = runningAverage.average;
- return averages;
+ averagesObject[averageCategory] = runningAverage.average;
+ return averagesObject;
}, {});
const max = Math.max(...Object.values(averages));
const min = Math.min(...Object.values(averages));
- const scaledAverages = Object.keys(averages).reduce((scaledAverages, averageCategory) => {
+ const scaledAverages = Object.keys(averages).reduce((scaledAveragesObject, averageCategory) => {
const value = averages[averageCategory];
- scaledAverages[averageCategory] = internals.scale(value, min, max);
- return scaledAverages;
+ scaledAveragesObject[averageCategory] = internals.scale(value, min, max);
+ return scaledAveragesObject;
}, {});
return scaledAverages;
@@ -65,6 +73,9 @@ export default Vue.component('posts', {
},
methods: {
+
+ // Reset the size of the canvas on resize
+
onResize() {
this.$el.width = window.innerWidth;
@@ -114,28 +125,27 @@ export default Vue.component('posts', {
// Iterate over the segments
- for (let currentSegment = 0; currentSegment < segments; ++currentSegment) {
- const segmentStart = currentSegment * period;
- const segmentEnd = currentSegment + period;
+ for (let i = 0; i < segments; ++i) {
+ const segmentStart = i * period;
- const category = keys[currentSegment];
- const magnitude = values[currentSegment];
+ const category = keys[i];
+ const magnitude = values[i];
const segmentHeight = Math.round(Math.random() * internals.kRandomJitter + magnitude * (canvas.height / 2) / 100);
// Calculate the gradient using the correct color according to
// scale
const color = internals.kColors[category] || 'black';
- let currentGradientPosition = currentSegment * gradientBandWidth + internals.kGradientFade;
+ let currentGradientPosition = i * gradientBandWidth + internals.kGradientFade;
fillGradient.addColorStop(currentGradientPosition, color);
- currentGradientPosition = (currentSegment + 1) * gradientBandWidth - internals.kGradientFade;
+ currentGradientPosition = (i + 1) * gradientBandWidth - internals.kGradientFade;
fillGradient.addColorStop(currentGradientPosition, color);
// This draws the sine wave
- for (let angle = 0; angle < 180; ++angle) {
- const currentPixel = segmentStart + angle * period / 180;
- const currentAngle = angle + 180 * (currentSegment % 2);
+ for (let j = 0; j < 180; ++j) {
+ const currentPixel = segmentStart + j * period / 180;
+ const currentAngle = j + 180 * (i % 2);
const currentRadians = currentAngle * Math.PI / 180;
const currentHeight = segmentHeight * Math.sin(internals.kFrequency * currentRadians);
diff --git a/lib/services/data.js b/lib/services/data.js
index cc6c5ee..c7f6744 100644
--- a/lib/services/data.js
+++ b/lib/services/data.js
@@ -1,3 +1,4 @@
+/* global WebSocket */
const internals = {
kSocketLocation: 'ws://localhost:1987',
@@ -18,7 +19,45 @@ const internals = {
}
};
+/**
+ * The data structure representing the sorting hat data
+ *
+ * @typedef tSortingHatData
+ * @type object
+ * @param {number} state the current state: 0 for waiting, 1 for
+ * polling, 2 for cool down.
+ * @param {string} [winner] the winner after polling, might be null if
+ * no winner is detected
+ * @param {Object.<string,tRunningAverages>} runningAverages the running averages for
+ * the different categories, used to render the waves
+ */
+
+/**
+ * The running averages, including the current sum and count
+ *
+ * @typedef tRunningAverages
+ * @type object
+ * @param {number} sum the current total
+ * @param {number} count the number of samples
+ * @param {number} average the average (sum / count)
+ */
+
+/**
+ * The main data service, connects to a socket and updates the internal
+ * data structure
+ *
+ * @class DataService
+ */
export default {
+
+ /**
+ * Returns the internal data structure, intended to be used as the data
+ * property in vue components
+ *
+ * @memberof DataService
+ * @method data
+ * @return tSortingHatData
+ */
data() {
if (!internals.socket) {
diff --git a/lib/sorting_hat.js b/lib/sorting_hat.js
index 4534a9f..2568b75 100644
--- a/lib/sorting_hat.js
+++ b/lib/sorting_hat.js
@@ -7,6 +7,12 @@ import StatusComponent from './components/status';
const internals = {};
+/**
+ * The main vue application, it is composed by the other components, no real
+ * logic otherwise
+ *
+ * @class SortingHat
+ */
internals.SortingHat = {
start() {
@@ -21,6 +27,7 @@ internals.SortingHat = {
}
};
+// Instantiates the app
internals.run = function () {