{"id":35121,"date":"2025-11-28T23:21:49","date_gmt":"2025-11-28T15:21:49","guid":{"rendered":"https:\/\/18r.shixinote.com\/?p=35121"},"modified":"2025-12-21T11:37:36","modified_gmt":"2025-12-21T03:37:36","slug":"%e9%9b%b6%e5%a7%8b%e4%b9%8b%e9%96%80%ef%bd%9c%e7%a6%ae%e5%8c%85%e6%8b%9b%e5%8b%9f%e5%8d%b7%e5%96%ae%e5%83%b9%e8%a8%88%e7%ae%97","status":"publish","type":"post","link":"https:\/\/18r.shixinote.com\/?p=35121","title":{"rendered":"\u96f6\u59cb\u4e4b\u9580\uff5c\u79ae\u5305\u62db\u52df\u5377\u55ae\u50f9\u8a08\u7b97"},"content":{"rendered":"\n<p class=\"has-text-align-center\"><strong>\u7981\u6b62\u622a\u5716\u8f49\u50b3\u4efb\u4f55\u5e73\u53f0<\/strong><\/p>\n\n\n\n<p><\/p>\n\n\n\r\n<div id=\"gacha-cp-container\">\r\n  <div class=\"cp-controls\">\r\n    <label class=\"cp-toggle\">\r\n      <input type=\"checkbox\" id=\"include-normal-checkbox\" checked>\r\n      <span>\u8a08\u5165\u4e00\u822c\u62db\u52df\u5238<\/span>\r\n    <\/label>\r\n\r\n    <label class=\"cp-toggle\">\r\n      <input type=\"checkbox\" id=\"show-limited-checkbox\" checked>\r\n      <span>\u986f\u793a\u9650\u6642\u79ae\u5305<\/span>\r\n    <\/label>\r\n\r\n    <label class=\"cp-toggle\">\r\n      <input type=\"checkbox\" id=\"show-permanent-checkbox\" checked>\r\n      <span>\u986f\u793a\u5e38\u99d0\u79ae\u5305<\/span>\r\n    <\/label>\r\n\r\n    <label class=\"cp-toggle\">\r\n      <input type=\"checkbox\" id=\"only-available-checkbox\" checked>\r\n      <span>\u53ea\u986f\u793a\u76ee\u524d\u53ef\u8cb7 CP \u6392\u540d<\/span>\r\n    <\/label>\r\n  <\/div>\r\n\r\n  <div class=\"cp-table-wrapper\">\r\n    <table id=\"gacha-cp-table\">\r\n      <thead>\r\n        <tr>\r\n          <th>\u79ae\u5305\u540d\u7a31<\/th>\r\n          <th>\u985e\u578b<\/th>\r\n          <th>\u767d\u8272\u840a\u666e\u6676<\/th>\r\n          <th>\u9650\u8cfc\u6b21\u6578<\/th>\r\n          <th>\u7e3d EC \u6d88\u8017<\/th>\r\n          <th>\u9650\u5b9a\u5238<\/th>\r\n          <th>\u4e00\u822c\u5238<\/th>\r\n          <th>\u7da0\u8272\u840a\u666e\u6676<\/th>\r\n          <th>\u7e3d\u62bd\u6578<\/th>\r\n          <th>\u5e73\u5747\u6bcf\u62bd EC<\/th>\r\n        <\/tr>\r\n      <\/thead>\r\n      <tbody>\r\n        <tr><td colspan=\"10\">\u5c1a\u672a\u8f09\u5165\u79ae\u5305\u8cc7\u6599\u3002<\/td><\/tr>\r\n      <\/tbody>\r\n    <\/table>\r\n  <\/div>\r\n\r\n  <p class=\"cp-note\">\r\n    \u5099\u8a3b\uff1a<br>\r\n    1. \u82e5\u79ae\u5305\u6c92\u6709\u62db\u52df\u5238\u6216\u7da0\u8272\u840a\u666e\u6676\uff0c\u5247\u7121\u6cd5\u8a08\u7b97\u5e73\u5747\u6bcf\u62bd\u6210\u672c\u3002<br>\r\n    2. \u79ae\u5305\u53ef\u80fd\u642d\u914d\u5176\u4ed6\u734e\u52f5\uff0c\u56e0\u6b64\u5e73\u5747\u6bcf\u62bd EC \u50c5\u4f9b\u53c3\u8003\u3002<br>\r\n    3. \u767d\u8272\u840a\u666e\u6676\u6210\u672c\u4ee5\u300c\u5be6\u969b\u7e3d\u82b1\u8cbb ECion \u7d44\u5408\u300d\u8a08\u7b97\u3002<br>\r\n  <\/p>\r\n<\/div>\r\n\r\n<style>\r\n  #gacha-cp-container {\r\n    margin: 0;\r\n    padding: 0;\r\n  }\r\n\r\n  .cp-controls{\r\n    display: flex;\r\n    flex-wrap: wrap;\r\n    align-items: center;\r\n    gap: 8px 16px;\r\n  }\r\n\r\n  .cp-toggle{\r\n    display: inline-flex;\r\n    align-items: center;\r\n    gap: 6px;\r\n    line-height: 1.2;\r\n    margin: 0;\r\n  }\r\n\r\n  \/*\r\n    \u9019\u6bb5\u662f\u70ba\u4e86\u907f\u514d WordPress \u4e3b\u984c\u628a checkbox \u5f04\u6b6a\u6216\u8b8a\u5f62\r\n    \u82e5\u4f60\u63db\u4e3b\u984c\u5f8c\u4ecd\u6709\u6b6a\u6389\uff0c\u518d\u8ddf\u6211\u8aaa\uff0c\u6211\u6703\u91dd\u5c0d\u8a72\u4e3b\u984c\u52a0\u300c\u66f4\u7cbe\u6e96\u7684\u8986\u5beb\u300d\r\n  *\/\r\n  .cp-toggle input[type=\"checkbox\"]{\r\n    appearance: auto !important;\r\n    -webkit-appearance: checkbox !important;\r\n\r\n    width: 16px !important;\r\n    height: 16px !important;\r\n    margin: 0 !important;\r\n\r\n    position: static !important;\r\n    transform: none !important;\r\n\r\n    padding: 0 !important;\r\n    border: initial !important;\r\n    border-radius: 0 !important;\r\n    background: initial !important;\r\n    box-shadow: none !important;\r\n\r\n    flex: 0 0 16px;\r\n    vertical-align: middle;\r\n  }\r\n\r\n  .cp-table-wrapper {\r\n    width: 100%;\r\n    overflow-x: auto;\r\n    margin-top: 8px;\r\n  }\r\n\r\n  #gacha-cp-table {\r\n    width: 100%;\r\n    max-width: 100%;\r\n    border-collapse: collapse;\r\n  }\r\n\r\n  #gacha-cp-table tbody tr {\r\n    border-bottom: 1px solid #e5e5e5;\r\n  }\r\n\r\n  #gacha-cp-table thead tr {\r\n    border-bottom: 1px solid #dcdcdc;\r\n  }\r\n\r\n  #gacha-cp-table,\r\n  #gacha-cp-table th,\r\n  #gacha-cp-table td {\r\n    border: none !important;\r\n  }\r\n\r\n  #gacha-cp-table th,\r\n  #gacha-cp-table td {\r\n    padding: 6px 8px;\r\n    text-align: center;\r\n    white-space: nowrap;\r\n  }\r\n\r\n  #gacha-cp-table thead {\r\n    background-color: #f4f4f4;\r\n  }\r\n\r\n  #gacha-cp-table th {\r\n    font-weight: 600;\r\n    font-size: 13px;\r\n  }\r\n\r\n  #gacha-cp-table td {\r\n    font-size: 13px;\r\n  }\r\n\r\n  #gacha-cp-table td:first-child,\r\n  #gacha-cp-table th:first-child {\r\n    text-align: left !important;\r\n  }\r\n\r\n  .cp-note {\r\n    font-size: 12px;\r\n    color: #666;\r\n    margin-top: 10px;\r\n  }\r\n\r\n  @media (max-width: 600px) {\r\n    #gacha-cp-container {\r\n      font-size: 13px;\r\n      padding: 12px;\r\n    }\r\n    #gacha-cp-table th,\r\n    #gacha-cp-table td {\r\n      font-size: 12px;\r\n      padding: 3px 4px;\r\n    }\r\n  }\r\n<\/style>\r\n\r\n<script>\r\n  \/**********************\r\n   * \u5168\u57df\u8cc7\u6599\r\n   **********************\/\r\n  let whiteBundles = [];\r\n  let packages = [];\r\n\r\n  \/**********************\r\n   * \u8b80\u53d6 JSON\r\n   **********************\/\r\n  async function loadData() {\r\n    try {\r\n      \/\/ \u4f60\u7684 JSON \u57fa\u5e95\u8def\u5f91\r\n      const baseUrl = \"https:\/\/18r.shixinote.com\/zerowake-gates\/\";\r\n\r\n      \/\/ \u540c\u6642\u8f09\u5165\u5169\u500b\u6a94\u6848\uff0c\u52a0\u5feb\u901f\u5ea6\r\n      const [whiteRes, pkgRes] = await Promise.all([\r\n        fetch(baseUrl + \"whiteBundles.json\"),\r\n        fetch(baseUrl + \"packages.json\")\r\n      ]);\r\n\r\n      if (!whiteRes.ok) throw new Error(\"\u7121\u6cd5\u8f09\u5165 whiteBundles.json\");\r\n      if (!pkgRes.ok) throw new Error(\"\u7121\u6cd5\u8f09\u5165 packages.json\");\r\n\r\n      whiteBundles = await whiteRes.json();\r\n      packages = await pkgRes.json();\r\n    } catch (err) {\r\n      console.error(err);\r\n      const tbody = document.querySelector(\"#gacha-cp-table tbody\");\r\n      if (tbody) {\r\n        tbody.innerHTML = `<tr><td colspan=\"10\">\u8cc7\u6599\u8f09\u5165\u5931\u6557\uff1a${err.message}<\/td><\/tr>`;\r\n      }\r\n    }\r\n  }\r\n\r\n  \/**********************\r\n   * \u683c\u5f0f\u5316\u5de5\u5177\r\n   **********************\/\r\n  \/\/ \u6574\u6578\u5343\u5206\u4f4d\r\n  function formatInt(num) {\r\n    if (num === null || num === undefined || isNaN(num)) return \"-\";\r\n    return Number(num).toLocaleString(\"en-US\", { maximumFractionDigits: 0 });\r\n  }\r\n\r\n  \/\/ \u5c0f\u6578\u5343\u5206\u4f4d\r\n  function formatFloat(num, digits = 2) {\r\n    if (num === null || num === undefined || isNaN(num)) return \"-\";\r\n    return Number(num).toLocaleString(\"en-US\", {\r\n      minimumFractionDigits: digits,\r\n      maximumFractionDigits: digits\r\n    });\r\n  }\r\n\r\n  \/\/ expireAt \u8f49 YYYY\/MM\/DD\uff08\u7528\u65bc\u985e\u578b\u6b04\uff09\r\n  function formatExpireDate(expireAt) {\r\n    if (!expireAt) return \"\";\r\n    const d = new Date(expireAt);\r\n    if (isNaN(d.getTime())) return \"\";\r\n\r\n    const yyyy = d.getFullYear();\r\n    const mm = String(d.getMonth() + 1).padStart(2, \"0\");\r\n    const dd = String(d.getDate()).padStart(2, \"0\");\r\n    return `${yyyy}\/${mm}\/${dd}`;\r\n  }\r\n\r\n  \/**********************\r\n   * \u9650\u6642 \/ \u904e\u671f \/ \u53ef\u8cb7\u5224\u65b7\uff08\u4f9d\u898f\u683c\uff1a\u53ea\u770b expireAt\uff09\r\n   **********************\/\r\n  \/\/ \u6709 expireAt \u2192 \u8996\u70ba\u9650\u6642\r\n  function isLimitedByExpireAt(pkg) {\r\n    return !!(pkg && pkg.expireAt);\r\n  }\r\n\r\n  \/\/ \u6709 expireAt \u4e14 now > expireAt \u2192 \u904e\u671f\r\n  function isExpired(pkg) {\r\n    if (!pkg || !pkg.expireAt) return false;\r\n\r\n    const now = new Date();\r\n    const expireTime = new Date(pkg.expireAt);\r\n\r\n    \/\/ \u82e5 expireAt \u683c\u5f0f\u932f\u8aa4\uff0c\u907f\u514d\u6574\u5f35\u8868\u6d88\u5931 \u2192 \u7576\u4f5c\u4e0d\u904e\u671f\r\n    if (isNaN(expireTime.getTime())) return false;\r\n\r\n    return now > expireTime;\r\n  }\r\n\r\n  \/\/ \u76ee\u524d\u53ef\u8cb7\uff1a\r\n  \/\/ - \u975e\u9650\u6642\uff08\u7121 expireAt\uff09\u2192 \u53ef\u8cb7\r\n  \/\/ - \u9650\u6642\uff08\u6709 expireAt\uff09\u2192 \u672a\u904e\u671f\u624d\u53ef\u8cb7\r\n  function isCurrentlyAvailable(pkg) {\r\n    if (!pkg) return false;\r\n    if (!pkg.expireAt) return true;\r\n    return !isExpired(pkg);\r\n  }\r\n\r\n  \/**********************\r\n   * whiteBundles DP\uff1a\u627e\u6700\u7701 EC \u7684\u767d\u6676\u7d44\u5408\r\n   **********************\/\r\n  function findBestWhiteBundleCombination(targetWhite) {\r\n    \/\/ \u9700\u6c42\u70ba 0 \u6216\u8ca0\u6578\uff1a\u8996\u70ba\u4e0d\u9700\u8981\u8cfc\u8cb7\r\n    if (targetWhite <= 0) {\r\n      return { totalWhite: 0, totalEc: 0, leftoverWhite: 0, combinationList: [] };\r\n    }\r\n    if (!whiteBundles || !whiteBundles.length) return null;\r\n\r\n    \/\/ \u627e\u51fa\u55ae\u4e00\u6700\u5927\u767d\u6676\u5305\uff0c\u7528\u65bc\u8a2d\u5b9a DP \u4e0a\u9650\uff08\u5141\u8a31\u8d85\u8cb7\uff09\r\n    let maxSingleWhite = 0;\r\n    whiteBundles.forEach(bundle => {\r\n      if (bundle.white > maxSingleWhite) maxSingleWhite = bundle.white;\r\n    });\r\n\r\n    \/\/ \u5141\u8a31\u8d85\u8cb7\u6700\u591a\u4e00\u500b\u6700\u5927\u5305\uff0c\u907f\u514d\u4e0d\u5920\u6e4a\r\n    const maxWhite = targetWhite + maxSingleWhite;\r\n\r\n    \/\/ dp[w]\uff1a\u6e4a\u5230 w \u767d\u6676\u7684\u6700\u5c0f EC\r\n    const dp = new Array(maxWhite + 1).fill(Infinity);\r\n    const prevIndex = new Array(maxWhite + 1).fill(-1);\r\n    const prevChoice = new Array(maxWhite + 1).fill(-1);\r\n\r\n    dp[0] = 0;\r\n\r\n    \/\/ \u7121\u9650\u6b21\u53d6\u7528\uff08unbounded\uff09DP\r\n    for (let i = 0; i <= maxWhite; i++) {\r\n      if (dp[i] === Infinity) continue;\r\n      for (let k = 0; k < whiteBundles.length; k++) {\r\n        const bundle = whiteBundles[k];\r\n        const nextWhite = i + bundle.white;\r\n        if (nextWhite > maxWhite) continue;\r\n\r\n        const nextEc = dp[i] + bundle.ec;\r\n        if (nextEc < dp[nextWhite]) {\r\n          dp[nextWhite] = nextEc;\r\n          prevIndex[nextWhite] = i;\r\n          prevChoice[nextWhite] = k;\r\n        }\r\n      }\r\n    }\r\n\r\n    \/\/ \u5f9e targetWhite \u5230 maxWhite \u4e2d\u6311\u300c\u6700\u7701 EC\u300d\uff1b\u540c EC \u6642\u6311\u8d85\u8cb7\u6700\u5c11\r\n    let bestWhite = -1;\r\n    let bestEc = Infinity;\r\n\r\n    for (let w = targetWhite; w <= maxWhite; w++) {\r\n      if (dp[w] === Infinity) continue;\r\n\r\n      if (dp[w] < bestEc) {\r\n        bestEc = dp[w];\r\n        bestWhite = w;\r\n      } else if (dp[w] === bestEc && bestWhite !== -1) {\r\n        const overCurrent = w - targetWhite;\r\n        const overBest = bestWhite - targetWhite;\r\n        if (overCurrent < overBest) bestWhite = w;\r\n      }\r\n    }\r\n\r\n    if (bestWhite === -1) return null;\r\n\r\n    \/\/ \u56de\u63a8\u7d44\u5408\r\n    const bundleCountMap = {};\r\n    let cursor = bestWhite;\r\n\r\n    while (cursor > 0) {\r\n      const choiceIndex = prevChoice[cursor];\r\n      const prev = prevIndex[cursor];\r\n      if (choiceIndex === -1 || prev === -1) break;\r\n\r\n      const used = whiteBundles[choiceIndex];\r\n      const key = used.white + \"-\" + used.ec;\r\n\r\n      if (!bundleCountMap[key]) {\r\n        bundleCountMap[key] = {\r\n          name: used.name,\r\n          white: used.white,\r\n          ec: used.ec,\r\n          count: 0\r\n        };\r\n      }\r\n      bundleCountMap[key].count += 1;\r\n      cursor = prev;\r\n    }\r\n\r\n    const combinationList = Object.values(bundleCountMap);\r\n\r\n    \/\/ \u7d71\u8a08\u7e3d\u767d\u6676\u8207\u7e3d EC\r\n    let totalWhite = 0;\r\n    let totalEc = 0;\r\n    combinationList.forEach(item => {\r\n      totalWhite += item.white * item.count;\r\n      totalEc += item.ec * item.count;\r\n    });\r\n\r\n    return {\r\n      totalWhite,\r\n      totalEc,\r\n      leftoverWhite: totalWhite - targetWhite,\r\n      combinationList\r\n    };\r\n  }\r\n\r\n  \/**********************\r\n   * CP \u8a08\u7b97\uff08EC \/ \u62bd\uff09\r\n   **********************\/\r\n  function calcPackageStats(pkg, includeNormal) {\r\n    let totalEc = 0;\r\n\r\n    \/\/ 1) \u5148\u7b97\u7e3d EC\r\n    if (pkg.type === \"whitePack\") {\r\n      const combo = findBestWhiteBundleCombination(pkg.requiredWhite);\r\n      if (!combo) return null;\r\n      totalEc = combo.totalEc;\r\n    } else if (pkg.type === \"ecDirect\") {\r\n      totalEc = pkg.directEcCost || 0;\r\n    } else {\r\n      \/\/ \u672a\u77e5 type\uff1a\u4e0d\u8a08\u7b97\r\n      return null;\r\n    }\r\n\r\n    \/\/ 2) \u518d\u7b97\u7e3d\u62bd\u6578\uff08\u4f9d\u898f\u683c\uff1alimited + normal(\u53ef\u9078) + green\/100\uff0c\u6700\u5f8c floor\uff09\r\n    const drawsFromLimited = pkg.limited || 0;\r\n    const drawsFromNormal = includeNormal ? (pkg.normal || 0) : 0;\r\n    const drawsFromGreen = (pkg.green || 0) \/ 100;\r\n\r\n    const totalDrawsRaw = drawsFromLimited + drawsFromNormal + drawsFromGreen;\r\n    const totalDraws = Math.floor(totalDrawsRaw);\r\n\r\n    \/\/ 3) \u5e73\u5747\u6bcf\u62bd EC\r\n    let costPerDraw = null;\r\n    if (totalDraws > 0) costPerDraw = totalEc \/ totalDraws;\r\n\r\n    return {\r\n      totalEc,\r\n      totalDraws,\r\n      drawsFromLimited,\r\n      drawsFromNormal,\r\n      drawsFromGreen,\r\n      costPerDraw\r\n    };\r\n  }\r\n\r\n  \/**********************\r\n   * \u985e\u578b\u6b04\u986f\u793a\uff08\u4f60\u6307\u5b9a\u7684\u7c21\u6f54\u683c\u5f0f\uff09\r\n   **********************\/\r\n  function buildTypeTextSimple(pkg) {\r\n    \/\/ \u4f60\u6307\u5b9a\u504f\u597d\u7684\u986f\u793a\uff1a\r\n    \/\/ - \u5546\u5e97-\u9650\u5b9a(2026\/01\/07)\r\n    \/\/ - \u5546\u5e97-\u4e00\u822c\r\n    \/\/ \u56e0\u6b64\u53ea\u5728\u300c\u5546\u5e97\u5206\u985e\u300d\u4e0a\u505a\u7c21\u55ae\u8f38\u51fa\u3002\r\n\r\n    const cat = (pkg && pkg.shopCategory) ? String(pkg.shopCategory) : \"\";\r\n    const expDate = formatExpireDate(pkg?.expireAt);\r\n\r\n    \/\/ \u5546\u5e97-\u9650\u5b9a\r\n    if (cat === \"limited\") {\r\n      \/\/ \u6709 expireAt \u2192 \u986f\u793a\u65e5\u671f\uff1b\u6c92\u6709 expireAt \u2192 \u5c31\u4e0d\u52a0\u65e5\u671f\r\n      return expDate ? `\u5546\u5e97-\u9650\u5b9a(${expDate})` : \"\u5546\u5e97-\u9650\u5b9a\";\r\n    }\r\n\r\n    \/\/ \u5546\u5e97-\u4e00\u822c\r\n    if (cat === \"normal\") {\r\n      \/\/ \u4f60\u5e0c\u671b\u4e00\u822c\u5c31\u7c21\u55ae\u986f\u793a\uff0c\u4e0d\u52a0\u65e5\u671f\r\n      return \"\u5546\u5e97-\u4e00\u822c\";\r\n    }\r\n\r\n    \/\/ \u5176\u4ed6\uff08\u9996\u9801\u89e3\u9396 \/ \u6d3b\u52d5\u901a\u884c\u8b49 \/ \u6708\u5361\u7b49\u7b49\uff09\uff1a\r\n    \/\/ \u5148\u7528\u975e\u5e38\u4fdd\u5b88\u7684 fallback\uff0c\u4e0d\u5f71\u97ff\u4f60\u60f3\u8981\u7684\u7c21\u6f54\u611f\u3002\r\n    \/\/ \u4f60\u672a\u4f86\u82e5\u5728 JSON \u52a0 source\/channel\uff0c\u6211\u518d\u5e6b\u4f60\u628a\u9019\u6bb5\u63d0\u5347\u5230\u66f4\u7cbe\u6e96\u3002\r\n    if (pkg?.availability?.type === \"unlock\") {\r\n      return expDate ? `\u89e3\u9396(${expDate})` : \"\u89e3\u9396\";\r\n    }\r\n\r\n    return expDate ? `\u5176\u4ed6(${expDate})` : \"\u5176\u4ed6\";\r\n  }\r\n\r\n  \/**********************\r\n   * \u8868\u683c\u6e32\u67d3\r\n   **********************\/\r\n  function renderTable() {\r\n    const tbody = document.querySelector(\"#gacha-cp-table tbody\");\r\n    if (!tbody) return;\r\n\r\n    const includeNormal = document.getElementById(\"include-normal-checkbox\")?.checked ?? true;\r\n    const showLimited = document.getElementById(\"show-limited-checkbox\")?.checked ?? true;\r\n    const showPermanent = document.getElementById(\"show-permanent-checkbox\")?.checked ?? true;\r\n    const onlyAvailable = document.getElementById(\"only-available-checkbox\")?.checked ?? false;\r\n\r\n    tbody.innerHTML = \"\";\r\n\r\n    if (!packages || !packages.length) {\r\n      tbody.innerHTML = `<tr><td colspan=\"10\">\u5c1a\u672a\u8f09\u5165\u79ae\u5305\u8cc7\u6599\u3002<\/td><\/tr>`;\r\n      return;\r\n    }\r\n\r\n    const rows = [];\r\n\r\n    packages.forEach(pkg => {\r\n      \/\/ \u2705 \u9650\u6642\/\u5e38\u99d0\u7be9\u9078\uff08\u4f9d\u898f\u683c\uff1aexpireAt\uff09\r\n      const limited = isLimitedByExpireAt(pkg);\r\n      if (limited && !showLimited) return;\r\n      if (!limited && !showPermanent) return;\r\n\r\n      \/\/ \u2705 \u53ea\u986f\u793a\u76ee\u524d\u53ef\u8cb7\r\n      if (onlyAvailable) {\r\n        \/\/ 1) \u4f9d expireAt \u5224\u65b7\u662f\u5426\u9084\u5728\u53ef\u8cfc\u8cb7\u671f\u9593\r\n        if (!isCurrentlyAvailable(pkg)) return;\r\n\r\n        \/\/ 2) \u9019\u8f2a\u5148\u4e0d\u52d5 maxPurchase\uff1amaxPurchase === 0 \u8996\u70ba\u4e0d\u53ef\u8cb7\r\n        if (pkg.maxPurchase === 0) return;\r\n      }\r\n\r\n      const stats = calcPackageStats(pkg, includeNormal);\r\n\r\n      \/\/ \u6c92\u6709\u62bd\u6578\u5c31\u4e0d\u986f\u793a\uff08\u907f\u514d\u9664\u4ee5 0\uff09\r\n      if (!stats || stats.totalDraws <= 0) return;\r\n\r\n      rows.push({ pkg, stats });\r\n    });\r\n\r\n    if (!rows.length) {\r\n      tbody.innerHTML = `<tr><td colspan=\"10\">\u76ee\u524d\u7be9\u9078\u689d\u4ef6\u4e0b\u6c92\u6709\u53ef\u986f\u793a\u7684\u79ae\u5305\u3002<\/td><\/tr>`;\r\n      return;\r\n    }\r\n\r\n    \/\/ CP \u6392\u540d\uff1a\u5e73\u5747\u6bcf\u62bd EC \u7531\u4f4e\u5230\u9ad8\r\n    rows.sort((a, b) => {\r\n      const ca = a.stats.costPerDraw;\r\n      const cb = b.stats.costPerDraw;\r\n      if (ca === null && cb === null) return 0;\r\n      if (ca === null) return 1;\r\n      if (cb === null) return -1;\r\n      return ca - cb;\r\n    });\r\n\r\n    rows.forEach(item => {\r\n      const pkg = item.pkg;\r\n      const s = item.stats;\r\n\r\n      \/\/ \u2705 \u985e\u578b\u6b04\uff1a\u4f9d\u4f60\u6307\u5b9a\u7684\u7c21\u6f54\u683c\u5f0f\r\n      const typeText = buildTypeTextSimple(pkg);\r\n\r\n      \/\/ \u9650\u8cfc\u986f\u793a\uff1a\u9019\u8f2a\u5148\u4e0d\u52d5\uff08\u7dad\u6301 maxPurchase\uff09\r\n      let limitText = \"\u4e0d\u9650\";\r\n      if (pkg.maxPurchase !== null && pkg.maxPurchase !== undefined) {\r\n        limitText = pkg.maxPurchase.toString();\r\n      }\r\n\r\n      \/\/ \u2705 \u767d\u8272\u840a\u666e\u6676\u6b04\u4f4d\uff1a\u986f\u793a\u9700\u6c42\u91cf requiredWhite\uff08\u4f60\u5df2\u6307\u5b9a\uff09\r\n      const whiteNeeded =\r\n        pkg.type === \"whitePack\" && pkg.requiredWhite && pkg.requiredWhite > 0\r\n          ? pkg.requiredWhite\r\n          : null;\r\n\r\n      const drawText = s.costPerDraw !== null ? formatFloat(s.costPerDraw, 2) : \"-\";\r\n\r\n      const tr = document.createElement(\"tr\");\r\n      tr.innerHTML = `\r\n        <td>${pkg.name ?? \"-\"}<\/td>\r\n        <td>${typeText}<\/td>\r\n        <td>${whiteNeeded !== null ? formatInt(whiteNeeded) : \"-\"}<\/td>\r\n        <td>${limitText}<\/td>\r\n        <td>${formatInt(s.totalEc)}<\/td>\r\n        <td>${formatInt(s.drawsFromLimited)}<\/td>\r\n        <td>${formatInt(s.drawsFromNormal)}<\/td>\r\n        <td>${formatInt(pkg.green || 0)}<\/td>\r\n        <td>${formatInt(s.totalDraws)}<\/td>\r\n        <td>${drawText}<\/td>\r\n      `;\r\n\r\n      tbody.appendChild(tr);\r\n    });\r\n  }\r\n\r\n  \/**********************\r\n   * \u521d\u59cb\u5316\r\n   **********************\/\r\n  document.addEventListener(\"DOMContentLoaded\", async () => {\r\n    await loadData();\r\n\r\n    \/\/ \u76e3\u807d checkbox \u8b8a\u52d5\r\n    document.getElementById(\"include-normal-checkbox\")?.addEventListener(\"change\", renderTable);\r\n    document.getElementById(\"show-limited-checkbox\")?.addEventListener(\"change\", renderTable);\r\n    document.getElementById(\"show-permanent-checkbox\")?.addEventListener(\"change\", renderTable);\r\n    document.getElementById(\"only-available-checkbox\")?.addEventListener(\"change\", renderTable);\r\n\r\n    renderTable();\r\n  });\r\n<\/script>\r\n\n","protected":false},"excerpt":{"rendered":"<p>\u7981\u6b62\u622a\u5716\u8f49\u50b3\u4efb\u4f55\u5e73\u53f0<\/p>\n","protected":false},"author":1,"featured_media":35130,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[85],"tags":[],"class_list":["post-35121","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-85"],"blocksy_meta":[],"jetpack_featured_media_url":"https:\/\/18r.shixinote.com\/wp-content\/uploads\/2025\/11\/IMG_3294.jpg","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/18r.shixinote.com\/index.php?rest_route=\/wp\/v2\/posts\/35121","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/18r.shixinote.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/18r.shixinote.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/18r.shixinote.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/18r.shixinote.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=35121"}],"version-history":[{"count":7,"href":"https:\/\/18r.shixinote.com\/index.php?rest_route=\/wp\/v2\/posts\/35121\/revisions"}],"predecessor-version":[{"id":35235,"href":"https:\/\/18r.shixinote.com\/index.php?rest_route=\/wp\/v2\/posts\/35121\/revisions\/35235"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/18r.shixinote.com\/index.php?rest_route=\/wp\/v2\/media\/35130"}],"wp:attachment":[{"href":"https:\/\/18r.shixinote.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=35121"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/18r.shixinote.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=35121"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/18r.shixinote.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=35121"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}