关于网站签到功能的设计
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 )); } }
各位屌丝,有什么可以进一步优化的,欢迎联系我,共同进步是我觉得最开心的事情!
no pays,no gains!
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did47118