awacke1 commited on
Commit
9541dc1
·
verified ·
1 Parent(s): c4e4866

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +138 -121
index.html CHANGED
@@ -19,8 +19,8 @@
19
  <gradio-file name="app.py" entrypoint>
20
  import gradio as gr
21
  import json
22
- from dataclasses import dataclass
23
- import numpy as np
24
 
25
  class GameState:
26
  def __init__(self):
@@ -29,160 +29,177 @@ class GameState:
29
  "minerals": 50,
30
  "circuits": 0
31
  }
32
- self.grid = [[None for _ in range(8)] for _ in range(8)]
33
- self.buildings = {
34
- "solarPanel": {
35
- "cost": {"minerals": 10},
36
- "produces": "energy",
37
- "color": "#FEF08A"
38
- },
39
- "mineralExtractor": {
40
- "cost": {"energy": 10},
41
- "produces": "minerals",
42
- "color": "#D1D5DB"
43
- },
44
- "circuitFactory": {
45
- "cost": {"energy": 15, "minerals": 15},
46
- "produces": "circuits",
47
- "color": "#BBF7D0"
48
- }
49
- }
50
 
51
- game_state = GameState()
 
 
 
 
 
52
 
53
- def update_game(action_type, data):
54
- if action_type == "tick":
55
- # Update resources based on buildings
56
- for row in range(8):
57
- for col in range(8):
58
- building_type = game_state.grid[row][col]
59
- if building_type:
60
- produces = game_state.buildings[building_type]["produces"]
61
- game_state.resources[produces] += 1
62
 
63
- elif action_type == "build":
64
- row, col, building_type = data
65
- if game_state.grid[row][col] is not None:
66
- return {"error": "Cell already occupied"}
67
-
68
- building = game_state.buildings[building_type]
69
- # Check if can afford
70
- for resource, cost in building["cost"].items():
71
- if game_state.resources[resource] < cost:
72
- return {"error": "Not enough resources"}
 
 
 
 
 
73
 
74
- # Pay costs
75
- for resource, cost in building["cost"].items():
76
- game_state.resources[resource] -= cost
 
77
 
78
- # Place building
79
- game_state.grid[row][col] = building_type
 
 
 
 
80
 
81
- return {
82
- "resources": game_state.resources,
83
- "grid": game_state.grid,
84
- "buildings": game_state.buildings
85
- }
 
 
 
 
 
 
 
86
 
87
  def create_ui():
88
- html = """
 
 
 
 
 
 
89
  <div style="max-width: 800px; margin: 0 auto; padding: 1rem;">
90
- <div id="resources" style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-bottom: 1rem;"></div>
91
- <div id="buildings" style="display: flex; gap: 1rem; margin-bottom: 1rem;"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  <div id="message" style="text-align: center; color: #2563EB; font-weight: 500; margin: 0.5rem 0;"></div>
93
- <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>
 
 
 
 
 
 
 
 
 
94
  </div>
95
 
96
  <script>
97
- let selectedBuilding = null;
 
98
 
99
- function updateUI(gameState) {
100
- // Update resources
101
- document.getElementById('resources').innerHTML = Object.entries(gameState.resources)
102
- .map(([resource, amount]) => `
103
- <div style="padding: 0.75rem; border-radius: 0.5rem; background: ${getResourceColor(resource)}">
104
- ${resource}: ${amount}
105
- </div>
106
- `).join('');
107
 
108
- // Update buildings
109
- document.getElementById('buildings').innerHTML = Object.entries(gameState.buildings)
110
- .map(([type, data]) => `
111
- <button onclick="selectBuilding('${type}')"
112
- style="padding: 1rem; border-radius: 0.5rem; cursor: pointer; background: ${data.color};
113
- ${type === selectedBuilding ? 'outline: 2px solid #3B82F6;' : ''}">
114
- ${type}<br>
115
- Cost: ${Object.entries(data.cost).map(([r, c]) => `${c} ${r}`).join(', ')}
116
- </button>
117
- `).join('');
118
 
119
  // Update grid
120
- document.getElementById('grid').innerHTML = gameState.grid.map((row, i) =>
121
- row.map((cell, j) => `
122
- <button onclick="placeBuilding(${i}, ${j})"
123
- style="aspect-ratio: 1; border-radius: 0.5rem; border: none; cursor: pointer;
124
- background: ${cell ? gameState.buildings[cell].color : 'white'}">
125
- </button>
126
- `).join('')
127
- ).join('');
128
- }
129
-
130
- function getResourceColor(resource) {
131
- switch(resource) {
132
- case 'energy': return '#FEF9C3';
133
- case 'minerals': return '#F3F4F6';
134
- case 'circuits': return '#DCFCE7';
135
- default: return 'white';
136
- }
137
- }
138
 
139
- function selectBuilding(type) {
140
- selectedBuilding = type;
141
- syncGameState("tick", null);
142
- }
143
 
144
- function placeBuilding(row, col) {
145
- if (!selectedBuilding) {
146
  document.getElementById('message').textContent = 'Select a building first!';
147
  return;
148
- }
149
- syncGameState("build", [row, col, selectedBuilding]);
150
- }
151
-
152
- // Resource production tick
153
- setInterval(() => syncGameState("tick", null), 1000);
154
 
155
- // Initial state
156
- syncGameState("tick", null);
 
 
 
 
157
  </script>
158
  """
