Skip to content

Instantly share code, notes, and snippets.

@Jehong-Ahn
Created September 17, 2018 07:46
Show Gist options
  • Save Jehong-Ahn/e07e50fdb08f5285fbcda43c717d2cb1 to your computer and use it in GitHub Desktop.
Save Jehong-Ahn/e07e50fdb08f5285fbcda43c717d2cb1 to your computer and use it in GitHub Desktop.
조편성 프로그램
var sheet = SpreadsheetApp.getActiveSheet();
var room = "";
var token = "";
var sheetUrl = "";
function chatClear() {
clear();
chat(
"오늘은 런치미팅을 진행합니다.\n"
+ "12시 30분까지 아래 시트에 부재사유 및 추가인원을 기입하여 주십시오.\n"
+ sheetUrl
);
}
function chatGenerate() {
var groups = generate();
var [i, msg] = groups.reduce(function([i, msg], group) {
msg += ++i + "조: ";
msg += group.map(function(row) { return row[1]; }).join(", ") + "\n";
return [i, msg];
}, [0, "오늘의 런치미팅 조를 발표합니다.\n"]);
chat(msg);
}
function clear() {
var range = sheet.getRange(2, 5, sheet.getLastRow());
range.clear();
}
function chat(msg) {
var res = UrlFetchApp.fetch(
'https://api.chatwork.com/v2/rooms/'+room+'/messages',
{
method: 'POST',
payload: 'body=' + msg,
headers: { 'X-ChatWorkToken': token },
}
);
}
function generate() {
var rows = sheet.getDataRange().getValues();
var groups = [];
function _partition(isValid, assign) {
rows = rows.reduce(function(remains, row) {
if (isValid(row)) assign(row);
else remains.push(row);
return remains;
}, []);
}
// 헤더 제거
rows.shift();
// 부재자 제외
rows = rows.filter(function(row) { return row[4]===''; });
var total = rows.length;
// 임원, 팀장 기준으로 조 편성
_partition(function(row) {
return ( row[0]==="임원" || ["팀장", "수석"].indexOf(row[2])>-1 );
}, function(row) {
groups.push([row]);
});
// 일본어만 가능한 사람을 배치
_partition(function(row) {
return row[3]==="일본어만";
}, function(row) {
groups[_getRandomInt(groups.length)].push(row);
});
// 일본어 가능한 사람을 배치
_partition(function(row) {
return row[3]==="일본어 가능";
}, function(row) {
var i = groups.findIndex(function(group) {
return group.findIndex(function(row) { return row[3]==="일본어만"; }) > -1
&& group.findIndex(function(row) { return row[3]==="일본어 가능"; }) === -1;
});
groups[( i>-1 ? i : _getRandomInt(groups.length))].push(row);
});
// 인원수 적은 순서대로 정렬
groups.sort(function(a,b) {
return a.length - b.length;
});
// 남은 인원을 배치 (인원수 적은 그룹에 우선 배치)
// Logger.log(total +' '+ groups.length +' '+ Math.ceil(total/groups.length));
for(var i=1; i<=Math.ceil(total/groups.length); i++) {
for(var j=0; j<groups.length; j++) {
var group = groups[j];
if (i!==group.length) break;
var rand = _getRandomInt(rows.length);
group.push(rows[rand]);
rows.splice(rand, 1);
if (rows.length===0) break;
}
if (rows.length===0) break;
}
// groups.forEach(function(group) { Logger.log(group); })
// Logger.log(rows);
return groups;
}
function _getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex
if (!Array.prototype.findIndex) {
Object.defineProperty(Array.prototype, 'findIndex', {
value: function(predicate) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
var thisArg = arguments[1];
// 5. Let k be 0.
var k = 0;
// 6. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kValue be ? Get(O, Pk).
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
// d. If testResult is true, return k.
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return k;
}
// e. Increase k by 1.
k++;
}
// 7. Return -1.
return -1;
},
configurable: true,
writable: true
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment