哈哈 今天再補充一個之前撒懶的筆記java
遊戲中的擂臺賽,遊戲玩家開始報名,進行海選賽,再進行32強賽、16強,8強,4強,半決賽,決賽算法
海選賽中失敗一次既被淘汰,最終決出32強(海選賽報名人數不足32人則直接晉級32強)spring
海選賽中報名的人數:n,分紅32組,apache
每組人數:m = n/32;dom
未分配組的人數:x = n%32;ide
1組,2組,3組,。。。。。32組的人員分配以下fetch
for(int i=0; i<32; i++){ group[i] = m + ((x-->0)? 1 : 0); }
如:總報名人數 n=134; 每組人數:m=n/32=4; 未分配人數:x=n%32=6ui
group[0]第1組 | group[1]第2組 | group[2]第3組 | group[3]第4組 | group[4]第5組 | group[5]第6組 | group[6]第7組 | group[7]第8組 | group[.....]第i組 | group[31]第32組 |
4+1=5 | 4+1=5 | 4+1=5 | 4+1=5 | 4+1=5 | 4+1=5 | 4 | 4 | 4 | 4 |
呵呵 也就是把剩下沒分完組的人加入到每組中,從第一組開始this
海選賽以兩兩隨機配對戰鬥,敗者淘汰, 海選賽中每組決出一名,海選賽結束後就決出了32強(固然能夠保留種子選手直接進入32強,相應的規則本身制定 哈哈)google
淘汰賽既32強開始機制簡單設爲PK失敗被淘汰,PK勝利就晉級(其實能夠採用世界盃的那種形式 哈哈)
貼上代碼
package models.competition; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import models.i18n.I18N; import models.i18n.I18NUtils; import models.user.GameUser; import play.i18n.Lang; import play.modules.morphia.Model; import play.modules.morphia.Model.AutoTimestamp; import com.google.code.morphia.annotations.Entity; import com.google.code.morphia.annotations.Transient; import exception.Constants; @Entity @AutoTimestamp @I18N(fields={"urankDesc","pkRankDesc"}) public class PkInfo extends Model{ public static final int PK_TYPE_SELECT = 1; public static final int PK_TYPE_PKOUT = 2; public static final int SELECT_PK_STATUS_CONTINUE = 0;//海選晉級下一輪 public static final int SELECT_PK_STATUS_OUT = 1;//海選被淘汰 public static final int SELECT_PK_STATUS_GOUP = 2;//成功闖入32強 /** * 第幾屆擂臺賽 */ public long code; /** * 級別類型 */ public int levelType; /** * 第幾輪 */ public int round; /** * 擂臺賽階段【1;海選賽,2:淘汰賽】 */ public int pkType; public int groupIndex; public String uid; public String pkUid; @Transient public String uname; @Transient public String pkName; /** * 進入幾強 */ public int urank; public String urankDesc; public int pkRank; public String pkRankDesc; /** * 海選用戶晉級狀態【0:晉級下一輪,1:被淘汰;2:出入32強】 */ @Transient public int uselectPkStatus; /** * 海選對手的晉級狀態【0:晉級下一輪,1:被淘汰;2:出入32強】 */ @Transient public int pkSelectPkStatus; /** * 戰鬥結果【true:user勝利,false:pkuser勝利】 */ public boolean result; public PkInfo(long code, int levelType, int groupIndex, int round, int pkType, String uid, String pkUid) { super(); this.code = code; this.levelType = levelType; this.groupIndex = groupIndex; this.round = round; this.pkType = pkType; this.uid = uid; this.pkUid = pkUid; } public static final int[] ranks={32,16,8,3,2,1}; public static final String rankContinueDesc=Constants.COMPETITION_RANK_CONTINUE_DESC_1; public static final String[] rankSuccDescs={ Constants.COMPETITION_RANK_SUCC_DESC_1, Constants.COMPETITION_RANK_SUCC_DESC_2, Constants.COMPETITION_RANK_SUCC_DESC_3, Constants.COMPETITION_RANK_SUCC_DESC_4, Constants.COMPETITION_RANK_SUCC_DESC_5, Constants.COMPETITION_RANK_SUCC_DESC_6, }; public static final String[] rankFailDescs={ Constants.COMPETITION_RANK_FAIL_DESC_1, Constants.COMPETITION_RANK_FAIL_DESC_2, Constants.COMPETITION_RANK_FAIL_DESC_3, Constants.COMPETITION_RANK_FAIL_DESC_4, Constants.COMPETITION_RANK_FAIL_DESC_5, Constants.COMPETITION_RANK_FAIL_DESC_6, }; public void loadUserInfo(){ GameUser gu = null; GameUser pkgu = null; if(this.uid != null){ gu = GameUser.getSimpleInfo(this.uid, new String[]{"name"}); } if(this.pkUid != null){ pkgu = GameUser.getSimpleInfo(this.pkUid, new String[]{"name"}); } if(gu != null){ this.uname = gu.name; } if( pkgu != null){ this.pkName = pkgu.name; }else{ this.pkName = "-"; } } /** * 海選 * user VS pker * @param result */ public void setSelectPkResult(boolean result, int uselectPkStatus,int pkSelectPkStatus){ this.result = result; //海選階段 if(this.pkType == PK_TYPE_SELECT){ //晉級32強 if(uselectPkStatus == SELECT_PK_STATUS_GOUP){ this.urank = ranks[0]; this.urankDesc = rankSuccDescs[0]; //海選被淘汰 }else if( uselectPkStatus == SELECT_PK_STATUS_OUT){ this.urankDesc = rankFailDescs[0]; //海選晉級下一輪 }else if( uselectPkStatus == SELECT_PK_STATUS_CONTINUE){ this.urankDesc = rankContinueDesc; } //晉級32強 if(pkSelectPkStatus == SELECT_PK_STATUS_GOUP){ this.pkRank = ranks[0]; this.pkRankDesc = rankSuccDescs[0]; //海選被淘汰 }else if( pkSelectPkStatus == SELECT_PK_STATUS_OUT){ this.pkRankDesc = rankFailDescs[0]; //海選晉級下一輪 }else if( pkSelectPkStatus == SELECT_PK_STATUS_CONTINUE){ this.pkRankDesc = rankContinueDesc; } } } /** * user VS pker * @param result */ public void setPkOutResult(boolean result){ this.result = result; //淘汰賽第一輪,晉級16強 if(this.round == 1){ if(result){ //user勝利 成功晉級16強 this.urank = ranks[1]; this.urankDesc = rankSuccDescs[1]; //pker失敗 晉級16強被淘汰 this.pkRank = ranks[0]; this.pkRankDesc = rankFailDescs[1]; }else{ //user勝利 成功晉級16強 this.urank = ranks[0]; this.urankDesc = rankFailDescs[1]; //pker失敗 晉級16強被淘汰 this.pkRank = ranks[1]; this.pkRankDesc = rankSuccDescs[1]; } //淘汰賽第二輪 晉級8強 }else if(this.round == 2){ if(result){ //user勝利 成功晉級8強 this.urank = ranks[2]; this.urankDesc = rankSuccDescs[2]; //pker失敗 晉級8強被淘汰 this.pkRank = ranks[1]; this.pkRankDesc = rankFailDescs[2]; }else{ //user勝利 成功晉級8強 this.urank = ranks[1]; this.urankDesc = rankFailDescs[2]; //pker失敗 晉級8強被淘汰 this.pkRank = ranks[2]; this.pkRankDesc = rankSuccDescs[2]; } //淘汰賽第三輪 晉級半決賽 }else if(this.round == 3){ if(result){ //user勝利 成功晉級半決賽 this.urank = ranks[3]; this.urankDesc = rankSuccDescs[3]; //pker失敗 晉級半決賽被淘汰 this.pkRank = ranks[2]; this.pkRankDesc = rankFailDescs[3]; }else{ //user勝利 成功晉級半決賽 this.urank = ranks[2]; this.urankDesc = rankFailDescs[3]; //pker失敗 晉級半決賽被淘汰 this.pkRank = ranks[3]; this.pkRankDesc = rankSuccDescs[3]; } //淘汰賽第四輪 半決賽 }else if(this.round == 4){ if(result){ //user勝利 成功晉級決賽 this.urank = ranks[4]; this.urankDesc = rankSuccDescs[4]; //pker失敗 半決賽被淘汰,得到擂臺賽季軍 this.pkRank = ranks[3]; this.pkRankDesc = rankFailDescs[4]; }else{ //user勝利 成功晉級半決賽 this.urank = ranks[3]; this.urankDesc = rankFailDescs[4]; //pker失敗 晉級半決賽被淘汰 this.pkRank = ranks[4]; this.pkRankDesc = rankSuccDescs[4]; } //淘汰賽第五輪 決賽 }else if(this.round == 5){ if(result){ //user勝利 成功晉級決賽 this.urank = ranks[5]; this.urankDesc = rankSuccDescs[5]; //pker失敗 半決賽被淘汰,得到擂臺賽季軍 this.pkRank = ranks[4]; this.pkRankDesc = rankFailDescs[5]; }else{ //user勝利 成功晉級半決賽 this.urank = ranks[4]; this.urankDesc = rankFailDescs[5]; //pker失敗 晉級半決賽被淘汰 this.pkRank = ranks[5]; this.pkRankDesc = rankSuccDescs[5]; } } } public static List<PkInfo> getTempList(String uid,List<PkInfo> list){ Comparator<PkInfo> sort = new Comparator<PkInfo>() { @Override public int compare(PkInfo o1, PkInfo o2) { long t1 = o1._getCreated(); long t2 = o2._getCreated(); return (int)(t2-t1); } }; Collections.sort(list,sort); List<PkInfo> templist = new ArrayList<PkInfo>(); PkInfo temp = null; for(PkInfo pkinfo : list){ pkinfo.loadUserInfo(); //若是本身在Pk陣列中則須要轉換 if(uid.equals(pkinfo.pkUid)){ temp = new PkInfo(pkinfo.code, pkinfo.levelType, pkinfo.groupIndex, pkinfo.round, pkinfo.pkType, uid, pkinfo.uid); temp.loadUserInfo(); temp.groupIndex = pkinfo.groupIndex; temp.urank = pkinfo.pkRank; temp.urankDesc = pkinfo.pkRankDesc; temp.pkName = pkinfo.uname; temp.pkRankDesc = pkinfo.urankDesc; temp.result = !pkinfo.result; templist.add(temp); }else{ templist.add(pkinfo); } } I18NUtils.setI18NFields(templist, Lang.get()); return templist; } }
package models.competition; import java.util.ArrayList; import java.util.List; import models.user.FightAttribute; import models.user.GameUser; import models.wow.UserWarcraft; import play.modules.morphia.Model; import service.util.RandomUtil; import com.google.code.morphia.annotations.Entity; import com.google.code.morphia.annotations.Transient; import exception.MonsterException; @Entity public class UserCompetition extends Model{ public static final int SIGN_STATUS_N = 0; public static final int SIGN_STATUS_Y = 1; public static final int RECEIVE_REWARD_STATUS_N = 0; public static final int RECEIVE_REWARD_STATUS_Y = 1; public static final int LEVEL_TYPE_NOMAL = 1; public static final int LEVEL_TYPE_HIGH = 2; public static final int LEVEL_SPLITER = 60; public static final int MAX_FAIL_TIMES = 3; /** * 第幾屆擂臺賽 */ public long code; /** * GameUser Id */ public String uid; @Transient public String name; @Transient public int level; /** * 報名狀態 */ public int signStatus; /** * 海選時的攻擊力 */ public long attackPower; /** * 級別類型 */ public int levelType; /** * 海選失敗的次數 */ public int failTimes; /** * 海選是否被淘汰 */ public boolean isSelectPkOut; /** * 淘汰賽是否被淘汰 */ public boolean isPkoutOut; /** * 淘汰賽排名【1,2,3(2個),8(4個),16(8個),32(16個)】(未進入淘汰賽的爲0) */ public int rank; /** * 領取獎勵狀態【0:未領取;1:已領取】 */ public int receiveRewardStatus; /** * 戰鬥記錄 */ @Transient public List<PkInfo> pkLogs; public UserCompetition(long code, String uid) { super(); this.code = code; this.uid = uid; this.signStatus = SIGN_STATUS_N; this.receiveRewardStatus = RECEIVE_REWARD_STATUS_N; } /** * 報名 */ public void sign(int levelType){ this.signStatus = SIGN_STATUS_Y; this.rank = 0; this.failTimes = MAX_FAIL_TIMES; this.levelType = levelType; } /** * 晉級 * @param pkInfo */ public void goUp(boolean isWin,int rank){ //海選失敗 if(!isWin && rank == 0){ this.failTimes--; //更新排名(淘汰賽失敗則記錄上一局的排名) }else if(rank > 0){ this.rank = rank; } } /** * 計算攻擊力 */ public void loadAttackPower(){ GameUser gu = GameUser.getSimpleInfo(this.uid, new String[]{"level", "camp", "dynamicProp"}); UserWarcraft userWarcraft = UserWarcraft.find("uid", this.uid).first(); long power = 0; if(gu != null){ //計算攻擊力 power = getFightValue(gu); //添加魔獸攻擊力 if(userWarcraft != null){ power += userWarcraft.getUserWeapon(); } } this.attackPower = power; } /** * 獲取用戶綜合戰鬥能力值 * @param gameUser Game User * @return int */ private int getFightValue(GameUser gameUser) { FightAttribute fightAttribute = gameUser.dynamicProp; return fightAttribute.maxHp + 10 * ((fightAttribute.mainWeaponMax + fightAttribute.mainWeaponMin)/2); } /** * 海選賽的選拔過程 * @param pker * @return */ public boolean getSelectPkResult(UserCompetition pker){ boolean isWin = false; long selfFightValue = this.attackPower; long upDownFightValue = selfFightValue * 10 / 100; long otherFightValue = pker.attackPower; if (otherFightValue - selfFightValue > upDownFightValue){ //困難級別 isWin = false; }else if (selfFightValue - otherFightValue > upDownFightValue){ //簡單級別 isWin = true; }else{ //普通級別取隨機 int winValue = 50; int resRandom = RandomUtil.getRandomValue(1, 100); if(winValue>resRandom){ isWin = true; }else{ isWin = false; } } if(isWin){ pker.isSelectPkOut = true; }else{ this.isSelectPkOut = true; } return isWin; } public static int getLevelType(int level){ if(level<LEVEL_SPLITER){ return LEVEL_TYPE_NOMAL; }else{ return LEVEL_TYPE_HIGH; } } public void loadUserInfo(){ GameUser gu = GameUser.getSimpleInfo(this.uid, new String[]{"name","level"}); if(gu != null){ this.name = gu.name; this.level = gu.level; } } }
package service.impl; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import exception.Constants; import exception.MonsterException; import models.AchievementResult; import models.competition.Competition; import models.competition.CompetitionReturn; import models.competition.CompetitionReward; import models.competition.PkInfo; import models.competition.UserCompetition; import models.fight.Battle; import models.fight.FightResult; import models.tdo.PageTDO; import models.user.FightableObj; import models.user.GameUser; import play.modules.morphia.Model.MorphiaQuery; import play.modules.spring.Spring; import service.CompetitionService; import service.GameUserService; import service.util.AchievementUtils; import service.util.RandomUtil; /** * @author ZhangYude * @date 2012-11-21 * @version 1.4 * @since 2012 * @desc: * 擂臺賽接口實現 */ public class CompetitionServiceImpl implements CompetitionService{ /** * 獲取用戶擂臺賽信息 * @param uid * @return */ @Override public CompetitionReturn getUserCompetitionInfo(String uid, int levelType) { GameUser gu = GameUser.getSimpleInfo(uid, new String[]{"level"}); CompetitionReturn cr = new CompetitionReturn(); Competition competition = Competition.find().order("-code").first(); if(competition == null){ // competition = createNextCompetitionInfo(); cr.statusStep = Competition.STATUS_IN_INIT; return cr; } int myLevelType = UserCompetition.getLevelType(gu.level); //傳入參數的狀況 if(levelType>0){ myLevelType = levelType; } // competition.updateStatus(); cr.code = competition.code; cr.statusStep = competition.status; cr.curLevel = gu.level; cr.curRankList = getUserCompetitionByLevelType(competition.code, myLevelType); cr.myPkInfoList = getPkInfoByLevelType(uid, competition.code, myLevelType,0); cr.signBeginTime = competition.signBeginTime; cr.signEndTime = competition.signEndTime; cr.selectBeginTime = competition.selectBeginTime; cr.pkoutBeginTime = competition.pkoutBeginTime; UserCompetition userCompetition = UserCompetition.find("uid,code,signStatus", uid,competition.code,UserCompetition.SIGN_STATUS_Y).first(); if(userCompetition == null){ cr.mySignStatus = UserCompetition.SIGN_STATUS_N; }else{ cr.mySignStatus = UserCompetition.SIGN_STATUS_Y; if(userCompetition.levelType == levelType || levelType == 0){ cr.curRank = userCompetition.rank; } } UserCompetition ucPerInfo = getUserCompetitionInfo(uid, competition.code-1); if(ucPerInfo != null && (ucPerInfo.levelType == levelType || levelType == 0)){ cr.perRank = ucPerInfo.rank; } return cr; } /** * 獲取上屆擂臺賽戰況結果信息 * @param levelType * @return */ @Override public CompetitionReturn getPerCompetitionInfo(int levelType) { CompetitionReturn cr = new CompetitionReturn(); Competition competition = Competition.find().order("-code").first(); if(competition != null && competition.code > 1){ cr.perRankList = getUserCompetitionByLevelType(competition.code-1,levelType); } return cr; } /** * 根據等級類型獲取擂臺賽戰況結果 * @param code * @param levelType * @param isCurrent * @return */ private UserCompetition getUserCompetitionInfo(String uid, long code){ UserCompetition uc = null; MorphiaQuery q = UserCompetition.find("code", code); q.filter("uid", uid); q.and(q.criteria("rank").greaterThan(0)); uc = q.first(); // uc.loadUserInfo(); return uc; } /** * 根據等級類型獲取擂臺賽戰況結果 * @param levelType * @return */ private List<UserCompetition> getUserCompetitionByLevelType(long code, int levelType){ Competition competition = Competition.find("code",code).first(); if(competition != null && competition.status != competition.STATUS_IN_CLOSED){ return null; } List<UserCompetition> list = new ArrayList<UserCompetition>(); MorphiaQuery q = UserCompetition.find("code", code); q.filter("levelType", levelType); q.and(q.criteria("rank").greaterThan(0)); list = q.asList(); for(UserCompetition uc : list){ uc.loadUserInfo(); } return list; } /** * 獲取戰況信息 * @param uid * @param code * @param levelType * @return */ private List<PkInfo> getPkInfoByLevelType(String uid, long code, int levelType, int pkType){ List<PkInfo> list = new ArrayList<PkInfo>(); MorphiaQuery q1 = PkInfo.find("code", code); MorphiaQuery q2 = PkInfo.find("code", code); if(uid != null){ q1.filter("uid", uid); q2.filter("pkUid", uid); } if(levelType>0){ q1.filter("levelType", levelType); q2.filter("levelType", levelType); } if(pkType>0){ q1.filter("pkType", pkType); q2.filter("pkType", pkType); } List<PkInfo> l1 = q1.asList(); List<PkInfo> l2 = q2.asList(); list.addAll(l1); list.addAll(l2); return PkInfo.getTempList(uid, list); // return list; } @Override public void beginSign() { Competition competition = Competition.find().order("-code").first(); if(competition != null){ competition.signBegin(); competition.save(); } } /** * 擂臺賽報名 * @param uid * @param levelType * @return */ @Override public CompetitionReturn sign(String uid, int levelType) { GameUser gu = GameUser.getSimpleInfo(uid, new String[]{"level"}); CompetitionReturn cr = new CompetitionReturn(); if(gu != null){ Competition competition = Competition.find().order("-code").first(); UserCompetition userCompetition = UserCompetition.find("code,uid", competition.code,uid).first(); long now = new Date().getTime(); // if(UserCompetition.getLevelType(gu.level) != levelType){ // throw new MonsterException(Constants.COMPETITION_SIGN_ERROR_LEVELTYPE_NOT_FIT); // }else if(now < competition.signBeginTime || now > competition.signEndTime){ // throw new MonsterException(Constants.COMPETITION_SIGN_ERROR_SIGNTIME_NOT_FIT); // } if(userCompetition == null){ userCompetition = new UserCompetition(competition.code, uid); } userCompetition.sign(levelType); userCompetition.save(); cr.mySignStatus = userCompetition.signStatus; } return cr; } /** * 獲取擂臺賽獎勵信息 * @return */ @Override public CompetitionReturn getCompetitionRewardInfo() { CompetitionReturn cr = new CompetitionReturn(); cr.nomalRewardList = CompetitionReward.getPrizePackageList(UserCompetition.LEVEL_TYPE_NOMAL); cr.highRewardList = CompetitionReward.getPrizePackageList(UserCompetition.LEVEL_TYPE_HIGH); return cr; } /** * 初始化下屆擂臺賽信息 */ @Override public Competition createNextCompetitionInfo() { Competition competition = new Competition(); competition.init(); competition.createNextCompetition(); competition.save(); return competition; } /** * 結束報名(計算參與者個戰鬥力) */ @Override public void endSign() { // TODO Auto-generated method stub Competition competition = Competition.find().order("-code").first(); if(competition != null){ competition.signEnd(); competition.save(); MorphiaQuery q = UserCompetition.createQuery(); q.filter("code", competition.code); q.filter("signStatus",UserCompetition.SIGN_STATUS_Y); long count = q.count(); int pageSize = 100; int pageCount=(int) (count%pageSize==0?(count/pageSize):(count/pageSize+1)); List<UserCompetition> list = null; for(int i=1;i<=pageCount;i++){ list=q.fetch(i, pageSize); for(UserCompetition uc:list){ uc.loadAttackPower(); uc.save(); } } } } /** * 開始海選 * a) 設定32個小組。 * b) 全部人隨機分配到32個小組(總人數/32,餘數平均分配)。 * c) 小組賽以淘汰賽制兩兩隨機配對戰鬥,敗者淘汰。 * d) 小組賽第一名出線參加淘汰賽。 */ @Override public boolean beginSelecting(int levelType) { Competition competition = Competition.find().order("-code").first(); if(competition != null){ competition.selectBegin(); competition.save(); MorphiaQuery q = UserCompetition.createQuery(); q.filter("code", competition.code); q.filter("levelType", levelType); q.and(q.criteria("failTimes").greaterThan(0)); q.filter("signStatus",UserCompetition.SIGN_STATUS_Y); long count = q.count(); //設置總共32頁 int pageCount = 32; if(count<=pageCount){ return true; } //每頁條數 int pageSize = (int) (count/pageCount); //32頁以後的條數 int pageSubSize = (int) (count%pageCount); List<UserCompetition> list = null; List<UserCompetition> templist = null; List<UserCompetition> winlist = null; List<UserCompetition> sublist = null; int groupIndex = 0 ; //取出33頁的數據 if(pageSubSize>0){ int start = (int) (count-pageSubSize); q.from(start); sublist = q.fetch(pageCount); } q.from(0); for(int i=1;i<=pageCount;i++){ groupIndex = i; list = new ArrayList<UserCompetition>(); //取一條加入當前組 if(i<=pageSubSize){ list.add(sublist.get(i-1)); } //若是每頁條數小於100條 if(pageSize<=100){ templist = q.fetch(i, pageSize); list.addAll(templist); //當前組開始一輪戰鬥 doSelectPking2(list,groupIndex); //若是每頁條數大於100條,則再分頁每頁100條進行處理 }else{ winlist = new ArrayList<UserCompetition>(); //分頁條數 int pageSize1 = 100; //偏移量(用於計算32組,每組分頁的起始位置) int offset = (i-1)*pageSize; //計算不滿100條的偏移量 int offsetSub = 0; //本組的總頁數 int pageCount1 = pageSize/pageSize1; //不滿100條的頁 int pageSubCount1 = pageSize%pageSize1>0?1:0; //不滿100條的頁的條數 int pageSubSize1 = pageSize%pageSize1; List<UserCompetition> sublist1 = null; //若是有不滿100條的頁單獨處理 if(pageSubCount1>0){ //計算餘數 offsetSub = pageSize - pageSubSize1; //只取剩餘條數 sublist1 = q.from(offsetSub).fetch(pageSubSize1); winlist.add(doSelectPking2(sublist1,groupIndex)); } //設置該組的起始偏移量 q.from(offset); for(int j=1;j<=pageCount1;j++){ //分頁取出 templist = q.fetch(j, pageSize1); list.addAll(templist); winlist.add(doSelectPking2(list,groupIndex)); } doSelectPking2(winlist,groupIndex); } } //處理競技32強的信息 // endSelectingPk(levelType); }else{ return true; } return false; } @Override public void endSelectingPk() { Competition competition = Competition.find().order("-code").first(); if(competition != null){ competition.selectEnd(); competition.save(); } } /** * 進行海選戰鬥算法1 * @param list */ public void doSelectPking(List<UserCompetition> list,int groupIndex){ List<UserCompetition> templist = new ArrayList<UserCompetition>(); List<UserCompetition> tlist = new ArrayList<UserCompetition>(); templist.addAll(list); tlist.addAll(list); UserCompetition pkerA = null; UserCompetition pkerB = null; int pkerAindex = 0; int pkerBindex = 0; boolean isWin = false; while(tlist.size()>1){ tlist.clear(); //從隊列中隨機選一個做爲第一個選手 pkerAindex = new Random().nextInt(templist.size()); pkerA = templist.remove(pkerAindex); //從剩餘的隊列中隨機選一個做爲第二個選手 pkerBindex = new Random().nextInt(templist.size()); pkerB = templist.remove(pkerBindex); //進行pk isWin = pkerA.getSelectPkResult(pkerB); PkInfo pkInfo = new PkInfo(pkerA.code, pkerA.levelType, groupIndex, 0, PkInfo.PK_TYPE_SELECT, pkerA.uid, pkerB.uid); if(isWin){ //若是A勝利了則從新回到隊列中,不然被淘汰 templist.add(pkerA); //競技32強 if(templist.size()==1){ pkInfo.setSelectPkResult(isWin, PkInfo.SELECT_PK_STATUS_GOUP, PkInfo.SELECT_PK_STATUS_OUT); //更新排名 pkerA.rank = PkInfo.ranks[0]; //晉級下一輪 }else{ pkInfo.setSelectPkResult(isWin, PkInfo.SELECT_PK_STATUS_CONTINUE, PkInfo.SELECT_PK_STATUS_OUT); } }else{ //若是B勝利了則從新回到隊列中,不然被淘汰 templist.add(pkerB); //競技32強 if(templist.size()==1){ pkInfo.setSelectPkResult(isWin, PkInfo.SELECT_PK_STATUS_OUT, PkInfo.SELECT_PK_STATUS_GOUP); //更新排名 pkerB.rank = PkInfo.ranks[0]; //晉級下一輪 }else{ pkInfo.setSelectPkResult(isWin, PkInfo.SELECT_PK_STATUS_OUT, PkInfo.SELECT_PK_STATUS_CONTINUE); } } pkInfo.save(); pkerA.save(); pkerB.save(); tlist.addAll(templist); } } /** * 進行海選戰鬥算法2 * @param list */ public UserCompetition doSelectPking2(List<UserCompetition> list, int groupIndex){ List<UserCompetition> templist = new ArrayList<UserCompetition>(); List<UserCompetition> winlist = new ArrayList<UserCompetition>(); List<UserCompetition> tlist = new ArrayList<UserCompetition>(); templist.addAll(list); winlist.addAll(list); tlist.addAll(list); UserCompetition pkerA = null; UserCompetition pkerB = null; int pkerAindex = 0; int pkerBindex = 0; boolean isWin = false; boolean isLastRound = list.size()<=2?true:false; int round = 0; UserCompetition winner = null; //當勝利者個數爲1的時候爲勝利 while(winlist.size()>1){ //輪次自增 round++; winlist.clear(); //進行第round輪死鬥賽 while(tlist.size()>1){ tlist.clear(); //從勝利的隊列中隨機選一個做爲第一個選手 pkerAindex = new Random().nextInt(templist.size()); pkerA = templist.remove(pkerAindex); //從勝利的隊列中隨機選一個做爲第二個選手 pkerBindex = new Random().nextInt(templist.size()); pkerB = templist.remove(pkerBindex); //進行pk isWin = pkerA.getSelectPkResult(pkerB); PkInfo pkInfo = new PkInfo(pkerA.code, pkerA.levelType,groupIndex, round, PkInfo.PK_TYPE_SELECT, pkerA.uid, pkerB.uid); if(isWin){ //若是A勝利了則放入到勝利隊列中,不然被淘汰 winlist.add(pkerA); //競技32強 if(isLastRound){ pkInfo.setSelectPkResult(isWin, PkInfo.SELECT_PK_STATUS_GOUP, PkInfo.SELECT_PK_STATUS_OUT); //更新排名 pkerA.rank = PkInfo.ranks[0]; //晉級下一輪 }else{ pkInfo.setSelectPkResult(isWin, PkInfo.SELECT_PK_STATUS_CONTINUE, PkInfo.SELECT_PK_STATUS_OUT); } }else{ //若是B勝利了則從新回到隊列中,不然被淘汰 winlist.add(pkerB); //競技32強 if(isLastRound){ pkInfo.setSelectPkResult(isWin, PkInfo.SELECT_PK_STATUS_OUT, PkInfo.SELECT_PK_STATUS_GOUP); //更新排名 pkerB.rank = PkInfo.ranks[0]; //晉級下一輪 }else{ pkInfo.setSelectPkResult(isWin, PkInfo.SELECT_PK_STATUS_OUT, PkInfo.SELECT_PK_STATUS_CONTINUE); } } pkInfo.save(); pkerA.save(); pkerB.save(); tlist.addAll(templist); } tlist.clear(); templist.addAll(winlist); tlist.addAll(templist); winlist.clear(); winlist.addAll(templist); if(templist.size()<=2){ isLastRound = true; } } return winner; } /** * 開始淘汰賽 */ @Override public boolean beginPkouting(int levelType) { Competition competition = Competition.find().order("-code").first(); if(competition != null){ competition.pkoutBegin(); competition.save(); MorphiaQuery q = UserCompetition.createQuery(); q.filter("code", competition.code); q.filter("levelType", levelType); q.filter("signStatus",UserCompetition.SIGN_STATUS_Y); q.filter("isSelectPkOut", false); q.order("-attackPower"); List<UserCompetition> list = q.fetch(32); int round = getRoundByRank(list.size()); //根據進入32強的人數判斷淘汰賽從第幾輪開始 for(int i=round;i<=5;i++){ doPkouting(list, i); } } return false; } /** * 淘汰賽PK * @param list * @param round */ public void doPkouting(List<UserCompetition> list, int round){ List<UserCompetition> templist = new ArrayList<UserCompetition>(); List<UserCompetition> rmvlist = new ArrayList<UserCompetition>(); templist.addAll(list); for(UserCompetition uc:list){ //過濾被淘汰掉的選手 if(uc.isPkoutOut){ templist.remove(uc); rmvlist.add(uc); } } list.removeAll(rmvlist); int size = templist.size(); int spliter = 0; if(size>1){ spliter = size%2==0?size/2:(size/2+1); } //分組 //A組 List<UserCompetition> listA = templist.subList(0, spliter); //B組 List<UserCompetition> listB = templist.subList(spliter,size); UserCompetition ucA = null; UserCompetition ucB = null; boolean isWin = false; for(int i=0;i<listA.size();i++){ ucA = listA.get(i); if(i<listB.size()){ ucB = listB.get(i); }else{ ucB = null; } //戰鬥 if(ucA !=null && ucB !=null){ PkInfo pkInfo = new PkInfo(ucA.code, ucA.levelType, 0, 0, PkInfo.PK_TYPE_PKOUT, ucA.uid, ucB.uid); pkInfo.round = round; isWin = battle(ucA.uid, ucB.uid).result; pkInfo.setPkOutResult(isWin); //A勝利晉級,則B被淘汰 if(isWin){ ucA.rank = getRankByRound(round); ucB.isPkoutOut = true; //B勝利晉級,則A被淘汰 }else{ ucB.rank = getRankByRound(round); ucA.isPkoutOut = true; } pkInfo.save(); ucA.save(); ucB.save(); } } } @Override public boolean endPkoutingPk(int levelType) { // TODO Auto-generated method stub return false; } public Battle battle(String uid, String targetId) { BattleServiceImpl battleService = new BattleServiceImpl(); //1. Construct data for fight GameUserService service = Spring.getBeanOfType(GameUserService.class); GameUser user = service.getSimpleInfoForFight(uid); //Refresh target user energy/physical/fight attributes. GameUser targetUser = service.getGameUser(targetId); targetUser.autoIncreaseLiveAttribute(); targetUser.save(); GameUser target = service.getSimpleInfoForFight(targetId); List<FightableObj> attacker = new ArrayList<FightableObj>(); attacker.add(user); List<FightableObj> anAttacker = new ArrayList<FightableObj>(); anAttacker.add(target); //2. Fight Battle battle = battleService.battleMultipleMembers(attacker, anAttacker); //3. Fight result process String winnerId = uid; String loserId = targetId; boolean isTargetWin = false; if(!battle.result){ winnerId = targetId; loserId = uid; isTargetWin = true; } Map<String,FightResult> map = doFightResult(winnerId, loserId, null,user.getId().toString()); FightResult result = map.get(uid); battle.fightNeeds = result; return battle; } public Map<String, FightResult> doFightResult(String winnerId, String loserId, String objId,String uid) { int loserConsumedFight = RandomUtil.getRandomValue(10, 20); int loserExp = 0; int loserFightPoint = 1; long loserHonor = 0; long winHonor = 0; int winExp = RandomUtil.getRandomValue(1, 4); int winFightPoint = RandomUtil.getRandomValue(1, 3); int winConsumedFight = RandomUtil.getRandomValue(1, 10); int finalWinExp = AchievementUtils.getExpForPK(winExp); int physicalPower = 1; FightResult loserResult = new FightResult(loserId, false, 0,loserHonor, loserExp, loserFightPoint, loserConsumedFight, physicalPower, objId); FightResult winnerResult = new FightResult(winnerId, true, 0,winHonor, finalWinExp, winFightPoint, winConsumedFight, physicalPower, objId); winnerResult.additionalExp = AchievementUtils.getAdditionalValue(AchievementResult.TYPE_EXP_PK); winnerResult.additionalMoney = AchievementUtils.getAdditionalValue(AchievementResult.TYPE_MONEY_PK); Map<String, FightResult> result = new HashMap<String, FightResult>(2); result.put(winnerId, winnerResult); result.put(loserId, loserResult); return result; } public int getRankByRound(int round){ int rank = 0; if(round == 1){ rank = 16; }else if(round == 2){ rank = 8; }else if(round == 3){ rank = 3; }else if(round == 4){ rank = 2; }else if(round == 5){ rank = 1; } return rank; } public int getRoundByRank(int rank){ int round = 0; if(rank>16){ round = 1; }else if(rank > 8 && rank <= 16){ round = 2; }else if(rank > 4 && rank <= 8){ round = 3; }else if(rank > 2 && rank <= 4){ round = 4; }else if(rank > 1 && rank <= 2){ round = 5; } return round; } /** * 自動發放獎勵 */ @Override public void autoRewarding() { Competition competition = Competition.find().order("-code").first(); if(competition != null){ competition.toReward(); competition.save(); MorphiaQuery q = UserCompetition.createQuery(); q.filter("code", competition.code); q.filter("signStatus",UserCompetition.SIGN_STATUS_Y); // q.filter("receiveRewardStatus", UserCompetition.RECEIVE_REWARD_STATUS_N); long count = q.count(); int pageSize = 100; int pageCount=(int) (count%pageSize==0?(count/pageSize):(count/pageSize+1)); List<UserCompetition> list = null; GameUser gu = null; for(int i=1;i<=pageCount;i++){ list=q.fetch(i, pageSize); for(UserCompetition uc:list){ gu = GameUser.findById(uc.uid); //發送禮包 CompetitionReward.rewardToUser(gu, uc.rank, uc.levelType); uc.receiveRewardStatus = UserCompetition.RECEIVE_REWARD_STATUS_Y; uc.save(); } } } } /** * 獲取本屆戰況信息 * @param pageNum * @return */ @Override public PageTDO getCompetitionPkInfo(int pageNum, int levelType) { Competition competition = Competition.find().order("-code").first(); if(competition == null){ return null; } List<PkInfo> list = null; long now = new Date().getTime(); MorphiaQuery q = PkInfo.find("code", competition.code); q.filter("levelType", levelType); q.order("-pkType,-groupIndex,-round"); long count = q.countAll(); int pageCount=(int) (count%PageTDO.pageSize==0?(count/PageTDO.pageSize):(count/PageTDO.pageSize+1)); list = q.fetch(pageNum, PageTDO.pageSize); for(PkInfo info: list){ info.loadUserInfo(); } if(competition.status == Competition.STATUS_IN_INIT || competition.status == Competition.STATUS_IN_SIGN || competition.status == Competition.STATUS_IN_SIGN_END){ list = null; } PageTDO page = new PageTDO(count,pageNum,pageCount,list); return page; } @Override public void clearData() { // TODO Auto-generated method stub Competition competition = Competition.find().order("-code").first(); if(competition == null){ return; } long code = competition.code-1; //清除上一屆PKinfo MorphiaQuery clearPkinfo = PkInfo.filter("code", code); PkInfo.delete(clearPkinfo); //清除上一屆報名表數據只保留三十二強數據 MorphiaQuery clearUserinfo = UserCompetition.filter("code", code); clearUserinfo.filter("isSelectPkOut", true); UserCompetition.delete(clearUserinfo); } }
package models.competition; import java.util.Date; import java.util.List; import org.apache.ivy.core.event.download.EndArtifactDownloadEvent; import play.modules.morphia.Model; import service.AppConfigKeyConstants; import service.util.AppConfigUtils; import service.util.DateUtils; import com.google.code.morphia.annotations.Entity; import com.google.code.morphia.annotations.Transient; @Entity public class Competition extends Model{ public static final int STATUS_IN_INIT = 0; public static final int STATUS_IN_SIGN = 1; public static final int STATUS_IN_SIGN_END = 11; public static final int STATUS_IN_SELECT = 2; public static final int STATUS_IN_SELECT_END = 22; public static final int STATUS_IN_PKOUT = 3; public static final int STATUS_IN_CLOSED = 4; public static final int COMPETITION_ENABLE_N = 0; public static final int COMPETITION_ENABLE_Y = 1; /** * 第幾屆擂臺賽 */ public long code; /** * 報名開始時間 */ public long signBeginTime; /** * 報名結束時間 */ public long signEndTime; /** * 海選開始時間 */ public long selectBeginTime; /** * 淘汰賽開始時間 */ public long pkoutBeginTime; /** * 初級淘汰賽對陣名單及結果 */ @Transient public List<PkInfo> nomalLevelPkList; /** * 高級淘汰賽對陣名單及結果 */ @Transient public List<PkInfo> highLevelPkList; /** * 所在狀態【1:報名中;2:海選中;3:淘汰賽;】 */ public int status; /** * 上一個擂臺賽結束的時候 新建一個擂臺賽 */ public void init(){ Competition competition = Competition.find().order("-code").first(); if(competition == null){ this.code = 1; }else{ this.code = competition.code+1; } //第一屆擂臺賽剛開始 //若是當前時間尚未到報名截止時間 if(competition == null){ this.signBeginTime = DateUtils.getTimeOfWeekByTime(1, 9, 0, 0).getTime(); this.signEndTime = DateUtils.getTimeOfWeekByTime(5, 9, 0, 0).getTime(); this.selectBeginTime = DateUtils.getTimeOfWeekByTime(5, 20, 0, 0).getTime(); this.pkoutBeginTime = DateUtils.getTimeOfWeekByTime(6, 20, 0, 0).getTime(); //下一屆 }else{ this.signBeginTime = DateUtils.getTimeOfNextWeekByTime(1, 9, 0, 0).getTime(); this.signEndTime = DateUtils.getTimeOfNextWeekByTime(5, 9, 0, 0).getTime(); this.selectBeginTime = DateUtils.getTimeOfNextWeekByTime(5, 20, 0, 0).getTime(); this.pkoutBeginTime = DateUtils.getTimeOfNextWeekByTime(6, 20, 0, 0).getTime(); } } /** * 檢查擂臺賽是否可用發佈使用 */ public static boolean checkEnable(){ int status = AppConfigUtils.getIntValue(AppConfigKeyConstants.COMPETITION_ENABLE_STATUS, COMPETITION_ENABLE_N); if(status == COMPETITION_ENABLE_N){ return false; }else if (status == COMPETITION_ENABLE_Y){ return true; } return false; } /** * 產生下一屆 */ public void createNextCompetition(){ this.status = STATUS_IN_INIT; } /** * 報名開始 */ public void signBegin(){ this.status = STATUS_IN_SIGN; } /** * 報名結束 */ public void signEnd(){ this.status = STATUS_IN_SIGN_END; } /** * 海選賽開始 */ public void selectBegin(){ this.status = STATUS_IN_SELECT; } /** * 海選賽結束 */ public void selectEnd(){ this.status = STATUS_IN_SELECT_END; } /** * 淘汰賽開始 */ public void pkoutBegin(){ this.status = STATUS_IN_PKOUT; } /** * 淘汰賽結束 */ public void toReward(){ this.status = STATUS_IN_CLOSED; } }