TeacherPuffy commited on
Commit
2b72810
·
verified ·
1 Parent(s): 5139467

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +314 -18
index.html CHANGED
@@ -1,19 +1,315 @@
1
- <!doctype html>
2
  <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
  <html>
3
+ <head>
4
+ <title>Cancer Game Theory</title>
5
+ <style>
6
+ body {
7
+ font-family: Arial, sans-serif;
8
+ margin: 20px;
9
+ background-color: #f0f8ff;
10
+ }
11
+ .header {
12
+ text-align: center;
13
+ padding: 20px;
14
+ background-color: #1e3799;
15
+ color: white;
16
+ border-radius: 10px;
17
+ margin-bottom: 20px;
18
+ }
19
+ .header h1 {
20
+ margin: 0;
21
+ font-size: 2.5em;
22
+ }
23
+ .rules {
24
+ background-color: #e8f4f8;
25
+ padding: 20px;
26
+ border-radius: 10px;
27
+ margin: 20px 0;
28
+ border: 2px solid #1e3799;
29
+ }
30
+ .rules h2 {
31
+ color: #1e3799;
32
+ margin-top: 0;
33
+ }
34
+ .rules ul {
35
+ line-height: 1.6;
36
+ }
37
+ canvas {
38
+ border: 2px solid #1e3799;
39
+ margin: 10px 0;
40
+ border-radius: 5px;
41
+ }
42
+ .controls {
43
+ margin: 10px 0;
44
+ padding: 15px;
45
+ border: 2px solid #1e3799;
46
+ border-radius: 5px;
47
+ background-color: white;
48
+ }
49
+ .param-group {
50
+ margin: 10px 0;
51
+ padding: 10px;
52
+ border-left: 4px solid #1e3799;
53
+ background-color: #f8f9fa;
54
+ }
55
+ .footer {
56
+ text-align: center;
57
+ margin-top: 20px;
58
+ padding: 10px;
59
+ color: #666;
60
+ font-size: 0.9em;
61
+ }
62
+ button {
63
+ background-color: #1e3799;
64
+ color: white;
65
+ border: none;
66
+ padding: 10px 20px;
67
+ border-radius: 5px;
68
+ cursor: pointer;
69
+ margin: 5px;
70
+ }
71
+ button:hover {
72
+ background-color: #0c2461;
73
+ }
74
+ </style>
75
+ </head>
76
+ <body>
77
+ <div class="header">
78
+ <h1>Cancer Game Theory</h1>
79
+ </div>
80
+
81
+ <div class="rules">
82
+ <h2>Simulation Rules</h2>
83
+ <ul>
84
+ <li>🦠 Cancer cells die when surrounded by 3+ cells within 40px</li>
85
+ <li>🩺 Cancer cells convert isolated healthy cells (no nearby healthy)</li>
86
+ <li>🧬 Cells reproduce based on type-specific rates</li>
87
+ <li>⚡ Cancer cells move faster than healthy cells</li>
88
+ <li>🧠 Neural networks control movement decisions</li>
89
+ <li>🎮 Adjust parameters below to influence outcomes</li>
90
+ </ul>
91
+ </div>
92
+
93
+ <div class="controls">
94
+ <h2>Simulation Parameters</h2>
95
+ <div class="param-group">
96
+ <label>Initial Healthy: <input type="number" id="initialHealthy" value="15" min="1"></label>
97
+ <label>Initial Cancer: <input type="number" id="initialCancer" value="8" min="1"></label>
98
+ <label>Mutation Rate: <input type="number" id="mutationRate" value="0.1" step="0.01" min="0"></label>
99
+ <label>Healthy Repro Rate: <input type="number" id="healthyRepro" value="2" min="0"></label>
100
+ <label>Cancer Repro Rate: <input type="number" id="cancerRepro" value="1" min="0"></label>
101
+ </div>
102
+
103
+ <button id="start">Start</button>
104
+ <button id="reset">Reset</button>
105
+ <div id="status">
106
+ Generation: <span id="genCount">1</span> |
107
+ Healthy: <span id="healthyCount">0</span> |
108
+ Cancer: <span id="cancerCount">0</span>
109
+ </div>
110
+ </div>
111
+
112
+ <canvas id="simCanvas" width="800" height="500"></canvas>
113
+
114
+ <div class="footer">
115
+ <p>Developed by Julian Herrera | For Biology LQHS</p>
116
+ <p>Simulation Purpose: Demonstrate evolutionary game theory in cancer biology</p>
117
+ </div>
118
+
119
+ <script>
120
+ const canvas = document.getElementById('simCanvas');
121
+ const ctx = canvas.getContext('2d');
122
+ let cells = [];
123
+ let animationId;
124
+ let generation = 1;
125
+ let frameCount = 0;
126
+ const cellRadius = 5;
127
+
128
+ function getNormal(mean = 0, std = 1) {
129
+ let u, v, s;
130
+ do {
131
+ u = Math.random() * 2 - 1;
132
+ v = Math.random() * 2 - 1;
133
+ s = u * u + v * v;
134
+ } while (s >= 1 || s === 0);
135
+ s = Math.sqrt(-2 * Math.log(s)/s);
136
+ return mean + std * u * s;
137
+ }
138
+
139
+ class NeuralNetwork {
140
+ constructor(parent = null) {
141
+ if(parent) {
142
+ this.weights1 = parent.weights1.map(row =>
143
+ row.map(w => w + getNormal(0, parseFloat(document.getElementById('mutationRate').value)))
144
+ );
145
+ this.weights2 = parent.weights2.map(row =>
146
+ row.map(w => w + getNormal(0, parseFloat(document.getElementById('mutationRate').value)))
147
+ );
148
+ } else {
149
+ this.weights1 = Array.from({length: 8}, () =>
150
+ Array.from({length: 4}, () => getNormal(0, 1)));
151
+ this.weights2 = Array.from({length: 4}, () =>
152
+ Array.from({length: 2}, () => getNormal(0, 1)));
153
+ }
154
+ }
155
+
156
+ activate(x) {
157
+ return x; // Linear activation for unlimited speed
158
+ }
159
+
160
+ predict(inputs) {
161
+ const hidden = this.weights1[0].map((_, i) =>
162
+ this.activate(inputs.reduce((sum, val, j) => sum + val * this.weights1[j][i], 0))
163
+ );
164
+ return this.weights2[0].map((_, i) =>
165
+ this.activate(hidden.reduce((sum, val, j) => sum + val * this.weights2[j][i], 0))
166
+ );
167
+ }
168
+ }
169
+
170
+ class Cell {
171
+ constructor(type, parent = null) {
172
+ this.type = type;
173
+ this.brain = parent ? new NeuralNetwork(parent.brain) : new NeuralNetwork();
174
+ this.x = parent ?
175
+ parent.x + (Math.random() * 40 - 20) :
176
+ Math.random() * canvas.width;
177
+ this.y = parent ?
178
+ parent.y + (Math.random() * 40 - 20) :
179
+ Math.random() * canvas.height;
180
+ }
181
+
182
+ getNearbyCells() {
183
+ return cells.filter(c => c !== this)
184
+ .map(c => ({
185
+ dx: c.x - this.x,
186
+ dy: c.y - this.y,
187
+ dist: Math.hypot(c.x - this.x, c.y - this.y),
188
+ type: c.type
189
+ })).sort((a, b) => a.dist - b.dist).slice(0, 4);
190
+ }
191
+
192
+ update() {
193
+ const nearby = this.getNearbyCells();
194
+ const inputs = [];
195
+
196
+ for(let i = 0; i < 4; i++) {
197
+ inputs.push(nearby[i] ? nearby[i].dist / 800 : 0);
198
+ inputs.push(nearby[i] ? (nearby[i].type === 'healthy' ? 0 : 1) : 0);
199
+ }
200
+
201
+ const [vx, vy] = this.brain.predict(inputs);
202
+
203
+ // Unlimited speed based on neural network output
204
+ this.x += vx;
205
+ this.y += vy;
206
+
207
+ // Cancer cells get inherent speed boost
208
+ if(this.type === 'cancer') {
209
+ this.x += vx * 0.5; // Additional 50% speed boost
210
+ this.y += vy * 0.5;
211
+ }
212
+
213
+ // Wrap around edges
214
+ this.x = (this.x + canvas.width) % canvas.width;
215
+ this.y = (this.y + canvas.height) % canvas.height;
216
+ }
217
+
218
+ draw() {
219
+ ctx.fillStyle = this.type === 'healthy' ? '#00ff00' : '#ff0000';
220
+ ctx.beginPath();
221
+ ctx.arc(this.x, this.y, cellRadius, 0, Math.PI * 2);
222
+ ctx.fill();
223
+ }
224
+ }
225
+
226
+ function checkCollisions() {
227
+ cells.forEach((cell, i) => {
228
+ if(cell.type === 'cancer') {
229
+ const neighbors = cells.filter(c => c !== cell &&
230
+ Math.hypot(c.x - cell.x, c.y - cell.y) < 40);
231
+ if(neighbors.length >= 3) {
232
+ cells.splice(i, 1);
233
+ return;
234
+ }
235
+
236
+ cells.forEach((other) => {
237
+ if(other.type === 'healthy' &&
238
+ Math.hypot(cell.x - other.x, cell.y - other.y) < cellRadius * 2) {
239
+ const healthyNeighbors = cells.filter(c =>
240
+ c !== other && c.type === 'healthy' &&
241
+ Math.hypot(c.x - other.x, c.y - other.y) < 60
242
+ );
243
+ if(healthyNeighbors.length === 0) {
244
+ other.type = 'cancer';
245
+ }
246
+ }
247
+ });
248
+ }
249
+ });
250
+ }
251
+
252
+ function reproduceCells() {
253
+ const healthyReproRate = parseInt(document.getElementById('healthyRepro').value);
254
+ const healthyCells = cells.filter(c => c.type === 'healthy');
255
+ const healthyCandidates = [...healthyCells].sort(() => Math.random() - 0.5).slice(0, healthyReproRate);
256
+ healthyCandidates.forEach(cell => cells.push(new Cell('healthy', cell)));
257
+
258
+ const cancerReproRate = parseInt(document.getElementById('cancerRepro').value);
259
+ const cancerCells = cells.filter(c => c.type === 'cancer');
260
+ const cancerCandidates = [...cancerCells].sort(() => Math.random() - 0.5).slice(0, cancerReproRate);
261
+ cancerCandidates.forEach(cell => cells.push(new Cell('cancer', cell)));
262
+ }
263
+
264
+ function updateStatus() {
265
+ document.getElementById('genCount').textContent = generation;
266
+ document.getElementById('healthyCount').textContent =
267
+ cells.filter(c => c.type === 'healthy').length;
268
+ document.getElementById('cancerCount').textContent =
269
+ cells.filter(c => c.type === 'cancer').length;
270
+ }
271
+
272
+ function animate() {
273
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
274
+
275
+ frameCount++;
276
+ if(frameCount % 60 === 0) {
277
+ generation++;
278
+ reproduceCells();
279
+ updateStatus();
280
+ }
281
+
282
+ cells.forEach(cell => cell.update());
283
+ checkCollisions();
284
+ cells.forEach(cell => cell.draw());
285
+
286
+ animationId = requestAnimationFrame(animate);
287
+ }
288
+
289
+ document.getElementById('start').addEventListener('click', () => {
290
+ if(!animationId) animate();
291
+ });
292
+
293
+ document.getElementById('reset').addEventListener('click', () => {
294
+ cancelAnimationFrame(animationId);
295
+ animationId = null;
296
+ generation = 1;
297
+ frameCount = 0;
298
+ cells = [];
299
+
300
+ const initialHealthy = parseInt(document.getElementById('initialHealthy').value);
301
+ const initialCancer = parseInt(document.getElementById('initialCancer').value);
302
+
303
+ for(let i = 0; i < initialHealthy; i++) cells.push(new Cell('healthy'));
304
+ for(let i = 0; i < initialCancer; i++) cells.push(new Cell('cancer'));
305
+
306
+ updateStatus();
307
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
308
+ cells.forEach(cell => cell.draw());
309
+ });
310
+
311
+ // Initialize simulation
312
+ document.getElementById('reset').click();
313
+ </script>
314
+ </body>
315
+ </html>