Aryanshh commited on
Commit
eaea692
·
1 Parent(s): ad1b007

feat: Add native volume controls for manufacturing and esg offset bounds

Browse files
Files changed (3) hide show
  1. dashboard/app.js +6 -1
  2. dashboard/index.html +5 -2
  3. netzero_nav/env.py +33 -16
dashboard/app.js CHANGED
@@ -159,8 +159,13 @@ window.execute = async function(type, event, shipment_id = null) {
159
  actionObj.quantity = qty;
160
  } else if (type === 'produce') {
161
  actionObj.product = document.getElementById('product-select').value;
 
 
 
162
  } else if (type === 'offset') {
163
- actionObj.offset_amount = 100.0;
 
 
164
  } else if (type === 'skip') {
165
  actionObj.action_type = 'skip';
166
  } else if (type === 'cancel') {
 
159
  actionObj.quantity = qty;
160
  } else if (type === 'produce') {
161
  actionObj.product = document.getElementById('product-select').value;
162
+ const qty = parseInt(document.getElementById('produce-qty-input').value) || 1;
163
+ actionObj.quantity = qty;
164
+ spawnFeedback(`Initiated x${qty} run`, event.clientX, event.clientY);
165
  } else if (type === 'offset') {
166
+ const amt = parseFloat(document.getElementById('offset-qty-input').value) || 10;
167
+ actionObj.offset_amount = amt;
168
+ spawnFeedback(`Purchased ${amt} offsets`, event.clientX, event.clientY);
169
  } else if (type === 'skip') {
170
  actionObj.action_type = 'skip';
171
  } else if (type === 'cancel') {
dashboard/index.html CHANGED
@@ -71,6 +71,7 @@
71
  <option value="EcoPhone">Produce EcoPhone</option>
72
  <option value="GreenTab">Produce GreenTab</option>
73
  </select>
 
74
  </div>
75
  <div class="op-actions">
76
  <button onclick="execute('produce', event)" class="btn btn-primary">Start Run</button>
@@ -84,8 +85,10 @@
84
  <div id="section-offset" class="op-section">
85
  <h4>ESG Strategy</h4>
86
  <div class="op-row">
87
- <div class="op-inputs">
88
- <span class="op-text">Carbon Offset Purchase (100 units)</span>
 
 
89
  </div>
90
  <div class="op-actions">
91
  <button onclick="execute('offset', event)" class="btn btn-primary">Buy Offset</button>
 
71
  <option value="EcoPhone">Produce EcoPhone</option>
72
  <option value="GreenTab">Produce GreenTab</option>
73
  </select>
74
+ <input type="number" id="produce-qty-input" value="1" min="1" max="100" class="qty-select">
75
  </div>
76
  <div class="op-actions">
77
  <button onclick="execute('produce', event)" class="btn btn-primary">Start Run</button>
 
85
  <div id="section-offset" class="op-section">
86
  <h4>ESG Strategy</h4>
87
  <div class="op-row">
88
+ <div class="op-inputs" style="align-items: center;">
89
+ <span class="op-text" style="font-size: 0.95rem; font-weight: 500;">Carbon Offset Purchase</span>
90
+ <input type="number" id="offset-qty-input" value="10" min="1" max="500" step="10" class="qty-select" style="width: 80px;">
91
+ <span class="op-text" style="font-size: 0.85rem; color: var(--text-muted);">units</span>
92
  </div>
93
  <div class="op-actions">
94
  <button onclick="execute('offset', event)" class="btn btn-primary">Buy Offset</button>
netzero_nav/env.py CHANGED
@@ -151,22 +151,39 @@ class AtlasEcoEnv:
151
 
152
  def _handle_production(self, action: Action, info: dict) -> float:
153
  if not action.product: return -5.0
154
- if action.product == "EcoPhone":
155
- if self.inventory.chips >= 1 and self.inventory.sensors >= 1:
156
- self.inventory.chips -= 1
157
- self.inventory.sensors -= 1
158
- for i, o in enumerate(self.pending_orders):
159
- if o.product == "EcoPhone":
160
- o.quantity -= 1
161
- if o.quantity <= 0:
162
- self.pending_orders.pop(i)
163
- self.cash_balance += o.reward
164
- return 100.0
165
- return 10.0
166
- else:
167
- info["error"] = "Missing parts"
168
- return -10.0
169
- return 0.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
  def _handle_offset(self, action: Action, info: dict) -> float:
172
  if not action.offset_amount: return -5.0
 
151
 
152
  def _handle_production(self, action: Action, info: dict) -> float:
153
  if not action.product: return -5.0
154
+ qty = action.quantity if action.quantity else 1
155
+
156
+ # Determine part requirements depending on product. To keep simulation clean, both use chips.
157
+ req_chips = qty
158
+ req_sensors = qty if action.product == "EcoPhone" else 0
159
+ req_batteries = qty if action.product == "GreenTab" else 0
160
+
161
+ if self.inventory.chips >= req_chips and self.inventory.sensors >= req_sensors and self.inventory.batteries >= req_batteries:
162
+ self.inventory.chips -= req_chips
163
+ self.inventory.sensors -= req_sensors
164
+ self.inventory.batteries -= req_batteries
165
+
166
+ total_reward = 10.0 * qty
167
+ remaining_produce = qty
168
+
169
+ orders_to_remove = []
170
+ for o in self.pending_orders:
171
+ if o.product == action.product and remaining_produce > 0:
172
+ fulfilled = min(o.quantity, remaining_produce)
173
+ o.quantity -= fulfilled
174
+ remaining_produce -= fulfilled
175
+ if o.quantity <= 0:
176
+ orders_to_remove.append(o)
177
+ total_reward += o.reward
178
+ self.cash_balance += o.reward
179
+
180
+ for o in orders_to_remove:
181
+ self.pending_orders.remove(o)
182
+
183
+ return total_reward
184
+ else:
185
+ info["error"] = "Missing parts for run"
186
+ return -10.0
187
 
188
  def _handle_offset(self, action: Action, info: dict) -> float:
189
  if not action.offset_amount: return -5.0