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
来源:https://www.cnblogs.com/snidget/archive/2013/01/22/2871590.html