作为一个成长中的架构师,编码能力是万不能停止的,这个算法是之前在上一家单位帮助同事们自助订餐写的,纯爱好自己码敲的,刚好这段时间重新整理代码,发现了它,分享给大家,请大家品评指教。
如上图所示,输入人数点击开始点菜,系统自动会为你按照人均20的标准给出合理的菜单,这个人均标准是系统默认设置的,可以调整参数。如果输入人数的同时输入限定金额,则会以此金额为总花费的参考,保证不超过此金额下最优的给出建议菜单。当然如果同时输入了人数和限定金额,那么限定金额/人数不能低于系统设置的人均最低值,比如人数6人,限定金额50,人均很不到10块,下个毛管子。 3.基本原理:根据人数或限定金额得到本次菜单的可用总金额,同时根据人数按照一定荤素比例计算各类菜需要的个数,如6个人需要三个肉菜,一个蔬菜,一个凉菜,6分主食。(这个菜个数的计算是随机的,凉菜随机出现,主食可以是米饭也可以是饺子之类的,这个也是随机的。同时蔬菜和肉菜的比例虽然固定,但是每次随机会有小的调整,有上下浮动。);得到每类菜的个数后开始从对应类别中随机选择,得到结果后按照金额的限制先排序再进行适当剔除或重选,使得总限定金额最优化,最后得到菜单并输出。 4.核心JS函数解释说明:
1 var dishRate=[0.4,0.5,0.1]; // meat,vege,cold2 var leastAveragePayed = 10; // Average consumption money3 var defaultAveragePayed = 20; // default consumption money 4 var eatRiceFlag = true; // if eat rice or other things5 var eatRiceRate = 8; // the rate people eat rice;6 var eachRicePayed = 3; // each rice cost how much7 var moneyLimit = false; 8 var outRangeMoney = 5; // can over money9 var allDishArray = []; // 饭店所有的菜品
基本参数有:荤蔬搭配比例、人均最少消费、默认人均消费、要米饭还是其他主食、要米饭的概率、每碗米饭的价钱、是否有总消费限制、上下浮动的空间、饭店所有的菜品(这个需要初始化,将菜品按荤蔬凉菜汤米饭等类别分开,具体代码没有贴上来,看附件里)
1 function execute(){ 2 var peoples=eatPeoples.value; 3 var money=payMoney.value; 4 if("" == peoples){ 5 resultMes.innerText = "请输入用餐人数!"; 6 return; 7 } 8 if(!/^/d+$/.test(peoples) || (("" != money) && !/^/d+$/.test(money))){ 9 resultMes.innerText = "输入格式不对,请重新输入!";10 return;11 }12 if(""!=money.replace(/[/s]+/g,"")){13 moneyLimit = true;14 }15 randomChooseDish(peoples,money); 16 }
做了一些基本的输入有效性验证,比如人数不能为空,输入格式校验等,然后进入randomChooseDish方法开始点菜
randomChooseDish方法如下:
1 function randomChooseDish(peoples,money){ 2 var tempPeoples=parseInt(peoples); 3 var tempSumMoney= (""==money)?tempPeoples*parseInt(defaultAveragePayed):parseInt(money); 4 if(!checkCondition(tempPeoples,tempSumMoney)){ 5 return; 6 } 7 var dishNumArray= getDishNumArray(tempPeoples); //get dishNumArray 8 9 var haspayedMoney=0; 10 if(eatRiceFlag){11 // eat rice,reduce the rice money12 hasPayedMoney = eachRicePayed*tempPeoples;13 } 14 15 var beenChoosedArray = beginChooseDishesAndIndexs(dishNumArray);16 17 sortChoosedArray(beenChoosedArray);18 // when dishes are been choosed ,should check19 checkAndChangeDishes(beenChoosedArray,hasPayedMoney,tempSumMoney); 20 21 // show result22 showChooseResult(beenChoosedArray,hasPayedMoney,tempPeoples); 23 }
确定人数和总金额,checkCondition做基本的条件判断,比如人数不能少于2人,总金额/人数不能低于人均最低值等;getDishNumArray用于根据人数和初始化荤素比例计算每类菜品需要点的数量;beginChooseDishesAndIndexs用于开始随机点菜;sortChoosedArray用于排序,从贵到便宜,这样对于便宜的菜可以有更多搭配的方式;checkAndChangeDishes用于对选择的菜进行金额限制检查,如果超过限制则开始从最便宜的菜调整菜,直到菜单合格;showChooseResult用于将结果显示到页面上。下面是具体每个函数的源码,有注释。
1 function checkCondition(tempPeoples,tempSumMoney){ 2 if(tempPeoples<2){ 3 //alert(); 4 resultMes.innerText = "一个人下馆子?太奢侈了."; 5 return false; 6 } 7 if(tempPeoples>25){ 8 //alert(); 9 resultMes.innerText = "人数太多,一桌坐不下!";10 return false;11 }12 13 if(tempSumMoney<tempPeoples*leastAveragePayed){14 //alert();15 resultMes.innerText ="太抠了吧,都不到人均消费10块!";16 return false;17 }18 return true;19 }
1 // get meat,vege,cold numArray 2 function getDishNumArray(tempPeoples){ 3 var numArray=[Math.ceil(tempPeoples*dishRate[0]),getRandomRate(8)?Math.ceil(tempPeoples*dishRate[1]):Math.floor(tempPeoples*dishRate[1]),Math.round(tempPeoples*dishRate[2])]; // meat,vege,cold 4 5 if(getSumArray(numArray)<=tempPeoples+1 || tempPeoples>=10){ 6 var soupNum = Math.floor(tempPeoples/4) 7 numArray[numArray.length]=soupNum>2?2:soupNum; // add soup,soup num small then 2 8 } 9 10 eatRiceFlag = getRandomRate(eatRiceRate);11 if(!eatRiceFlag){12 // eat others13 var mainRiceNum = Math.floor(tempPeoples/3);14 numArray[numArray.length]=mainRiceNum>5?5:mainRiceNum; // add rice, mainrice nums small then 515 }16 return numArray;17 }
1 function beginChooseDishesAndIndexs(dishNumArray){ 2 var resultArray=[]; 3 var hasChoosedDishes=[]; // save be choosed dish 4 var hasChoosedIndexs=[]; // save be choosed in sourceArray index 5 var m = getRandom(dishNumArray.length); //random pos start 6 var dishLength=dishNumArray.length; 7 for(var i=0;i<dishLength;i++){ 8 var index = ((i+m)>=dishLength)?i+m-dishLength:(i+m); 9 var dishNum=dishNumArray[index];10 var tempSingleChoosed = []; // temp singleType choosed array 11 for(var n=0;n<dishNum;n++){12 var singleTypeArray = allDishArray[index];13 var singleTypeIndex = getRandom(singleTypeArray.length); 14 //alert(tempSingleChoosed+"and"+singleTypeIndex);15 while(tempSingleChoosed.length <= singleTypeArray.length && checkIfInArray(tempSingleChoosed,singleTypeIndex)){16 singleTypeIndex = getRandom(singleTypeArray.length); // if now index is choosed,choose again 17 //alert("reGet"+singleTypeIndex);18 }19 if(tempSingleChoosed.length == singleTypeArray.length){20 continue; // if singleTypeDish all been choosed, beak this circle,to next type dish21 }22 hasChoosedDishes[hasChoosedDishes.length] = singleTypeArray[singleTypeIndex]23 tempSingleChoosed[tempSingleChoosed.length] = singleTypeIndex; // ramark the temp position24 hasChoosedIndexs[hasChoosedIndexs.length] = index+","+singleTypeIndex; // ramark the position25 }26 } // all dish has choosed 27 resultArray.push(hasChoosedDishes);28 resultArray.push(hasChoosedIndexs); 29 return resultArray;30 }
1 // when dishes been choosed ,sort it,from big to small 2 function sortChoosedArray(beenChoosedArray){ 3 var hasChoosedDishes=beenChoosedArray[0]; // save be choosed dish 4 var hasChoosedIndexs=beenChoosedArray[1]; // save be choosed in sourceArray index 5 for(var i=0;i<hasChoosedDishes.length;i++){ 6 for(var j=i;j<hasChoosedDishes.length;j++){ 7 if(getDishAmount(hasChoosedDishes[i])>getDishAmount(hasChoosedDishes[j])){ 8 var temp = hasChoosedDishes[i]; 9 hasChoosedDishes[i] = hasChoosedDishes[j];10 hasChoosedDishes[j] = temp;11 // also should syn the choosedIndex12 var temp2 = hasChoosedIndexs[i];13 hasChoosedIndexs[i] = hasChoosedIndexs[j];14
新闻热点
疑难解答