# GhostRacer
## 第五組
:::spoiler 期中報告
----
# 類似商品
- [隨機文字練習(Keybr)](https://www.keybr.com/)
- 不能與他人較量
- [英文文章練習(Typeracer)](https://play.typeracer.com/)
- 需自行修改錯誤的輸入
- 延遲相當嚴重
- 比賽的對手會有奇怪的行為
- 共同問題
- 不能手機輸入
- 對於打贏比賽不會有太多成就感,無法吸引使用者留下
----
# 5 Whys?
- 整合各網站打字優點和統計資料優點
- 著重訓練使用者打字穩定度
- 無現存語音練習網站
- 無現存網站可供跨裝置練習
- 可與過去的自己較量,確認自己的進步
- 增加英文語音聽打
----
# 整合優點
- 具備多種文本材料,增加訓練多樣性
- 可供多種裝置使用
- 對於打錯字有可選擇不同處理方法
- 整合統計資料
---
# 支援輸入內容
- 英文
- 英文語音
----
# 模式
- 自我練習
- 對手對戰
- 天梯賽
----
# 自我練習
- 可自由選擇文本模式
- 可自由選擇錯字處理模式
- 可自由選擇文本內容
----
# 對手對戰
- 盡可能找到「正確率類似」且「速度類似」的對手
- 有「過去的回放」參與對戰,可供進步參考
- 前幾名可獲得點數獎勵
----
# 天梯賽
- 隨機文本隨機錯字處理模式
- 一開始比賽時下定固定點數,最終成績已當時比賽狀態乘點數倍率做計分
----
# 點數使用
- 分析自己的打字狀態
- 進行天梯賽
----
# 文本來源
- [English dictionary](https://sourceforge.net/projects/mysqlenglishdictionary/)
- The holy bible
----
# 語音輸入
- [Speech to text API (By google)](https://cloud.google.com/speech-to-text/?hl=zh-tw&utm_source=google&utm_medium=cpc&utm_campaign=japac-TW-all-en-dr-bkws-all-all-trial-e-dr-1009882&utm_content=text-ad-none-none-DEV_c-CRE_502851390683-ADGP_Hybrid+%7C+BKWS+-+EXA+%7C+Txt+~+AI+%26+ML+~+Speech-to-Text_Speech+-+Text-KWID_43700030642373166-kwd-29212806777&userloc_1012810-network_g&utm_term=KW_google%20speech%20to%20text%20api&gclid=Cj0KCQjwsLWDBhCmARIsAPSL3_3gfhd-nvwZixDU9LCASnaFJHrSmx7H0qkNt8on3Hztk-L1eo1wzAsaAj96EALw_wcB&gclsrc=aw.ds)
----
# Thank you
## Do not go to next page
----
# Listen Racer
- 文字會被念出來!
- 然後你要打成字!
:::
## spec
一開始進入網頁到自由練習模式,並且給予使用者登入的按鈕,如果按登入則會跳到登入介面
登入完後有三個選項可以選
不管哪個模式除了顯示文本給使用者外還要做比賽的動畫。
此外關於使用者輸入文字的狀態也要顯示給使用者看
- 自由模式
- 模式設定
- 給玩家選擇錯誤檢測
- 給玩家選擇打字方式
- 隨機產生文本
- 聽打練習
- 玩家自行輸入/上傳文本
- 選擇打錯偵測模式
- 需自行按delete
- 打錯會卡住
- 模式設定完後按開始,即可開始練習,練習完的資料要做存檔
- 對戰模式
- 模式設定
- 模式設定
- 隨機產生文本
- 選擇打錯偵測模式
- 需自行按delete
- 打錯會卡住
- 模式設定完後開始則會生成model補足人數,如果沒有其他真人參與有機會遇到故事模式model
- 結束後操作
- 如果前三名發放獎金
- 如果超越曾經的自己很多發放故事動畫
- 超過故事模式model發放動畫
- 天梯模式
- 選擇下注金額
- 顯示該次天梯模式和打錯偵測模式(隨機產生)
- 利用codeforce之類的規則計算玩家這次天梯上升或下降的分數
- 然後乘倍率顯示給玩家(這裡可以做個動畫或隨便)
- 故事線描述
- 一開始預設3-5個主線npc和3-5支線npc
- 主線npc依序在玩家挑戰完前一個後才會出現,支線則隨機出現
- 給予每個npc一個小故事,然後輸他和贏他各一個小故事或是輸他可以沒有故事
---
## API
建議加上 `Access-Control-Allow-Origin`
### 範例
API名字/.../... 描述 類別
request: 變數名稱:描述:變數型態,...
response: 變數名稱:描述:變數型態,...
(以json傳送)
### public
<!-- createAccount 創立帳號 POST
req: account:帳號:string,passwd:密碼:string
res: success:是否成功:bool,throw:錯誤原因:string
validAccount 驗證帳號 POST
req: account:帳號:string,passwd:密碼:string
res: success:是否成功:bool,throw:錯誤原因:string -->
### private
#### 使用須知
header要附帶一個變數token:為使用者帳號,沒附帶就回傳401,驗證錯誤就回傳403
#### getProfile/ID 取得某人資料 GET
```json
res: {
ID:自己ID:string,
speed:打字速度:int,
money:金錢:int,
nickname:帳號名稱:string ,
img:投貼:int(待新增)
acc:準確率:int
}
```
- Expected response
```json
{
"ID":"root",
"speed":1,
"money":0,
"nickname":"root",
"img":4,
"acc":0,
"todayRaces": 12,
"lastThree": [0, 0, 1]
}
```
The example below shows that the user had played 12 games this day. Also, the [1st, 2nd, 3rd] last game were [lose, lose, win] respectively. `0` means lose and `1` means win, if it is'n exists then it will be `-1`.
#### updateHistory 上傳過去資料 POST
```json
req: {
acc:準確率:int,
speed:速度:int,
hash:文本hash:string,
win:是否為贏家:bool,
Opponent1:對手1:str,
Opponent2:對手2:str,
Opponent3:對手3:str
}
res: {
success:是否成功:bool,
throw:錯誤原因:string
}
```
(如果success是true然後throw非空,代表進行故事模式)
(acc傳%)
#### randomAticle 隨機取得文章 GET
```json
res: {
text:文章文本:string,
hash:文本hash:string
}
```
#### randomOpponent 取得競賽對手 POST
```json
req: {
ID:自己的ID:string,
Ladder:是否天梯:int,
hash:比賽文本hash:string
}
res: {
Opponent1:對手1:str,
Opponent2:對手2:str,
Opponent0:對手0:str,
Speed1:對手1速度:int,
Speed2:對手2速度:int,
Speed0:對手0速度:int,
}
```
Ladder!=0,Opponent只會有一個
#### addFriend 新增好友 POST
```json
req: {
ID:好友ID:string
}
res: {
success:是否成功:bool,
throw:錯誤原因:string
}
```
(錯誤可能原因:"Your friend doesn't exist")
#### getFriendList 取得好友列表 GET
```json
res: {
friend0:好友0:string,
friend1:好友1:string,
friend2:好友2:string,
...,
len:好友數量:int
}
```
#### getLadder 取得天梯選手資訊 GET
```json
res: {
data:天梯選手:list,
len:天梯選手數量:int
}
```
#### updateLadder 上傳天梯資料 POST
```json
req: {
speed:玩家速度:int,
hash:文本hash:string,
money:下注:int
win:是否為贏家:bool
}
res: {
success:是否成功:bool,
throw:錯誤原因:string,
result:上升或下降名次:int
}
```
(result:2147483647代表原本並未排名)
#### rankLadder 取得玩家天梯排名 GET
```json
req: {
result:排名:int
}
```
(result:-1代表原本並未排名)
#### changeMoney 更改玩家金錢 POST
```json
req: {
delta:更改數量正數代表增加負數代表減少:int
}
res: {
success:是否成功:bool,
throw:錯誤原因:string
}
```
(錯誤可能原因:"This User have enough money","Can't find user")
文本雜湊使用[sha256](https://www.npmjs.com/package/js-sha256)
<u><b><center>SEND TWO REQUESTS RESPECTIVELY ON BOTH WINNER AND LOSER</center></b></u>
---
代辦事項
- [ ] 開統一repo
> grorge deadline:5/28
- [ ] 確認後端API
deadline:5/28
- [ ] 確認前端UI架構
deadline:5/28
> Leon deadline: 5/30
- [ ] 製作基礎模板UI
deadline:5/31
> Leon deadline: 5/30
- [ ] 後端製作
deadline:5/31
---
建議使用 react/p5/phaser 做出樣板,需做出
- 動畫
- 與使用者的簡易互動
- 如果 Mouse hover 就放大
- 如果 Mouse hover 就變色
- 與草稿盡可能相似的樣子。
- 不需要 RWD。
- 顏色以草稿配色為主,最後再進行配色。
- 一個人負責兩到三個頁面,做 Typing Screen 的只需要把 Typing screen 做好。
## Packages
### Common
|package|version|
|-|-|
|webpack|4.43|
|webpack-cli|3.3.11|
|webpack-dev-server|3.11|
|babel|8.1|
|uuid|8.3|
|moment|2.29.1|
### Frontend
| package | version |
| -------- | -------- |
| boostrap| 5.0.2|
| p5 | 1.3.1|
| phaser | 3.15.1|
| redux | 4.1|
| react 全家桶 * | 17.0.2|
| axios | 0.21.1|
|
### Backend
| package | version |
| -------- | -------- |
|express|4.17|
|pg-promise|10.10.2|
## Pages
頁面有以下六個,其中一個是特別難的頁面。
- [ ] Intro page

> Leon Ng
- [ ] Login / Profile (if already logged in) page
> Leon Ng
- [ ] Global rank

> Lawrence Wu
- [ ] Friends page

> Lawrence Wu
- [ ] Ranked match

> Lawrence Wu
- [ ] Match result

> Lawrence Wu
- [ ] Typing screen (Very hard)

> Alice Chen
## Redux
### user-actions
**editor: Leon**
actions:
- @USER/START_LOADING
- @USER/END_LOADING
- @USER/LOGIN
- @USER/LOGOUT
- @USER/GET_DATA
- @USER/LIST_FRIENDS
|state item name|data type|description|
|-|-|-|
|ID|string|the id of current user (needed by Lawrence)|
|loggedIn|bool|logged in or not|
|username|string|user nickname|
|loading|bool|show loading screen or not|
|friends|list|list of friends|
|maxSpeed|int|
|avgSpeed|int|
|avgAccuracy|int|accuracy|
|avatar|int|User.img (needed by Lawrence)|
|friendsListMore|bool|list more or not|
### money-actions
- @MONEY/GET_MONEY
- @MONEY/CHANGE_MONEY
- @MONEY/DONE_CHANGE_MONEY
### play-actions
- @PLAY/ADD_STAKE
- @PLAY/LESS_STAKE
- @PLAY/SET_RESULT
- @PLAY/SET_OPPONENT
- @INPUT/START_GET_PARAGRAPH
- @PLAYER_STAT/SET_WPM
- @PLAYER_STAT/SET_ACCURACY
- @PLAYER_STAT/SET_TOTAL_TIME
- @GAME_STATE/GAME_HOLD
- @GAME_STATE/GAME_START
- @GAME_STATE/GAME_END
|state item name|data type|description|
|-|-|-|
|\*mode|string|either `multiple` or `single`|
|\*opponentID|string|對手的 id|
|\*stakeSize|int|下注多少錢|
|time\*|int|game duration (in seconds)|
|speed\*|int|speed in wpm|
|accuracy\*|int|accuracy in percentage|
|opponentTime|int|opponent game duration (in seconds)|
|\*opponentSpeed|int|opponent speed in wpm|
|opponentAccuracy|int|opponent accuracy in percentage|
|gameResult\*|bool|true if win, false if lose|
|gainedCoin|int|`= stakeSize if win else stakeSize / 2`|
|gainedRank|int|gained rank received from server|
|\*initialWords|string|get random article from server|
|wpm|int|player current speed during game|
|accuracy|int|player current accuracy during game|
|totalTime|int|player total time spent finishing article (in seconds)|
|gameState|int|0: hold, 1:start, 2:end|
## 06/04
### 報告事項
- 掃過一眼 API
- How to login
- 需要密碼嗎?
- 使用資料庫而不是單純的 File I/O
### App.jsx
- Page life cycle
- `show()`
- `/* Do whatever */`
- `handleGoToNextPage()`
- handleToPreviousPage
- handleToPage
- Parameters
- Name of next page
- ...Some other parameters
- showIntro
- Parameters
- showLoginOrProfile
- Parameters
- showGlobalRank
- Parameters
- showFriends
- Parameters
- showRankedMatch
- Parameters
- showMatchResult
- Parameters
- showTypingScreen
- Parameters
### 上一步的按鈕
- 負責人
- Leon Ng
### 需要跟後端要的資料
- 先把 [API](#API) 讀完
- 如果還有什麼資料後端給不齊的話,可以在這邊留言,建議盡早先講,這樣大家比較好處理 ><
## 06/11
### 代辦事項
1. API 說明
2. 各自DEMO報告
3. code review
4. 前端merge問題
5. 下周目標訂定
6. 目前遇到問題
7. 期末報告
8. 臨時動議
### Page redirecting
- 各個頁面的路徑
- `/` (intro page)
- `/loginOrProfile`
- `/globalRank`
- `/friendsPage`
- `/rankedMatch`
- `/matchResult`
- `/typingScreen`
- `?mode=multiple` 多人遊戲
- `?mode=single` 單人遊戲
### Merging
- 丟 Pull request 到 [Frontend Integrated](https://github.com/grorge123/GhostRacer/tree/Frontend-Integrated)
- 在下個禮拜開會前丟 Pull request
### Connect to backend
- 使用 [Axios](https://github.com/axios/axios) 對 backend 發 ajax
- Backend Server
- @grorge
### Auth
- 從 Auth 拿 login credentials
### After game data
- 我花了多久打完整篇文章
- 我的 word per minute 是多少
- 我的 Accuracy 是多少
- 對手花了多久打完整篇文章 (unit: minutes)
- 我的 word per minute 是多少
- 我的 Accuracy 是多少
- 用 Redux state 來傳遞訊息
## 06/18
### To Alice
- 在你的 page 把遊戲結果送給 Server 可以避免一直重複呼叫 API,不知道你會不會想要在你的 Page 送資料。
- 如果你需要的話,我可以幫把 API 包裝成 function
### To Grorge
- 決議是否「留下今日賽場數」
- `SELECT COUNT(*) FROM games as G, users AS U WHERE FLOOR(CURRENT_TIMESTAMP / 86400) * 86400 < G.timestamp AND G.user = U.id`
- `G.timestamp` 是這場遊戲什麼時候被紀錄到伺服器的(Unix timestamp)
- 然後那一串 SQL 就能直接得知今天賽場數了
- 砍!
- getUserProfile
- 得知前三場的勝負結果
### 賭金計算....?
- 下了 `stakeSize` 的賭金後
- 贏家 `+= stakeSize`
- 輸家 `-= FLOOR(stakeSize) / 2`
### 決議 User avatar 的圖片
- 有一個 Component 叫做 Avatar
- `<Avatar id={3} width={"2.0rem"}></Avatar>` 即可
- 圖片列表
- [Capoo](https://upload.wikimedia.org/wikipedia/en/8/88/Bugcat_Capoo.jpg)
- [Nyan Nyan Cat](https://64.media.tumblr.com/8210fd413c5ce209678ef82d65731443/tumblr_mjphnqLpNy1s5jjtzo1_400.gifv)
- [吳尚鴻](https://lh3.googleusercontent.com/proxy/4H1cCDxr1R-nTjrUO5JvAvwl9gYYizI2ivFOZ1-L5oKJWBDL0UixHASb5Ad2jZz9rCPHuG9C69KUexm5UVq9RQljHtDtP7-5S9kOppuQHagtzeHL1FGi)
- [Shiba inu](https://e7.pngegg.com/pngimages/998/380/png-clipart-shiba-inu-dogecoin-gif-internet-meme-egypt-dog-dog-like-mammal-dog-breed.png)
- [派對鸚鵡](https://memes.tw/user-gif-thumbnail/2b2f442a7b58d7a1b686fc8fdee3dfd6.gif)
- [Bubble Girl](https://www.pngjoy.com/pngm/561/8437107_happy-meme-girl-running-meme-transparent-png.png)
- [喵](https://i.imgur.com/HkjcSkj.png)
### 建議修正
#### 後端
1. 擋掉少參數的request
2. 將access權限重新整理
3. 修改api路徑
4. 將必要資料存快取
5. 建立資料庫index
#### 前端
1. UI風格統一
2. 增加動態動畫
3. 全版背景並且不要留白
4. 將圖片或常見按鈕裝飾
# Final Fix
- Get rid of `'` and `-` and `「」` on our text material