• 关于网站签到功能的设计


    1,最近网站要上一个签到的功能,一个多游戏的平台,每种游戏的官网都有签到功能,设计打算把数据放到平台。

    2,首先要设计签到表,这里直接给出过了一遍dba,需求人员,设计人员脑子的结果:

    最精彩的地方是signHistory的设计,直接存成bigint,通过转换成二进制来记录签到的历史;

    3,预览图

    4,功能抽取

    非常明显,只有三个主要的功能,第一个签到之前的登录;第二个,签到;第三个,领取礼包;

    功能                  功能概述 功能的具体逻辑  接口方法设计
    登录之前的查询 通过查询,以前签过到的,显示签到历史;没有签过到的,神马也不显示; 查询dt_sign表,通过gid和uid查询,如果查询到,返回签到信息,如果没有查到,返回提示信息  SignMsg loginQuery(int gid,int uid)
    签到 点击签到,如果当天已经签过到了,提示已经签过到了;如果从来没有签过到,插入数据,把积分设置为1,连续签到次数设置为1,最后修改时间设置为当天,历史为1;如果今天没有签过到,首先计算出有多少天没签到了,如果是昨天签了的,连续签到次数加1,历史左移一位,积分按照积分规则加上;如果超过两天没有签到,连续签到次数设置为1,历史左移天数位,积分加上签到单次的积分,时间为当前的修改时间; 首先查询dt_sign,按照gid和uid,如果没查到,插入记录;查到了,判断最后修改时间,做相应的处理; SignMsg todaySign(int gid,int uid)
    领取礼包 点击领取礼包,如果分数够,减去积分,允许该用户领取礼包;如果分数不过,提示积分不够; 点击领取礼包,如果分数够,减去积分,允许该用户领取礼包;如果分数不过,提示积分不够; SignMsg getGiftPack(int gid,int uid,int score)

    5,具体实现

    jdbc实现:

    复制代码
      1 package com.sz7road.userplatform.dao.jdbc;
      2 
      3 import com.google.common.base.Strings;
      4 import com.sz7road.userplatform.dao.SignDao;
      5 import com.sz7road.userplatform.ws.sign.ScoreRuleAndMoveByte;
      6 import com.sz7road.userplatform.ws.sign.Sign;
      7 import com.sz7road.userplatform.ws.sign.SignObject;
      8 import com.sz7road.utils.CommonDateUtils;
      9 import org.apache.commons.dbutils.DbUtils;
     10 import org.slf4j.Logger;
     11 import org.slf4j.LoggerFactory;
     12 
     13 import java.sql.*;
     14 import java.text.ParseException;
     15 import java.text.SimpleDateFormat;
     16 import java.util.*;
     17 import java.util.Date;
     18 
     19 /**
     20  * Created with IntelliJ IDEA.
     21  * User: cutter.li
     22  * Date: 13-1-18
     23  * Time: 上午11:01
     24  */
     25 public class SignDaoJdbcImp extends JdbcDaoSupport<SignObject> implements SignDao {
     26 
     27     private final static Logger log = LoggerFactory.getLogger(SignDaoJdbcImp.class);
     28 
     29     private Connection conn = null;
     30 
     31     @Override
     32     public Sign querySign(int uid, int gid) {
     33         Sign sign = new Sign();
     34         ResultSet rs = null;
     35         PreparedStatement preparedStatement = null;
     36         try {
     37             conn = getQueryRunner().getDataSource().getConnection();
     38             preparedStatement = conn.prepareStatement(" select * from db_userplatform.dt_sign where userid=? and gameid=? ;");
     39 
     40             preparedStatement.setInt(1, uid);
     41             preparedStatement.setInt(2, gid);
     42 
     43             rs = preparedStatement.executeQuery();
     44             if (rs.next()) {
     45                 sign.setCode(200);
     46                 sign.setMsg("成功的查询到签到信息!");
     47                 sign.setContinueSignCount(rs.getInt("signCount"));
     48                 sign.setTotalScore(rs.getInt("integration"));
     49                 sign.setLastModifyDate(new Date(rs.getDate("lastModifyTime").getTime()));
     50                 sign.setSignHistory(rs.getLong("signHistory"));
     51             } else {
     52                 sign.setCode(300);
     53                 sign.setMsg("该用户从来没有签过到!");
     54             }
     55 
     56         } catch (SQLException e) {
     57             sign.setCode(404);
     58             sign.setMsg("平台或者db异常!");
     59             e.printStackTrace();
     60         } finally {
     61             DbUtils.closeQuietly(rs);
     62             try {
     63                 DbUtils.close(preparedStatement);
     64             } catch (SQLException e) {
     65                 e.printStackTrace();
     66             }
     67             DbUtils.closeQuietly(conn);
     68         }
     69         return sign;
     70     }
     71 
     72 
     73     @Override
     74     public Sign signThenReturn(int uid, int gid) {
     75         Sign sign = new Sign();
     76         ResultSet rs = null;
     77         PreparedStatement preparedStatement = null, executePreparedStatement = null;
     78         try {
     79             conn = getQueryRunner().getDataSource().getConnection();
     80             preparedStatement = conn.prepareStatement(" select * from db_userplatform.dt_sign where userid=? and gameid=? ;");
     81             preparedStatement.setInt(1, uid);
     82             preparedStatement.setInt(2, gid);
     83 
     84             rs = preparedStatement.executeQuery();
     85             if (rs.next()) {//查到了更新
     86                 SignObject signObject = new SignObject();
     87                 signObject.setId(rs.getInt("id"));
     88                 signObject.setUid(rs.getInt("userid"));
     89                 signObject.setGid(rs.getInt("gameid"));
     90                 signObject.setSignCount(rs.getInt("signCount"));
     91                 signObject.setIntegration(rs.getInt("integration"));
     92                 signObject.setLastModifyTime(new Date(rs.getDate("lastModifyTime").getTime()));
     93                 signObject.setSignHistory(rs.getLong("signHistory"));
     94                 signObject.setExt(rs.getString("ext"));
     95 
     96 
     97                 Timestamp lastModifyTimeStamp = new Timestamp(signObject.getLastModifyTime().getTime());
     98                 Timestamp todayStartTimeStamp = CommonDateUtils.getTodayStartTimeStamp();
     99                 if (todayStartTimeStamp.after(lastModifyTimeStamp)) {//今天没有签过到
    100                  final  long missDays= (System.currentTimeMillis()-signObject.getLastModifyTime().getTime())/(24*60*60*1000);
    101                     int newSignCount=signObject.getSignCount();
    102                     String newExt="签到";
    103                    if(missDays==1)
    104                    {  //连续签到,加分,连续签到次数增加1 ,签到历史移动一位
    105                      newSignCount+=1;
    106                    }else
    107                    {//不连续签到,加分,连续签到次数为1,签到历史移动missDays位
    108                     newSignCount=1;
    109                    }
    110                     if(newSignCount>=91)
    111                     { //签到超过90天,连续签到次数重置为1
    112                         newSignCount=1;
    113                         newExt="连续签到天数重置为1,时间:"+CommonDateUtils.getDate(System.currentTimeMillis());
    114                     }
    115                    final long   newSignHistory= ScoreRuleAndMoveByte.moveByte(signObject.getSignHistory(),missDays);
    116                   final int  newIntegration=signObject.getIntegration()+ScoreRuleAndMoveByte.getScoreByRule(newSignCount);
    117                     executePreparedStatement = conn.prepareStatement(" update db_userplatform.dt_sign set signCount=? , integration=? , signHistory=? , lastModifyTime=? , ext=? where id=?; ");
    118                     executePreparedStatement.setInt(1, newSignCount);
    119                     executePreparedStatement.setInt(2, newIntegration);
    120                     executePreparedStatement.setLong(3, newSignHistory);
    121                     java.sql.Date signDate= new java.sql.Date(System.currentTimeMillis());
    
    122                     executePreparedStatement.setDate(4,signDate);
    123                     executePreparedStatement.setString(5,newExt);
    124                     executePreparedStatement.setInt(6,signObject.getId());
    125 
    126                     int effectRows = executePreparedStatement.executeUpdate();
    127 
    128                     if (effectRows >= 1) {
    129                         sign.setCode(206);
    130                         sign.setMsg("签到成功!成功更新数据!");
    131                         sign.setContinueSignCount(newSignCount);
    132                         sign.setLastModifyDate(signDate);
    133                         sign.setTotalScore(newIntegration);
    134                         sign.setSignHistory(newSignHistory);
    135                     } else {
    136                         sign.setCode(208);
    137                         sign.setMsg("签到失败,更新数据失败!");
    138                     }
    139                 }
    140                 else
    141                 {//今天已经签过到了
    142                     sign.setCode(300);
    143                     sign.setMsg("该用户今天已经签过到了!");
    144                     sign.setLastModifyDate(signObject.getLastModifyTime());
    145                     sign.setContinueSignCount(signObject.getSignCount());
    146                     sign.setSignHistory(signObject.getSignHistory());
    147                     sign.setTotalScore(signObject.getIntegration());
    148                 }
    149 
    150             } else {//没查到,插入
    151                 executePreparedStatement = conn.prepareStatement(" insert into db_userplatform.dt_sign(userid,gameid,signCount,integration,lastModifyTime,signHistory,ext) values(?,?,1,1,?,1,?); ");
    152                 executePreparedStatement.setInt(1, uid);
    153                 executePreparedStatement.setInt(2, gid);
    154                final java.sql.Date insertDate= new java.sql.Date(System.currentTimeMillis());
    155                 executePreparedStatement.setDate(3, insertDate);
    156                  executePreparedStatement.setString(4,"首次签到,时间:"+insertDate);
    157                 int effectRows = executePreparedStatement.executeUpdate();
    158 
    159                 if (effectRows >= 1) {
    160                     sign.setCode(200);
    161                     sign.setMsg("该用户第一次签到!成功插入数据!");
    162                     sign.setContinueSignCount(1);
    163                     sign.setLastModifyDate(insertDate);
    164                     sign.setTotalScore(1);
    165                     sign.setSignHistory(1);
    166                 } else {
    167                     sign.setCode(204);
    168                     sign.setMsg("该用户第一次签到,插入数据失败!");
    169                 }
    170 
    171             }
    172         } catch (SQLException e) {
    173             sign.setCode(404);
    174             sign.setMsg("平台或者db异常!");
    175             e.printStackTrace();
    176         } finally {
    177             DbUtils.closeQuietly(rs);
    178             try {
    179                 DbUtils.close(preparedStatement);
    180             } catch (SQLException e) {
    181                 e.printStackTrace();
    182             }
    183             DbUtils.closeQuietly(conn);
    184         }
    185         return sign;
    186     }
    187 
    188     @Override
    189     public Sign getGiftPackThenReturn(int uid, int gid, int giftPackScore) {
    190         Sign sign = new Sign();
    191         ResultSet rs = null;
    192         PreparedStatement preparedStatement = null, executePreparedStatement = null;
    193         try {
    194             conn = getQueryRunner().getDataSource().getConnection();
    195             preparedStatement = conn.prepareStatement(" select * from db_userplatform.dt_sign where userid=? and gameid=? and integration >=? ;");
    196 
    197             preparedStatement.setInt(1, uid);
    198             preparedStatement.setInt(2, gid);
    199             preparedStatement.setInt(3, giftPackScore);
    200 
    201             rs = preparedStatement.executeQuery();
    202             if (rs.next()) { //如果查到了减去积分
    203                 SignObject signObject = new SignObject();
    204 
    205                 signObject.setId(rs.getInt("id"));
    206                 signObject.setUid(rs.getInt("userid"));
    207                 signObject.setGid(rs.getInt("gameid"));
    208                 signObject.setSignCount(rs.getInt("signCount"));
    209                 signObject.setIntegration(rs.getInt("integration"));
    210                 signObject.setLastModifyTime(new Date(rs.getDate("lastModifyTime").getTime()));
    211                 signObject.setSignHistory(rs.getLong("signHistory"));
    212                 signObject.setExt(rs.getString("ext"));
    213 
    214 
    215                 executePreparedStatement = conn.prepareStatement(" update db_userplatform.dt_sign set integration=? where id=? ;");
    216                 executePreparedStatement.setInt(1, signObject.getIntegration() - giftPackScore);
    217                 executePreparedStatement.setInt(2, signObject.getId());
    218 
    219                 int effectRows = executePreparedStatement.executeUpdate();
    220 
    221                 if (effectRows >= 1) {
    222                     sign.setCode(200);
    223                     sign.setMsg("成功领取礼包,积分消耗" + giftPackScore);
    224                     sign.setLastModifyDate(signObject.getLastModifyTime());
    225                     sign.setContinueSignCount(signObject.getSignCount());
    226                     sign.setSignHistory(signObject.getSignHistory());
    227                     sign.setTotalScore(signObject.getIntegration() - giftPackScore);
    228                 } else { //减去积分失败
    229                     sign.setCode(400);
    230                     sign.setMsg("领取礼包失败,积分没有减去!");
    231                 }
    232             } else { //没查到,说明积分不够 返回300
    233                 sign.setCode(300);
    234                 sign.setMsg("积分不够领取礼包!");
    235             }
    236         } catch (Exception e) {//发生异常则是404
    237             sign.setCode(404);
    238             sign.setMsg("平台或db异常");
    239             e.printStackTrace();
    240         } finally {
    241             DbUtils.closeQuietly(rs);
    242             try {
    243                 DbUtils.close(preparedStatement);
    244             } catch (SQLException e) {
    245                 e.printStackTrace();
    246             }
    247             DbUtils.closeQuietly(conn);
    248         }
    249         return sign;
    250     }
    251 }
    复制代码


    移位和规则类:

    复制代码
    package com.sz7road.userplatform.ws.sign;
    
    import java.math.BigInteger;
    
    /**
     * Created with IntelliJ IDEA.
     * User: cutter.li
     * Date: 13-1-18
     * Time: 下午5:24
     * 移位和积分规则类
     */
    public class ScoreRuleAndMoveByte {
    
        public static Long moveByte(long oldHistory,long moveAmonut)
        {
            long moveResult= oldHistory<<moveAmonut;
           long result=  Long.parseLong(toFullBinaryString(moveResult),2)+1;
            return result;
        }
    
    
        /**
         * 读取
         * @param num
         * @return
         */
        private static String toFullBinaryString(long num) {
            final int size=42;
            char[] chs = new char[size];
            for(int i = 0; i < size; i++) {
                chs[size - 1 - i] = (char)(((num >> i) & 1) + '0');
            }
            return new String(chs);
        }
    
        /**
         * 按照积分规则,得到积分 ,
         * 积分规则如下:
         签到功能说明
         1.每天只能签到一次(按服务器系统时间为准)
         2.连续签到 额外奖励积分,同种礼包只能使用一次
         3.连续签到10天,一次性奖励2积分
         4.连续签到30天,一次性奖励10积分
         5.连续签到60天,一次性奖励30积分
         6.连续签到90天,一次性奖励100积分
         * @param signCount  连续签到次数
         * @return 增加的积分
         */
        public static  int getScoreByRule(int signCount)
        {
            int addScore=1;
    
            if(signCount==10)
            {
                addScore+=2;
            }
            else if(signCount==30)
            {
                addScore+=10;
            }
            else if(signCount==60)
            {
                addScore+=30;
            }
            else if(signCount==90)
            {
                addScore+=100;
            }
    
            return addScore;
        }
    
    
    
        public static  void main(String[] args)
        {
           long result= moveByte(1,3);
    
            System.out.println("移位结果:"+result);
    
            System.out.println("连续签到次数9:所增加的积分:"+getScoreByRule(9));
            System.out.println("连续签到次数10:所增加的积分:"+getScoreByRule(10));
            System.out.println("连续签到次数29:所增加的积分:"+getScoreByRule(29));
            System.out.println("连续签到次数30:所增加的积分:"+getScoreByRule(30));
            System.out.println("连续签到次数59:所增加的积分:"+getScoreByRule(59));
            System.out.println("连续签到次数60:所增加的积分:"+getScoreByRule(60));
            System.out.println("连续签到次数89:所增加的积分:"+getScoreByRule(89));
            System.out.println("连续签到次数90:所增加的积分:"+getScoreByRule(90));
            System.out.println("连续签到次数91:所增加的积分:"+getScoreByRule(91));
        }
    
    
    
    
    
    
    
    }
    复制代码

      各位屌丝,有什么可以进一步优化的,欢迎联系我,共同进步是我觉得最开心的事情!

    2013-01-22  16:22:24

    no pays,no gains!
  • 相关阅读:
    2022年第一天
    RestTemplate、 Ribbon、 OpenFeign 关系以及OpenFeign使用连接池
    linux下面编写简单的c++程序
    Rocket简介以及单机版安装
    事务源码(二)
    javaagent技术&Attach技术
    gateway网关原理
    Maven自定义插件以及使用
    AotucCrawler 快速爬取图片
    Monkey工具之fastbotiOS实践
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2871729.html
Copyright © 2020-2023  润新知