前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >服务端模块:周期性次数重置

服务端模块:周期性次数重置

作者头像
香菜聊游戏
发布2021-06-07 15:47:11
5840
发布2021-06-07 15:47:11
举报
文章被收录于专栏:香菜聊游戏香菜聊游戏

在游戏开发中经常会有每天限制次数的需求,这样的功能几乎在每个功能都可能出现,这种功能每个模块自己写又是重复的,因此需要统一处理。

比如:每日抽奖的免费次数,比如每天可打的副本次数等等功能。

今天这篇写一下这个每日次数限制的功能的实现。

1、设计需求

需要任何模块都可以调用,在查询的时候可以自动重置,并且自动入库,并且支持周,月等周期。

2、数据库设计

n_roleId : 玩家id,作为主键

n_reset_type : 枚举,不同的重置类型定义不同的id,作为主键

n_count :当前周期已经使用的数量,每次重置为0

s_extend :扩展字段,每种类型可以存一些自定义的数据到里面

d_update : 更新时间

d_create : 数据创建的时间

3、代码实现

3.1 枚举类型定义
代码语言:javascript
复制
package org.pdool.dayLimit;

/**
 * 重置次数限制类型
 */
public enum ResetLimitType {
    /**
     * 每日抽奖次数
     */
    LOTTERY_COUNT(1),
    /**
     *  每周收礼次数
     */
    RECEIVE_GIFT_COUNT(2,2),
    ;
    /**
     * 限制类型
     */
    private int limitType;
    /**
     * 重置类型 1 每天 2 每周 3 每月
     */
    private int resetType = 1;

    ResetLimitType(int limitType) {
        this.limitType = limitType;
    }

    ResetLimitType(int limitType, int resetType) {
        this.limitType = limitType;
        this.resetType = resetType;
    }

    public int getLimitType() {
        return limitType;
    }

    public int getResetType() {
        return resetType;
    }

    public static ResetLimitType valueOf(int limitType) {
        for (ResetLimitType resetLimitType : values()) {
            if (limitType == resetLimitType.getLimitType()) {
                return resetLimitType;
            }
        }
        return null;
    }
}

说明:枚举定义了2个构造函数。

默认的构造函数重置类型是1,也就是每日重置。

2个参数的构造函数,可以自定义重置类型,重置类型 1 每天 2 每周 3 每月

3.2 日期函数util
代码语言:javascript
复制
package org.pdool.dayLimit;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DateUtil {
    /**
     * 判断两个日期是否同一天
     *
     * @param beginDate
     * @param endDate
     * @return
     */
    public static boolean isSameDay(Date beginDate, Date endDate) {
        return getDiffDays(beginDate, endDate) == 0;
    }
    /**
     * 判断两个日期是否同一周
     *
     * @param beginDate
     * @param endDate
     * @return
     */
    public static boolean isSameWeek(Date beginDate, Date endDate) {
        Calendar begin = Calendar.getInstance();
        begin.setTime(beginDate);
        Calendar end = Calendar.getInstance();
        end.setTime(endDate);

        //换算beginDate的周一时间
        int beginDayOfWeek = begin.get(Calendar.DAY_OF_WEEK);
        if (beginDayOfWeek == 1) {
            begin.add(Calendar.DAY_OF_YEAR, -6);
        } else if (beginDayOfWeek > 2) {
            begin.add(Calendar.DAY_OF_YEAR, 2 - beginDayOfWeek);
        }

        //换算endDate的周一时间
        int endDayOfWeek = end.get(Calendar.DAY_OF_WEEK);
        if (endDayOfWeek == 1) {
            end.add(Calendar.DAY_OF_YEAR, -6);
        } else if (endDayOfWeek > 2) {
            end.add(Calendar.DAY_OF_YEAR, 2 - endDayOfWeek);
        }
        return ((end.get(Calendar.YEAR) == begin.get(Calendar.YEAR)) && (end.get(Calendar.DAY_OF_YEAR) == begin.get(Calendar.DAY_OF_YEAR)));
    }

    /**
     * 两个时间相差天数
     *
     * @param beginDate
     * @param endDate
     * @return
     */
    public static int getDiffDays(Date beginDate, Date endDate) {
        Calendar begin = Calendar.getInstance();
        begin.setTime(beginDate);
        begin.set(Calendar.HOUR_OF_DAY, 0);
        begin.set(Calendar.MINUTE, 0);
        begin.set(Calendar.SECOND, 0);
        begin.set(Calendar.MILLISECOND, 0);
        Calendar end = Calendar.getInstance();
        end.setTime(endDate);
        end.set(Calendar.HOUR_OF_DAY, 0);
        end.set(Calendar.MINUTE, 0);
        end.set(Calendar.SECOND, 0);
        end.set(Calendar.MILLISECOND, 0);
        return (int) ((end.getTimeInMillis() - begin.getTimeInMillis()) / (24 * 60 * 60 *1000));
    }


    /**
     * 判断2个时间
     *@param date
     *@param date2
     *@param state  1:比较是否是同一个月,2:比较是否是同一天,3:比较是否是同一年
     *@return boolean
     */
    public static boolean isSameMonth(Date date, Date date2)
    {
        Calendar begin = Calendar.getInstance();
        begin.setTime(date);
        Calendar end = Calendar.getInstance();
        end.setTime(date2);
        return (end.get(Calendar.YEAR) == begin.get(Calendar.YEAR)) && (end.get(Calendar.MONTH) == begin.get(Calendar.MONTH));
    }
}

