关于网站签到功能的设计
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!