The original game’s daily count reset was done like this? See if there are any bugs

table of Contents

1. Design requirements

2. Database design

3. Code implementation

4. Summary


image

In game development, there is often a need to limit the number of times per day. Such a function may appear in almost every function. This function is written by each module itself and is repeated, so it needs to be processed in a unified manner.

For example: the number of free daily lotteries, such as the number of copies that can be played each day, and so on.

Today I will write about the realization of this daily limit function.

1. Design requirements

Any module can be called, it can be automatically reset when inquiring, and automatically stored in the library, and supports weekly, monthly and other cycles.

2. Database design

image

n_roleId: player id, as the primary key

n_reset_type: enumeration, different reset types define different id as the primary key

n_count: the number of used in the current cycle, reset to 0 each time

s_extend: extended field, each type can store some custom data in it

d_update: update time

d_create: the time when the data was created

3. Code implementation

3.1 Enumeration type definition

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;  }}

Description: Enumeration defines 2 constructors.

The default constructor reset type is 1, which means daily reset.

2 parameter constructor, you can customize the reset type, reset type 1 daily 2 weekly 3 monthly

3.2 Date function util

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));  }}

Description: Realize the time comparison of days, months and weeks, you can judge whether the two times are on the same day, the same week, and the same month.

3.3 Definition of reset object

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;  }  }

Description: Reset the built-in methods of the object, such as checking and increasing the number of times.

addCount function, when no parameters are passed, the number of times is increased by 1 by default, and 1 time is increased on the current basis

When passing parameters, use the passed parameters, such as addCount(50), which will increase 50 times on the current basis.

3.4 How to use

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 Matters needing attention

1. The data storage operation is not implemented. When using the code, you need to change it according to your own project.

2. It is not encapsulated. The operation is automatically created when the object corresponding to the enumeration type does not exist. You can implement it yourself according to your own project code rules

In the above I defined a map, which can be encapsulated and implemented using the following code

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. Summary

The idea of ​​periodically limiting the number of times is very simple, that is, the number of times reset detection is performed wherever the number of visits is needed.

What we have to do is to make it simple and convenient, and encapsulate the logic more smoothly.

Okay, that's it for today, sleep.

Regular benefits

image