说明:实现了对天,月 和 周的时间比较,可以判断两个时间是否在同一天,同一周,同一个月。

3.3 重置对象的定义
代码语言:javascript
复制
package org.pdool.dayLimit;

import java.util.Date;

/**
 * 重置次数
 */
public class ResetCountVO {
    //  角色id
    private int roleId;
    //  重置的类型
    private ResetLimitType resetType;
    //已经消耗次数
    private int num;
    //最后更新时间
    private Date updateTime;
    //扩展信息
    private String extend;

    public int getRoleId() {
        return roleId;
    }

    public void setRoleId(int roleId) {
        this.roleId = roleId;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    public String getExtend() {
        return extend;
    }

    public void setExtend(String extend) {
        this.extend = extend;
    }

    public ResetLimitType getResetType() {
        return resetType;
    }

    public void setResetType(ResetLimitType resetType) {
        this.resetType = resetType;
    }

    /**
     * 获得次数
     *
     * @return
     */
    public int getCount() {
        int resetType = this.resetType.getResetType();
        Date now = new Date();
        if (resetType == 1) {
            //  每日重置
            if (DateUtil.isSameDay(now, updateTime)) {
                return this.num;
            }
        } else if (resetType == 2) {
            //  每周重置
            if (DateUtil.isSameWeek(now, updateTime)) {
                return this.num;
            }
        } else if (resetType == 3) {
            //  每月重置
            if (DateUtil.isSameMonth(now, updateTime)) {
                return this.num;
            }
        }
        this.num = 0;
        updateTime = now;
        return 0;
    }

    /**
     * 增加次数
     *
     * @param addCountArg
     * @return
     */
    public int addCount(int... addCountArg) {
        int count = getCount();
        int addCount = 1;
        if (addCountArg.length != 0) {
            addCount = addCountArg[0];
        }
        count += addCount;
        num = count;
        updateTime = new Date();
        return count;
    }


}

说明:重置对象自带的方法比如查和增加次数。

addCount 函数,在不传参数的时候,默认增加次数 1,在当前的基础上增加1 次

传递参数的时候,则使用传递的参数,比如 addCount(50),则在当前的基础上增加50次。

3.4 使用方法
代码语言:javascript
复制
package org.pdool.dayLimit;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class Aain {
    public static void main(String[] args) {
        Map<ResetLimitType,ResetCountVO> playerResetMap = new HashMap<>();
        ResetCountVO resetCountVO1 = new ResetCountVO();
        resetCountVO1.setResetType(ResetLimitType.LOTTERY_COUNT);
        resetCountVO1.setUpdateTime(new Date(1621870616000L));
        resetCountVO1.setNum(1);
        playerResetMap.put(ResetLimitType.LOTTERY_COUNT,resetCountVO1 );

        ResetCountVO resetCountVO2 = new ResetCountVO();
        resetCountVO2.setResetType(ResetLimitType.RECEIVE_GIFT_COUNT);
        resetCountVO2.setUpdateTime(new Date(1621870616000L));
        resetCountVO2.setNum(1000);
        playerResetMap.put(ResetLimitType.RECEIVE_GIFT_COUNT,resetCountVO2 );

        int count = resetCountVO1.getCount();
        System.out.println(count);

        int count2 = resetCountVO2.getCount();
        System.out.println(count2);
    }
}
3.5 注意事项

1、没有实现数据的入库操作,这个在使用代码的时候,需要根据自己的项目进行更改。

2、没有封装在枚举类型对应的对象不存在时自动创建操作,可以根据自己的项目代码规则自己实现

在上面的我定义了一个map ,可以使用 下面的代码进行封装实现

代码语言:javascript
复制
 ResetCountVO resetCountVO = playerResetMap.computeIfAbsent(ResetLimitType.LOTTERY_COUNT, k -> new ResetCountVO());
        if (resetCountVO.getUpdateTime() == null){
            resetCountVO.setResetType(ResetLimitType.LOTTERY_COUNT);
            resetCountVO.setUpdateTime(new Date(1621870616000L));
            resetCountVO.setNum(1);
        }

4、总结

周期性的限制次数的思想很简单,就是任何需要访问数量的地方进行次数重置检测。

我们要做的就是怎么实现的的简单方便,将逻辑进行封装的更顺手。

好了,今天就写到这吧,睡觉。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 香菜聊游戏 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、设计需求
  • 2、数据库设计
  • 3、代码实现
    • 3.1 枚举类型定义
      • 3.2 日期函数util
        • 3.3 重置对象的定义
          • 3.4 使用方法
            • 3.5 注意事项
            • 4、总结
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档