Commit cb379802 cb379802ece30bb2e58f605826cf25de76b654d2 by Vincent Peybernes

!1 Integrate developments for version 0.1.0

* development:
  #9 Prepare publish
  #9 Add licence
  #9 Prepare publish - add README
  #10 Error in new test 20x9
  #8 Improve result test of election - add display matrix job
  #8 Improve result test of election - add display matrix job
  Implement addVotes
  #9 Prepare publish
  Update results_data.json (Jose de la Mancha - Test 20x9)
  #8 Improve result test of election
  Update .gitlab-ci.yml
  Update .gitlab-ci.yml
  Update .gitlab-ci.yml
  #7 Add build task to transpil
2 parents 4d61bcc8 7a2b23bb
Pipeline #27 for cb379802 passed in 1 minute 39 seconds
.idea
node_modules
dist
\ No newline at end of file
......
......@@ -6,9 +6,22 @@ cache:
stages:
- test
- build
node_test:
stage: test
script:
- npm install
- npm test
display_details:
stage: test
when: manual
script:
- node tests/node/displayResults.js
build:
stage: build
script:
- npm install
- npm run build
......
.gitlab
.gitlab-ci.yml
.gitignore
tests
node_modules
*.log
\ No newline at end of file
The MIT License (MIT)
Copyright (c) 2016 Vincent Peybernes
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# RelativePlacementJS
[![build status](http://gitlab.techniv.fr/WestCoastSwing/RelativePlacement/badges/master/build.svg)](http://gitlab.techniv.fr/WestCoastSwing/RelativePlacement/commits/master)
This library provide an placement system with the relative placement algorithm used in
West Coast Swing dance competitions.
## Understading relative placement
Relative placement is a placement system where electors (judges) provide there own placement
of each candidates.
The algorithm consist to search for each place a majority of votes for a candidate at this
placement or a greater placement.
You can refer to [this explain from boogiebythebay.org][1] for all the details.
## Get RelativePlacementJS
```shell
npm install relative-placement-js --save
```
With node:
```javascript
var RelativePlacement = require('relative-placement-js');
```
With browser:
```html
<script src="{BASE_PATH}/node_modules/relative-placement-js/dist/relative-placement.js"></script>
<!-- Or the original ES6 sources -->
<script src="{BASE_PATH}/node_modules/relative-placement-js/lib/relative-placement.js"></script>
```
With AngularJS:
```javascript
angular.module('myApp', ['relative-placement-js']).controller('MyCtrl', [
'$scope', 'RelativePlacement',
function($scope, RelativePlacement){
}
]);
```
## Use RelativePlacementJS
```javascript
var contest = new RelativePlacement();
contest.addCandidates(['A','B','C']);
contest.addCandidate('D');
contest.addVote(['A','B','C','D']);
contest.addVotes([
['A','B','C','D'],
['A','C','B','D'],
['A','B','D','C'],
['B','A','C','D'],
['B','A','D','C']
]);
var result = contest.getResult(); // return ['A','B','C','D'];
```
[1]: http://www.boogiebythebay.org/sitebuildercontent/sitebuilderfiles/bbb_relativeplacement.pdf
\ No newline at end of file
/**
* Created by Techniv on 05/12/2016.
*/
const srcPath = './lib/relative-placement.js';
const distPath = './dist/';
var gulp = require('gulp');
var babel = require('gulp-babel');
var del = require('del');
gulp.task('default', ['build']);
gulp.task('build',['clean'], ()=>{
return gulp.src(srcPath)
.pipe(babel({
presets: ['es2015']
}))
.pipe(gulp.dest(distPath));
});
gulp.task('clean',() => {
return del(distPath);
});
\ No newline at end of file
/**
* Created by Techniv on 30/11/2016.
* @module relative_placement
* @module relativePlacement
*/
(function (define) {
module.exports = define();
(function (definition) {
// Node export
if(global && module && module.exports) return module.exports = definition();
//Browser export
if(window){
if(angular && angular.version.major == 1) return angular.module('relative-placement-js').factory('RelativePlacement', definition);
if(requirejs) return define(definition());
window.RelativePlacement = definition();
}
})(function(){
/**
......@@ -74,7 +82,14 @@
candidate.votes.push(i);
}
};
RelativePlacement.prototype.addVotes = function () {};
/**
*
* @param {String[][]} votes
*/
RelativePlacement.prototype.addVotes = function (votes) {
votes.forEach(vote => this.addVote(vote));
};
RelativePlacement.prototype.getResult = function () {
return relativePlacement(this.votes, this.candidateList);
};
......@@ -163,7 +178,6 @@
return 0;
});
result = result.concat(proposed.map(candidate => candidate.name));
cursor = result.length;
proposed.splice(0);
continue;
}
......
{
"name": "relative-placement-js",
"version": "0.0.1",
"description": "JavaScript Relative Placement calculator for dance competitions.",
"author":{
"name": "Techniv",
"email": "contact@techniv.fr"
},
"main": "./lib/relative-placement.js",
"repository":{
"type": "git",
"url": "http://gitlab.techniv.fr/WestCoastSwing/RelativePlacement"
},
"bugs": {
"url": "http://gitlab.techniv.fr/WestCoastSwing/RelativePlacement/issues"
},
"devDependencies": {
"gulp": "*",
"nodeunit": "*",
"mocha": "*",
"karma": "*",
"karma-mocha": "*"
"gulp-babel": "*",
"del": "*",
"babel-preset-es2015": "*",
"mocha": "*"
},
"scripts": {
"build": "./node_modules/.bin/gulp build",
"test" : "./node_modules/.bin/mocha bdd tests/node/**/*Spec.js"
},
"engines": {
"node": ">=6.9.*"
}
}
......
......@@ -2,7 +2,7 @@
* Created by Techniv on 30/11/2016.
*/
var assert = require('assert');
var RelativePlacement = require('../../relative-placement');
var RelativePlacement = require('../../lib/relative-placement');
describe('RelativePlacement global', () => {
it('should provide RelativePlacement constructor', () => {
......@@ -158,5 +158,18 @@ describe('RelativePlacement global', () => {
assert.ok(candidates.every(name => result.indexOf(name) != -1));
assert.ok(result.every(name => candidates.indexOf(name) != -1));
});
it('should have placements sum in candidates', () => {
election.addVote(['A', 'B', 'C']);
election.addVote(['B', 'A', 'C']);
election.addVote(['A', 'C', 'B']);
election.getResult();
var candidate = election.candidateList['A'];
assert.equal(candidate.placements.length, 3);
assert.equal(candidate.cumulativePlacement.length, 3);
assert.equal(candidate.votes.length, 4);
});
});
});
\ No newline at end of file
......
......@@ -3,7 +3,7 @@
*/
var assert = require('assert');
/** @type RelativePlacement.relativePlacement */
var relativePlacement = require('../../relative-placement').relativePlacement;
var relativePlacement = require('../../lib/relative-placement').relativePlacement;
/** @var {TestData[]} */
var testDataList = require('./results_data.json');
describe('RelativePlacement algo', () => {
......@@ -19,6 +19,7 @@ describe('RelativePlacement algo', () => {
(testData,id) => {
testData.id = id;
it('#'+id+': '+(testData.comment||''), ()=>{
id;
var votes = compileVotes(testData);
var result = relativePlacement(votes);
......
/**
* Created by Techniv on 07/12/2016.
*/
var RelativePlacement = require('../../lib/relative-placement');
var data = require('./results_data.json');
var util = require('util');
var exitCode = 0;
console.log('############################');
console.log('# Details of result matrix #');
console.log('############################');
console.log('');
console.log('The cadidate are display in order of placement');
console.log('');
console.log('Column:');
console.log('Expected | (*error)Candidate\t[Votes]\t[Sum matrix (Sum score)]');
console.log('');
console.log('');
console.log('');
console.log('');
data.forEach((testCase, num) => {
console.log("#"+ num + ": "+testCase.comment);
var election = new RelativePlacement();
var votes = compileVotes(testCase);
election.addCandidates(votes[0]);
election.addVotes(votes);
var result = election.getResult();
var expected = testCase.result;
var candidates = election.candidateList;
result.forEach((candidateName, place) => {
var log = [];
var candidate = candidates[candidateName];
log.push(expected[place]);
log.push('\t|\t');
if(candidateName != expected[place]) exitCode = 1;
(candidateName != expected[place]) ? log.push('*') : log.push(' ');
log.push(candidateName);
log.push('\t');
log.push(util.format(candidate.votes));
log.push('\t[');
for (var i = 0; i < candidate.placements.length; i++){
log.push(i==0 ? ' ' : ', ');
log.push(candidate.placements[i]);
log.push('(');
log.push(candidate.cumulativePlacement[i]);
log.push(') ');
}
log.push(' ]');
console.log(log.join(''));
});
console.log('-------------------------------------------------------------------');
console.log('');
console.log('');
});
process.exit(exitCode);
/**
* @param {TestData} testData
* @return {String[][]}
*/
function compileVotes(testData){
var votes = testData.votes;
var compileVotes = [];
var candidates = Object.keys(votes);
var voteNumber = votes[candidates[0]].length;
for(let i = 0; i < voteNumber; i++){
let compileVote = [];
for(let name in votes){
compileVote[votes[name][i]-1] = name;
}
compileVotes[i] = compileVote;
}
return compileVotes;
}
\ No newline at end of file
......@@ -45,5 +45,31 @@
"Couple H": [3,7,7,7,3]
},
"result":["Couple A","Couple B","Couple C","Couple D","Couple E","Couple F","Couple G","Couple H"]
},
{
"comment": "Jose de la Mancha - Test 20x9",
"votes":{
"101": [11,4,9,14,2,6,15,8,1],
"102": [9,7,19,20,4,8,16,1,10],
"103": [7,9,3,2,5,13,7,6,8],
"104": [14,11,1,16,16,1,17,20,7],
"105": [8,16,18,18,6,3,14,3,11],
"106": [19,14,6,8,12,9,2,9,9],
"107": [2,3,5,11,19,10,6,16,19],
"108": [18,8,16,10,18,14,1,4,17],
"109": [15,10,11,3,20,5,8,17,5],
"110": [12,12,7,4,14,15,18,12,16],
"111": [13,5,2,5,17,17,10,15,18],
"112": [4,17,15,9,13,2,11,2,12],
"113": [5,6,13,12,1,20,5,11,20],
"114": [17,19,10,1,11,11,13,5,13],
"115": [6,15,8,19,3,18,12,19,3],
"116": [3,1,14,13,8,19,9,7,6],
"117": [10,18,17,15,7,7,3,13,2],
"118": [1,20,12,17,10,12,19,10,14],
"119": [16,13,4,6,15,4,4,18,15],
"120": [20,2,20,7,9,16,20,14,4]
},
"result":["103","101","116","106","102","107","117","109","112","113","105","114","115","118","110","119","111","104","120","108"]
}
]
\ No newline at end of file
......