159
  return gr.HTML(html)
160
 
161
- def handle_action(action_type, data):
162
- return json.dumps(update_game(action_type, data))
163
-
164
  with gr.Blocks() as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  ui = create_ui()
166
- action = gr.State("tick")
167
- data = gr.State(None)
168
 
169
- demo.load(lambda: handle_action("tick", None), None, _js="(o) => { updateUI(JSON.parse(o)) }")
 
170
 
171
- demo.load(None, None, _js="""
172
- function(arg) {
173
- window.syncGameState = function(actionType, actionData) {
174
- gradioApp().querySelector("gradio-app").props.action_type = actionType;
175
- gradioApp().querySelector("gradio-app").props.action_data = actionData;
176
- updateUI(JSON.parse(handle_action(actionType, actionData)));
177
- }
178
- }
179
- """)
180
 
181
  demo.launch()
182
  </gradio-file>
183
 
184
  <gradio-requirements>
185
- # No additional requirements needed
186
  </gradio-requirements>
187
  </gradio-lite>
188
  </body>
 
19
  <gradio-file name="app.py" entrypoint>
20
  import gradio as gr
21
  import json
22
+
23
+ GRID_SIZE = 8
24
 
25
  class GameState:
26
  def __init__(self):
 
29
  "minerals": 50,
30
  "circuits": 0
31
  }
32
+ self.grid = [[None for _ in range(GRID_SIZE)] for _ in range(GRID_SIZE)]
33
+ self.message = ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
+ def to_json(self):
36
+ return json.dumps({
37
+ "resources": self.resources,
38
+ "grid": self.grid,
39
+ "message": self.message
40
+ })
41
 
42
+ def process_click(row, col, building_type, state_json):
43
+ if not state_json:
44
+ return GameState().to_json()
45
+
46
+ state = json.loads(state_json)
47
+ game = GameState()
48
+ game.resources = state["resources"]
49
+ game.grid = state["grid"]
 
50
 
51
+ # Building costs
52
+ costs = {
53
+ "solarPanel": {"minerals": 10},
54
+ "mineralExtractor": {"energy": 10},
55
+ "circuitFactory": {"energy": 15, "minerals": 15}
56
+ }
57
+
58
+ # Check if we can afford the building
59
+ if building_type in costs:
60
+ can_afford = True
61
+ for resource, cost in costs[building_type].items():
62
+ if game.resources[resource] < cost:
63
+ can_afford = False
64
+ game.message = f"Not enough {resource}!"
65
+ break
66
 
67
+ if can_afford:
68
+ # Deduct resources
69
+ for resource, cost in costs[building_type].items():
70
+ game.resources[resource] -= cost
71
 
72
+ # Place building
73
+ if game.grid[row][col] is None:
74
+ game.grid[row][col] = building_type
75
+ game.message = f"Placed {building_type}"
76
+ else:
77
+ game.message = "Space already occupied!"
78
 
79
+ # Produce resources from buildings
80
+ for r in range(GRID_SIZE):
81
+ for c in range(GRID_SIZE):
82
+ building = game.grid[r][c]
83
+ if building == "solarPanel":
84
+ game.resources["energy"] += 1
85
+ elif building == "mineralExtractor":
86
+ game.resources["minerals"] += 1
87
+ elif building == "circuitFactory":
88
+ game.resources["circuits"] += 1
89
+
90
+ return game.to_json()
91
 
92
  def create_ui():
