SimFactory2 / index.html
awacke1's picture
Update index.html
c4e4866 verified
raw
history blame
6.81 kB
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Factory Game</title>
<script type="module" crossorigin src="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.css" />
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
}
</style>
</head>
<body>
<gradio-lite>
<gradio-file name="app.py" entrypoint>
import gradio as gr
import json
from dataclasses import dataclass
import numpy as np
class GameState:
def __init__(self):
self.resources = {
"energy": 50,
"minerals": 50,
"circuits": 0
}
self.grid = [[None for _ in range(8)] for _ in range(8)]
self.buildings = {
"solarPanel": {
"cost": {"minerals": 10},
"produces": "energy",
"color": "#FEF08A"
},
"mineralExtractor": {
"cost": {"energy": 10},
"produces": "minerals",
"color": "#D1D5DB"
},
"circuitFactory": {
"cost": {"energy": 15, "minerals": 15},
"produces": "circuits",
"color": "#BBF7D0"
}
}
game_state = GameState()
def update_game(action_type, data):
if action_type == "tick":
# Update resources based on buildings
for row in range(8):
for col in range(8):
building_type = game_state.grid[row][col]
if building_type:
produces = game_state.buildings[building_type]["produces"]
game_state.resources[produces] += 1
elif action_type == "build":
row, col, building_type = data
if game_state.grid[row][col] is not None:
return {"error": "Cell already occupied"}
building = game_state.buildings[building_type]
# Check if can afford
for resource, cost in building["cost"].items():
if game_state.resources[resource] < cost:
return {"error": "Not enough resources"}
# Pay costs
for resource, cost in building["cost"].items():
game_state.resources[resource] -= cost
# Place building
game_state.grid[row][col] = building_type
return {
"resources": game_state.resources,
"grid": game_state.grid,
"buildings": game_state.buildings
}
def create_ui():
html = """
<div style="max-width: 800px; margin: 0 auto; padding: 1rem;">
<div id="resources" style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-bottom: 1rem;"></div>
<div id="buildings" style="display: flex; gap: 1rem; margin-bottom: 1rem;"></div>
<div id="message" style="text-align: center; color: #2563EB; font-weight: 500; margin: 0.5rem 0;"></div>
<div id="grid" style="display: grid; grid-template-columns: repeat(8, 1fr); gap: 0.25rem; background: #F3F4F6; padding: 0.5rem; border-radius: 0.5rem;"></div>
</div>
<script>
let selectedBuilding = null;
function updateUI(gameState) {
// Update resources
document.getElementById('resources').innerHTML = Object.entries(gameState.resources)
.map(([resource, amount]) => `
<div style="padding: 0.75rem; border-radius: 0.5rem; background: ${getResourceColor(resource)}">
${resource}: ${amount}
</div>
`).join('');
// Update buildings
document.getElementById('buildings').innerHTML = Object.entries(gameState.buildings)
.map(([type, data]) => `
<button onclick="selectBuilding('${type}')"
style="padding: 1rem; border-radius: 0.5rem; cursor: pointer; background: ${data.color};
${type === selectedBuilding ? 'outline: 2px solid #3B82F6;' : ''}">
${type}<br>
Cost: ${Object.entries(data.cost).map(([r, c]) => `${c} ${r}`).join(', ')}
</button>
`).join('');
// Update grid
document.getElementById('grid').innerHTML = gameState.grid.map((row, i) =>
row.map((cell, j) => `
<button onclick="placeBuilding(${i}, ${j})"
style="aspect-ratio: 1; border-radius: 0.5rem; border: none; cursor: pointer;
background: ${cell ? gameState.buildings[cell].color : 'white'}">
</button>
`).join('')
).join('');
}
function getResourceColor(resource) {
switch(resource) {
case 'energy': return '#FEF9C3';
case 'minerals': return '#F3F4F6';
case 'circuits': return '#DCFCE7';
default: return 'white';
}
}
function selectBuilding(type) {
selectedBuilding = type;
syncGameState("tick", null);
}
function placeBuilding(row, col) {
if (!selectedBuilding) {
document.getElementById('message').textContent = 'Select a building first!';
return;
}
syncGameState("build", [row, col, selectedBuilding]);
}
// Resource production tick
setInterval(() => syncGameState("tick", null), 1000);
// Initial state
syncGameState("tick", null);
</script>
"""
return gr.HTML(html)
def handle_action(action_type, data):
return json.dumps(update_game(action_type, data))
with gr.Blocks() as demo:
ui = create_ui()
action = gr.State("tick")
data = gr.State(None)
demo.load(lambda: handle_action("tick", None), None, _js="(o) => { updateUI(JSON.parse(o)) }")
demo.load(None, None, _js="""
function(arg) {
window.syncGameState = function(actionType, actionData) {
gradioApp().querySelector("gradio-app").props.action_type = actionType;
gradioApp().querySelector("gradio-app").props.action_data = actionData;
updateUI(JSON.parse(handle_action(actionType, actionData)));
}
}
""")
demo.launch()
</gradio-file>
<gradio-requirements>
# No additional requirements needed
</gradio-requirements>
</gradio-lite>
</body>
</html>