awacke1 commited on
Commit
11033f0
·
verified ·
1 Parent(s): 8cdadb5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -86
app.py CHANGED
@@ -17,7 +17,7 @@ import streamlit.components.v1 as components
17
  from gradio_client import Client
18
  from streamlit_marquee import streamlit_marquee
19
  import folium
20
- from streamlit_folium import folium_static
21
  import glob
22
  import pytz
23
  from collections import defaultdict
@@ -486,7 +486,10 @@ def log_performance_metrics():
486
  # -----------------------------------------------------------
487
  # Enhanced 3D Game HTML (With dynamic insertion of username and fluid movement)
488
  # -----------------------------------------------------------
489
- # Note: Added velocity-based movement for smoother control.
 
 
 
490
  rocky_map_html = f"""
491
  <!DOCTYPE html>
492
  <html lang="en">
@@ -543,7 +546,7 @@ rocky_map_html = f"""
543
  const camera = new THREE.PerspectiveCamera(75, 800 / 600, 0.1, 1000);
544
  camera.position.set(0, 50, 50);
545
  camera.lookAt(0, 0, 0);
546
- const renderer = new THREE.WebGLRenderer({ antialias: true });
547
  renderer.setSize(800, 600);
548
  document.getElementById('gameContainer').appendChild(renderer.domElement);
549
 
@@ -555,7 +558,7 @@ rocky_map_html = f"""
555
  sunLight.castShadow = true;
556
  scene.add(sunLight);
557
  const groundGeometry = new THREE.PlaneGeometry(100, 100);
558
- const groundMaterial = new THREE.MeshStandardMaterial({ color: 0x228B22 });
559
  const ground = new THREE.Mesh(groundGeometry, groundMaterial);
560
  ground.rotation.x = -Math.PI / 2;
561
  ground.receiveShadow = true;
@@ -563,12 +566,12 @@ rocky_map_html = f"""
563
 
564
  // Fluid Movement Variables
565
  let velocity = new THREE.Vector2(0, 0);
566
- const acceleration = 50; // Increase for faster acceleration
567
- const friction = 5; // Friction factor to smooth movement
568
 
569
  // Player Setup
570
  let xPos = 0, zPos = 0;
