好久没有写日志了,今天写一下上周做的 2010世界杯模拟抽签的程序
这是一个既要管前端效果又要管抽签逻辑规则还得组织数据跟后台接口的应用,抽签的主要规则是:
有1.2.3.4四档球队,每档次8支队伍,要将这32支队伍分成 ABCD...GH 八个组,每组各有一个第一档次至第四档次的球队,
每组的欧洲球队不能超过两支,
其他大洲的球队不成超过一支,
在抽第三档的球队的时候跟第一档次的欧洲球队对抗的南美球队不能超过两支,
在抽第三档的球队的时候跟第一档次的欧洲球队对抗的非洲球队不能超过三支,
先抽选第一档次的球队,然后是第二档次。。。直至第四档次,前一档次球队未被抽完时,其他档次不能进行选择,
抽中的符合抽签规则的球队会根据选择的分组出现在相应位置,
全部选完将数据填充到一个 对象中保存方便后台调用。
程序涉及到的要点:
针对每支球队的下拉菜单,
点击选项后的数据存贮和结果显示
点选后根据抽签规则进行可用性检测
-当前档次球队A组选定则其他球队A选项失效
-大洲球队个数超限制相应组选项失效
-分组对抗球队规则检测
全部选择完毕后的数据填充
其主要难点在于每次抽签的可用性检测,尤其是分组对抗的规则,因为各组的球队都是抽签生成的,所有比较数据无一固定,必须由抽签的结果进行遍历对比,才可得出结果。于是就有了一大堆检测规则:
//按照特殊规则检测
var ranks = [];
$( " #res td " ).each( function (i){
if ($( this ).attr( " id " ).match( " 1 " ) && $( this ).attr( " class " ).match( " euro " )){
var rank1e = $( this ).attr( " id " ).replace( " 1 " , "" );
var tmpid = $( this ).attr( " id " ).replace( " 1 " , " 3 " );
if (rank1.length < 5 ){
return false ;
} else if ( $( " # " + tmpid).data( " land " ) == lands ){
var tims = 0 ;
var maxt = maxteams;
var tmprank = rank1;
var tmpgrp = $( " # " + tmpid).data( " group " );
for ( var x in tmprank){
if (tmprank[x] == tmpgrp){
ranks.push(tmpgrp);
ranks = unique(ranks);
if (ranks.length >= maxt){
for ( var j in tmprank){
for ( var k in ranks){
if ( tmprank[j] == ranks[k] ){
tmprank[j] = " markext " ;
tims ++ ;
if (tims == maxt){
for ( var m in tmprank){
$( " #grade3 " ).find( " . " + lands).find( " . " + tmprank[m]).addClass( " hide " );
// alert("."+lands +"."+ tmprank[m] )
}
}
}
}
}
}
}
}
}
}
})
}
// 按一般规则检测可选分组
function chk(){
$( " #res td " ).each( function (i){
if ($( this ).data( " land " ) && $( this ).data( " land " ) !== " euro " ) {
var land = $( this ).data( " land " );
var group = $( this ).data( " group " );
$( " . " + land).find( " . " + group).addClass( " hide " );
} else if ( $( this ).data( " land " ) && $( this ).data( " land " ) == " euro " ) {
var land = " euro " ;
var group = $( this ).data( " group " );
if ($( " #res " ).find( " . " + group + " euro " ).length >= 2 ){
$( " . " + land).find( " . " + group).addClass( " hide " );
}
}
})
}
其中可用性以及菜单可视性的检查以及分组对比等多数功能利用jquery的addClass 和 class选择符 完成,对于数据的存储虽然可以用data方法可以方便的存储,但是动态存储和在页面上随时调取,class的作用还是比data来的方便,因为你可以用$(".class")确定相应元素的个数 而data则无法进行选择~ 用class来标记和存储数据很不错,也多亏了jquery的强大的选择器。
菜单可视性的检查:
//通过检查上级球队所选个数 判断当前档次球队是否可选
if((!dl.hasClass("sld")) && ( (gde=="grade1")|| (gde=="grade2" && $("#grade1").find(".sld").length==8)|| (gde=="grade3" && $("#grade2").find(".sld").length==8) || (gde=="grade4" && $("#grade3").find(".sld").length==8))){
动态检查球队对抗情况时,用到了数组删除重复元素的功能:
var str = " \x0f " + A.join( " \x0f " );
while ( / (\w+)[^\1]*\1 / .test(str))
str = str.replace( " \x0f " + RegExp.$ 1 , "" );
return str.substr( 1 ).split( " \x0f " );
}
用data方法标记当前球队的相关数据和信息:
$("#"+tarid).html(dt).data("nation",dd).data("land",cont).data("group",group);
程序最终虽然实现,但是由于随着操作次数的增多,监测的操作也会增多,导致运行稍有缓慢,跟事件冒泡也有关系,但是还没有来得及仔细优化,先上线了。
地址如下点此查看:http://soccer.titan24.com/app/soccer/drawgame/index.php
最后附上代码有兴趣的可以看看:
/*
*trance2005@163.com
*QQ:397902738
*MSN:trancelover@live.cn
*2009-11-21
*/
$(document).ready( function (){
// 结果数据
var grp = {a1: "" , a2: "" , a3: "" , a4: '' ,
b1: "" , b2: "" , b3: "" , b4: '' ,
c1: "" , c2: "" , c3: "" , c4: '' ,
d1: "" , d2: "" , d3: "" , d4: '' ,
e1: "" , e2: "" , e3: "" , e4: '' ,
f1: "" , f2: "" , f3: "" , f4: '' ,
g1: "" , g2: "" , g3: "" , g4: '' ,
h1: "" , h2: "" , h3: "" , h4: '' }
// 确定南非的a1位置
$( " #grade1 " ).find( " .a " ).addClass( " hide " );
$( " #a1 " ).data( " nation " , " 南非 " ).data( " land " , " afic " ).data( " group " , " a " ).addClass( " a " );
// 主函数开始
$( " .teams " ).find( " dl " ).mouseover( function (e){
var dl = $(e.target).parents( " dl " ) || $(e.target);
var div = dl.parents( " .teams " );
var gde = div.attr( " id " );
if (( ! dl.hasClass( " sld " )) && ( (gde == " grade1 " ) || (gde == " grade2 " && $( " #grade1 " ).find( " .sld " ).length == 8 ) || (gde == " grade3 " && $( " #grade2 " ).find( " .sld " ).length == 8 ) || (gde == " grade4 " && $( " #grade3 " ).find( " .sld " ).length == 8 ))){
var cont = dl.attr( " class " ).split( " " )[ 0 ];
var dt = dl.find( " dt " ).find( " a " );
dt = dt.clone().addClass(cont);
var dd = dl.find( " dd a " ).html();
var grade = div.attr( " grade " );
var gx = parseInt(Math.floor(dl.offset().left)) + 40 + " px " ;
var gy = parseInt(Math.floor(dl.offset().top)) - 14 + " px " ;
var menu = dl.find( " .grp " );
var group;
var tarid;
dl.siblings( " dl " ).find( " .grp " ).hide();
menu.css({ " top " :gy, " left " :gx}).show();
menu.find( " li " ).click( function (e){
var li = $(e.target).parents( " li " ) || $(e.target);
if ( ! li.hasClass( " hide " )){
group = li.attr( " class " ).split( " " )[ 0 ];
tarid = group + grade;
$( " # " + tarid).html(dt).data( " nation " ,dd).data( " land " ,cont).data( " group " ,group);
if ( ! (cont == " euro " )){
$( " # " + tarid).addClass(group);
} else if (cont == " euro " ){
var euroteam = group + " euro "
$( " # " + tarid).addClass(euroteam);
}
dl.addClass( " sld " );
div.find( " . " + group).addClass( " hide " );
menu.hide();
if (gde == " grade2 " && $( " #grade1 " ).find( " .sld " ).length == 8 ){
prerank();
}
if ((gde == " grade1 " && menu.find( " .hide " ).length == 8 ) || ! (gde == " grade1 " )){
chk();
if (gde == " grade3 " && cont == " south " ){
chkext( " south " , 2 );
}
if (gde == " grade3 " && cont == " afic " ){
chkext( " afic " , 3 );
}
if (gde == " grade4 " && $( " #dcnt " ).find( " li.hide " ).length == 256 ){
filldata();
return false ;
}
return false ;
}
return false ;
}
})
return false ;
}
return false ;
})
var rank1 = [];
function prerank(){
if (rank1.length < 5 ){
$( " #res td " ).each( function (i){
if ($( this ).attr( " id " ).match( " 1 " ) && $( this ).attr( " class " ).match( " euro " )){
var rank1e = $( this ).attr( " id " ).replace( " 1 " , "" );
rank1.push(rank1e);
}
})
}
}
// 删除数组中重复的元素
function unique(A) {
var str = " \x0f " + A.join( " \x0f " );
while ( / (\w+)[^\1]*\1 / .test(str))
str = str.replace( " \x0f " + RegExp.$ 1 , "" );
return str.substr( 1 ).split( " \x0f " );
}
// 按照特殊规则检测
function chkext(lands,maxteams){
var ranks = [];
$( " #res td " ).each( function (i){
if ($( this ).attr( " id " ).match( " 1 " ) && $( this ).attr( " class " ).match( " euro " )){
var rank1e = $( this ).attr( " id " ).replace( " 1 " , "" );
var tmpid = $( this ).attr( " id " ).replace( " 1 " , " 3 " );
if (rank1.length < 5 ){
return false ;
} else if ( $( " # " + tmpid).data( " land " ) == lands ){
var tims = 0 ;
var maxt = maxteams;
var tmprank = rank1;
var tmpgrp = $( " # " + tmpid).data( " group " );
for ( var x in tmprank){
if (tmprank[x] == tmpgrp){
ranks.push(tmpgrp);
ranks = unique(ranks);
if (ranks.length >= maxt){
for ( var j in tmprank){
for ( var k in ranks){
if ( tmprank[j] == ranks[k] ){
tmprank[j] = " markext " ;
tims ++ ;
if (tims == maxt){
for ( var m in tmprank){
$( " #grade3 " ).find( " . " + lands).find( " . " + tmprank[m]).addClass( " hide " );
// alert("."+lands +"."+ tmprank[m] )
}
}
}
}
}
}
}
}
}
}
})
}
// 按一般规则检测可选分组
function chk(){
$( " #res td " ).each( function (i){
if ($( this ).data( " land " ) && $( this ).data( " land " ) !== " euro " ) {
var land = $( this ).data( " land " );
var group = $( this ).data( " group " );
$( " . " + land).find( " . " + group).addClass( " hide " );
} else if ( $( this ).data( " land " ) && $( this ).data( " land " ) == " euro " ) {
var land = " euro " ;
var group = $( this ).data( " group " );
if ($( " #res " ).find( " . " + group + " euro " ).length >= 2 ){
$( " . " + land).find( " . " + group).addClass( " hide " );
}
}
})
}
// 将最终结果填充到 grp中
function filldata(){
for ( var x in grp){
grp[x] = $( " # " + x).data( " nation " );
// alert(grp[x]);
}
}
/*
//测试结果
$("#res td").click(function(){
alert($(this).find("a").attr("class"))
})
*/
// end of document.ready
})