# H01 季後賽
## 本筆記網站
怕格式跑掉
https://hackmd.io/@ruserxd/BkLL8QB0R
## 本次目標
自行製作一個 mlb 季後賽表
首先,透過 json 檔案讀取例行賽的對戰紀錄表 -> 資料
接著,對資料進行處理,
有兩個聯盟 (American, National),每個聯盟有三個區域 (West, Central, East)
需要從每個聯盟挑出 2 個種子, 4 個外卡
每個區域 (Region) 都會有一個分區冠軍,從三個裡面選出兩個當作種子,剩下的一個為外卡
接著再從 3 個區域不是冠軍依照勝率 (高) 取出 3 對當做外卡
同分修改:
此次針對的數據為 2023 mlb 例行賽
因為有同勝場敗場的隊伍
我選擇修改數據 sry
原始兩隊數據為 wins:90, losses:72
```json
{
"team": "Houston Astros",
"wins": 91,
"losses": 71
},
{
"team": "Texas Rangers",
"wins": 89,
"losses": 73
}
```
## Preventive Programming
### 1. SLF4J-Log4j
這部分算是個人習慣,平常使用 Spring Boot 框架,都會有 SLF4J 在裡頭
結果自己要導入的時候好麻煩,有些版本 1.多得,看文章說有出現安全性漏洞
不建議用,以下是後來找到的版本
```xml
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>2.0.16</version>
</dependency>
```
還要設置對應的 log4j.properties 才能有希望呈現的時間顏色...(預設紅色)
這時才理解到 Spring Boot 的好 (當然還有其他的好)
```java
// 獲得該區域的資料
private void getRegionsData(JSONObject jsonLeague, String region, HashMap<String, List<TeamData>> hashLeague) {
..省略
for (Object obj : teams) {
..大量程式碼省略
hashLeague.get(region).add(teamData);
log.info("成功存入" + teamData);
}
}
```
Example:

### 2. assert
為了避免出現資料的隊伍不足,可能今年一堆隊伍退出聯盟,因為內部沒錢
出現不符合一個聯盟 6 隊打季後賽的情況
設計了一段 assert 在 SortingRanking.java 上
`assert sortingLeague.size() == 6: "Need 6 teams for 本季季後賽,組別不夠打...";`
`for (int i = 0; i < 3 && i < regionLoser.size(); i++)`
**(此測試請使用src/main/resources/mlbTeamsJsonRecord/record_2023_forAssert.json)**
```java
// 會先找每個區域的第一名出來, 把它放到對應的 Winner, 其餘放到 loser, 接著在按規則做排序
private ArrayList<TeamData> rankingLeague(HashMap<String, List<TeamData>> hashLeague) {
..大量程式碼省略
// 利用 winRate 進行排序
regionLoser.sort((a, b) -> Double.compare(b.winRate, a.winRate));
for (int i = 0; i < 3 && i < regionLoser.size(); i++)
sortingLeague.add(regionLoser.get(i));
assert sortingLeague.size() == 6: "Need 6 teams for 本季季後賽,組別不夠打...";
return sortingLeague;
}
```
Example:

### 3. try-cathch-finally
當我們在讀取 Json 檔案時,會希望 Json 是一個固定格式的檔案
當沒讀取到希望的聯盟名稱時會 throw 一段 error message
並結束時獲得一個訊息
**(此測試請使用src/main/resources/mlbTeamsJsonRecord/record_2023_forTryCatchFinally.json)**
```java
// 聯盟
private static final String[] leagues = {"American League", "National League"};
// 獲取 Json 的資料
void getDataFromJsonFile(String filePath) {
try {
Object ob = new JSONParser().parse(new FileReader(filePath));
JSONObject js = (JSONObject) ob;
for (String league : leagues) {
// 這個聯盟的 Json 物件
JSONObject leagueJson = (JSONObject) js.get(league);
// 如果沒找到對應的 league
if (leagueJson == null) {
throw new IllegalArgumentException("League not found in JSON: " + league);
}
... 程式碼省略
}
} catch (IOException | ParseException e) {
log.error(e);
} finally {
log.info("抓取 Json 結束");
}
}
```
Example:

### 4. 三層式架構
我將整個架構分為三個步驟 (物件) 操作
- 步驟:
讀取 Json -> 對資料處理 -> 依照資料輸出結果
- 對應類別 Class:
GetDataFromJson -> ShowMLBResult -> SortingRanking
這樣當哪個步驟出錯時,可以比較有效率的找出是哪裡的問題並修正,同時也較好閱讀程式碼
## 其餘部分
### model
對於 mlb 數據的設計
會有對應的隊伍名稱、勝場、敗場、勝率
運用一些 lombok 簡化我們需要寫的程式碼
```java
package org.example.model;
import lombok.Builder;
import lombok.Data;
// lombok 簡化程式碼
@Builder
@Data
public class TeamData {
public String teamName;
public Long win;
public Long lose;
public Float winRate;
}
```
### 使用此專案
打開 Main 類別 -> run code
若想測試 Assert 請記得打上 -ea
**又或是使用已設置的 MainRunner**
路徑可根據想測試的項目做使用
- 1 Assert
(src/main/resources/mlbTeamsJsonRecord/record_2023_forAssert.json)
- 2 try-catch-finally
(src/main/resources/mlbTeamsJsonRecord/record_2023_forTryCatchFinally.json)
- 3 Orignal version
(src/main/resources/mlbTeamsJsonRecord/record_2023.json)
人性化設置 -> 透過輸入選擇即可
```java
public static void main(String[] args) {
// 初始化可使用路徑
initial();
Scanner scanner = new Scanner(System.in);
ShowMLBResult showMLBResult = new ShowMLBResult();
System.out.println("\n請問要執行哪個測試檔案");
System.out.println("1. Assert");
System.out.println("2. Try-Catch");
System.out.println("3. Original Version");
System.out.print("請輸入選項 (1-3): ");
String input = scanner.nextLine();
switch (input) {
case "1", "2", "3" -> {
int index = Integer.parseInt(input) - 1;
System.out.println("\n執行: " + paths.get(index));
showMLBResult.ShowMLBResult(paths.get(index));
}
default -> System.out.println("無效的輸入");
}
}
```