1. 程式人生 > 實用技巧 >黃金點遊戲bs架構(四)——基本實現

黃金點遊戲bs架構(四)——基本實現

黃金點遊戲bs架構——基本實現

1.設計框架Review

​ 首先,由於本次實現與前一次進行較大重整,我們先來看一下最初的設計思路和框架,因為現在的設計迴歸了最初的設計方案,和最初設計方案契合度較高。

用例分析
  • 使用者進入網站主介面,會看到前幾輪的黃金點

  • 使用者嘗試登記自己的點數,被要求登入賬號

  • 登入賬號頁面可以點選連結進行註冊

  • 註冊介面要求輸入使用者名稱、電子郵箱(用於找回密碼)密碼和確認密碼

  • 登入介面要求輸入使用者名稱和密碼

  • 登入後回到主頁,但此登記點數不會彈出登入提示,而是會顯示登記成功或者已經登記過了

  • 滿人後計算得分、將比賽記入歷史,進入下一輪比賽

前端設計 後端設計
1.index.html主頁 1.資料庫
· 當沒有登入時提供登入、註冊按鈕
· 當登入時提供使用者主頁、退出登入按鈕
· 顯示最近比賽資訊
· 進行投票
· 使用者-密碼sha256雜湊碼
· 場次-黃金點
· 場次-使用者-登記數字-時間
2.login.html登入介面 2.Redis
· 當有登入時重定向到使用者主頁
· 當沒有登入時提供使用者名稱框、密碼框,將資訊加密後發給伺服器
· submits:當前場次的 使用者-登記數字-時間
· sessions:session-user
3.register.html註冊介面 3.服務
· 當有登入時重定向到使用者主頁
·
當沒有登入時提供使用者名稱框、密碼框,將資訊加密後發給伺服器
· register 根據使用者名稱和密碼進行註冊
· login 根據使用者名稱和密碼登入並生成session,銷燬過期session
4.home.html使用者主頁 4.介面(均返回簡單文字或json物件)
· 當沒有登入時重定向到登入介面
· 當登入時提供使用者分值、最近使用者歷史的展示 提供主頁、退出登入按鈕
· 進行投票
· login?username=***?password=*** 返回登入結果和臨時token
· register?username=***?password=***返回註冊結果
· vote?token=***
返回時間
· usercredit?token=***返回使用者積分
· userhistory?token=***返回使用者歷史記錄
· history?page=*** 從最近開始分頁,返回歷史記錄
2.前端設計圖樣展示

​ 因此,根據上述設計框架,對前端進行重新設計,得到如下符合要求的介面,且看圖樣展示。上次開發使用的模板是Metronic 4.5版本,而這次升級了頁面造型,採用Metronic 7.10來實現。新的模板帶來新的問題,如註冊登入的傳值都採用FormValidation這個外掛進行,所以實現起來比較陌生。

  • index.html主頁

    • 下圖為未登入時的初始介面,未登入時不展現輸入投票數字的選框,但是顯示最近比賽的資訊,點選登入會跳轉至登入註冊頁面進行登入。

    • 下圖是登陸完成後的頁面,主頁其他都未變,除了參與比賽的介面展現投票選框和當前參與該輪黃金點遊戲的玩家人數。

  • login.html登入介面

    • 登入介面與註冊介面合併至同一個html檔案中編寫,點選註冊一個可以跳轉到註冊介面,點選忘記密碼可以跳轉到密碼找回介面。

    • 下圖為註冊介面,選框對空置進行檢測,如果未填完,不允許跳轉。

    • 忘記密碼介面如下,需要輸入註冊時的電子郵箱來獲取重置密碼的驗證碼。

  • home.html使用者主頁

    • 使用者頁面顯示使用者的資訊,歷史積分與歷史參與遊戲的記錄。
3.後端程式碼展示
核心程式碼

GameLogicService.java

package com.foolriver.goldenpoint.service;

import com.foolriver.goldenpoint.model.RoundRecord;
import com.foolriver.goldenpoint.model.SubmitRecord;
import com.foolriver.goldenpoint.model.UserRecord;
import com.foolriver.goldenpoint.repository.RoundRecordRepositoy;
import com.foolriver.goldenpoint.repository.SessionRecordRepository;
import com.foolriver.goldenpoint.repository.SubmitRecordRepository;
import com.foolriver.goldenpoint.repository.UserRecordRepository;
import lombok.Getter;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.LinkedList;
import java.util.List;

@Service
public class GameLogicService {
    @Resource
    SessionRecordRepository sessionRecordRepository;
    @Resource
    RoundRecordRepositoy roundRecordRepositoy;
    @Resource
    SubmitRecordRepository submitRecordRepository;
    @Resource
    UserRecordRepository userRecordRepository;

    @Getter
    static int personCount=0;
    @Getter
    static String currentRoundId=null;