571
- const shapeGeometries = {
572
  "sphere": new THREE.SphereGeometry(1, 16, 16),
573
  "cube": new THREE.BoxGeometry(2, 2, 2),
574
  "cylinder": new THREE.CylinderGeometry(1, 1, 2, 16),
@@ -578,173 +581,163 @@ rocky_map_html = f"""
578
  "octahedron": new THREE.OctahedronGeometry(1),
579
  "tetrahedron": new THREE.TetrahedronGeometry(1),
580
  "icosahedron": new THREE.IcosahedronGeometry(1)
581
- };
582
- const playerMaterial = new THREE.MeshPhongMaterial({ color: {next(c["color"] for c in EDGE_TTS_VOICES if c["name"] == st.session_state.username)} });
583
- const playerMesh = new THREE.Mesh(shapeGeometries["{next(c['shape'] for c in EDGE_TTS_VOICES if c['name'] == st.session_state.username)}"], playerMaterial);
584
  playerMesh.position.set(xPos, 1, zPos);
585
  playerMesh.castShadow = true;
586
  scene.add(playerMesh);
587
  let score = 0, treasureCount = 0;
588
  let lastActive = performance.now() / 1000;
589
-
590
- // Key Flags
591
  let moveLeft = false, moveRight = false, moveUp = false, moveDown = false, collect = false;
592
 
593
- document.addEventListener('keydown', (event) => {
594
- switch (event.code) {
595
  case 'ArrowLeft': case 'KeyA': moveLeft = true; break;
596
  case 'ArrowRight': case 'KeyD': moveRight = true; break;
597
  case 'ArrowUp': case 'KeyW': moveUp = true; break;
598
  case 'ArrowDown': case 'KeyS': moveDown = true; break;
599
  case 'Space': collect = true; break;
600
- }
601
  lastActive = performance.now() / 1000;
602
- });
603
- document.addEventListener('keyup', (event) => {
604
- switch (event.code) {
605
  case 'ArrowLeft': case 'KeyA': moveLeft = false; break;
606
  case 'ArrowRight': case 'KeyD': moveRight = false; break;
607
  case 'ArrowUp': case 'KeyW': moveUp = false; break;
608
  case 'ArrowDown': case 'KeyS': moveDown = false; break;
609
  case 'Space': collect = false; break;
610
- }
611
- });
612
 
613
- // Fluid Movement Update using velocity-based control
614
- function updatePlayer(delta) {
615
- // Accelerate based on key presses
616
  if (moveLeft) velocity.x -= acceleration * delta;
617
  if (moveRight) velocity.x += acceleration * delta;
618
  if (moveUp) velocity.y -= acceleration * delta;
619
  if (moveDown) velocity.y += acceleration * delta;
620
- // Apply friction
621
  velocity.x -= velocity.x * friction * delta;
622
  velocity.y -= velocity.y * friction * delta;
623
- // Update positions
624
  xPos += velocity.x * delta;
625
  zPos += velocity.y * delta;
626
- // Clamp position boundaries
627
  xPos = Math.max(-40, Math.min(40, xPos));
628
  zPos = Math.max(-40, Math.min(40, zPos));
629
  playerMesh.position.set(xPos, 1, zPos);
630
- ws.send(`${playerName}|MOVE:${xPos}:${zPos}`);
631
- // Treasure collection
632
- if (collect) {
633
- for (let i = treasures.length - 1; i >= 0; i--) {
634
- if (playerMesh.position.distanceTo(treasures[i].position) < 2) {
635
  const id = Object.keys(treasureMeshes).find(key => treasureMeshes[key] === treasures[i]);
636
  scene.remove(treasures[i]);
637
  treasures.splice(i, 1);
638
  delete treasureMeshes[id];
639
  score += 50;
640
  treasureCount += 1;
641
- ws.send(`${playerName}|SCORE:${score}`);
642
- ws.send(`${playerName}|TREASURE:${treasureCount}`);
643
- }
644
- }
645
- }
646
- // Update camera position for a dynamic view
647
  camera.position.lerp(new THREE.Vector3(xPos, 50, zPos + 50), 0.1);
648
  camera.lookAt(new THREE.Vector3(xPos, 0, zPos));
649
- document.getElementById('timeout').textContent = `Timeout: ${Math.max(0, (60 - (performance.now()/1000 - lastActive)).toFixed(0))}s`;
650
- document.getElementById('score').textContent = `Score: $${score}`;
651
- document.getElementById('treasures').textContent = `Treasures: $${treasureCount}`;
652
- }
653
 
654
- // Update functions for other players, treasures, and world objects remain similar
655
- function updatePlayers(playerData) {
656
- playerData.forEach(player => {
657
- if (!playerMeshes[player.username]) {
658
  const geometry = shapeGeometries[player.shape] || new THREE.BoxGeometry(2, 2, 2);
659
- const material = new THREE.MeshPhongMaterial({ color: player.color });
660
  const mesh = new THREE.Mesh(geometry, material);
661
  mesh.castShadow = true;
662
  scene.add(mesh);
663
  playerMeshes[player.username] = mesh;
664
- }
665
  const mesh = playerMeshes[player.username];
666
  mesh.position.set(player.x, 1, player.z);
667
- players[player.username] = { mesh: mesh, score: player.score, treasures: player.treasures };
668
- if (player.username === playerName) {
669
  xPos = player.x;
670
  zPos = player.z;
671
  score = player.score;
672
  treasureCount = player.treasures;
673
  playerMesh.position.set(xPos, 1, zPos);
674
- }
675
- });
676
- document.getElementById('players').textContent = `Players: ${Object.keys(playerMeshes).length}`;
677
  const leaderboard = playerData.sort((a, b) => b.score - a.score)
678
- .map(p => `${p.username}: $${p.score}`)
679
  .join('<br>');
680
- document.getElementById('leaderboard').innerHTML = `Leaderboard<br>${leaderboard}`;
681
- }
682
 
683
- function updateTreasures(treasureData) {
684
- treasureData.forEach(t => {
685
- if (!treasureMeshes[t.id]) {
686
  const treasure = new THREE.Mesh(
687
  new THREE.SphereGeometry(1, 8, 8),
688
- new THREE.MeshPhongMaterial({ color: 0xffff00 })
689
  );
690
  treasure.position.set(t.x, 1, t.z);
691
  treasure.castShadow = true;
692
  treasureMeshes[t.id] = treasure;
693
  treasures.push(treasure);
694
  scene.add(treasure);
695
- } else {
696
  treasureMeshes[t.id].position.set(t.x, 1, t.z);
697
- }
698
- });
699
- Object.keys(treasureMeshes).forEach(id => {
700
- if (!treasureData.some(t => t.id === id)) {
701
  scene.remove(treasureMeshes[id]);
702
  treasures = treasures.filter(t => t !== treasureMeshes[id]);
703
  delete treasureMeshes[id];
704
- }
705
- });
706
- }
707
 
708
- function updateWorldObjects(objectData) {
709
- objectData.forEach(obj => {
710
- if (!worldObjectMeshes[obj.type + obj.x + obj.z]) {
711
  const geometry = shapeGeometries[obj.shape] || new THREE.BoxGeometry(2, 2, 2);
712
- const material = new THREE.MeshPhongMaterial({ color: obj.color });
713
  const objMesh = new THREE.Mesh(geometry, material);
714
  objMesh.position.set(obj.x, 1, obj.z);
715
  objMesh.castShadow = true;
716
  worldObjectMeshes[obj.type + obj.x + obj.z] = objMesh;
717
  worldObjects.push(objMesh);
718
  scene.add(objMesh);
719
- }
720
- });
721
- }
722
 
723
- ws.onmessage = function(event) {
724
  const data = event.data;
725
- if (data.startsWith('MAP_UPDATE:')) {
726
  const playerData = JSON.parse(data.split('MAP_UPDATE:')[1]);
727
  updatePlayers(playerData);
728
- } else if (data.startsWith('CHAT_UPDATE:')) {
729
  const chatData = JSON.parse(data.split('CHAT_UPDATE:')[1]);
730
  const chatBox = document.getElementById('chatBox');
731
- chatBox.innerHTML = chatData.map(line => `<p>${line}</p>`).join('');
732
  chatBox.scrollTop = chatBox.scrollHeight;
733
- } else if (data.startsWith('GAME_STATE:')) {
734
  const gameState = JSON.parse(data.split('GAME_STATE:')[1]);
735
  updatePlayers(gameState.players);
736
  updateTreasures(gameState.treasures);
737
  updateWorldObjects(gameState.world_objects);
738
- } else if (!data.startsWith('PRAIRIE_UPDATE:')) {
739
  const [sender, message] = data.split('|');
740
  const chatBox = document.getElementById('chatBox');
741
- chatBox.innerHTML += `<p>${sender}: ${message}</p>`;
742
  chatBox.scrollTop = chatBox.scrollHeight;
743
- }
744
- };
745
 
746
  let lastTime = performance.now();
747
- function animate() {
748
  requestAnimationFrame(animate);
749
  const currentTime = performance.now();
750
  const delta = (currentTime - lastTime) / 1000;
@@ -753,7 +746,7 @@ rocky_map_html = f"""
753
  treasures.forEach(t => t.rotation.y += delta);
754
  worldObjects.forEach(o => o.rotation.y += delta * 0.5);
755
  renderer.render(scene, camera);
756
- }
757
  animate();
