---
# System prepended metadata

title: 通貨膨脹-台鐵便當

---

# 通貨膨脹-台鐵便當
### 選擇原因:
* 便捷性：
適合上班族、學生和經常外出的人士，隨時隨地享用家常美食。
保溫功能強大，適合各種場合使用，如戶外活動、辦公室午餐等。
* 文化與情感價值：
台鐵便當盒在許多文化中象徵著家人的關愛和溫暖，特別是家長為孩子準備的便當中，承載著情感價值。
### SQLlit
![螢幕擷取畫面 2024-05-22 011600](https://hackmd.io/_uploads/H1PTVucmC.png)
## Code+解釋
### 前端
1. 頭部 (Head)：

* 設置字符編碼為UTF-8。
* 設置視口以支持響應式設計。
* 設置頁面標題。
* 引入CSS樣式和Chart.js庫。

2. 表單 (Form)：
* 包含日期選擇器（開始日期和結束日期）和便當種類選擇下拉菜單。
* 提交按鈕。

3. 畫布 (Canvas)：
* 用於顯示折線圖的畫布元素。

:::spoiler **HTML**
````javascript=
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>台鐵便當價格趨勢</title>
  <link rel="stylesheet" href="styles.css">
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<form id="data-form">
  <label for="startDate">開始日期:</label>
  <input type="date" id="startDate" name="startDate">
  <label for="endDate">結束日期:</label>
  <input type="date" id="endDate" name="endDate">
  <label for="bento">便當種類:</label>
  <select id="bento" name="bento">
    <option value="臺鐵排骨便當(經濟)">臺鐵排骨便當(經濟)</option>
    <option value="古早味爌肉便當">古早味爌肉便當</option>
    <option value="照燒雞丁便當">照燒雞丁便當</option>
    <option value="臺鐵素食便當(白飯)">臺鐵素食便當(白飯)</option>
    <option value="臺鐵素食便當(燉飯)">臺鐵素食便當(燉飯)</option>
    <option value="臺鐵排骨便當(八角)">臺鐵排骨便當(八角)</option>
    <option value="五行素便當">五行素便當</option>
    <option value="迷迭香雞腿排便當">迷迭香雞腿排便當</option>
    <option value="臺鐵雞腿便當(圓紙)">臺鐵雞腿便當(圓紙)</option>
    <option value="臺鐵鯖魚便當(圓紙)">臺鐵鯖魚便當(圓紙)</option>
    <option value="懷舊排骨菜飯(圓木)">懷舊排骨菜飯(圓木)</option>
    <option value="客家紅麴雞便當">客家紅麴雞便當</option>
    <option value="薑汁燒肉飯">薑汁燒肉飯</option>
    <option value="芋香牛蒡飯">芋香牛蒡飯</option>
  </select>
  <button type="submit">提交</button>
</form>
<canvas id="myChart"></canvas>
<script>
  document.getElementById('data-form').addEventListener('submit', function(event) {
    event.preventDefault();

    const startDate = document.getElementById('startDate').value;
    const endDate = document.getElementById('endDate').value;
    const bento = document.getElementById('bento').value;

    fetch(`/api/prices?startDate=${startDate}&endDate=${endDate}&bento=${bento}`)
            .then(response => {
              if (!response.ok) {
                throw new Error('Network response was not ok');
              }
              return response.json();
            })
            .then(data => {
              const dates = data.prices.map(price => new Date(price.date));
              const prices = data.prices.map(price => price.price);

              drawChart(dates, prices);
            })
            .catch(error => {
              console.error('Error:', error);
              // Handle the error
            });
  });

  function drawChart(dates, prices) {
    const ctx = document.getElementById('myChart').getContext('2d');

    if (window.myChart) {
      window.myChart.destroy();
    }

    window.myChart = new Chart(ctx, {
      type: 'line',
      data: {
        labels: dates,
        datasets: [{
          label: 'Price Trend',
          data: prices,
          borderColor: 'rgb(75, 192, 192)',
          tension: 0.1
        }]
      },
      options: {
        scales: {
          x: {
            type: 'time',
            time: {
              unit: 'month',
              displayFormats: {
                month: 'YYYY-MM'
              }
            },
            title: {
              display: true,
              text: 'Time'
            }
          },
          y: {
            title: {
              display: true,
              text: 'Price'
            }
          }
        }
      }
    });
  }
</script>
</body>
</html>
````
:::
### 後端
1. 引入套件：
* express: 這是一個流行的 Node.js Web 框架，用於處理 HTTP 請求和路由。
*  path: Node.js 的內置模組，用於處理文件路徑。
* sqlite3: 這是 SQLite 資料庫的 Node.js 綁定，用於操作 SQLite 資料庫。
* cors: 這是一個 Express 中間件，用於處理跨來源資源共享（CORS）。

2. 建立 Express 應用程式實例：
* 使用 express() 建立了一個 Express 應用程式。

3. 設置中間件：
* cors()：啟用 CORS 支持，允許跨來源請求。

4. 連接資料庫：
* 使用 sqlite3 打開 SQLite 資料庫連接。
* 如果連接成功，則創建一個名為 bento_prices 的資料表，該表包含 id、date、bento_type 和 price 欄位。

5. 定義路由：
* GET /api/prices：當收到此路由的 GET 請求時，使用提供的查詢參數（startDate、endDate 和 bento）從資料庫中檢索對應的價格資料。
* 如果查詢成功，將結果以 JSON 格式返回，並將日期格式化為 ISO 8601 標準。

6. 設置靜態資源路徑：
* 使用 express.static 中間件指定了靜態資源的路徑，這將使 Express 伺服器能夠提供靜態檔案（如 HTML、CSS、JavaScript）。

7. 啟動伺服器：
* 使用 app.listen() 啟動了一個 HTTP 伺服器，監聽在本地端口 3000 上。
:::spoiler **app.js**
````javascript=
const express = require('express');
const path = require('path');
const sqlite3 = require('sqlite3').verbose();
const cors = require('cors');

const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

const dbPath = path.join(__dirname, 'db', 'sqlite.db');
const db = new sqlite3.Database(dbPath, (err) => {
    if (err) {
        console.error('Error connecting to database:', err.message);
    } else {
        console.log('Connected to SQLite database:', dbPath);
        db.run(`CREATE TABLE IF NOT EXISTS bento_prices (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            date DATE NOT NULL,
            bento_type TEXT NOT NULL,
            price REAL NOT NULL
        )`, (err) => {
            if (err) {
                console.error('Error creating bento_prices table:', err.message);
            } else {
                console.log('bento_prices table created successfully.');
            }
        });
    }
});

// 查询价格趋势
app.get('/api/prices', (req, res) => {
    const { startDate, endDate, bento } = req.query;
    const sql = `
        SELECT date, price 
        FROM bento_prices 
        WHERE bento_type = ? AND date BETWEEN ? AND ?
        ORDER BY date
    `;
    db.all(sql, [bento, startDate, endDate], (err, rows) => {
        if (err) {
            console.error('Error executing query:', err.message);
            res.status(500).json({ error: err.message });
            return;
        }
        console.log('Query results:', rows);

        // 格式化日期為 ISO 8601 格式
        const formattedRows = rows.map(row => ({
            date: new Date(row.date).toISOString(),
            price: parseFloat(row.price)
        }));

        res.json({ prices: formattedRows });
    });
});

app.use(express.static(path.join(__dirname, 'public')));

const PORT = 3000;
app.listen(PORT, () => {
    console.log(`Server running at http://localhost:${PORT}`);
});

module.exports = app;

````
:::
