Last active
January 6, 2022 10:25
-
-
Save motsu0/381b8b93c9b38565b8eff1c78731f1ac to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#input-name{ | |
display: block; | |
width: 80%; | |
min-width: 80%; | |
max-width: 80%; | |
height: 150px; | |
margin: 0 auto; | |
} | |
#sel-times{ | |
display: block; | |
margin: 16px auto; | |
} | |
#bt-play{ | |
display: block; | |
margin: 20px auto; | |
cursor: pointer; | |
} | |
#bt-reset{ | |
display: block; | |
margin: 20px 0 20px auto; | |
border: none; | |
background-color: #fff; | |
color: #2C9400; | |
cursor: pointer; | |
} | |
.res-unit{ | |
padding: 0 8px; | |
margin: 8px 0; | |
border: 1px solid #aaa; | |
border-radius: 5px; | |
} | |
.res-title{ | |
padding: 8px; | |
border-bottom: 1px solid #aaa; | |
} | |
.res-body{ | |
padding: 8px; | |
margin-top: 4px; | |
} | |
.person{ | |
display: inline-block; | |
padding: 2px 8px; | |
margin: 4px; | |
border: 1px solid #71AB09; | |
} | |
/* */ | |
.loading-guage-outer{ | |
box-sizing: border-box; | |
width: 50%; | |
height: 40px; | |
margin: 0 auto; | |
position: relative; | |
border: 1px solid #333; | |
} | |
.loading-text,#loading-guage{ | |
width: 100%; | |
height: 100%; | |
position: absolute; | |
top: 0; | |
left: 0; | |
} | |
.loading-text{ | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
z-index: 2; | |
} | |
#loading-guage{ | |
z-index: 1; | |
width: 0; | |
background-color: #C8E6C9; | |
} | |
/* */ | |
#msg-box{ | |
box-sizing: border-box; | |
width: 100%; | |
position: fixed; | |
bottom: 10px; | |
left: 0; | |
z-index: 1000; | |
text-align: center; | |
pointer-events: none; | |
} | |
#message{ | |
display: inline-block; | |
box-sizing: border-box; | |
max-width: 90%; | |
padding: 10px 20px; | |
border: 2px solid #BF360C; | |
background-color: #FBE9E7; | |
color: #BF360C; | |
word-break: break-all; | |
opacity: 1; | |
pointer-events: auto; | |
} | |
#message.off{ | |
opacity: 0; | |
transition: opacity 1s; | |
pointer-events: none; | |
} | |
.invisivle{ | |
visibility: hidden; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<textarea id="input-name" placeholder="Aさん | |
Bさん | |
Cさん | |
Dさん | |
Eさん | |
Fさん | |
Gさん | |
Hさん | |
"> | |
Aさん | |
Bさん | |
Cさん | |
Dさん | |
Eさん | |
Fさん | |
Gさん | |
Hさん | |
</textarea> | |
<select id="sel-times"> | |
<option value="infinite">同じ組み合わせのペアを許可する</option> | |
<option value="once">同じ組み合わせのペアを許可しない</option> | |
</select> | |
<button id="bt-play">ペア分けを決める</button> | |
<button id="bt-reset">リセット</button> | |
<div id="loading-area" class="hide"> | |
<div class="loading-guage-outer"> | |
<div class="loading-text">ペアを作成中</div> | |
<div id="loading-guage"></div> | |
</div> | |
</div> | |
<div id="output"></div> | |
<div id="msg-box"> | |
<div id="message" class="off">データを保存しました。</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class nowLoading{ | |
constructor(){ | |
this.area = document.getElementById('loading-area'); | |
this.guage = document.getElementById('loading-guage'); | |
} | |
start(){ | |
this.guage.style.width = 0; | |
this.area.classList.remove('hide'); | |
} | |
change(n){ | |
this.guage.style.width = n+'%'; | |
} | |
stop(){ | |
this.area.classList.add('hide'); | |
} | |
} | |
const worker_name = 'path/to/make-pair-worker2.js'; | |
const input_name = document.getElementById('input-name'); | |
const output = document.getElementById('output'); | |
const sel_times = document.getElementById('sel-times'); | |
const bt_play = document.getElementById('bt-play'); | |
const bt_reset = document.getElementById('bt-reset'); | |
const message = document.getElementById('message'); | |
let worker; | |
let pair_list; | |
let res_index = 0; | |
// | |
input_name.addEventListener('input',shokika); | |
sel_times.addEventListener('change',shokika); | |
bt_play.addEventListener('click',chooseFunc); | |
bt_reset.addEventListener('click',shokika); | |
const nowloading = new nowLoading(); | |
// | |
function shokika(){ | |
if(worker!==undefined) worker.terminate(); | |
output.textContent = ''; | |
pair_list = []; | |
res_index = 0; | |
nowloading.stop(); | |
bt_play.classList.remove('invisible'); | |
} | |
function chooseFunc(){ | |
//稼働開始 | |
bt_play.classList.add('invisible'); | |
nowloading.start(); | |
// | |
if(sel_times.value=='infinite'){ | |
makeFree(); | |
}else{ | |
if(res_index==0){ | |
makePairSet(); | |
}else{ | |
outputPairSet(); | |
} | |
} | |
} | |
function makePairSet(){ | |
//名前セット作成 | |
const name_list = input_name.value.split(/\r\n|\r|\n/).map(v=>v.replace(/^[\s ]*$/,'')).filter(v=>v!='').map((v,i)=>{return {id:i,name:v}}); | |
if(name_list.length<2){ | |
nowloading.stop(); | |
msgBox('ペア分けに必要な人数に足りません。') | |
return; | |
} | |
// ペア分け 最大数まで作成 workerで並列処理 | |
worker = new Worker(worker_name); | |
worker.addEventListener('message',e=>{ | |
if(e.data.end){ | |
pair_list = e.data.list; | |
shuffle(pair_list); | |
outputPairSet(); | |
}else{ | |
nowloading.change(e.data.progress*100); | |
} | |
}); | |
worker.postMessage(name_list); | |
} | |
function makeFree(){ | |
//名前セット作成 | |
const name_list = input_name.value.split(/\r\n|\r|\n/).map(v=>v.replace(/^[\s ]*$/,'')).filter(v=>v!=''); | |
if(name_list.length<2){ | |
nowloading.stop(); | |
msgBox('ペア分けに必要な人数に足りません。') | |
return; | |
} | |
shuffle(name_list); | |
const rec = []; | |
pair_list = []; | |
while(name_list.length>1){ | |
rec.push(name_list.splice(0,2)); | |
if(name_list.length==1){ | |
rec.push([name_list.shift()]); | |
} | |
} | |
pair_list.push(rec); | |
outputPairSet(); | |
} | |
function outputPairSet(){ | |
//上限 | |
const res_max = pair_list.length; | |
if(sel_times.value!='infinite'&&res_index+1>res_max){ | |
nowloading.stop(); | |
msgBox('可能な組み合わせがありません。'); | |
return; | |
} | |
//出力 | |
//要素作成 | |
const res_unit = document.createElement('div'); | |
res_unit.classList.add('res-unit'); | |
const res_title = document.createElement('div'); | |
res_title.classList.add('res-title'); | |
res_title.textContent = `ペア分け結果(${res_index+1}回目)`; | |
const res_body = document.createElement('div'); | |
res_body.classList.add('res-body'); | |
const rec_id = (()=>{ | |
if(sel_times.value=='infinite'){ | |
return 0; | |
}else{ | |
return res_index; | |
} | |
})(); | |
for(let p=0;p<pair_list[rec_id].length;p++){ | |
pair_list[rec_id][p].forEach((p,i)=>{ | |
if(i==1){ | |
const and = document.createTextNode('&'); | |
res_body.appendChild(and); | |
} | |
const person = document.createElement('span'); | |
person.classList.add('person'); | |
person.textContent = p; | |
res_body.appendChild(person); | |
}); | |
if(p<pair_list[rec_id].length-1) res_body.appendChild(document.createElement('br')); | |
} | |
res_index++; | |
//組み立て | |
res_unit.appendChild(res_title); | |
res_unit.appendChild(res_body); | |
output.prepend(res_unit); | |
//後処理 | |
nowloading.stop(); | |
bt_play.classList.remove('invisible'); | |
} | |
function randomMN(m,n){ | |
const d = Math.max(m,n)-Math.min(m,n); | |
return Math.floor(Math.random()*(d+1)+Math.min(m,n)); | |
} | |
function shuffle(array){ | |
for(let i=array.length-1;i>=1;i--){ | |
const j = randomMN(0,i); | |
[array[j],array[i]] = [array[i],array[j]]; | |
} | |
} | |
function msgBox(str){ | |
message.textContent = str; | |
message.classList.remove('off'); | |
setTimeout(()=>{ | |
message.classList.add('off'); | |
},1000); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
self.addEventListener('message',e=>{ | |
self.postMessage({end:true,list:combi(e.data)}); | |
}); | |
function combi(array){ | |
const list = []; | |
if(array.length%2==1) array.push({id:array.length,name:''}); | |
//組み合わせ総数計算 | |
const len_max = calcLen(array); | |
//組み合わせ列挙 | |
sub_combi(array,[]); | |
//並び替え | |
sort(); | |
//重複削除 | |
return delSame(list); | |
function calcLen(arr){ | |
const n = Math.ceil(arr.length/2)*2; | |
let res = 1; | |
for(let i=0;2*i+1<n;i++){ | |
res *= (2*i+1); | |
} | |
return res; | |
} | |
function sub_combi(arr,rec){ | |
const item1 = arr.shift(); | |
arr.forEach((v,i)=>{ | |
const item2 = arr[i]; | |
const new_array = arr.slice(0,i).concat(arr.slice(i+1)); | |
const record = rec.slice(); | |
record.push([item1,item2].filter(val=>val.name!='')); | |
if(new_array.length<2){ | |
list.push(record); | |
self.postMessage({end:false,progress:list.length/len_max}); | |
}else{ | |
sub_combi(new_array,record); | |
} | |
}); | |
} | |
function sort(){ | |
for(let r=0;r<list.length;r++){ | |
for(let p=0;p<list[r].length;p++){ | |
list[r][p].sort((a,b)=>{ | |
return a.id - b.id; | |
}); | |
} | |
list[r].sort((pair_a,pair_b)=>{ | |
if(pair_a.length==1){ | |
return 1; | |
}else if(pair_b.length==1){ | |
return -1; | |
}else if(pair_a[0].id!=pair_b[0].id){ | |
return pair_a[0].id - pair_b[0].id; | |
}else{ | |
return pair_a[1].id - pair_b[1].id; | |
} | |
}); | |
} | |
list.sort((rec_a,rec_b)=>{ | |
for(let p=0;p<rec_b.length;p++){ | |
for(let d=0;d<rec_b[p].length;d++){ | |
if(rec_a[p][d].id!=rec_b[p][d].id){ | |
return rec_a[p][d].id - rec_b[p][d].id; | |
} | |
} | |
} | |
return 1; | |
}); | |
} | |
function delSame(list){ | |
const data_list = []; | |
const already = {}; | |
list.forEach(rec=>{ | |
const id_set = []; | |
for(let p=0;p<rec.length;p++){ | |
const pair_id = rec[p].map(v=>v.id).join('-'); | |
if(already[pair_id]){ | |
return; | |
} | |
id_set.push(pair_id); | |
} | |
id_set.forEach(id=>{ | |
already[id] = true; | |
}); | |
data_list.push(rec.map(pair=>pair.map(v=>v.name))); | |
}); | |
return data_list; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment