遊戲中的擂臺賽

 
 

哈哈 今天再補充一個之前撒懶的筆記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;
    }
}
相關文章
相關標籤/搜索