Spaces:
Running
Running
| <html lang="id"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>Kalkulator Pay Out Time Sumur Minyak</title> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <style> | |
| :root { | |
| --bg-color: #f4f6f8; | |
| --card-bg: #ffffff; | |
| --primary: #1f4f7b; | |
| --primary-soft: #e5edf7; | |
| --border-color: #d0d7e2; | |
| --text-main: #1f2933; | |
| --text-muted: #6b7280; | |
| --accent: #0f766e; | |
| --danger: #b91c1c; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| } | |
| body { | |
| margin: 0; | |
| font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; | |
| background: radial-gradient(circle at top left, #e5edf7, #f4f6f8); | |
| color: var(--text-main); | |
| } | |
| .page { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| padding: 24px 16px 40px; | |
| } | |
| .header { | |
| display: flex; | |
| flex-wrap: wrap; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 20px; | |
| gap: 12px; | |
| } | |
| .title-block h1 { | |
| margin: 0; | |
| font-size: 24px; | |
| color: var(--primary); | |
| letter-spacing: 0.03em; | |
| } | |
| .title-block p { | |
| margin: 4px 0 0; | |
| font-size: 13px; | |
| color: var(--text-muted); | |
| } | |
| .badge { | |
| padding: 4px 10px; | |
| border-radius: 999px; | |
| font-size: 11px; | |
| background: var(--primary-soft); | |
| color: var(--primary); | |
| border: 1px solid var(--border-color); | |
| } | |
| .layout { | |
| display: grid; | |
| grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.3fr); | |
| gap: 20px; | |
| } | |
| @media (max-width: 900px) { | |
| .layout { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| .card { | |
| background: var(--card-bg); | |
| border-radius: 10px; | |
| padding: 16px 18px 18px; | |
| box-shadow: 0 10px 25px rgba(15, 23, 42, 0.08); | |
| border: 1px solid rgba(148, 163, 184, 0.35); | |
| } | |
| .card-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 10px; | |
| } | |
| .card-header h2 { | |
| margin: 0; | |
| font-size: 16px; | |
| color: var(--primary); | |
| } | |
| .card-header span { | |
| font-size: 11px; | |
| color: var(--text-muted); | |
| } | |
| .note { | |
| font-size: 12px; | |
| background: #f9fafb; | |
| border-radius: 8px; | |
| padding: 10px 10px 10px 12px; | |
| border: 1px dashed var(--border-color); | |
| margin-bottom: 10px; | |
| color: var(--text-muted); | |
| } | |
| .note b { | |
| color: var(--text-main); | |
| } | |
| fieldset { | |
| border: 1px solid var(--border-color); | |
| border-radius: 8px; | |
| padding: 10px 12px 12px; | |
| margin: 0 0 10px; | |
| } | |
| legend { | |
| padding: 0 6px; | |
| font-size: 12px; | |
| color: var(--text-muted); | |
| } | |
| label { | |
| display: flex; | |
| flex-direction: column; | |
| margin-top: 6px; | |
| font-size: 12px; | |
| color: var(--text-main); | |
| } | |
| label span { | |
| margin-bottom: 2px; | |
| } | |
| input[type="number"] { | |
| padding: 6px 8px; | |
| border-radius: 6px; | |
| border: 1px solid var(--border-color); | |
| font-size: 13px; | |
| outline: none; | |
| transition: border-color 0.15s, box-shadow 0.15s, background 0.15s; | |
| } | |
| input[type="number"]:focus { | |
| border-color: var(--primary); | |
| box-shadow: 0 0 0 1px rgba(37, 99, 235, 0.18); | |
| background: #f9fafb; | |
| } | |
| button { | |
| margin-top: 8px; | |
| padding: 7px 14px; | |
| border-radius: 999px; | |
| border: none; | |
| font-size: 13px; | |
| font-weight: 500; | |
| background: linear-gradient(135deg, var(--primary), #2563eb); | |
| color: #ffffff; | |
| cursor: pointer; | |
| box-shadow: 0 8px 18px rgba(37, 99, 235, 0.35); | |
| transition: transform 0.1s, box-shadow 0.1s, filter 0.1s; | |
| } | |
| button:hover { | |
| filter: brightness(1.03); | |
| transform: translateY(-1px); | |
| box-shadow: 0 10px 22px rgba(37, 99, 235, 0.4); | |
| } | |
| button:active { | |
| transform: translateY(0); | |
| box-shadow: 0 5px 10px rgba(37, 99, 235, 0.25); | |
| } | |
| .result-main { | |
| font-size: 14px; | |
| margin-bottom: 4px; | |
| } | |
| .result-main.success { | |
| color: var(--accent); | |
| } | |
| .result-main.warning { | |
| color: var(--danger); | |
| } | |
| .result-sub { | |
| font-size: 12px; | |
| color: var(--text-muted); | |
| margin-bottom: 6px; | |
| } | |
| .pill-row { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 6px; | |
| margin-bottom: 2px; | |
| } | |
| .pill { | |
| font-size: 11px; | |
| padding: 4px 8px; | |
| border-radius: 999px; | |
| background: #f3f4f6; | |
| color: var(--text-muted); | |
| border: 1px solid #e5e7eb; | |
| } | |
| table { | |
| border-collapse: collapse; | |
| width: 100%; | |
| margin-top: 10px; | |
| font-size: 11px; | |
| table-layout: fixed; | |
| } | |
| th, td { | |
| border: 1px solid #e5e7eb; | |
| padding: 4px 5px; | |
| text-align: right; | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| th { | |
| background: #f3f4f6; | |
| font-weight: 600; | |
| color: #4b5563; | |
| position: sticky; | |
| top: 0; | |
| z-index: 1; | |
| } | |
| td.left, th.left { | |
| text-align: left; | |
| } | |
| .table-wrapper { | |
| max-height: 420px; | |
| overflow: auto; | |
| border-radius: 8px; | |
| border: 1px solid #e5e7eb; | |
| margin-top: 8px; | |
| background: #ffffff; | |
| } | |
| .footer-note { | |
| margin-top: 6px; | |
| font-size: 11px; | |
| color: var(--text-muted); | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="page"> | |
| <div class="header"> | |
| <div class="title-block"> | |
| <h1>Pay Out Time Analyzer</h1> | |
| <p>Simulasi keekonomian sumur minyak berbasis decline curve & cash flow tahunan.</p> | |
| </div> | |
| <div class="badge">Oil & Gas • Investment Tool</div> | |
| </div> | |
| <div class="layout"> | |
| <!-- PANEL INPUT --> | |
| <div class="card"> | |
| <div class="card-header"> | |
| <h2>Input Parameter</h2> | |
| <span>Step 1 · Isi data</span> | |
| </div> | |
| <div class="note"> | |
| <b>Cara penggunaan singkat</b><br> | |
| Isi parameter investasi, biaya operasi, dan data produksi di bawah, lalu tekan tombol | |
| <b>Hitung POT</b>. Sistem akan menghitung revenue, cash flow, dan tahun tercapainya pay out time. | |
| </div> | |
| <form id="potForm" onsubmit="event.preventDefault(); hitungPOT();"> | |
| <fieldset> | |
| <legend>Investasi & Ekonomi</legend> | |
| <label> | |
| <span>Investasi awal (Capex) [USD]</span> | |
| <input type="number" id="capex" value="2000000" step="1000" min="0" required> | |
| </label> | |
| <label> | |
| <span>Harga minyak [USD/bbl]</span> | |
| <input type="number" id="oilPrice" value="70" step="0.1" min="0" required> | |
| </label> | |
| <label> | |
| <span>Biaya maintenance harian [USD/hari]</span> | |
| <input type="number" id="maintDaily" value="800" step="1" min="0" required> | |
| </label> | |
| <label> | |
| <span>Biaya service tahunan [USD/tahun]</span> | |
| <input type="number" id="serviceYearly" value="50000" step="1000" min="0" required> | |
| </label> | |
| <label> | |
| <span>Pajak + royalty (% dari revenue)</span> | |
| <input type="number" id="taxRate" value="20" step="1" min="0" max="100" required> | |
| </label> | |
| </fieldset> | |
| <fieldset> | |
| <legend>Produksi & Decline</legend> | |
| <label> | |
| <span>Produksi awal tahun pertama [bbl/hari]</span> | |
| <input type="number" id="qi" value="800" step="1" min="0" required> | |
| </label> | |
| <label> | |
| <span>Decline rate tahunan (exponential) [%/tahun]</span> | |
| <input type="number" id="decline" value="15" step="0.1" min="0" max="100" required> | |
| </label> | |
| <label> | |
| <span>Jumlah tahun simulasi (maksimum)</span> | |
| <input type="number" id="years" value="15" step="1" min="1" required> | |
| </label> | |
| <label> | |
| <span>Batas economic limit produksi [bbl/hari]</span> | |
| <input type="number" id="qlim" value="50" step="1" min="0" required> | |
| </label> | |
| </fieldset> | |
| <button type="submit">Hitung POT</button> | |
| </form> | |
| <div class="footer-note"> | |
| Catatan: Model ini menggunakan decline exponential tahunan dan pendekatan laju rata-rata | |
| untuk estimasi produksi tahunan. | |
| </div> | |
| </div> | |
| <!-- PANEL HASIL --> | |
| <div class="card"> | |
| <div class="card-header"> | |
| <h2>Hasil Perhitungan</h2> | |
| <span>Step 2 · Interpretasi</span> | |
| </div> | |
| <div id="resultSummary"> | |
| <div class="result-main warning"> | |
| Belum ada perhitungan. Isi parameter di kiri lalu tekan Hitung POT. | |
| </div> | |
| <div class="result-sub"> | |
| Sistem akan menampilkan estimasi waktu balik modal (pay out time) dan tabel cash flow tahunan. | |
| </div> | |
| </div> | |
| <div class="pill-row"> | |
| <div class="pill" id="pillCapex">Capex: -</div> | |
| <div class="pill" id="pillPrice">Harga Minyak: -</div> | |
| <div class="pill" id="pillQi">q<sub>i</sub> awal: -</div> | |
| <div class="pill" id="pillDecline">Decline: -</div> | |
| <div class="pill" id="pillYears">Horizon: -</div> | |
| </div> | |
| <div class="table-wrapper" id="tableWrapper" style="display:none;"> | |
| <table id="resultTable"> | |
| <thead> | |
| <tr> | |
| <th class="left">Tahun</th> | |
| <th>q awal (bbl/h)</th> | |
| <th>q akhir (bbl/h)</th> | |
| <th>Q tahunan (bbl)</th> | |
| <th>Revenue (USD)</th> | |
| <th>Opex (USD)</th> | |
| <th>Net CF (USD)</th> | |
| <th>CF Kumulatif (USD)</th> | |
| </tr> | |
| </thead> | |
| <tbody></tbody> | |
| </table> | |
| </div> | |
| <div class="footer-note"> | |
| Interpretasi umum: | |
| jika cash flow kumulatif berubah dari negatif menjadi positif, titik tersebut | |
| adalah waktu tercapainya pay out time (POT). | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| /* | |
| RINGKASAN LOGIKA PERHITUNGAN | |
| 1. Decline exponential: | |
| q(t) = q_i * e^(-D * t) (D dalam satuan per tahun, desimal). | |
| 2. Untuk tiap tahun t: | |
| - q_start = laju awal tahun (bbl/hari) | |
| - q_end = q_start * e^(-D) | |
| - q_avg = (q_start + q_end) / 2 | |
| - jika q_avg < q_limit → produksi = 0 (sumur dianggap tidak ekonomis). | |
| Produksi tahunan: | |
| Q_year = q_avg * 365 | |
| 3. Revenue & biaya: | |
| - Revenue kotor = Q_year * harga_minyak | |
| - Revenue setelah pajak/royalty: | |
| Rev_after_tax = Revenue * (1 - taxRate) | |
| - Opex = maintDaily * 365 + serviceYearly | |
| - NetCF = Rev_after_tax - Opex | |
| 4. Cash flow kumulatif: | |
| - Tahun 0: CF_0 = -Capex | |
| - Tahun t: CF_t = NetCF_t | |
| CFK_t = CFK_(t-1) + CF_t | |
| 5. Pay Out Time: | |
| - Cari t di mana CFK berubah dari negatif ke positif. | |
| - Interpolasi linier: | |
| fraction = (0 - CFK_(t-1)) / (CFK_t - CFK_(t-1)) | |
| POT_exact = (t - 1) + fraction (tahun sejak mulai produksi). | |
| */ | |
| function hitungPOT() { | |
| const capex = parseFloat(document.getElementById('capex').value); | |
| const oilPrice = parseFloat(document.getElementById('oilPrice').value); | |
| const maintDaily = parseFloat(document.getElementById('maintDaily').value); | |
| const serviceYearly = parseFloat(document.getElementById('serviceYearly').value); | |
| const taxRate = parseFloat(document.getElementById('taxRate').value) / 100.0; | |
| const qi = parseFloat(document.getElementById('qi').value); | |
| const decline = parseFloat(document.getElementById('decline').value) / 100.0; | |
| const years = parseInt(document.getElementById('years').value, 10); | |
| const qlim = parseFloat(document.getElementById('qlim').value); | |
| const tbody = document.querySelector('#resultTable tbody'); | |
| tbody.innerHTML = ''; | |
| // Update pill info | |
| document.getElementById('pillCapex').textContent = 'Capex: ' + formatNumber(capex) + ' USD'; | |
| document.getElementById('pillPrice').textContent = 'Harga Minyak: ' + formatNumber(oilPrice) + ' USD/bbl'; | |
| document.getElementById('pillQi').textContent = 'qᵢ awal: ' + formatNumber(qi) + ' bbl/hari'; | |
| document.getElementById('pillDecline').textContent = 'Decline: ' + (decline * 100).toFixed(1) + ' %/tahun'; | |
| document.getElementById('pillYears').textContent = 'Horizon: ' + years + ' tahun'; | |
| let cfKumulatif = -capex; | |
| let potExact = null; | |
| // Baris tahun 0 | |
| let row0 = document.createElement('tr'); | |
| row0.innerHTML = ` | |
| <td class="left">0</td> | |
| <td>-</td> | |
| <td>-</td> | |
| <td>0</td> | |
| <td>0</td> | |
| <td>0</td> | |
| <td>${formatNumber(-capex)}</td> | |
| <td>${formatNumber(cfKumulatif)}</td> | |
| `; | |
| tbody.appendChild(row0); | |
| let qiYear = qi; | |
| for (let t = 1; t <= years; t++) { | |
| let qStart = qiYear; | |
| let qEnd = qiYear * Math.exp(-decline); | |
| let qAvg = (qStart + qEnd) / 2.0; | |
| if (qAvg < qlim) { | |
| qAvg = 0; | |
| qStart = 0; | |
| qEnd = 0; | |
| } | |
| let Qyear = qAvg * 365.0; | |
| let revenue = Qyear * oilPrice; | |
| let revenueAfterTax = revenue * (1 - taxRate); | |
| let opex = maintDaily * 365.0 + serviceYearly; | |
| let netCF = revenueAfterTax - opex; | |
| let prevCFK = cfKumulatif; | |
| cfKumulatif += netCF; | |
| let row = document.createElement('tr'); | |
| row.innerHTML = ` | |
| <td class="left">${t}</td> | |
| <td>${formatNumber(qStart)}</td> | |
| <td>${formatNumber(qEnd)}</td> | |
| <td>${formatNumber(Qyear)}</td> | |
| <td>${formatNumber(revenueAfterTax)}</td> | |
| <td>${formatNumber(opex)}</td> | |
| <td>${formatNumber(netCF)}</td> | |
| <td>${formatNumber(cfKumulatif)}</td> | |
| `; | |
| tbody.appendChild(row); | |
| if (potExact === null && prevCFK < 0 && cfKumulatif >= 0) { | |
| let fraction = (0 - prevCFK) / (cfKumulatif - prevCFK); | |
| potExact = (t - 1) + fraction; | |
| } | |
| qiYear = qEnd; | |
| } | |
| document.getElementById('tableWrapper').style.display = 'block'; | |
| const summaryDiv = document.getElementById('resultSummary'); | |
| if (potExact !== null) { | |
| summaryDiv.innerHTML = ` | |
| <div class="result-main success"> | |
| Pay Out Time tercapai sekitar tahun ke-${potExact.toFixed(2)} (± ${potExact.toFixed(2)} tahun sejak mulai produksi). | |
| </div> | |
| <div class="result-sub"> | |
| Cash flow kumulatif menjadi positif sebelum atau pada tahun simulasi terakhir. Nilai POT dihitung dengan interpolasi linier antar tahun. | |
| </div> | |
| `; | |
| } else { | |
| summaryDiv.innerHTML = ` | |
| <div class="result-main warning"> | |
| Pay Out Time belum tercapai dalam horizon ${years} tahun simulasi. | |
| </div> | |
| <div class="result-sub"> | |
| Cash flow kumulatif tetap negatif. Pertimbangkan optimasi biaya, peningkatan produksi, atau perpanjangan horizon simulasi untuk evaluasi lebih lanjut. | |
| </div> | |
| `; | |
| } | |
| } | |
| function formatNumber(num) { | |
| return Number(num).toLocaleString('en-US', { maximumFractionDigits: 2 }); | |
| } | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-qwensite.hf.space/logo.svg" alt="qwensite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-qwensite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >QwenSite</a> - 🧬 <a href="https://enzostvs-qwensite.hf.space?remix=alterzick/pot-sumur-v1" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> | |