<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bảng tính giá tờ rơi</title>
<style>
    body {
        font-family: Arial, sans-serif;
        display: flex;
        justify-content: center;
        align-items: center;
        min-height: 100vh;
        background-color: #f4f4f4;
    }
    .calculator-container {
        background: #fff;
        padding: 20px;
        border-radius: 8px;
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        max-width: 500px;
        width: 100%;
    }
    .calculator-container h2 {
        text-align: center;
        margin-bottom: 20px;
    }
    .calculator-container label {
        display: block;
        margin-bottom: 5px;
        font-weight: bold;
    }
    .calculator-container input, .calculator-container select {
        width: 100%;
        padding: 8px;
        margin-bottom: 15px;
        border: 1px solid #ddd;
        border-radius: 4px;
        font-size: 14px;
    }
    .result {
        font-size: 18px;
        font-weight: bold;
        color: #333;
        text-align: center;
    }
    .notes {
        font-size: 12px;
        color: #555;
        margin-top: 10px;
    }
</style>
</head>
<body>

<div class="calculator-container">
    <h2>Bảng Tính Giá Tờ Rơi</h2>

    <label for="length">Nhập kích thước chiều cao (mm):</label>
    <input type="number" id="length" placeholder="Ví dụ 297" oninput="calculatePrice()">

    <label for="width">Nhập kích thước chiều ngang (mm):</label>
    <input type="number" id="width" placeholder="Ví dụ 210" oninput="calculatePrice()">

    <label for="paperType">Chọn Loại Giấy (gsm):</label>
    <select id="paperType" onchange="calculatePrice()">
        <option value="100">Giấy Couche 100 gsm</option>
        <option value="120">Giấy Couche 120 gsm</option>
        <option value="150">Giấy Couche 150 gsm</option>
        <option value="200">Giấy Couche 200 gsm</option>
        <option value="300">Giấy Couche 300 gsm</option>
    </select>

    <label for="quantity">Nhập số lượng cần in:</label>
    <input type="number" id="quantity" placeholder="Ví dụ 1000" oninput="calculatePrice()">

    <label for="printSides">Nhập số mặt cần in:</label>
    <select id="printSides" onchange="calculatePrice()">
        <option value="1">In 1 mặt</option>
        <option value="2">In 2 mặt</option>
    </select>

    <label for="lamination">Chọn loại màng muốn cán:</label>
    <select id="lamination" onchange="calculatePrice()">
        <option value="none">Không Cán</option>
        <option value="glossy1">Cán Bóng 1 mặt</option>
        <option value="glossy2">Cán Bóng 2 mặt</option>
        <option value="matte1">Cán Mờ 1 mặt</option>
        <option value="matte2">Cán Mờ 2 mặt</option>
    </select>

    <label for="folding">Chọn đường Cấn:</label>
    <select id="folding" onchange="calculatePrice()">
        <option value="none">Không Cấn</option>
        <option value="fold1">Cấn 1 đường</option>
        <option value="fold2">Cấn 2 đường</option>
        <option value="fold3">Cấn 3 đường</option>
    </select>

    <label>Đơn Giá trên 1 tờ:</label>
    <div class="result" id="totalPrice">0 VND</div>

    <div class="notes" id="calculationNotes"></div>
</div>