758
  </script>
759
  </body>
@@ -850,7 +843,8 @@ def main():
850
  fill_opacity=0.7,
851
  popup=f"{player['username']} ({player['animal']})"
852
  ).add_to(prairie_map)
853
- folium_static(prairie_map, width=600, height=400)
 
854
  animal = st.selectbox("Choose Animal 🐾", ["prairie_dog", "deer", "sheep", "groundhog"])
855
  location = st.selectbox("Move to 📍", list(PRAIRIE_LOCATIONS.keys()))
856
  if st.button("Move 🚶"):
 
17
  from gradio_client import Client
18
  from streamlit_marquee import streamlit_marquee
19
  import folium
20
+ from streamlit_folium import st_folium # Updated: use st_folium instead of folium_static
21
  import glob
22
  import pytz
23
  from collections import defaultdict
 
486
  # -----------------------------------------------------------
487
  # Enhanced 3D Game HTML (With dynamic insertion of username and fluid movement)
488
  # -----------------------------------------------------------
489
+ # Precompute the player's color and shape to simplify f-string expressions.
490
+ player_color = next(c["color"] for c in EDGE_TTS_VOICES if c["name"] == st.session_state.username)
491
+ player_shape = next(c["shape"] for c in EDGE_TTS_VOICES if c["name"] == st.session_state.username)
492
+
493
  rocky_map_html = f"""
494
  <!DOCTYPE html>
495
  <html lang="en">
 
546
  const camera = new THREE.PerspectiveCamera(75, 800 / 600, 0.1, 1000);
547
  camera.position.set(0, 50, 50);
548
  camera.lookAt(0, 0, 0);
549
+ const renderer = new THREE.WebGLRenderer({{ antialias: true }});
550
  renderer.setSize(800, 600);
551
  document.getElementById('gameContainer').appendChild(renderer.domElement);
552
 
 
558
  sunLight.castShadow = true;
559
  scene.add(sunLight);
560
  const groundGeometry = new THREE.PlaneGeometry(100, 100);
561
+ const groundMaterial = new THREE.MeshStandardMaterial({{ color: 0x228B22 }});
562
  const ground = new THREE.Mesh(groundGeometry, groundMaterial);
563
  ground.rotation.x = -Math.PI / 2;
564
  ground.receiveShadow = true;
 
566
 
567
  // Fluid Movement Variables
568
  let velocity = new THREE.Vector2(0, 0);
569
+ const acceleration = 50;
570
+ const friction = 5;
571
 
572
  // Player Setup
573
  let xPos = 0, zPos = 0;
574
+ const shapeGeometries = {{
575
  "sphere": new THREE.SphereGeometry(1, 16, 16),
576
  "cube": new THREE.BoxGeometry(2, 2, 2),
577
  "cylinder": new THREE.CylinderGeometry(1, 1, 2, 16),
 
581
  "octahedron": new THREE.OctahedronGeometry(1),
582
  "tetrahedron": new THREE.TetrahedronGeometry(1),
583
  "icosahedron": new THREE.IcosahedronGeometry(1)
584
+ }};
585
+ const playerMaterial = new THREE.MeshPhongMaterial({{ color: {player_color} }});
586
+ const playerMesh = new THREE.Mesh(shapeGeometries["{player_shape}"], playerMaterial);
587
  playerMesh.position.set(xPos, 1, zPos);
588
  playerMesh.castShadow = true;
589
  scene.add(playerMesh);
590
  let score = 0, treasureCount = 0;
591
  let lastActive = performance.now() / 1000;
 
 
592
  let moveLeft = false, moveRight = false, moveUp = false, moveDown = false, collect = false;
593
 
594
+ document.addEventListener('keydown', (event) => {{
595
+ switch (event.code) {{
596
  case 'ArrowLeft': case 'KeyA': moveLeft = true; break;
597
  case 'ArrowRight': case 'KeyD': moveRight = true; break;
598
  case 'ArrowUp': case 'KeyW': moveUp = true; break;
599
  case 'ArrowDown': case 'KeyS': moveDown = true; break;
600
  case 'Space': collect = true; break;
601
+ }}
602
  lastActive = performance.now() / 1000;
603
+ }});
604
+ document.addEventListener('keyup', (event) => {{
605
+ switch (event.code) {{
606
  case 'ArrowLeft': case 'KeyA': moveLeft = false; break;
607
  case 'ArrowRight': case 'KeyD': moveRight = false; break;
608
  case 'ArrowUp': case 'KeyW': moveUp = false; break;
609
  case 'ArrowDown': case 'KeyS': moveDown = false; break;
610
  case 'Space': collect = false; break;
611
+ }}
612
+ }});
613
 
614
+ function updatePlayer(delta) {{
 
 
615
  if (moveLeft) velocity.x -= acceleration * delta;
616
  if (moveRight) velocity.x += acceleration * delta;
617
  if (moveUp) velocity.y -= acceleration * delta;
618
  if (moveDown) velocity.y += acceleration * delta;
 
619
  velocity.x -= velocity.x * friction * delta;
620
  velocity.y -= velocity.y * friction * delta;
 
621
  xPos += velocity.x * delta;
622
  zPos += velocity.y * delta;
 
623
  xPos = Math.max(-40, Math.min(40, xPos));
624
  zPos = Math.max(-40, Math.min(40, zPos));
625
  playerMesh.position.set(xPos, 1, zPos);
626
+ ws.send(`${{playerName}}|MOVE:${{xPos}}:${{zPos}}`);
627
+ if (collect) {{
628
+ for (let i = treasures.length - 1; i >= 0; i--) {{
629
+ if (playerMesh.position.distanceTo(treasures[i].position) < 2) {{
 
630
  const id = Object.keys(treasureMeshes).find(key => treasureMeshes[key] === treasures[i]);
631
  scene.remove(treasures[i]);
632
  treasures.splice(i, 1);
633
  delete treasureMeshes[id];
634
  score += 50;
635
  treasureCount += 1;
636
+ ws.send(`${{playerName}}|SCORE:${{score}}`);
637
+ ws.send(`${{playerName}}|TREASURE:${{treasureCount}}`);
638
+ }}
639
+ }}
640
+ }}
 
641
  camera.position.lerp(new THREE.Vector3(xPos, 50, zPos + 50), 0.1);
642
  camera.lookAt(new THREE.Vector3(xPos, 0, zPos));
643
+ document.getElementById('timeout').textContent = `Timeout: ${{Math.max(0, (60 - (performance.now()/1000 - lastActive)).toFixed(0))}}s`;
644
+ document.getElementById('score').textContent = `Score: $${{score}}`;
645
+ document.getElementById('treasures').textContent = `Treasures: $${{treasureCount}}`;
646
+ }}
647
 
648
+ function updatePlayers(playerData) {{
649
+ playerData.forEach(player => {{
650
+ if (!playerMeshes[player.username]) {{
 
651
  const geometry = shapeGeometries[player.shape] || new THREE.BoxGeometry(2, 2, 2);
652
+ const material = new THREE.MeshPhongMaterial({{ color: player.color }});
653
  const mesh = new THREE.Mesh(geometry, material);
654
  mesh.castShadow = true;
655
  scene.add(mesh);
656
  playerMeshes[player.username] = mesh;
657
+ }}
658
  const mesh = playerMeshes[player.username];
659
  mesh.position.set(player.x, 1, player.z);
660
+ players[player.username] = {{ mesh: mesh, score: player.score, treasures: player.treasures }};
661
+ if (player.username === playerName) {{
662
  xPos = player.x;
663
  zPos = player.z;
664
  score = player.score;
665
  treasureCount = player.treasures;
666
  playerMesh.position.set(xPos, 1, zPos);
667
+ }}
668
+ }});
669
+ document.getElementById('players').textContent = `Players: ${{Object.keys(playerMeshes).length}}`;
670
  const leaderboard = playerData.sort((a, b) => b.score - a.score)
671
+ .map(p => `${{p.username}}: $${{p.score}}`)
672
  .join('<br>');
673
+ document.getElementById('leaderboard').innerHTML = `Leaderboard<br>${{leaderboard}}`;
674
+ }}
675
 
676
+ function updateTreasures(treasureData) {{
677
+ treasureData.forEach(t => {{
678
+ if (!treasureMeshes[t.id]) {{
679
  const treasure = new THREE.Mesh(
680
  new THREE.SphereGeometry(1, 8, 8),
681
+ new THREE.MeshPhongMaterial({{ color: 0xffff00 }})
682
  );
683
  treasure.position.set(t.x, 1, t.z);
684
  treasure.castShadow = true;
685
  treasureMeshes[t.id] = treasure;
686
  treasures.push(treasure);
687
  scene.add(treasure);
688
+ }} else {{
689
  treasureMeshes[t.id].position.set(t.x, 1, t.z);
690
+ }}
691
+ }});
692
+ Object.keys(treasureMeshes).forEach(id => {{
693
+ if (!treasureData.some(t => t.id === id)) {{
694
  scene.remove(treasureMeshes[id]);
695
  treasures = treasures.filter(t => t !== treasureMeshes[id]);
696
  delete treasureMeshes[id];
697
+ }}
698
+ }});
699
+ }}
700
 
701
+ function updateWorldObjects(objectData) {{
702
+ objectData.forEach(obj => {{
703
+ if (!worldObjectMeshes[obj.type + obj.x + obj.z]) {{
704
  const geometry = shapeGeometries[obj.shape] || new THREE.BoxGeometry(2, 2, 2);
705
+ const material = new THREE.MeshPhongMaterial({{ color: obj.color }});
706
  const objMesh = new THREE.Mesh(geometry, material);
707
  objMesh.position.set(obj.x, 1, obj.z);
708
  objMesh.castShadow = true;
709
  worldObjectMeshes[obj.type + obj.x + obj.z] = objMesh;
710
  worldObjects.push(objMesh);
711
  scene.add(objMesh);
712
+ }}
713
+ }});
714
+ }}
715
 
716
+ ws.onmessage = function(event) {{
717
  const data = event.data;
718
+ if (data.startsWith('MAP_UPDATE:')) {{
719
  const playerData = JSON.parse(data.split('MAP_UPDATE:')[1]);
720
  updatePlayers(playerData);
721
+ }} else if (data.startsWith('CHAT_UPDATE:')) {{
722
  const chatData = JSON.parse(data.split('CHAT_UPDATE:')[1]);
723
  const chatBox = document.getElementById('chatBox');
724
+ chatBox.innerHTML = chatData.map(line => `<p>${{line}}</p>`).join('');
725
  chatBox.scrollTop = chatBox.scrollHeight;
726
+ }} else if (data.startsWith('GAME_STATE:')) {{
727
  const gameState = JSON.parse(data.split('GAME_STATE:')[1]);
728
  updatePlayers(gameState.players);
729
  updateTreasures(gameState.treasures);
730
  updateWorldObjects(gameState.world_objects);
731
+ }} else if (!data.startsWith('PRAIRIE_UPDATE:')) {{
732
  const [sender, message] = data.split('|');
733
  const chatBox = document.getElementById('chatBox');
734
+ chatBox.innerHTML += `<p>${{sender}}: ${{message}}</p>`;
735
  chatBox.scrollTop = chatBox.scrollHeight;
736
+ }}
737
+ }};
738
 
739
  let lastTime = performance.now();
740
+ function animate() {{
741
  requestAnimationFrame(animate);
742
  const currentTime = performance.now();
743
  const delta = (currentTime - lastTime) / 1000;
 
746
  treasures.forEach(t => t.rotation.y += delta);
747
  worldObjects.forEach(o => o.rotation.y += delta * 0.5);
748
  renderer.render(scene, camera);
749
+ }}
750
  animate();
751
  </script>
752
  </body>
 
843
  fill_opacity=0.7,
844
  popup=f"{player['username']} ({player['animal']})"
845
  ).add_to(prairie_map)
846
+ # Updated to use st_folium instead of folium_static
847
+ st_folium(prairie_map, width=600, height=400)
848
  animal = st.selectbox("Choose Animal 🐾", ["prairie_dog", "deer", "sheep", "groundhog"])
849
  location = st.selectbox("Move to 📍", list(PRAIRIE_LOCATIONS.keys()))
850
  if st.button("Move 🚶"):