# JS直播班-BMI kata練習_書豪經驗分享
## 1. 用了哪些軟體錄製跟記錄倒數
※ 我的電腦是WIN10環境,以下軟體皆是以WIN10的環境進行。
### 。錄影軟體:[ActivePresenter](https://atomisystems.com/download/) 8.3.2版
這是老師的google表單中推薦的軟體,[使用教學](https://hackmd.io/@Albertnotes/HJEOF92dI)在此。
我在錄製時是選擇沒有錄聲音,所以不會把一邊聽的音樂錄進去。
為了公正無爭議,所以我錄全螢幕,右下角可以看到WINDOWS的時間

跟教學文中比較不一樣的地方是「導出」的地方沒有Youtube這個選項,
所以我是導出成「視頻」(就是影片啦),再另外上傳到Youtube去的。

***
### 。記錄倒數:鬧鐘與時鐘(WIN10內建的)
點左下角的WINDOWS圖案,然後直接打字「鬧鐘」就會出現囉!

一開始練習時,我訂了3個計時器:5分鐘 & 10分鐘 & 1小時
5分鐘、10分鐘:想知道5分鐘、10分鐘時我大約可以寫到哪裡
1小時:先瞭解自己第一次大概要花多久時間,所以訂長一點
然後隨著速度變快,就只留下目標的計時器

***
### 。寫Code軟體:[VSCode(Visual Studio Code)](https://code.visualstudio.com/)
插件:Live Server
這個插件,可以在存檔時,就自動重新整理網頁內容,所以console.log也會自動重整成最新的,可以省下跳到網頁視窗重整的時間。

使用時,按右下角的「Go Live」就會開啟網頁,每當存檔時,就能直接在那個網頁上即時重整囉!

另外提醒一下,如果想要讓人知道自己按了什麼按鍵,就要開啟「Toggle Screencast Mode」模式
像這樣:

以下講解開啟此模式的步驟:
左上角功能列:檢視 → 命令選擇區 (會在中間出現命令選擇區介面)

在命令選擇區裡,輸入「Toggle Screencast Mode」

點擊搜尋出來的「Toggle Screencast Mode」模式,就開啟完成

***
## 2. 如何做前置作業,以及安排視窗切割
### 。視窗安排:如下圖
- 左邊用來寫Code
- 為了能即時看到Console.log的結果,所以我把網頁開在右邊
- 另一個網頁準備好Google翻譯,需要時可以查
- 又另一個視窗,那是計時器

***
### 。前置作業 & 練習過程:
(1) 先看清楚題目要求、此程式的目標要做什麼
(2) 查清楚BMI規則、初步整理需要的規則
(3) 把Code寫出來,看是否達成題目要求
(4) 開始優化Code,把Code改成自己覺得好的樣子
(5) 按照寫好的Code,整理自己的邏輯思緒,記得大致上要寫哪些東西
(6) 開始重寫,提升流暢度,優化哪邊該先寫等流程
(7) 評估哪些地方讓我用滑鼠來回滾動查找的,把資訊整理在一起方便看
(8) 繼續重寫,提升流暢度,優化流程
(9) 達到自己當前的極限
(10) 評估要怎樣改Code才有辦法達成時間目標(10分鐘、5分鐘),或沒有辦法達成(?)
(11) 參考別人寫的Code有什麼優點可以借鏡、自己花很多時間的操作有沒有快速鍵可幫忙?
(12) 為了極速特化而精簡Code
(13) 繼續重寫,提升流暢度,優化流程
(14) 知道自己有沒有辦法達成:可行 → 再更快;不可行 → 先這樣就好
***
## 3. 編輯器熱鍵分享
我...我好像沒怎麼用熱鍵(遮臉)
存檔:Ctrl + s
複製:Ctrl + c
貼上:Ctrl + v
還原:Ctrl + z
跳到那行最後面:End
跳到那行最前面:Home
選取一段文字:滑鼠連點兩下
有一些打過的指令,會在打的過程中出現,可以按Tab省打幾個字
***
## 4. BMI kata 的程式碼分享
### 。程式碼:亦可在[codepen](https://codepen.io/zshao1031/pen/qBqMXWz)上看
```scss=
// 【預先整理的資料】
// BMI值計算公式: BMI = 體重(公斤) / 身高(公尺)平方
// overThin 過輕 BMI < 18.5 您的體重過輕,健康指數為藍色
// normal 正常 18.5 <= BMI < 24 您的體重正常,健康指數為紅色
// overWeight 過重 24 <= BMI < 27 您的體重過重,健康指數為澄色
// mildFat 輕度肥胖 27 <= BMI < 30 您的體重輕度肥胖,健康指數為黃色
// moderateFat 中度肥胖 30 <= BMI < 35 您的體重中度肥胖,健康指數為黑色
// severeFat 重度肥胖 35 <= BMI 您的體重重度肥胖,健康指數為綠色
// 【第二階段題目附的程式碼】
const bmiStatesData = {
"overThin": {
"state": "過輕",
"color": "藍色"
},
"normal": {
"state": "正常",
"color": "紅色"
},
"overWeight": {
"state": "過重",
"color": "澄色"
},
"mildFat": {
"state": "輕度肥胖",
"color": "黃色"
},
"moderateFat": {
"state": "中度肥胖",
"color": "黑色"
},
"severeFat": {
"state": "重度肥胖",
"color": "綠色"
}
}
// 【以下是自己寫的程式碼】
let bmiHistoryData = []; // 第三階段用
function printBmi(cm,kg){
let bmi = (kg/((cm/100)**2)).toFixed(2); // 算出BMI
let state;
// 若輸入的是文字,或是讓bmi變成0或負數,就是資料有誤
if(bmi == "NaN" || bmi <= 0){
console.log("您的數值輸入錯誤,請重新輸入");
return; // 輸入資料有誤,就不需要進行後面的行動了,所以直接return跳出
} else if( bmi < 18.5) state = "overThin"; // 過輕
else if( bmi < 24) state = "normal"; // 正常
else if( bmi < 27) state = "overWeight"; // 過重
else if( bmi < 30) state = "mildFat"; // 輕度肥胖
else if( bmi < 35) state = "moderateFat"; // 中度肥胖
else state = "severeFat"; // 重度肥胖
// 印出第一階段、第二階段結果用
console.log(`您的體重${bmiStatesData[state].state},健康指數為${bmiStatesData[state].color}`);
// 以物件的形式,將此次的bmi、state結果存入bmiHistoryData陣列裡
bmiHistoryData.push({bmi,state});
}
// 第三階段,印出最終結果
function showHistoryData(){
console.log(`您總共計算 ${bmiHistoryData.length} 次 BMI 紀錄,最後一次 BMI 指數為 ${bmiHistoryData[bmiHistoryData.length-1].bmi},體重${bmiStatesData[bmiHistoryData[bmiHistoryData.length-1].state].state}!健康指數為${bmiStatesData[bmiHistoryData[bmiHistoryData.length-1].state].color}!`);
}
printBmi(178, 20);
printBmi(178, 70);
printBmi(178, 85);
// printBmi(178, 90);
// printBmi(178, 110);
// printBmi(178, 130);
printBmi("身高","體重");
showHistoryData();
```
***
### 題目:按照第一階段、第二階段、第三階段的順序寫出符合題目要求的程式碼
### 【第一階段】
```scss=
【第一階段】請寫 printBmi 函式,並印出對應狀態
printBmi(178, 20) >> 印出 console.log 文字為「您的體重過輕」
printBmi(178, 70) >> 印出 console.log 文字為「您的體重正常」
printBmi(178, 85)>> 印出 console.log 文字為「您的體重過重」
printBmi(178, 90)>> 印出 console.log 文字為「您的體重輕度肥胖」
printBmi(178, 110)>> 印出 console.log 文字為「您的體重中度肥胖」
printBmi(178, 130)>> 印出 console.log 文字為「您的體重重度肥胖」
printBmi("身高","體重")>> 印出 console.log 文字為「您的數值輸入錯誤,請重新輸入」
```
。我的解題流程:
1. 題目要求要印出查BMI的結果,所以先查BMI的規則
公式是要輸入身高、體重來計算出一個數值,再用此數值落在哪個區間判斷此人體態狀況
2. 題目給的 printBmi(178, 70); 看起來是輸入身高178公分、體重70公斤
而 printBmi 這個函式,必須要能印出題目指定的體態結果
(※ 提醒:公式中的身高是用「公尺」來計算,資料要是用公分必須要先換算)
3. 用題目給的數值試算BMI,確定體態的評估結果與題目要求的結果一致,確定理解題目無誤
4. 寫出BMI的計算公式,確認算出的數字正確
5. 寫出BMI各區間的if else判斷式,確認體態評估的結果正確
6. 思考輸入怎樣的內容會無法計算(輸入非數字)、或被判定為錯誤資料(BMI為0或負數 )
7. 將錯誤資料的判斷式加入原本的判斷式中(修改Code)
8. 確認結果與題目要求的相符
※ 我所用的程式碼,基本上都是老師教過的,但格式簡化的部分~有些是老師沒提過的
(A) if(判斷式)後面如果只有一條指令,就可以省略 {} 而直接接在後面寫。
```scss=
像是這樣:if( bmi < 24) state = "normal";
跟這樣是相同的:if( bmi < 24){ state = "normal"; }
也跟這樣是相同的:
if( bmi < 24){
state = "normal";
}
```
(B) bmi狀態的if判斷式,若輸入的是非數字,數學公式會無法計算,所以結果會是NaN
而這個NaN是字串,所以判斷式中要用""括起來
```scss=
if(bmi == "NaN" || bmi <= 0)
```
(C ) 上課沒直接教到的還有算「n次方」的寫法,還有取小數點以下x位的寫法
```scss=
例如,要計算 a 的 b次方,寫成:
a ** b;
這邊要算的是平方,所以寫成 ** 2
BMI公式 = 體重(公斤) / 身高(公尺)的平方
bmi = kg / ((cm / 100) ** 2)
而除法算出來常常小數點會有非常多位,這邊只要顯示到小數點以下第二位就好了
所以加上 .toFixed(2)
bmi = (kg / ((cm / 100) ** 2)).toFixed(2);
```
***
### 【第二階段】
```scss=
【第二階段】請程式碼裡加入此(bmiStatesData)變數,並嘗試運用此變數裡的資訊。
printBmi(178, 20) >> 印出 console.log 文字為「您的體重過輕,健康指數為藍色」
printBmi(178, 70) >> 印出 console.log 文字為「您的體重正常,健康指數為紅色」
printBmi(178, 85)>> 印出 console.log 文字為「您的體重過重,健康指數為澄色」
printBmi(178, 90)>> 印出 console.log 文字為「您的體重輕度肥胖,健康指數為黃色」
printBmi(178, 110)>> 印出 console.log 文字為「您的體重中度肥胖,健康指數為黑色」
printBmi(178, 130)>> 印出 console.log 文字為「您的體重重度肥胖,健康指數為綠色」
printBmi("身高","體重")>> 印出 console.log 文字為「您的數值輸入錯誤,請重新輸入」
```
。我的解題流程:
1. 跟第一階段比起來,要求印出的內容只多了要印出顏色的後半句
2. 題目要求必須使用bmiStatesData裡的資料,這些資料包含了結果文字中要的體態跟顏色
3. 在第一階段的判斷式中,修改Code為記錄bmiStatesData裡分類用的英文(屬性)
4. 將印出結果的文字改為第二階段要求的那些文字
5. 憑第3點中記錄的英文(屬性),將文字中的體態與顏色,換成吃bmiStatesData的資料
※ 使用的語法,沒有超出上課所教內容
***
### 【第三階段】
```scss=
【第三階段】儲存每筆計算資料,多一個變數為 bmiHistoryData,並賦予空陣列來儲存計算物件資料,若數值輸入錯誤,則不儲存。
printBmi(178, 20) >> 印出 console.log 文字為「您的體重過輕,健康指數為藍色」
printBmi(178, 70) >> 印出 console.log 文字為「您的體重正常,健康指數為紅色」
printBmi(178, 85)>> 印出 console.log 文字為「您的體重過重,健康指數為澄色」
showHistoryData() >> 印出 console.log 文字為「您總共計算 3 次 BMI 紀錄,最後一次 BMI 指數為 26.83,體重過重!健康指數為澄色!」
```
。我的解題流程:
1. 要求要將BMI查詢結果記錄在陣列中、且輸入錯誤的資料不儲存
2. 要求要有一個showHistoryData()函式來印出一段不同的文字
3. 要求包括「計算了幾次(有幾筆資料)」、最後一筆資料的「BMI數值」、「體態」、「顏色」
4. 在printBmi函式裡,增加將資料記入(push)陣列的程式碼
5. 在showHistoryData函式哩,去讀陣列的資料,來印出題目要求的結果
※ 經老師提點,記資料到陣列時,應該只要記錄關鍵的內容
※ 我原本寫的還會記錄一些重複的描述文字,這樣要是想要用別的文字內容來顯示 BMI 結果,這樣的記錄就會因為寫太死而做不到,而且還會浪費記憶體,確實應該精簡
※ 後來再看一次老師錄的影片,裡面是用物件去記關鍵內容,我已改為用物件去記錄
但這邊是用簡寫的方法寫的,比較如下:
```scss=
原本的寫法:
bmiHistoryData.push(`BMI 指數為 ${bmi},體重${bmiStatesData[state].state}!健康指數為${bmiStatesData[state].color}!`);
新的寫法:用物件去記關鍵內容
bmiHistoryData.push({bmi,state});
該物件完整寫法是這樣:
{
bmi: bmi,
state: state
}
若左邊的名稱跟右邊的變數名稱相同的話,可以簡寫成這樣:
{
bmi,
state
}
而若再把這個物件縮在一行內寫,就變成 {bmi, state} 了
把這個物件push到陣列裡,就變成 bmiHistoryData.push({bmi,state}); 了
```
***
## 5. 如何安排時間與頻率來進行訓練
其實我沒特別安排...這週末剛好沒啥事,而且外面又下大雨,是個適合專心練習的日子
在上課老師講解主線任務時~我就躍躍欲試了,所以一下課我就立刻開始寫第一遍,因為我打字速度還算可以,印象中花了18分鐘左右完成第一次。
然後覺得不滿意的地方有點多,就又想立刻動手改起來
結果,調整了一下就能接近10分鐘了,就開始準備起錄影
就順著一股想一直做下去的心情一直又改又寫又錄的,達到了7分多的速度
那時評估這樣下去,就算手順再更順,頂多也只能6分多近7分,於是就決定休息了
隔天,看到有人回報他的影片,於是參考了一下後有了靈感
又開始改code,發現這樣的寫法很可以!
然後開始拚5分內,練習到達標!
過程大概就是這樣...憑心情XD