Browse Source

first commit: POC application.

master
kaval 2 years ago
parent
commit
9e64ec6ff7
11 changed files with 322 additions and 0 deletions
  1. +177
    -0
      app.js
  2. +79
    -0
      css/app.css
  3. BIN
      fonts/Roboto-Light.ttf
  4. +1
    -0
      images/add.svg
  5. +1
    -0
      images/group.svg
  6. +1
    -0
      images/play.svg
  7. +1
    -0
      images/random.svg
  8. +1
    -0
      images/round.svg
  9. +1
    -0
      images/upload.svg
  10. +40
    -0
      index.html
  11. +20
    -0
      people_sample.txt

+ 177
- 0
app.js View File

@@ -0,0 +1,177 @@
const TESTS_LIST = ['Charles', 'Baruch','Frédéric', 'John', 'Dan',
'Linus', 'Nina', 'Mikhaïl', 'Russel', 'Françoise',
'Albert', 'Beth', 'Erykah', 'Aretha', 'Lucio',
'Bartleby','Zach','Patti','Aesop','Vernon']

var participants;

function loadParticipantsFileChooser(){
document.getElementById('filechooser').click()
}
function loadTest(){
addParticipants(TESTS_LIST)
}

function loadParticipantsFromFile(file){

let reader = new FileReader();
let contents = reader.readAsText(file);
reader.onload = function(event) {
let contents = reader.result;
let lines = contents.split('\n');
addParticipants(lines)
};

}

function addParticipants(list){
list.forEach(function(item) {
if(item.trim() !== '')
addParticipant(item)
});
}

function addParticipant(name){
var newInput = document.createElement('input');
newInput.setAttribute('class','participant');
newInput.setAttribute('placeholder','participant');
if(name)
newInput.value = name;
document.getElementById('participants').appendChild(newInput)

}

function russellize(){
let availablesPerParticipants = new Map()

participants.forEach(function (p) {
availablesPerParticipants.set(p,participants.slice().filter(el => el !== p))
});

let k = document.getElementById('nbPerGroup').value
let nbRounds = document.getElementById('nbRounds').value
let nbGroups = Math.ceil(participants.length / k)
let rounds = new Array()

for(let i = 1; i <= nbRounds; i++){
let round = new Array()
let availables = participants.slice()
for(let j = 0; j < nbGroups ; j++){
let currentGroup = new Array()
let toTest = availables.slice()
while(currentGroup.length < k){
let random = Math.floor(Math.random()*toTest.length)
let randomParticipant = toTest[random]
let ok = true
toTest.splice(random, 1);
// console.log(randomParticipant + '/' + random)
currentGroup.forEach(function (p) {
if(availablesPerParticipants.get(p).indexOf(randomParticipant)<0){
ok = false
return
}
})

if(!ok && toTest.length === 0){
return false
}

if(ok){
let randomEq = availables.indexOf(randomParticipant)
availables.splice(randomEq, 1);
// console.log(availables)
currentGroup.forEach(function (p) {
let l = availablesPerParticipants.get(p)
let index = l.indexOf(randomParticipant)
l.splice(index,1)
})
currentGroup.push(randomParticipant)
}
}
round.push(currentGroup)
}
rounds.push(round)
}

return rounds
}


function run(){
doIt()
}

function doIt(){

participants = new Array()

var inputs = document.getElementsByClassName('participant')
for(var i = 0; i < inputs.length; i++){
participants.push(inputs[i].value)
}

let rounds = false
let attempts = 0
while(!rounds){
attempts ++
rounds = russellize()
}
console.log(rounds)
console.log("Attempts = " + attempts)
let stats = new Map()
participants.forEach(function (p) {
let l = new Array()
stats.set(p,l)
rounds.forEach(function (round) {
round.forEach(function (group) {
if(group.indexOf(p)>=0){
group.forEach(function (p2) {
if(p !== p2){
l.push(p2)
}
})
}
})
})
})

document.getElementById('rounds').innerHTML=''
let view = renderRounds(rounds)
document.getElementById('rounds').appendChild(view)
}

function renderRounds(rounds){
let x = 1
let roundsBlock = document.createElement('div')
rounds.forEach(function (round) {
let roundBlockWrap = document.createElement('div')
let roundBlock = document.createElement('div')
let roundTitle = document.createElement('h2')
let roundTitleText = document.createTextNode('Round ' + x)
roundTitle.appendChild(roundTitleText)
roundBlockWrap.appendChild(roundTitle)
roundBlock.classList.add('round')
let y = 1
round.forEach(function (group) {
let groupBlock = document.createElement('div')
let groupTitle = document.createElement('h4')
let groupTitleText = document.createTextNode('Group ' + y)
groupTitle.append(groupTitleText)
groupBlock.append(groupTitle)
roundBlock.append(groupBlock)
let list = document.createElement('ul')
groupBlock.appendChild(list)
groupBlock.classList.add('group')
group.forEach(function (p) {
let item = document.createElement('li')
item.appendChild(document.createTextNode(p))
list.appendChild(item)
})
y ++
})
x++
roundBlockWrap.append(roundBlock)
roundsBlock.appendChild(roundBlockWrap)
})
return roundsBlock
}

+ 79
- 0
css/app.css View File

@@ -0,0 +1,79 @@
@font-face {
font-family: 'Roboto';
src: url('../fonts/Roboto-Light.ttf');
}

html, body{
margin:0px;
padding:0px;
font-family: 'Roboto';
}
#rounds, #participants{
padding:10px;
}
.round{
display:flex;
flex-wrap: wrap;
}
.group{
margin:5px;
border: 1px solid #aaa;
border-radius:3px;
padding:5px;
width: 15%;

}
h4{
margin:5px;
}
.group ul {
list-style-type: square;
}
label{
display:inline-block;
}

