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

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +167 -185
index.html CHANGED
@@ -1,207 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
  import json
3
- from dataclasses import dataclass, asdict
4
  import numpy as np
5
 
6
- @dataclass
7
- class Building:
8
- type: str
9
- color: str
10
- cost: dict
11
- produces: str
12
-
13
- class FactoryGame:
14
  def __init__(self):
15
- self.grid_size = 8
16
- self.grid = [[None for _ in range(self.grid_size)] for _ in range(self.grid_size)]
17
- self.resources = {"energy": 50, "minerals": 50, "circuits": 0}
18
-
 
 
19
  self.buildings = {
20
- "solarPanel": Building(
21
- type="solarPanel",
22
- color="#FEF08A", # yellow-200
23
- cost={"minerals": 10},
24
- produces="energy"
25
- ),
26
- "mineralExtractor": Building(
27
- type="mineralExtractor",
28
- color="#D1D5DB", # gray-300
29
- cost={"energy": 10},
30
- produces="minerals"
31
- ),
32
- "circuitFactory": Building(
33
- type="circuitFactory",
34
- color="#BBF7D0", # green-200
35
- cost={"energy": 15, "minerals": 15},
36
- produces="circuits"
37
- )
38
  }
39
 
40
- def to_json(self):
41
- return json.dumps({
42
- "grid": self.grid,
43
- "resources": self.resources,
44
- "buildings": {k: asdict(v) for k, v in self.buildings.items()}
45
- })
46
-
47
- def can_afford(self, building_type):
48
- building = self.buildings[building_type]
49
- return all(self.resources.get(resource, 0) >= cost
50
- for resource, cost in building.cost.items())
51
-
52
- def place_building(self, row, col, building_type):
53
- if not self.can_afford(building_type):
54
- return False, "Not enough resources!"
55
-
56
- if self.grid[row][col] is not None:
57
- return False, "Cell already occupied!"
58
-
59
- # Deduct costs
60
- building = self.buildings[building_type]
61
- for resource, cost in building.cost.items():
62
- self.resources[resource] -= cost
63
-
64
- # Place building
65
- self.grid[row][col] = building_type
66
- return True, "Building placed successfully!"
67
 
68
- def update_resources(self):
69
- for row in range(self.grid_size):
70
- for col in range(self.grid_size):
71
- building_type = self.grid[row][col]
 
 
72
  if building_type:
73
- building = self.buildings[building_type]
74
- self.resources[building.produces] = self.resources.get(building.produces, 0) + 1
75
-
76
- def create_game_html():
77
- return """
78
- <html>
79
- <head>
80
- <style>
81
- .game-container { max-width: 800px; margin: 0 auto; padding: 1rem; }
82
- .resources { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-bottom: 1rem; }
83
- .resource { padding: 0.75rem; border-radius: 0.5rem; }
84
- .buildings { display: flex; gap: 1rem; margin-bottom: 1rem; }
85
- .building { padding: 1rem; border-radius: 0.5rem; cursor: pointer; text-align: center; }
86
- .building.selected { outline: 2px solid #3B82F6; }
87
- .grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 0.25rem; background: #F3F4F6; padding: 0.5rem; border-radius: 0.5rem; }
88
- .cell { aspect-ratio: 1; border-radius: 0.5rem; border: none; cursor: pointer; }
89
- .message { text-align: center; color: #2563EB; font-weight: 500; margin: 0.5rem 0; }
90
- </style>
91
- </head>
92
- <body>
93
- <div class="game-container">
94
- <div class="resources" id="resources"></div>
95
- <div class="buildings" id="buildings"></div>
96
- <div class="message" id="message"></div>
97
- <div class="grid" id="grid"></div>
98
- </div>
99
- <script>
100
- let game = null;
101
- let selectedBuilding = null;
102
 
103
- function updateUI() {
104
- if (!game) return;
105
-
106
- // Update resources
107
- const resourcesDiv = document.getElementById('resources');
108
- resourcesDiv.innerHTML = Object.entries(game.resources)
109
- .map(([resource, amount]) => `
110
- <div class="resource" style="background: ${getResourceColor(resource)}">
111
- ${resource}: ${amount}
112
- </div>
113
- `).join('');
114
-
115
- // Update buildings selection
116
- const buildingsDiv = document.getElementById('buildings');
117
- buildingsDiv.innerHTML = Object.entries(game.buildings)
118
- .map(([type, data]) => `
119
- <button class="building ${type === selectedBuilding ? 'selected' : ''}"
120
- style="background: ${data.color}"
121
- onclick="selectBuilding('${type}')">
122
- ${type}<br>
123
- Cost: ${Object.entries(data.cost).map(([r, c]) => `${c} ${r}`).join(', ')}
124
- </button>
125
- `).join('');
126
 
127
- // Update grid
128
- const gridDiv = document.getElementById('grid');
129
- gridDiv.innerHTML = game.grid.map((row, i) =>
130
- row.map((cell, j) => `
131
- <button class="cell"
132
- style="background: ${cell ? game.buildings[cell].color : 'white'}"
133
- onclick="placeBuilding(${i}, ${j})">
134
- </button>
135
- `).join('')
136
- ).join('');
137
- }
138
 
139
- function getResourceColor(resource) {
140
- switch(resource) {
141
- case 'energy': return '#FEF9C3';
142
- case 'minerals': return '#F3F4F6';
143
- case 'circuits': return '#DCFCE7';
144
- default: return 'white';
145
- }
146
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
- function selectBuilding(type) {
149
- selectedBuilding = type;
150
- updateUI();
151
- }
 
 
 
 
 
 
152
 
153
- function placeBuilding(row, col) {
154
- if (!selectedBuilding) {
155
- document.getElementById('message').textContent = 'Select a building first!';
156
- return;
157
- }
158
-
159
- gradioCallback([row, col, selectedBuilding]).then(response => {
160
- game = JSON.parse(response);
161
- updateUI();
162
- });
 
 
 
 
 
 
 
163
  }
164
-
165
- function initialize(gameState) {
166
- game = JSON.parse(gameState);
167
- updateUI();
 
 
 
 
 
 
 
168
  }
169
-
170
- // Resource production tick
171
- setInterval(() => {
172
- if (game) {
173
- gradioCallback(['tick']).then(response => {
174
- game = JSON.parse(response);
175
- updateUI();
176
- });
177
- }
178
- }, 1000);
179
- </script>
180
- </body>
181
- </html>
182
  """
 
183
 
184
- def create_interface():
185
- game = FactoryGame()
186
-
187
- def handle_action(action):
188
- if isinstance(action, list) and len(action) == 3:
189
- row, col, building_type = action
190
- game.place_building(row, col, building_type)
191
- elif action == 'tick':
192
- game.update_resources()
193
- return game.to_json()
194
 
195
- with gr.Blocks() as demo:
196
- gr.HTML(create_game_html())
197
- game_state = gr.State(game.to_json())
198
- demo.load(lambda: game.to_json(), None, game_state)
199
- demo.load(None, js="initialize(arguments[0])", inputs=[game_state])
200
- callback = demo.load(handle_action, inputs=gr.State([]), outputs=game_state)
201
- demo.load(None, js=f"window.gradioCallback = {callback}")
202
 
203
- return demo
 
 
 
 
 
 
 
 
 
 
 
204
 
205
- if __name__ == "__main__":
206
- interface = create_interface()
207
- interface.launch()
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Factory Game</title>
7
+ <script type="module" crossorigin src="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.js"></script>
8
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.css" />
9
+ <style>
10
+ html, body {
11
+ margin: 0;
12
+ padding: 0;
13
+ height: 100%;
14
+ }
15
+ </style>
16
+ </head>
17
+ <body>
18
+ <gradio-lite>
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):
27
+ self.resources = {
28
+ "energy": 50,
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>
189
+ </html>