<script>
    const paperPricesPerReam = {
        "100": 630000,
        "120": 730000,
        "150": 910000,
        "200": 1250000,
        "300": 1970000
    };

    const printCosts = {
        "430x325": { base: 550000, extraPerRun: 120 },
        "650x430": { base: 800000, extraPerRun: 240 },
        "860x650": { base: 1200000, extraPerRun: 360 },
        "A3": 3000
    };

    const laminationRates = {
        "glossy": 1800,
        "matte": 2000
    };

    const foldingRates = {
        "fold1": 200,
        "fold2": 300,
        "fold3": 400
    };

    const digitalPrintThreshold = 500;
    const digitalPrintCostPerRun = 1000;

    function calculatePaperCostPerSheet(gsm) {
        const pricePerReam = paperPricesPerReam[gsm];
        return pricePerReam ? pricePerReam / 500 : 0;
    }

    function addBleedToDimensions(length, width) {
        const bleed = 2;
        return {
            lengthWithBleed: length + 2 * bleed,
            widthWithBleed: width + 2 * bleed
        };
    }

    function calculateMaxProductsPerSheet(sheetLength, sheetWidth, productLength, productWidth, margin = 5) {
        // Chỉ trừ lề từ chiều rộng (sheetWidth)
        const usableWidth = sheetWidth ;
        const usableLength = sheetLength - 2 * margin;

        const fitNoRotation = Math.floor(usableLength / productLength) * Math.floor(usableWidth / productWidth);
        const fitWithRotation = Math.floor(usableLength / productWidth) * Math.floor(usableWidth / productLength);
        return Math.max(fitNoRotation, fitWithRotation);
    }

    function calculatePrintCost(sheetSize, runs, printSides) {
        if (sheetSize === "A3") {
            return digitalPrintCostPerRun * runs * (printSides === 2 ? 2 : 1);
        }

        const { base, extraPerRun } = printCosts[sheetSize];

        if (runs <= 2000) return base;

        const extraRuns = runs - 2000;
        const extraCost = extraRuns * extraPerRun * (printSides === 2 ? 2 : 1);
        return base + extraCost;
    }

    function calculateOptimalPrintCost(sheetsNeeded, printSides, quantity, productLength, productWidth) {
        if (quantity <= digitalPrintThreshold) {
            const maxProductsA3 = calculateMaxProductsPerSheet(420, 297, productLength, productWidth);
            const sheetsNeededA3 = Math.ceil(quantity / maxProductsA3);
            const minCost = calculatePrintCost("A3", sheetsNeededA3, printSides);
            return {
                minCost,
                chosenSheetSize: "A3",
                sheetsNeeded: sheetsNeededA3,
                maxProductsPerSheet: maxProductsA3,
                totalRuns: sheetsNeededA3
            };
        }

        const sheetSizes = [
            { size: "430x325", sheetLength: 430, sheetWidth: 325 },
            { size: "650x430", sheetLength: 650, sheetWidth: 430 },
            { size: "860x650", sheetLength: 860, sheetWidth: 650 }
        ];

        let optimalCost = Infinity;
        let chosenSheetSize = "";
        let finalSheetsNeeded = 0;
        let finalMaxProductsPerSheet = 0;
        let totalRuns = 0;

        for (const sheet of sheetSizes) {
            const maxProducts = calculateMaxProductsPerSheet(sheet.sheetLength, sheet.sheetWidth, productLength, productWidth);
            const sheetsNeededForSize = Math.ceil(quantity / maxProducts);
            const runs = sheetsNeededForSize;
            const cost = calculatePrintCost(sheet.size, runs, printSides);

            if (cost < optimalCost) {
                optimalCost = cost;
                chosenSheetSize = sheet.size;
                finalSheetsNeeded = sheetsNeededForSize;
                finalMaxProductsPerSheet = maxProducts;
                totalRuns = runs;
            }
        }

        return {
            minCost: optimalCost,
            chosenSheetSize,
            sheetsNeeded: finalSheetsNeeded,
            maxProductsPerSheet: finalMaxProductsPerSheet,
            totalRuns
        };
    }

    function calculateLaminationCost(widthM, lengthM, sheets, sides, type) {
        const rate = laminationRates[type];
        const areaPerSheet = widthM * lengthM;
        return rate * areaPerSheet * sheets * sides;
    }

    function calculateFoldingCost(sheets, foldingType) {
        const rate = foldingRates[foldingType];
        return rate * sheets;
    }

    function calculatePrice() {
        const length = parseFloat(document.getElementById("length").value) || 0;
        const width = parseFloat(document.getElementById("width").value) || 0;
        const paperType = document.getElementById("paperType").value;
        const quantity = parseFloat(document.getElementById("quantity").value) || 0;
        const printSides = parseFloat(document.getElementById("printSides").value) || 1;
        const lamination = document.getElementById("lamination").value;
        const folding = document.getElementById("folding").value;

        if (length === 0 || width === 0 || quantity === 0) {
            document.getElementById("totalPrice").innerText = "0 VND";
            document.getElementById("calculationNotes").innerHTML = "";
            return;
        }

        const paperCostPerSheet = calculatePaperCostPerSheet(paperType);
        const dimensionsWithBleed = addBleedToDimensions(length, width);
        const productLength = dimensionsWithBleed.lengthWithBleed;
        const productWidth = dimensionsWithBleed.widthWithBleed;

        let sheetsNeeded, printingCost, chosenSheetSize, maxProductsPerSheet, totalRuns;

        // Tính số sản phẩm tối đa trên khổ giấy 860x650mm
        const maxProducts860x650 = calculateMaxProductsPerSheet(860, 650, productLength, productWidth);
        const sheetsNeeded860x650 = Math.ceil(quantity / maxProducts860x650);

        // Lựa chọn khổ giấy in tối ưu
        const optimalResult = calculateOptimalPrintCost(sheetsNeeded860x650, printSides, quantity, productLength, productWidth);
        printingCost = optimalResult.minCost;
        chosenSheetSize = optimalResult.chosenSheetSize;
        sheetsNeeded = optimalResult.sheetsNeeded;
        maxProductsPerSheet = optimalResult.maxProductsPerSheet;
        totalRuns = optimalResult.totalRuns;

        let wastageSheets = 0;
        if (chosenSheetSize === "A3") {
            wastageSheets = 5;
        } else {
            wastageSheets = 100;
        }

        const totalSheetsWithWastage = sheetsNeeded + wastageSheets;

        const totalPaperCost = paperCostPerSheet * totalSheetsWithWastage * printSides;

        let basePrice = totalPaperCost + printingCost;

        let laminationCost = 0;
        if (lamination.includes("glossy") || lamination.includes("matte")) {
            const sides = lamination.includes("2") ? 2 : 1;
            const laminationType = lamination.includes("glossy") ? "glossy" : "matte";
            laminationCost = calculateLaminationCost(productWidth / 1000, productLength / 1000, totalSheetsWithWastage, sides, laminationType);
        }

        let foldingCost = 0;
        if (folding !== "none") {
            foldingCost = calculateFoldingCost(totalSheetsWithWastage, folding);
        }

        basePrice += laminationCost + foldingCost;
        const totalWithMargin = basePrice * 1.2;
        const unitPrice = Math.ceil(totalWithMargin / quantity);

        // Tính tổng số tờ giấy 860x650 cần dùng
        const total860x650Sheets = chosenSheetSize === "860x650" ? totalSheetsWithWastage : Math.ceil(totalSheetsWithWastage / (860 / optimalResult.maxProductsPerSheet));

        document.getElementById("totalPrice").innerText = unitPrice.toLocaleString("vi-VN") + " VND";

        document.getElementById("calculationNotes").innerHTML = `
            Khổ giấy chọn: ${chosenSheetSize}<br>
            Số sản phẩm trên mỗi tờ ${chosenSheetSize}: ${maxProductsPerSheet}<br>
            Tổng số tờ giấy ${chosenSheetSize} (bao gồm bù hao): ${totalSheetsWithWastage} tờ<br>
            Số tờ bù hao: ${wastageSheets} tờ<br>
            Tổng số tờ giấy 860x650 cần dùng: ${total860x650Sheets} tờ<br>
            Chi phí giấy: ${totalPaperCost.toLocaleString("vi-VN")} VND<br>
            Chi phí in: ${printingCost.toLocaleString("vi-VN")} VND<br>
            Chi phí cán màng: ${laminationCost.toLocaleString("vi-VN")} VND<br>
            Chi phí cấn: ${foldingCost.toLocaleString("vi-VN")} VND<br>
            Tổng cộng (bao gồm 20%): ${totalWithMargin.toLocaleString("vi-VN")} VND<br>
            Đơn giá trên mỗi tờ: ${unitPrice.toLocaleString("vi-VN")} VND
        `;
    }
</script>

</body>
</html>
 phân tích mã