.participant{
margin:2px;
}

#participants{
border-bottom: 2px solid black;
padding-bottom:10px;
margin-top:20px;
}
nav{
display: flex;
justify-content: space-between;
padding:10px;
}
button{
background-color: white;
border: 1px solid #333;
border-radius: 2px;
cursor:pointer;
}

button img{
vertical-align: middle;
}
button:hover{
background-color: #ddd;
}

#settings > div{
height:32px;
}

#settings input{
width:80px;
}

#settings img{
vertical-align: bottom;
margin-right:10px;
}

#filechooser{
display:none;
}

BIN
fonts/Roboto-Light.ttf View File


+ 1
- 0
images/add.svg View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/><path d="M0 0h24v24H0z" fill="none"/></svg>

+ 1
- 0
images/group.svg View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/></svg>

+ 1
- 0
images/play.svg View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/><path d="M0 0h24v24H0z" fill="none"/></svg>

+ 1
- 0
images/random.svg View File

@@ -0,0 +1 @@
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 512 512" height="512px" id="Layer_1" version="1.1" viewBox="0 0 512 512" width="512px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g id="_x23_231f20ff"><path d="M409.434,82.96c30.04,25.7,60.08,51.42,89.971,77.29c-29.49,26.511-60.15,51.851-90.101,77.9 c0.07-17.43-0.11-34.851,0.061-52.271c-19,0.03-38-0.109-56.99,0.061c-9.13,0.02-17.72,4.58-23.87,11.16 c-54.55,56.779-109.21,113.46-163.74,170.26c-6.06,6.29-14.51,10.4-23.34,10.32c-34.689,0.22-69.39-0.17-104.069,0.229 c-12.891-0.38-23.95-12.06-23.94-24.89c-0.64-13.91,11.62-25.9,25.28-26.311c27.55-0.26,55.13,0.15,82.68-0.189 c10.05-0.061,18.9-5.92,25.24-13.32c53.72-55.939,107.5-111.83,161.25-167.75c6.04-6.59,14.72-10.65,23.68-10.85 c25.939-0.11,51.89,0.1,77.82-0.101C409.313,117.32,409.174,100.141,409.434,82.96z"/><path d="M32.764,134.48c37.5-0.311,75.131,0.03,112.69-0.08c9.68-0.43,19.54,3.2,26.12,10.43 c15.609,16.061,31.05,32.311,46.57,48.46c6.359,6.5,9.85,15.96,7.64,24.98c-2.41,11.04-12.98,19.819-24.36,19.71 c-7.729,0.35-14.85-3.59-20.54-8.48c-10.64-11.34-20.84-23.12-31.649-34.31c-6.19-6.3-15.09-9.41-23.83-9.29 c-27.99-0.12-55.98,0.08-83.971-0.09c-11.14-0.34-23.02-5.601-27.13-16.66C7.974,155.07,17.654,137.19,32.764,134.48z"/><path d="M261.554,278.17c9.67-7.729,24.83-6.609,33.36,2.32c11.689,11.98,23.13,24.21,34.83,36.18 c6.08,6.41,14.84,10.07,23.67,9.98c18.66-0.07,37.319,0.08,55.99-0.09c-0.19-17.11-0.07-34.221-0.04-51.33 c30.27,25.64,60.31,51.55,90.3,77.52c-29.95,25.95-60.061,51.71-90.221,77.41c-0.38-17.5,0.04-35.01-0.189-52.51 c-25.97-0.24-51.94-0.021-77.91-0.11c-8.95-0.08-17.57-4.35-23.56-10.91c-16.73-17.27-33.73-34.27-50.29-51.689 C247.904,304.471,250.034,286.36,261.554,278.17z"/></g></svg>

+ 1
- 0
images/round.svg View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM8 17.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5zM9.5 8c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5S9.5 9.38 9.5 8zm6.5 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></svg>

+ 1
- 0
images/upload.svg View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h4v-2H5V8h14v10h-4v2h4c1.1 0 2-.9 2-2V6c0-1.1-.89-2-2-2zm-7 6l-4 4h3v6h2v-6h3l-4-4z"/></svg>

+ 40
- 0
index.html View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Round table groups generator</title>
<link href="css/app.css" rel="stylesheet">
<script src="app.js"></script>
</head>
<body>
<nav>
<div>
<button title="load participants from file" onclick="loadParticipantsFileChooser()">
<img src='images/upload.svg' />
</button>
<button title="load test participants" onclick="loadTest()">
<img src='images/random.svg'width="24px"/>
</button>
<button title="add participant" onclick="addParticipant()">
<img src='images/add.svg' />
</button>
<button id="btn-do-it" title="run" onclick="run()">
<img src="images/play.svg"/>
</button>
<input id="filechooser" type="file" onchange="loadParticipantsFromFile(this.files[0])"/>
</div>
<div id="settings">
<div><label><img title="Table/Group size" src="images/group.svg"></label><input title="Table/Group size" type="number" value="4" id="nbPerGroup"/></div>
<div>
<label><img title="Number of rounds" src="images/round.svg"></label><input type="number" title="Number of rounds" value="6" id="nbRounds"/>
</div>
</div>
</nav>

<div id="participants"></div>

<div id="rounds"></div>

</body>
</html>

+ 20
- 0
people_sample.txt View File

@@ -0,0 +1,20 @@
Janeth
Versie
Mayola
Toni
Geoffrey
Suanne
Chang
Genaro
Shona
Arletta
Tiesha
Jo
Madge
Roselyn
Delmar
Staci
Christoper
Bernice
Alvera
Charlesetta

Loading…
Cancel
Save