Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

83 modo de juego calculadora humana #84

Merged
merged 4 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions webapp/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Config from "./pages/Config/Config.js";
import Login from "./components/Login/Login.js";
import Register from "./components/Register/Register.js";
import Perfil from "./pages/Perfil/Perfil.js";
import CalculadoraHumana from "./pages/Calculadora/Calculadora.js";


function App() {
Expand All @@ -32,6 +33,7 @@ function App() {
<Route path="/sobre" element={<Sobre />} />
<Route path="/home/clasico" element={<Clasico />} />
<Route path="/home/bateria" element={<Bateria />} />
<Route path="/home/calculadora" element={<CalculadoraHumana />} />
<Route path="/stats" element={<Stats />} />
<Route path="/ranking" element={<Ranking />} />
<Route path="/perfil" element={<Perfil />} />
Expand Down
169 changes: 169 additions & 0 deletions webapp/src/pages/Calculadora/Calculadora.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import React, { useState, useEffect } from "react";
import Nav from "../../components/Nav/Nav.js";
import Footer from "../../components/Footer/Footer.js";
import { Link } from "react-router-dom";
import { Box, Flex, Heading, Button, Input } from "@chakra-ui/react";

const generateRandomOperation = () => {
let operators = ["+", "-", "*", "/"];
let operator = operators[Math.floor(Math.random() * operators.length)];
let num1 = Math.floor(Math.random() * 10 + 1);
let num2 = Math.floor(Math.random() * 10 + 1);
if (operator === "/") {
let numCandidates = findDivisors(num1);
let num2 = numCandidates[Math.floor(Math.random() * numCandidates.length)];
return `${num1} ${operator} ${num2}`;
}

return `${num1} ${operator} ${num2}`;
};

function findDivisors(num) {
const divisors = [];
const sqrtNum = Math.sqrt(Math.abs(num));

for (let i = 1; i <= sqrtNum; i++) {
if (num % i === 0) {
divisors.push(i);
if (i !== sqrtNum) {
divisors.push(num / i);
}
}
}

return divisors;
}

const CalculadoraHumana = () => {
const TIME = 60;

const [valSubmit, setValSubmit] = useState("");
const [puntuacion, setPuntuacion] = useState(0);
const [operation, setOperation] = useState(generateRandomOperation());
const [tiempoRestante, setTiempoRestante] = useState(TIME);
const [juegoTerminado, setJuegoTerminado] = useState(false);
const [progressPercent, setProgressPercent] = useState(100);

useEffect(() => {
if (tiempoRestante === 0) {
setJuegoTerminado(true);
}
const timer = setInterval(() => {
setTiempoRestante((prevTiempo) => (prevTiempo <= 0 ? 0 : prevTiempo - 1));
}, 1000);
return () => clearInterval(timer);
// eslint-disable-next-line
}, [tiempoRestante]);

useEffect(() => {
setProgressPercent((tiempoRestante / TIME) * 100);

const timer = setInterval(() => {
setTiempoRestante((prevTiempo) =>
prevTiempo <= 0 ? 0 : prevTiempo - 0.01
);
}, 10);

return () => clearInterval(timer);
// eslint-disable-next-line
}, [tiempoRestante]);

const handleAnswer = (valSubmit) => {
setValSubmit("");
valSubmit = Number(valSubmit);

let evalued = eval(operation);
if (valSubmit === evalued) {
setPuntuacion(puntuacion + 1);
let newOperation = generateOperation(valSubmit);
setOperation(newOperation);
} else {
setJuegoTerminado(true);
}
};

const generateOperation = (valSubmit) => {
valSubmit = Number(valSubmit);

let operators = ["+", "-", "*", "/"];
let operator = operators[Math.floor(Math.random() * operators.length)];
let num1 = Math.floor(Math.random() * 10 + 1);
let operation = `${valSubmit} ${operator} ${num1}`;
if (operator === "/") {
if(valSubmit === 0){
return `${valSubmit} ${operator} ${1}`;
}
let numCandidates = findDivisors(valSubmit);
let num2 =
numCandidates[Math.floor(Math.random() * numCandidates.length)];
return `${valSubmit} ${operator} ${num2}`;
}
return operation;
};

const handleRepetirJuego = () => {
setPuntuacion(0);
setTiempoRestante(60);
setJuegoTerminado(false);
setOperation(generateRandomOperation());
};

const handleKeyDown = (event) => {
if (event.key === "Enter") {
handleAnswer(Number(event.target.value));
}
};

return (
<>
<Nav />
<Flex justify="center" align="center" h="70vh">
<Box p={6} borderWidth="1px" borderRadius="lg" boxShadow="lg">
{juegoTerminado ? (
<Box textAlign="center">
<Heading as="h2">¡Juego terminado!</Heading>
<p p={2}>Tu puntuación: {puntuacion}</p>
<Button onClick={handleRepetirJuego} colorScheme="teal" m={2}>
Repetir Juego
</Button>
<Link to="/home" style={{ marginLeft: "10px" }}>
Volver al Menú Principal
</Link>
</Box>
) : (
<Box>
<Heading as="h2" mb={4}>
¿{operation}?
</Heading>
<Input
type="number"
title="number"
value={valSubmit}
onChange={(e) => setValSubmit(e.target.value)}
onKeyDown={handleKeyDown}
/>
<Button mt={3} onClick={() => handleAnswer(Number(valSubmit))}>
{" "}
Enviar{" "}
</Button>
<Box textAlign="center" mt={4}>
<p>Tiempo restante: {Math.floor(tiempoRestante)}</p>
<p>Puntuación: {puntuacion}</p>
<Box w="100%" bg="gray.100" borderRadius="lg" mt={4}>
<Box
bg="teal.500"
h="4px"
width={`${progressPercent}%`}
></Box>
</Box>
</Box>
</Box>
)}
</Box>
</Flex>
<Footer />
</>
);
};

export default CalculadoraHumana;
151 changes: 151 additions & 0 deletions webapp/src/pages/Calculadora/Calculadora.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import React from "react";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import CalculadoraHumana from "./Calculadora";
import { MemoryRouter } from "react-router-dom";

test("renders the game screen", () => {
render(
<MemoryRouter>
<CalculadoraHumana />
</MemoryRouter>
);

// Check if the game screen is rendered
expect(screen.getByText(/¿/i)).toBeInTheDocument();
expect(screen.getByTitle(/number/i)).toBeInTheDocument();
expect(screen.getByRole("button", { name: /enviar/i })).toBeInTheDocument();
expect(screen.getByText(/tiempo restante/i)).toBeInTheDocument();
expect(screen.getByText(/puntuación/i)).toBeInTheDocument();
});

test("handles correct answer", () => {
render(
<MemoryRouter>
<CalculadoraHumana />
</MemoryRouter>
);

// Get the initial score
const initialScore = parseInt(
screen
.getByText(/puntuación: (\d+)/i)
.textContent.split(":")[1]
.trim()
);

// Get the initial operation
var initialOperation = screen.getByText(/(\d+)\s*([-+*/])\s*(\d+)/).textContent;
initialOperation = initialOperation.substring(1, initialOperation.length - 1);

// Get the input field and submit button
const inputField = screen.getByTitle(/number/i);
const submitButton = screen.getByRole("button", { name: /enviar/i });

// Enter the correct answer and submit
fireEvent.change(inputField, { target: { value: eval(initialOperation) } });
fireEvent.click(submitButton);

// Check if the score has increased
var updatedScore = parseInt(
screen
.getByText(/puntuación: (\d+)/i)
.textContent.split(":")[1]
.trim()
);
expect(updatedScore).toBe(initialScore + 1);

// Get next operation
var nextOperation = screen.getByText(/(\d+)\s*([-+*/])\s*(\d+)/).textContent;
nextOperation = nextOperation.substring(1, nextOperation.length - 1);

// Enter the correct answer and submit
fireEvent.change(inputField, { target: { value: eval(nextOperation) } });
fireEvent.keyDown(inputField, { key: 'Enter', code: 'Enter' });

// Check if the score has increased
updatedScore = parseInt(
screen
.getByText(/puntuación: (\d+)/i)
.textContent.split(":")[1]
.trim()
);
expect(updatedScore).toBe(initialScore + 2);
});

test("handles incorrect answer", () => {
render(
<MemoryRouter>
<CalculadoraHumana />
</MemoryRouter>
);

// Get the initial score
const initialScore = parseInt(
screen
.getByText(/puntuación: (\d+)/i)
.textContent.split(":")[1]
.trim()
);

// Get the input field and submit button
const inputField = screen.getByTitle(/number/i);
const submitButton = screen.getByRole("button", { name: /enviar/i });

// Enter an incorrect answer and submit
fireEvent.change(inputField, { target: { value: 0 } });
fireEvent.click(submitButton);

// Check if the score remains the same
const updatedScore = parseInt(
screen
.getByText(/puntuación: (\d+)/i)
.textContent.split(":")[1]
.trim()
);
expect(updatedScore).toBe(initialScore);
});

test("handles game over", () => {
render(
<MemoryRouter>
<CalculadoraHumana />
</MemoryRouter>
);

// Get the initial score
const initialScore = parseInt(
screen
.getByText(/puntuación: (\d+)/i)
.textContent.split(":")[1]
.trim()
);

// Get the input field and submit button
const inputField = screen.getByTitle(/number/i);
const submitButton = screen.getByRole("button", { name: /enviar/i });

// Enter an incorrect answer and submit until game over
while (!screen.queryByText(/juego terminado/i)) {
fireEvent.change(inputField, { target: { value: 0 } });
fireEvent.click(submitButton);
}

// Check if the game over screen is rendered
expect(screen.getByText(/juego terminado/i)).toBeInTheDocument();
expect(screen.getByText(/tu puntuación: (\d+)/i)).toBeInTheDocument();

// Check if the score remains the same
const updatedScore = parseInt(
screen
.getByText(/puntuación: (\d+)/i)
.textContent.split(":")[1]
.trim()
);
expect(updatedScore).toBe(initialScore);

screen.getByText(/repetir juego/i).click();

waitFor(() => {
expect(screen.getByText(/¿/i)).toBeInTheDocument();
});
});
10 changes: 10 additions & 0 deletions webapp/src/pages/Home/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ const Home = () => {
route="/home/bateria"
/>
</Box>
<Box p={2}>
<CustomModal
title="Calculadora Humana"
text="
En el modo Calculadora Humana, tendrás que resolver operaciones matemáticas en un tiempo limitado.
¡Demuestra tus habilidades matemáticas y rapidez para superar este desafío!
"
route="/home/calculadora"
/>
</Box>
{error && (
<Box mb={4} color="red">
Hubo un error al cargar las preguntas. Por favor, inténtalo más tarde.
Expand Down