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

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +195 -147
index.html CHANGED
@@ -1,159 +1,207 @@
1
- import React, { useState, useEffect } from 'react';
2
- import { AlertCircle, Axe, Box, Building, Cpu, Factory, Zap } from 'lucide-react';
 
 
3
 
4
- const Game = () => {
5
- const [selectedTool, setSelectedTool] = useState(null);
6
- const [grid, setGrid] = useState(() =>
7
- Array(8).fill().map(() => Array(8).fill({ type: null, color: 'white' }))
8
- );
9
- const [resources, setResources] = useState({ energy: 50, minerals: 50, circuits: 0 });
10
- const [tick, setTick] = useState(0);
11
- const [researchProgress, setResearchProgress] = useState({ automation: 0, speed: 0 });
12
- const [message, setMessage] = useState('');
13
 
14
- const tools = {
15
- solarPanel: {
16
- cost: { minerals: 10 },
17
- color: 'bg-yellow-200',
18
- produces: 'energy',
19
- icon: <Zap className="w-6 h-6" />
20
- },
21
- mineralExtractor: {
22
- cost: { energy: 10 },
23
- color: 'bg-gray-300',
24
- produces: 'minerals',
25
- icon: <Box className="w-6 h-6" />
26
- },
27
- circuitFactory: {
28
- cost: { energy: 15, minerals: 15 },
29
- color: 'bg-green-200',
30
- produces: 'circuits',
31
- icon: <Cpu className="w-6 h-6" />
32
- }
33
- };
 
 
 
 
 
 
34
 
35
- // Game tick for resource production
36
- useEffect(() => {
37
- const timer = setInterval(() => {
38
- setTick(t => t + 1);
39
- setResources(prev => {
40
- const newResources = { ...prev };
41
- grid.forEach(row => {
42
- row.forEach(cell => {
43
- if (cell.type && tools[cell.type]) {
44
- const produces = tools[cell.type].produces;
45
- newResources[produces] = (newResources[produces] || 0) + 1;
46
- }
47
- });
48
- });
49
- return newResources;
50
- });
51
- }, 1000);
52
-
53
- return () => clearInterval(timer);
54
- }, [grid]);
55
-
56
- const handleCellClick = (rowIndex, colIndex) => {
57
- if (!selectedTool) {
58
- setMessage('Select a building first!');
59
- return;
60
- }
61
-
62
- const tool = tools[selectedTool];
63
- const canAfford = Object.entries(tool.cost).every(
64
- ([resource, cost]) => resources[resource] >= cost
65
- );
66
 
67
- if (!canAfford) {
68
- setMessage('Not enough resources!');
69
- return;
70
- }
71
 
72
- // Deduct costs
73
- setResources(prev => {
74
- const newResources = { ...prev };
75
- Object.entries(tool.cost).forEach(([resource, cost]) => {
76
- newResources[resource] -= cost;
77
- });
78
- return newResources;
79
- });
80
 
81
- // Place building
82
- setGrid(prev => {
83
- const newGrid = [...prev];
84
- newGrid[rowIndex] = [...prev[rowIndex]];
85
- newGrid[rowIndex][colIndex] = {
86
- type: selectedTool,
87
- color: tool.color
88
- };
89
- return newGrid;
90
- });
91
 
92
- // Show success message
93
- setMessage(`Built ${selectedTool}!`);
94
- setTimeout(() => setMessage(''), 2000);
95
- };
96
 
97
- return (
98
- <div className="p-4 max-w-4xl mx-auto">
99
- {/* Resources */}
100
- <div className="grid grid-cols-3 gap-4 mb-6">
101
- <div className="p-3 bg-yellow-100 rounded-lg flex items-center gap-2">
102
- <Zap className="w-4 h-4" />
103
- <span>Energy: {resources.energy}</span>
104
- </div>
105
- <div className="p-3 bg-gray-100 rounded-lg flex items-center gap-2">
106
- <Box className="w-4 h-4" />
107
- <span>Minerals: {resources.minerals}</span>
108
- </div>
109
- <div className="p-3 bg-green-100 rounded-lg flex items-center gap-2">
110
- <Cpu className="w-4 h-4" />
111
- <span>Circuits: {resources.circuits}</span>
112
- </div>
113
- </div>
114
 
115
- {/* Tool Selection */}
116
- <div className="mb-6">
117
- <div className="flex gap-4 mb-4">
118
- {Object.entries(tools).map(([name, data]) => (
119
- <button
120
- key={name}
121
- onClick={() => setSelectedTool(name)}
122
- className={`p-4 rounded-lg flex flex-col items-center ${data.color}
123
- ${selectedTool === name ? 'ring-2 ring-blue-500' : ''}`}
124
- >
125
- {data.icon}
126
- <span className="text-sm mt-2">{name.replace(/([A-Z])/g, ' $1').trim()}</span>
127
- <span className="text-xs mt-1">
128
- Cost: {Object.entries(data.cost).map(([r, c]) => `${c} ${r}`).join(', ')}
129
- </span>
130
- </button>
131
- ))}
 
 
 
 
 
132
  </div>
133
- {message && (
134
- <div className="text-center text-sm font-medium text-blue-600 mb-2">
135
- {message}
136
- </div>
137
- )}
138
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
 
140
- {/* Game Grid */}
141
- <div className="grid grid-cols-8 gap-1 bg-gray-100 p-2 rounded-lg">
142
- {grid.map((row, rowIndex) => (
143
- row.map((cell, colIndex) => (
144
- <button
145
- key={`${rowIndex}-${colIndex}`}
146
- onClick={() => handleCellClick(rowIndex, colIndex)}
147
- className={`w-16 h-16 rounded-lg ${cell.type ? tools[cell.type].color : 'bg-white'}
148
- hover:bg-opacity-80 transition-colors flex items-center justify-center`}
149
- >
150
- {cell.type && tools[cell.type].icon}
151
- </button>
152
- ))
153
- ))}
154
- </div>
155
- </div>
156
- );
157
- };
 
 
158
 
159
- export default Game;
 
 
 
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()