見出し画像

本の重さと宅配の箱数計算機v2:任意のサイズに対応 & ハトロン判追加×Claude 3.5 Sonnet

Claudeを課金してから使いまくってます。
それでも毎日毎日AIのアップデートやニューバージョンのリリースが凄くて、全然収まらないですね~。

余談

最近AIで挑戦してみたこと

windowsOFFICEファイルに使われているフォント一覧をエクセルシートにリストアップするvba。且つ開いているPC環境に有るか無いかも一覧される。
これは残念ながら断念しました。
入稿データで良く複数人の著者から、例えば1冊の書籍で10人分くらいの入稿データが入ってくる場合って弊社結構多いのですけど、docxにしてもpptxにしてもxlsxにしても、特にpptか、変なフォント使っている時あるんですよね。これたくさんあると、ファイル開いて~設定のフォント検索まで結構遠くて正直面倒なんです。なので一気に使用されているフォントリストできないかなと思った次第です。でもね、よく見ると「MS Pゴシック」がフォントなしってなんじゃらホイ😫 これがどうしても解消できなかった。
内部のvbaコードはファイルを全部開いてチェックする割にはまぁそこそこ早い処理には出来たんだけど、これじゃ使えんわ、残念😩
↓↓↓ こんな感じね

本題

本の重さと宅配の箱数計算機v2

今日見積もった仕事で64x170(mm)ってホテルの朝食と夕食チケットあるんですけど、64x170仕上がりクラフトペーパーデュプロHT124kg墨1/1で各5000枚。さて宅配便何箱? ..…分からん😅
って事で、今までのA4、B5、A5に任意のサイズってのを追加し、判型にハトロン判も追加してアプデしてみました。
見積りで発送の時はこれで計算し、概算見積もりとして営業に提出してます。我ながら便利と思ってる😊

html+CSS+javascript

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>本の重さと宅急便箱数計算機v2</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; margin: 0; padding: 20px; }
        .container { display: flex; }
        .left-column { flex: 0 0 250px; }
        .right-column { width: 250px; margin-left: 20px; }
        h1 { color: #333; font-size: 26px; margin-top: 0; margin-bottom: 1px; }
        h2 { font-size: 20px; margin-top: 0; margin-bottom: 2px; }
        form { margin-bottom: 5px; }
        label { display: block; margin-bottom: 5px; }
        input, select, button {
            width: 100%;
            margin-bottom: 5px;
            box-sizing: border-box;
            padding: 6px;
            font-size: 16px;
        }
        .flex-container {
            display: flex;
            gap: 10px;
        }
        .half-width {
            flex: 1;
            box-sizing: border-box;
        }
        button {
            background-color: #4e4f52;
            color: white;
            border: none;
            cursor: pointer;
            padding: 10px;
            font-size: 16px;
        }
        button:hover { background-color: #45a049; }
        #result, #totalWeight, #bookWeight {
            background-color: #f2f2f2;
            padding: 2px;
            padding-left: 10px;
            border-radius: 10px;
            margin-top: 2px;
            margin-bottom: 2px;
            height: auto;
        }
        #customSizeInputs {
            display: none;
            margin-bottom: 5px;
        }
        #customSizeInputs .flex-container {
            gap: 10px;
        }

        @media screen and (max-width: 767px) {
            body {
                display: flex;
                justify-content: center;
                align-items: center;
                min-height: 100vh;
            }
            .container {
                width: 100%;
                max-width: 250px;
            }
            .left-column {
                flex: 1;
            }
        } 
    </style>
