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