|
|
@@ -56,9 +56,9 @@ let capexMetric: MetricType = (localStorage.getItem('roi-capex-metric') as Metri
|
|
|
let opexMetric: MetricType = (localStorage.getItem('roi-opex-metric') as MetricType) || 'vwap';
|
|
|
let revenueMetric: MetricType = (localStorage.getItem('roi-revenue-metric') as MetricType) || 'vwap';
|
|
|
|
|
|
-// EXTREME DETAIL: Changed state variables from numerical ints to strings to natively support
|
|
|
-// the 'omit' and 'dynamic' categorical values alongside the raw number options.
|
|
|
-let roundTripOption: string = localStorage.getItem('roi-round-trip') || '0';
|
|
|
+// EXTREME DETAIL: Because '0' is no longer an option in the UI, we update the fallback
|
|
|
+// state to 'omit' to prevent the script from trying to load a non-existent dropdown item.
|
|
|
+let roundTripOption: string = localStorage.getItem('roi-round-trip') || 'omit';
|
|
|
let showNegativeProfit: boolean = localStorage.getItem('roi-show-negative') !== 'false';
|
|
|
let workingCapitalOption: string = localStorage.getItem('roi-working-capital-opt') || 'dynamic';
|
|
|
let targetPermitOption: string = localStorage.getItem('roi-target-permit') || '2';
|
|
|
@@ -75,8 +75,9 @@ async function render() {
|
|
|
if (!metricControlsInitialized) {
|
|
|
const controls = document.createElement('div');
|
|
|
controls.style.marginBottom = '15px';
|
|
|
- // EXTREME DETAIL: Converted Round Trip and Permit Number to distinct <select> dropdowns.
|
|
|
- // Injected `<option value="omit">Omit From Calculation</option>` at the top of all three.
|
|
|
+ // EXTREME DETAIL: We generate the massive dropdown arrays on the fly using ES6 interpolation.
|
|
|
+ // Array.from({length: x}) creates an empty array of size x, and the mapping function evaluates
|
|
|
+ // the index (i) to inject the correct incremental HTML options directly into the template string.
|
|
|
controls.innerHTML = `
|
|
|
<label style="margin-right: 15px;">CapEx Price:
|
|
|
<select id="capex-metric"><option value="vwap">VWAP</option><option value="bid">Bid</option><option value="ask">Ask</option></select>
|
|
|
@@ -94,15 +95,7 @@ async function render() {
|
|
|
Round Trip (hrs):
|
|
|
<select id="round-trip">
|
|
|
<option value="omit">Omit From Calculation</option>
|
|
|
- <option value="0">0</option>
|
|
|
- <option value="2">2</option>
|
|
|
- <option value="4">4</option>
|
|
|
- <option value="8">8</option>
|
|
|
- <option value="12">12</option>
|
|
|
- <option value="24">24</option>
|
|
|
- <option value="48">48</option>
|
|
|
- <option value="72">72</option>
|
|
|
- <option value="168">168</option>
|
|
|
+ ${Array.from({length: 25}, (_, i) => `<option value="${i + 1}">${i + 1}</option>`).join('')}
|
|
|
</select>
|
|
|
</label>
|
|
|
<label style="margin-right: 15px;">
|
|
|
@@ -110,7 +103,6 @@ async function render() {
|
|
|
<select id="working-capital">
|
|
|
<option value="omit">Omit From Calculation</option>
|
|
|
<option value="dynamic">Max for Shipment (dynamic)</option>
|
|
|
- <option value="0">0</option>
|
|
|
<option value="1">1</option>
|
|
|
<option value="2">2</option>
|
|
|
<option value="3">3</option>
|
|
|
@@ -126,16 +118,7 @@ async function render() {
|
|
|
Permit Number:
|
|
|
<select id="target-permit">
|
|
|
<option value="omit">Omit From Calculation</option>
|
|
|
- <option value="1">1</option>
|
|
|
- <option value="2">2</option>
|
|
|
- <option value="3">3</option>
|
|
|
- <option value="4">4</option>
|
|
|
- <option value="5">5</option>
|
|
|
- <option value="6">6</option>
|
|
|
- <option value="7">7</option>
|
|
|
- <option value="8">8</option>
|
|
|
- <option value="9">9</option>
|
|
|
- <option value="10">10</option>
|
|
|
+ ${Array.from({length: 49}, (_, i) => `<option value="${i + 2}">${i + 2}</option>`).join('')}
|
|
|
</select>
|
|
|
</label>
|
|
|
`;
|
|
|
@@ -267,8 +250,6 @@ async function render() {
|
|
|
|
|
|
let capex_val = p.capex[capexMetric] / bases;
|
|
|
|
|
|
- // EXTREME DETAIL: Conditionally evaluate OpEx constraints based on the new dropdown selection.
|
|
|
- // If 'omit' is selected, activeWorkingCapitalDays remains 0, suppressing the cost completely.
|
|
|
let activeWorkingCapitalDays = 0;
|
|
|
if (workingCapitalOption !== 'omit') {
|
|
|
if (workingCapitalOption === 'dynamic') {
|
|
|
@@ -281,7 +262,6 @@ async function render() {
|
|
|
capex_val += (opex_val * activeWorkingCapitalDays);
|
|
|
}
|
|
|
|
|
|
- // EXTREME DETAIL: Target permits safely bypassed if 'omit' is active.
|
|
|
let hq_capex = 0;
|
|
|
if (targetPermitOption !== 'omit') {
|
|
|
const targetPermit = parseInt(targetPermitOption, 10);
|
|
|
@@ -294,7 +274,6 @@ async function render() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // EXTREME DETAIL: Little's Law ship mathematics safely bypassed if 'omit' is active.
|
|
|
let shipsNeeded = 0;
|
|
|
let activeShipCapex = 0;
|
|
|
if (roundTripOption !== 'omit') {
|
|
|
@@ -379,9 +358,6 @@ async function render() {
|
|
|
'+ worker consumables\n\n' +
|
|
|
`(${formatSigFig(p.revenue_val)} - ${formatSigFig(p.opex_val)}) = ${formatSigFig(p.profit_per_base)}`;
|
|
|
|
|
|
- // EXTREME DETAIL: Conditionally rendered the CapEx Tooltip breakdown.
|
|
|
- // If the user selected 'Omit From Calculation' for any parameter, that specific line
|
|
|
- // completely vanishes from the hover tooltip, confirming to the user that it was removed.
|
|
|
const capexCell = tr.querySelectorAll('td')[4];
|
|
|
capexCell.dataset.tooltip = `Base Construction: ${formatSigFig(p.capex[capexMetric] / (p.area / 500))}`;
|
|
|
|