好久没有写日志了,今天写一下上周做的 2010世界杯模拟抽签的程序
这是一个既要管前端效果又要管抽签逻辑规则还得组织数据跟后台接口的应用,抽签的主要规则是:
有1.2.3.4四档球队,每档次8支队伍,要将这32支队伍分成 ABCD...GH 八个组,每组各有一个第一档次至第四档次的球队,
每组的欧洲球队不能超过两支,
其他大洲的球队不成超过一支,
在抽第三档的球队的时候跟第一档次的欧洲球队对抗的南美球队不能超过两支,
在抽第三档的球队的时候跟第一档次的欧洲球队对抗的非洲球队不能超过三支,
先抽选第一档次的球队,然后是第二档次。。。直至第四档次,前一档次球队未被抽完时,其他档次不能进行选择,
抽中的符合抽签规则的球队会根据选择的分组出现在相应位置,
全部选完将数据填充到一个 对象中保存方便后台调用。
程序涉及到的要点:
针对每支球队的下拉菜单,
点击选项后的数据存贮和结果显示
点选后根据抽签规则进行可用性检测
-当前档次球队A组选定则其他球队A选项失效
-大洲球队个数超限制相应组选项失效
-分组对抗球队规则检测
全部选择完毕后的数据填充
其主要难点在于每次抽签的可用性检测,尤其是分组对抗的规则,因为各组的球队都是抽签生成的,所有比较数据无一固定,必须由抽签的结果进行遍历对比,才可得出结果。于是就有了一大堆检测规则:
//按照特殊规则检测
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
"
);
}
}
})
}
其中可用性以及菜单可视性的检查以及分组对比等多数功能利用jquery的addClass 和 class选择符 完成,对于数据的存储虽然可以用data方法可以方便的存储,但是动态存储和在页面上随时调取,class的作用还是比data来的方便,因为你可以用$(".class")确定相应元素的个数 而data则无法进行选择~ 用class来标记和存储数据很不错,也多亏了jquery的强大的选择器。
菜单可视性的检查:
Code
//通过检查上级球队所选个数 判断当前档次球队是否可选
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))){
动态检查球队对抗情况时,用到了数组删除重复元素的功能:
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
"
);
}
用data方法标记当前球队的相关数据和信息:
$("#"+tarid).html(dt).data("nation",dd).data("land",cont).data("group",group);
程序最终虽然实现,但是由于随着操作次数的增多,监测的操作也会增多,导致运行稍有缓慢,跟事件冒泡也有关系,但是还没有来得及仔细优化,先上线了。
地址如下点此查看:http://soccer.titan24.com/app/soccer/drawgame/index.php
最后附上代码有兴趣的可以看看:
/*
*JavaScript 世界杯抽签程序 by trance
*[email protected]
*QQ:397902738
*MSN:[email protected]
*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
})