    private void settleRound(){
        RoundRecord roundRecord=roundRecordRepositoy.findByUuid(currentRoundId);
        List<SubmitRecord> submitRecords=submitRecordRepository.findByRoundUuid(currentRoundId);
        roundRecord.setEndTime(new Timestamp(System.currentTimeMillis()));
        roundRecord.setPersonCount(submitRecords.size());
        double goldenPoint=0;
        for(SubmitRecord submitRecord:submitRecords){
            goldenPoint+=submitRecord.getValue();
        }
        goldenPoint/=roundRecord.getPersonCount();
        roundRecord.setGoldenPoint(goldenPoint);
        roundRecordRepositoy.save(roundRecord);

        List<SubmitRecord> submitWinners=new LinkedList<SubmitRecord>();
        List<SubmitRecord> submitLosers=new LinkedList<SubmitRecord>();
        double errorMax=0,errorMin=Double.MAX_VALUE;
        for(SubmitRecord submitRecord:submitRecords){
            if(errorMax>Math.abs(submitRecord.getValue()-goldenPoint)){
                errorMax=Math.abs(submitRecord.getValue()-goldenPoint);
                submitLosers.clear();
                submitLosers.add(submitRecord);
            }else if(errorMax==Math.abs(submitRecord.getValue()-goldenPoint)){
                submitLosers.add(submitRecord);
            }
            if(errorMin<Math.abs(submitRecord.getValue()-goldenPoint)){
                errorMin=Math.abs(submitRecord.getValue()-goldenPoint);
                submitWinners.clear();
                submitWinners.add(submitRecord);
            }else if(errorMin==Math.abs(submitRecord.getValue()-goldenPoint)){
                submitWinners.add(submitRecord);
            }
        }
        for(SubmitRecord submitWinner:submitWinners){
            UserRecord userRecord=userRecordRepository.findByUuid(submitWinner.getUserUuid());
            userRecord.setCredit(userRecord.getCredit()+1.0/ submitWinners.size());
            userRecordRepository.save(userRecord);
        }
        for(SubmitRecord submitLoser:submitLosers){
            UserRecord userRecord=userRecordRepository.findByUuid(submitLoser.getUserUuid());
            userRecord.setCredit(userRecord.getCredit()-1.0/ submitLosers.size());
            userRecordRepository.save(userRecord);
        }
        roundRecord=new RoundRecord();
        roundRecordRepositoy.save(roundRecord);

    }

    public void ifNotInitializedThenInit(){
        RoundRecord roundRecord=roundRecordRepositoy.findByGoldenPointIsNull();
        if(roundRecord==null){
            roundRecord=new RoundRecord();
        }
        roundRecordRepositoy.save(roundRecord);
        currentRoundId=roundRecord.getUuid();
    }

}

UserManageService.java

package com.foolriver.goldenpoint.service;

import com.foolriver.goldenpoint.model.SessionRecord;
import com.foolriver.goldenpoint.model.UserRecord;
import com.foolriver.goldenpoint.repository.SessionRecordRepository;
import com.foolriver.goldenpoint.repository.UserRecordRepository;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class UserManageService {
    @Resource
    UserRecordRepository userRecordRepository;

    @Resource
    SessionRecordRepository sessionRecordRepository;

    public boolean register(String username, String passwordSHA256) {
        UserRecord userRecord = userRecordRepository.findByUsername(username);
        if (userRecord == null) {
            userRecord = new UserRecord();
            userRecord.setUsername(username);
            userRecord.setPasswordSHA256(passwordSHA256);
            userRecordRepository.save(userRecord);
            return true;
        }
        return false;
    }

    public String login(String username, String passwordSHA256) {
        UserRecord userRecord = userRecordRepository.findByUsername(username);
        if (userRecord != null && userRecord.getPasswordSHA256().compareTo(passwordSHA256) == 0) {
            SessionRecord sessionRecord = sessionRecordRepository.findByUserUuid(userRecord.getUuid());

            if (sessionRecord == null) {
                sessionRecord = new SessionRecord();
                sessionRecord.setUserUuid(userRecord.getUuid());
            }
            sessionRecordRepository.save(sessionRecord);
            return sessionRecord.getUuid();
        }
        return null;
    }

    public boolean isUsernameExist(String username) {
        UserRecord userRecord = userRecordRepository.findByUsername(username);
        return userRecord != null ? true : false;
    }

    public void logout(String sessionId){
        SessionRecord sessionRecord=sessionRecordRepository.findByUuid(sessionId);
        if (sessionRecord!=null){
            sessionRecordRepository.delete(sessionRecord);
        }
    }
}

4.缺陷與後續迭代
  1. 當前登入有一些問題,就是上線和下線的資訊沒有在js中儲存,導致使用者資訊在一段時間中未能延續,所以後續需要新增cookie來儲存使用者上線和下線的資訊
  2. 在輸入選框中未對輸入進行限制,所以容易產生bug,在後續需要新增正則表示式對其進行限制
  3. 使用者密碼需要採用sha256雜湊碼進行轉換,前端還未實現該功能