---
# System prepended metadata

title: JS直播班-BMI kata練習_書豪經驗分享

---

# JS直播班-BMI kata練習_書豪經驗分享
https://hackmd.io/ybNNKhe_TBWJHUicjlhsRA?edit
## 1. 用了哪些軟體錄製跟記錄倒數

※ 我的電腦是WIN10環境，以下軟體皆是以WIN10的環境進行。

### 。錄影軟體：[ActivePresenter](https://atomisystems.com/download/) 8.3.2版
　　　　　　這是老師的google表單中推薦的軟體，[使用教學](https://hackmd.io/@Albertnotes/HJEOF92dI)在此。
　　　　　　我在錄製時是選擇沒有錄聲音，所以不會把一邊聽的音樂錄進去。
　　　　　　為了公正無爭議，所以我錄全螢幕，右下角可以看到WINDOWS的時間
　　　![](https://i.imgur.com/L5sNQeu.png)

跟教學文中比較不一樣的地方是「導出」的地方沒有Youtube這個選項，
所以我是導出成「視頻」(就是影片啦)，再另外上傳到Youtube去的。
![](https://i.imgur.com/mJGZQJB.png)

***

### 。記錄倒數：鬧鐘與時鐘（WIN10內建的）
　　　　　　點左下角的WINDOWS圖案，然後直接打字「鬧鐘」就會出現囉！
![](https://i.imgur.com/20husrH.png)

一開始練習時，我訂了3個計時器：5分鐘 & 10分鐘 & 1小時
5分鐘、10分鐘：想知道5分鐘、10分鐘時我大約可以寫到哪裡
1小時：先瞭解自己第一次大概要花多久時間，所以訂長一點

然後隨著速度變快，就只留下目標的計時器

![](https://i.imgur.com/rMkCuM8.png)

***

### 。寫Code軟體：[VSCode（Visual Studio Code）](https://code.visualstudio.com/)

插件：Live Server
這個插件，可以在存檔時，就自動重新整理網頁內容，所以console.log也會自動重整成最新的，可以省下跳到網頁視窗重整的時間。
![](https://i.imgur.com/0bj1HfK.png)

使用時，按右下角的「Go Live」就會開啟網頁，每當存檔時，就能直接在那個網頁上即時重整囉！
![](https://i.imgur.com/QAgiUL1.png)

另外提醒一下，如果想要讓人知道自己按了什麼按鍵，就要開啟「Toggle Screencast Mode」模式
像這樣：
![](https://i.imgur.com/RAaf9lq.png)

以下講解開啟此模式的步驟：
左上角功能列：檢視 → 命令選擇區 （會在中間出現命令選擇區介面）
![](https://i.imgur.com/JipwtZc.png)

在命令選擇區裡，輸入「Toggle Screencast Mode」
![](https://i.imgur.com/vHDDbak.png)

點擊搜尋出來的「Toggle Screencast Mode」模式，就開啟完成
![](https://i.imgur.com/nm45ZWy.png)

***

## 2. 如何做前置作業，以及安排視窗切割

### 。視窗安排：如下圖
　　- 左邊用來寫Code
　　- 為了能即時看到Console.log的結果，所以我把網頁開在右邊
　　- 另一個網頁準備好Google翻譯，需要時可以查
　　- 又另一個視窗，那是計時器
![](https://i.imgur.com/2pwckfc.png)

***

### 。前置作業 & 練習過程：
(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

