index.html 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. <!DOCTYPE html>
  2. <html lang="es">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Player Simulator</title>
  6. <!-- Bootstrap 5 -->
  7. <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
  8. <style>
  9. body {
  10. background-color: #f5f6fa;
  11. }
  12. .log {
  13. background: #1e1e1e;
  14. color: #00ff9c;
  15. height: 220px;
  16. overflow-y: auto;
  17. font-family: monospace;
  18. padding: 10px;
  19. border-radius: 5px;
  20. font-size: 0.85rem;
  21. }
  22. </style>
  23. </head>
  24. <body>
  25. <div class="container my-4">
  26. <h1 class="mb-4 text-center">🌍 - Player Simulator</h1>
  27. <div class="row g-4">
  28. <div class="col-md-12">
  29. <div class="alert alert-primary">
  30. 🧑 Jugador actual: <strong id="playerId"></strong>
  31. </div>
  32. </div>
  33. <!-- Acciones manuales -->
  34. <div class="col-md-6">
  35. <div class="card shadow-sm">
  36. <div class="card-header bg-primary text-white">
  37. 🎮 Acciones manuales
  38. </div>
  39. <div class="card-body d-flex flex-wrap gap-2">
  40. <button class="btn btn-outline-primary" onclick="sendAction('EXPLORE')">🧭 Explorar</button>
  41. <button class="btn btn-outline-success" onclick="sendAction('GATHER')">🌿 Recolectar</button>
  42. <button class="btn btn-outline-danger" onclick="sendAction('FIGHT')">⚔ Combatir</button>
  43. <button class="btn btn-outline-secondary" onclick="sendAction('REST')">💤 Descansar</button>
  44. </div>
  45. </div>
  46. </div>
  47. <!-- Acciones automáticas fijas -->
  48. <div class="col-md-6">
  49. <div class="card shadow-sm">
  50. <div class="card-header bg-warning">
  51. ⏱ Acciones automáticas
  52. </div>
  53. <div class="card-body">
  54. <div class="row g-2">
  55. <div class="col-md-6">
  56. <label class="form-label">Acción</label>
  57. <select id="autoAction" class="form-select">
  58. <option value="EXPLORE">Explorar</option>
  59. <option value="GATHER">Recolectar</option>
  60. <option value="FIGHT">Combatir</option>
  61. <option value="REST">Descansar</option>
  62. </select>
  63. </div>
  64. <div class="col-md-6">
  65. <label class="form-label">Cada (ms)</label>
  66. <input type="number" id="interval" class="form-control" value="2000">
  67. </div>
  68. </div>
  69. <div class="mt-3 d-flex gap-2">
  70. <button class="btn btn-success" onclick="startAuto()">▶ Iniciar</button>
  71. <button class="btn btn-danger" onclick="stopAuto()">⏹ Detener</button>
  72. <span class="badge bg-secondary align-self-center" id="autoStatus">Detenido</span>
  73. </div>
  74. </div>
  75. </div>
  76. </div>
  77. <!-- Simulación aleatoria -->
  78. <div class="col-md-6">
  79. <div class="card shadow-sm">
  80. <div class="card-header bg-dark text-white">
  81. 🎲 Simulación aleatoria
  82. </div>
  83. <div class="card-body">
  84. <label class="form-label">Intervalo (ms)</label>
  85. <input type="number" id="randomInterval" class="form-control mb-3" value="1000">
  86. <div class="d-flex gap-2">
  87. <button class="btn btn-success" onclick="startRandomSimulation()">🎲 Iniciar</button>
  88. <button class="btn btn-danger" onclick="stopRandomSimulation()">⏹ Detener</button>
  89. <span class="badge bg-secondary align-self-center" id="randomStatus">Detenida</span>
  90. </div>
  91. </div>
  92. </div>
  93. </div>
  94. <!-- Consultas -->
  95. <div class="col-md-6">
  96. <div class="card shadow-sm">
  97. <div class="card-header bg-info text-white">
  98. 📊 Consultas
  99. </div>
  100. <div class="card-body d-flex flex-wrap gap-2">
  101. <button class="btn btn-outline-info" onclick="fetchState()">🌍 Estado del mundo</button>
  102. <button class="btn btn-outline-info" onclick="fetchStats()">👤 Stats del jugador</button>
  103. </div>
  104. </div>
  105. </div>
  106. <!-- Log -->
  107. <div class="col-12">
  108. <div class="card shadow-sm">
  109. <div class="card-header bg-secondary text-white">
  110. 🧾 Log de eventos
  111. </div>
  112. <div class="card-body">
  113. <div class="log" id="log"></div>
  114. </div>
  115. </div>
  116. </div>
  117. </div>
  118. </div>
  119. <script>
  120. const WORLD_API = "http://localhost:8020/world";
  121. const ACTIONS = ["EXPLORE", "GATHER", "FIGHT", "REST"];
  122. let autoTimer = null;
  123. let randomTimer = null;
  124. function generatePlayerId() {
  125. return "player-" + crypto.randomUUID();
  126. }
  127. let playerId = localStorage.getItem("playerId");
  128. if (!playerId) {
  129. playerId = generatePlayerId();
  130. localStorage.setItem("playerId", playerId);
  131. }
  132. document.addEventListener("DOMContentLoaded", () => {
  133. document.getElementById("playerId").innerText = playerId;
  134. log(`Jugador registrado con id: ${playerId}`);
  135. });
  136. function log(message) {
  137. const logDiv = document.getElementById("log");
  138. let output;
  139. if (typeof message === "object") {
  140. output = JSON.stringify(message, null, 2);
  141. }
  142. else if (typeof message === "string") {
  143. try {
  144. const parsed = JSON.parse(message);
  145. output = JSON.stringify(parsed, null, 2);
  146. } catch {
  147. output = message;
  148. }
  149. }
  150. else {
  151. output = String(message);
  152. }
  153. const entry = document.createElement("pre");
  154. entry.textContent = output;
  155. logDiv.appendChild(entry);
  156. logDiv.scrollTop = logDiv.scrollHeight;
  157. }
  158. function sendAction(action) {
  159. console.log('sending action '+action);
  160. fetch(`${WORLD_API}/action`, {
  161. method: "POST",
  162. headers: {
  163. "Content-Type": "application/json"
  164. },
  165. body: JSON.stringify({
  166. playerId: playerId,
  167. action: action
  168. })
  169. })
  170. .then(res => res.json())
  171. .then(data => {
  172. log(`➡ Acción (${action}): `);
  173. log(data);
  174. })
  175. .catch(err => { log(`❌ Error (${action}): ${err}`); });
  176. }
  177. function fetchState() {
  178. fetch(`${WORLD_API}/state`)
  179. .then(res => res.json())
  180. .then(data => {
  181. log(`🌍 Estado mundo: `);
  182. log(data);
  183. })
  184. .catch(err => log("❌ Error al obtener el estado del mundo"));
  185. }
  186. function fetchStats() {
  187. fetch(`${WORLD_API}/players/${playerId}/stats`)
  188. .then(res => res.json())
  189. .then(data => {
  190. log(`📊 Stats jugador:`);
  191. log(data);
  192. })
  193. .catch(err => log("❌ Error al obtener estadísticas"));
  194. }
  195. function startAuto() {
  196. if (autoTimer) return;
  197. const action = document.getElementById("autoAction").value;
  198. const interval = parseInt(document.getElementById("interval").value);
  199. autoTimer = setInterval(() => sendAction(action), interval);
  200. document.getElementById("autoStatus").className = "badge bg-success";
  201. document.getElementById("autoStatus").innerText = "En ejecución";
  202. log(`▶ Acción automática: ${action} cada ${interval} ms`);
  203. }
  204. function stopAuto() {
  205. clearInterval(autoTimer);
  206. autoTimer = null;
  207. document.getElementById("autoStatus").className = "badge bg-secondary";
  208. document.getElementById("autoStatus").innerText = "Detenido";
  209. log(`⏹ Acción automática detenida`);
  210. }
  211. function startRandomSimulation() {
  212. if (randomTimer) return;
  213. const interval = parseInt(document.getElementById("randomInterval").value);
  214. randomTimer = setInterval(() => {
  215. const action = ACTIONS[Math.floor(Math.random() * ACTIONS.length)];
  216. sendAction(action);
  217. }, interval);
  218. document.getElementById("randomStatus").className = "badge bg-success";
  219. document.getElementById("randomStatus").innerText = "En ejecución";
  220. log(`🎲 Simulación aleatoria cada ${interval} ms`);
  221. }
  222. function stopRandomSimulation() {
  223. clearInterval(randomTimer);
  224. randomTimer = null;
  225. document.getElementById("randomStatus").className = "badge bg-secondary";
  226. document.getElementById("randomStatus").innerText = "⛔ Detenida";
  227. log(`⏹ Simulación aleatoria detenida`);
  228. }
  229. </script>
  230. </body>
  231. </html>