</head>
<body>
    <div class="container">
        <div class="left-column">
            <h1>本の重さ計算機</h1>
            <h2>&宅配便の箱数計算v2</h2>
            <form id="calculatorForm">
                <label for="bookSize">仕上がり:</label>
                <select id="bookSize" required>
                    <option value="A4">A4</option>
                    <option value="B5">B5</option>
                    <option value="A5">A5</option>
                    <option value="custom">任意のサイズ</option>
                </select>
                <div id="customSizeInputs">
                    <div class="flex-container">
                        <div class="half-width">
                            <label for="customWidth">横 (mm):</label>
                            <input type="number" id="customWidth" min="1">
                        </div>
                        <div class="half-width">
                            <label for="customHeight">縦 (mm):</label>
                            <input type="number" id="customHeight" min="1">
                        </div>
                    </div>
                </div>
                <div class="flex-container">
                    <div class="half-width">
                        <label for="paperSize">判型:</label>
                        <select id="paperSize" required>
                            <option value="A判">A判</option>
                            <option value="菊判">菊判</option>
                            <option value="四六判">四六判</option>
                            <option value="ハトロン判">ハトロン判</option>
                        </select>
                    </div>
                    <div class="half-width">
                        <label for="weight">本文斤量:</label>
                        <select id="weight" required></select>
                    </div>
                </div>
                <label for="pages">ページ数:</label>
                <input type="number" id="pages" required min="1">
                <label for="copies">部数:</label>
                <input type="number" id="copies" required min="1">
                <button type="button" id="calculateButton">計算</button>
            </form>
            <div id="bookWeight"></div>
            <div id="totalWeight"></div>
            <div id="result"></div>
        </div>
    </div>
