智能隨機分組系統(代碼帶備註)

現在很多場景下都需要對現有人員進行隨機分組,比如老師對班上的同學進行隨機分組,以小組形式完成一項作業;再比如公司戶外團建活動,對員工進行隨機分組,組隊玩遊戲等等。今天給大家分享的就是一個隨機分組案例,用戶只需要輸入總人數和每組人數,系統就可進行智能隨機分組(效果如下圖),之所以說智能,是因爲該系統具備以下幾點智能功能:

  1. 表單輸入框非空驗證;
  2. 輸入框失去焦點時,自動將用戶輸入的數字進行四捨五入轉換,防止用戶輸入小數;
  3. 單選按鈕選擇否時,將對最後分組剩餘人數進行隨機分配到已分配好的小組中,且每個小組人數差不會超過1人;
  4. 當用戶輸入分組不合理時(即最後分組剩餘人數大於分組數時),系統會進行智能分析,並最後給出兩個建議分組優化方案!用戶可直接選擇對應方案,使最終分組合理。比如:

下面獻上該案列的全部代碼:

<!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/)這個網站,非常棒的一個開發資源網站,裏面提供了很多的案例、插件、常用代碼,你也可以在上面發佈你的作品,喜歡開發的你不容錯過哦!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章