93
+ building_colors = {
94
+ "solarPanel": "#FEF08A",
95
+ "mineralExtractor": "#D1D5DB",
96
+ "circuitFactory": "#BBF7D0"
97
+ }
98
+
99
+ html = f"""
100
  <div style="max-width: 800px; margin: 0 auto; padding: 1rem;">
101
+ <div id="resources" style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-bottom: 1rem;">
102
+ <div style="padding: 0.75rem; border-radius: 0.5rem; background: #FEF9C3;">Energy: <span id="energy">50</span></div>
103
+ <div style="padding: 0.75rem; border-radius: 0.5rem; background: #F3F4F6;">Minerals: <span id="minerals">50</span></div>
104
+ <div style="padding: 0.75rem; border-radius: 0.5rem; background: #DCFCE7;">Circuits: <span id="circuits">0</span></div>
105
+ </div>
106
+
107
+ <div style="display: flex; gap: 1rem; margin-bottom: 1rem;">
108
+ <button onclick="window.selectedBuilding='solarPanel'" style="padding: 1rem; border-radius: 0.5rem; background: #FEF08A;">
109
+ Solar Panel<br>Cost: 10 minerals
110
+ </button>
111
+ <button onclick="window.selectedBuilding='mineralExtractor'" style="padding: 1rem; border-radius: 0.5rem; background: #D1D5DB;">
112
+ Mineral Extractor<br>Cost: 10 energy
113
+ </button>
114
+ <button onclick="window.selectedBuilding='circuitFactory'" style="padding: 1rem; border-radius: 0.5rem; background: #BBF7D0;">
115
+ Circuit Factory<br>Cost: 15 energy, 15 minerals
116
+ </button>
117
+ </div>
118
+
119
  <div id="message" style="text-align: center; color: #2563EB; font-weight: 500; margin: 0.5rem 0;"></div>
120
+
121
+ <div id="grid" style="display: grid; grid-template-columns: repeat({GRID_SIZE}, 1fr); gap: 0.25rem; background: #F3F4F6; padding: 0.5rem; border-radius: 0.5rem;">
122
+ {''''.join(f'''
123
+ <button
124
+ onclick="placeBuilding({r}, {c})"
125
+ id="cell-{r}-{c}"
126
+ style="aspect-ratio: 1; border-radius: 0.5rem; border: none; cursor: pointer; background: white;">
127
+ </button>
128
+ ''' for r in range(GRID_SIZE) for c in range(GRID_SIZE))}
129
+ </div>
130
  </div>
131
 
132
  <script>
133
+ window.selectedBuilding = null;
134
+ window.gameState = null;
135
 
136
+ function updateUI(state) {
137
+ window.gameState = state;
 
 
 
 
 
 
138
 
139
+ // Update resources
140
+ document.getElementById('energy').textContent = state.resources.energy;
141
+ document.getElementById('minerals').textContent = state.resources.minerals;
142
+ document.getElementById('circuits').textContent = state.resources.circuits;
 
 
 
 
 
 
143
 
144
  // Update grid
145
+ for (let r = 0; r < {GRID_SIZE}; r++) {{
146
+ for (let c = 0; c < {GRID_SIZE}; c++) {{
147
+ const cell = document.getElementById(`cell-${{r}}-${{c}}`);
148
+ const building = state.grid[r][c];
149
+ cell.style.background = building ? buildingColors[building] : 'white';
150
+ }}
151
+ }}
152
+
153
+ // Update message
154
+ document.getElementById('message').textContent = state.message;
155
+ }}
 
 
 
 
 
 
 
156
 
157
+ const buildingColors = {json.dumps(building_colors)};
 
 
 
158
 
159
+ function placeBuilding(row, col) {{
160
+ if (!window.selectedBuilding) {{
161
  document.getElementById('message').textContent = 'Select a building first!';
162
  return;
163
+ }}
164
+ send_click(row, col, window.selectedBuilding, JSON.stringify(window.gameState));
165
+ }}
 
 
 
166
 
167
+ // Production tick
168
+ setInterval(() => {{
169
+ if (window.gameState) {{
170
+ send_click(-1, -1, null, JSON.stringify(window.gameState));
171
+ }}
172
+ }}, 1000);
173
  </script>
174
  """
175
  return gr.HTML(html)
176
 
 
 
 
177
  with gr.Blocks() as demo:
178
+ state = gr.State()
179
+ click_handler = gr.Interface(
180
+ fn=process_click,
181
+ inputs=[
182
+ gr.Number(label="Row"),
183
+ gr.Number(label="Col"),
184
+ gr.Text(label="Building"),
185
+ gr.Text(label="State")
186
+ ],
187
+ outputs=gr.Text(label="New State"),
188
+ live=True
189
+ )
190
+
191
  ui = create_ui()
 
 
192
 
193
+ def update_ui(value):
194
+ return value
195
 
196
+ click_handler.load(lambda: GameState().to_json())
197
+ demo.load(lambda: None, None, _js="() => { window.send_click = (row, col, building, state) => { "+click_handler.jsfn+"(row, col, building, state).then((v) => updateUI(JSON.parse(v))) } }")
 
 
 
 
 
 
 
198
 
199
  demo.launch()
200
  </gradio-file>
201
 
202
  <gradio-requirements>
 
203
  </gradio-requirements>
204
  </gradio-lite>
205
  </body>