<script>
    const weightOptions = {
        '四六判': [45, 55, 62, 67.5, 68, 70, 72.5, 73, 90, 110, 135, 160, 180],
        '菊判': [31, 38, 39.5, 47, 48.5, 50.5, 62.5, 76.5, 93.5, 111, 125],
        'A判': [28.5, 35, 36.5, 40, 43, 43.5, 44.5, 46.5, 57.5, 70.5, 86.5],
        'ハトロン判': [54, 65, 75.5, 92, 108, 129.5]
    };

    const baseSize = {
        '四六判': [788, 1091],
        '菊判': [636, 939],
        'A判': [625, 880],
        'ハトロン判': [900, 1200]
    };

    function updateWeightOptions() {
        const paperSize = document.getElementById('paperSize').value;
        const weightSelect = document.getElementById('weight');
        weightSelect.innerHTML = '';
        weightOptions[paperSize].forEach(weight => {
            const option = document.createElement('option');
            option.value = weight;
            option.textContent = weight + ' kg';
            weightSelect.appendChild(option);
        });
    }

    function toggleCustomSize() {
        const bookSize = document.getElementById('bookSize').value;
        const customSizeInputs = document.getElementById('customSizeInputs');
        customSizeInputs.style.display = bookSize === 'custom' ? 'block' : 'none';
        if (bookSize === 'custom') {
            document.getElementById('customWidth').focus();
        }
    }

    function getBookSize() {
        const bookSize = document.getElementById('bookSize').value;
        const sizes = {
            "A4": [210, 297],
            "A5": [148, 210],
            "B5": [182, 257]
        };

        if (bookSize === 'custom') {
            const width = parseInt(document.getElementById('customWidth').value);
            const height = parseInt(document.getElementById('customHeight').value);
            if (!width || !height) {
                alert("カスタムサイズの縦と横を入力してください。");
                return null;
            }
            return [width, height];
        }

        return sizes[bookSize];
    }

    function calculateResults() {
        const paperSize = document.getElementById('paperSize').value;
        const paperWeight = parseFloat(document.getElementById('weight').value);
        let pages = parseInt(document.getElementById('pages').value);
        const copies = parseInt(document.getElementById('copies').value);

        const dimensions = getBookSize();
        if (!dimensions) return;
        const [width, height] = dimensions;

        if (!paperSize || isNaN(paperWeight) || isNaN(pages) || isNaN(copies)) {
            alert("全てのフィールドに値を入力してください。");
            return;
        }

        // ページ数を偶数に調整
        if (pages % 2 !== 0) {
            pages++;
            document.getElementById('pages').value = pages;
        }

        const [baseWidth, baseHeight] = baseSize[paperSize];
        const sheetWeight = paperWeight / (baseWidth * baseHeight) * (width * height);
        const book_weight = sheetWeight * pages / 2;
        const total_weight = book_weight * copies / 1000;

        document.getElementById('bookWeight').innerHTML = `1冊の重さ: ${book_weight.toFixed(1)} g`;
        document.getElementById('totalWeight').innerHTML = `総重量: ${total_weight.toFixed(2)} kg`;

        const yamato = [
            { name: '60サイズ(2kg)', max: 60, maxWeight: 2000 },
            { name: '80サイズ(5kg)', max: 80, maxWeight: 5000 },
            { name: '100サイズ(10kg)', max: 100, maxWeight: 10000 },
            { name: '120サイズ(15kg)', max: 120, maxWeight: 15000 },
            { name: '140サイズ(20kg)', max: 140, maxWeight: 20000 },
            { name: '160サイズ(25kg)', max: 160, maxWeight: 25000 }
        ];

        const boxVolume = width + height + 10;
        let result = '';
        let weightCalculation = '';
        for (const size of yamato) {
            const booksPerBoxByVolume = Math.floor(size.max / boxVolume);
            const booksPerBoxByWeight = Math.floor(size.maxWeight / book_weight);
            const booksPerBox = Math.min(booksPerBoxByVolume, booksPerBoxByWeight);
            let boxesNeeded;
            if (booksPerBox > 0) {
                boxesNeeded = Math.ceil(copies / booksPerBox);
                result += `${size.name}: ${boxesNeeded} 箱(1箱あたり最大${booksPerBox}冊)<br>`;
            } else {
                boxesNeeded = Math.ceil(total_weight * 1000 / size.maxWeight);
                result += `${size.name}: ${boxesNeeded} 箱<br>`;
                weightCalculation = '(重さで計算)';
            }
        }
        document.getElementById('result').innerHTML = result + weightCalculation;
    }

    // イベントリスナーの設定
    document.getElementById('calculateButton').addEventListener('click', calculateResults);
    document.getElementById('paperSize').addEventListener('change', updateWeightOptions);
    document.getElementById('bookSize').addEventListener('change', toggleCustomSize);

    // 判型でEnterキーを押した時に本文斤量にフォーカスを移動
    document.getElementById('paperSize').addEventListener('keydown', function(event) {
        if (event.key === 'Enter') {
            event.preventDefault();
            document.getElementById('weight').focus();
        }
    });

    // 本文斤量でEnterキーを押した時にページ数にフォーカスを移動
    document.getElementById('weight').addEventListener('keydown', function(event) {
        if (event.key === 'Enter') {
            event.preventDefault();
            document.getElementById('pages').focus();
        }
    });

    // カスタムサイズ入力欄のEnterキーイベント
    document.getElementById('customWidth').addEventListener('keydown', function(event) {
        if (event.key === 'Enter') {
            event.preventDefault();
            document.getElementById('customHeight').focus();
        }
    });

    document.getElementById('customHeight').addEventListener('keydown', function(event) {
        if (event.key === 'Enter') {
            event.preventDefault();
            document.getElementById('paperSize').focus();
        }
    });

    // 既存のEnterキーイベント
    document.getElementById('pages').addEventListener('keydown', function(event) {
        if (event.key === 'Enter') {
            event.preventDefault();
            let pages = parseInt(this.value);
            if (pages % 2 !== 0) {
                pages++;
                this.value = pages;
            }
            document.getElementById('copies').focus();
        }
    });

    document.getElementById('copies').addEventListener('keydown', function(event) {
        if (event.key === 'Enter') {
            event.preventDefault();
            document.getElementById('calculateButton').click();
        }
    });

    // 初期化
    window.onload = updateWeightOptions;
</script>
</body>
</html>


いいなと思ったら応援しよう!