現在很多場景下都需要對現有人員進行隨機分組,比如老師對班上的同學進行隨機分組,以小組形式完成一項作業;再比如公司戶外團建活動,對員工進行隨機分組,組隊玩遊戲等等。今天給大家分享的就是一個隨機分組案例,用戶只需要輸入總人數和每組人數,系統就可進行智能隨機分組(效果如下圖),之所以說智能,是因爲該系統具備以下幾點智能功能:
- 表單輸入框非空驗證;
- 輸入框失去焦點時,自動將用戶輸入的數字進行四捨五入轉換,防止用戶輸入小數;
- 單選按鈕選擇否時,將對最後分組剩餘人數進行隨機分配到已分配好的小組中,且每個小組人數差不會超過1人;
- 當用戶輸入分組不合理時(即最後分組剩餘人數大於分組數時),系統會進行智能分析,並最後給出兩個建議分組優化方案!用戶可直接選擇對應方案,使最終分組合理。比如:
下面獻上該案列的全部代碼:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Marco智能隨機分組系統</title>
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
<link href="https://cdn.bootcss.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet">
<style>
* {
margin:0;
padding:0;
}
html,body {
height:100%;
background:#3ba;
}
input {
overflow:hidden;
}
label.a {
float:left;
height:38px;
line-height:18px;
}
input[type="number"] {
width:100px;
}
table {
margin-top:10px;
border:1px solid #ccc;
border-collapse:collapse;
}
td {
text-align:center;
border:1px solid #ccc;
}
.box {
position:absolute;
min-width:500px;
border:4px solid #fc0;
padding:20px;
left:50%;
transform:translateX(-50%);
background:#fff;
}
h2 {
text-align:center;
color:#58bc58;
margin-bottom:20px;
font-weight:bold;
}
.form-group {
overflow:hidden;
}
.radio {
overflow:hidden;
margin-bottom:5px;
}
.radio .b {
float:left;
margin-right:10px;
}
</style>
</head>
<body>
<div class="box">
<h2>智能隨機分組系統</h2>
<div class="form-group">
<label for="total" class="a">請輸入總人數:</label>
<input type="number" class="form-control" id="total" aria-describedby="emailHelp">
</div>
<div class="form-group">
<label for="qty" class="a">請輸入每組人數:</label>
<input type="number" class="form-control" id="qty">
</div>
<div class="radio">
<p class="b">最後一組人數不足時,是否成立一組:</p>
<div class="custom-control custom-radio b">
<input type="radio" id="customRadio1" name="single" class="custom-control-input" checked="" value="yes">
<label class="custom-control-label" for="customRadio1">是</label>
</div>
<div class="custom-control custom-radio b">
<input type="radio" id="customRadio2" name="single" class="custom-control-input" value="no">
<label class="custom-control-label" for="customRadio2">否</label>
</div>
</div>
<button class="btn btn-outline-success" id="btn">開始分組</button>
<div id="output"></div>
</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
$("input.form-control").blur(function(e) {
$(this).val(Math.round(e.target.value));
})
$("#btn").click(function() {
var total = $('#total').val() * 1;
var qty = $("#qty").val() * 1;
var $single = $('input[name=single]');
var _single;
$single.each((idx, item) => {
if (item.checked) { // 判斷剩餘人數是否獨立生成一組
_single = item.value;
}
})
// 表單驗證
if (total == "") {
alert("請輸入總人數!")
$('#total').focus();
return false;
} else if (qty == "") {
alert("請輸入每組人數!");
$("#qty").focus();
return false;
}
if (qty > total) {
alert("每組人數不能大於總人數!");
$("#qty").focus();
return false;
} else {
var grounp = _single == "yes" ? Math.ceil(total / qty) : Math.floor(total / qty);
if (_single == "no") { // 如果剩餘人數不單獨生成一組,則需進行以下驗證
var rem = total % qty;
if (rem > grounp) { // 如果剩餘人數大於組數
// 建議增大人數
var adviceMore = qty + parseInt(rem / grounp);
// 建議減少人數
var adviceLess = qty - 1;
var lessGrounp = parseInt(total / adviceLess); //減1後的組數
var lessRem = total % adviceLess; // 減1後剩餘人數
while (lessRem > lessGrounp) { // while 循環直到剩餘人數小於組數
adviceLess--;
lessGrounp = parseInt(total / adviceLess);
lessRem = total % adviceLess;
}
var num = prompt("當前分組方式最後剩餘人數" + rem + ",大於分組數" + grounp + ",您可選擇: 1、增大每組人數(建議" + adviceMore + "人)或 2、減少每組人數(建議" + adviceLess + "人),以使分組合適!請選擇(1或2):")
if (num == "1") {
$("#qty").val(adviceMore); // 增大人數
} else if (num == "2") {
$("#qty").val(adviceLess); // 減少人數
} else {
$("#qty").val(adviceMore);
alert("溫馨提示:您的選擇有誤,已默認爲您選擇方案1!")
}
return false;
}
}
var total_arr = [];
for (var i = 1; i <= total; i++) { // 根據總人數生成總人數編號數組
total_arr.push(i);
}
var arr_big = []; // 用於存放所有分組,結果集
for (var i = 1; i <= grounp; i++) { // 遍歷分組數
var arr_min = []; // 用於存放每個分組的人員編號
for (var j = 1; j <= qty; j++) { // 嵌套遍歷每個分組的人數
if (total_arr.length <= 0) { // 若總人數數組已經被刪光,證明已經全部分配完,此時可結束當前循環
break;
}
var randomIdx = parseInt(Math.random() * total_arr.length); // 生成一個 0?總人數 的隨機數,用於在總人數數組中隨機抽取編號
arr_min.push(total_arr[randomIdx]); // 將抽取的編號加入當前所循環的分組
total_arr.splice(randomIdx, 1); // 加入後,刪除該編號
}
arr_big.push(arr_min); // 一個小分組添加完畢後,加入結果集
}
if (total_arr.length > 0) { // 若上面遍歷完所有分組後,總人數數組還有編號,則這些編號是剩餘人數,應隨機分配給以上小分組
var randomArr = []; // 定義一個臨時數組,用於存放已經有被分配到剩餘編號的小分組
for (var i = 0; i < total_arr.length; i++) { //遍歷剩餘人數
var randomNum = parseInt(Math.random() * arr_big.length) // 生成一個 0?分組數 的隨機數,用於在目前所有小分組中隨機抽取一個小分組
while (randomArr.includes(randomNum)) { // while循環直到該小分組是沒有被分配過剩餘編號的
randomNum = parseInt(Math.random() * arr_big.length)
}
randomArr.push(randomNum); // 將分配過剩餘編號的小分組記錄到臨時數組
arr_big[randomNum].push(total_arr[i]); // 將當前遍歷的剩餘編號加入隨機篩選出來的小分組
}
}
//寫入頁面
var $table = $('<table class="table table-bordered"></table>');
arr_big.forEach((item, idx) => {
var $tr = $(`<tr><td scope="row">第${idx+1}組</td></tr>`);
item.forEach((item2, idx) => {
$tr.append($(`<td scope="row">${item2}</td>`))
})
$table.append($tr);
})
$("#output").html('');
$table.appendTo("#output");
}
})
})
</script>
</body>
</html>
主要的js代碼我都寫了備註說明,相信大家都看得懂,有什麼問題歡迎一起探討!
另外,該案例我在jq插件庫發表過,案例地址:http://www.jq22.com/webqd4314,在這裏也給大家推薦jq插件庫(http://www.jq22.com/)這個網站,非常棒的一個開發資源網站,裏面提供了很多的案例、插件、常用代碼,你也可以在上面發佈你的作品,喜歡開發的你不容錯過哦!