diff --git a/src/practicau2_1.py b/src/practicau2_1.py new file mode 100644 index 0000000..6d94fe3 --- /dev/null +++ b/src/practicau2_1.py @@ -0,0 +1,209 @@ + +COMANDOS = ["compra", "venta", "saldo", "reset", "deshacer", "fin"] +MENSAJE_ERROR = "*ERROR* Entrada inválida" + + +def comprobar_importe(valor: str) -> bool: + """ + Verifica si el importe proporcionado es un número válido. + + Args: + valor (str): Cadena que representa el importe a verificar. + + Returns: + bool: True si el valor es un número válido (positivo, negativo o con punto decimal), False en caso contrario. + """ + if valor.startswith("-"): + valor = valor[1:] + + if valor.count(".") > 1: + return False + + valor = valor.replace(".", "") + return valor.isdigit() + + +def comprobar_comando(comando: str) -> bool: + """ + Verifica si el comando está dentro de la lista de comandos válidos. + + Args: + comando (str): Cadena que representa el comando ingresado por el usuario. + + Returns: + bool: True si el comando está en la lista de comandos válidos, False en caso contrario. + """ + return comando in COMANDOS + + +def mostrar_mensaje_error(): + """ + Muestra el mensaje de error por entrada inválida. + """ + print(MENSAJE_ERROR) + + +def procesar_compra(saldo: float, importe: float) -> float: + """ + Procesa una operación de compra y actualiza el saldo restando el importe. + + Args: + saldo (float): El saldo actual. + importe (float): El importe a restar por la compra. + + Returns: + float: El saldo actualizado después de realizar la compra. + """ + return saldo - importe + + +def procesar_venta(saldo: float, importe: float) -> float: + """ + Procesa una operación de venta y actualiza el saldo sumando el importe. + + Args: + saldo (float): El saldo actual. + importe (float): El importe a sumar por la venta. + + Returns: + float: El saldo actualizado después de realizar la venta. + """ + return saldo + importe + + +def mostrar_saldo(saldo: float, cont_compras: int, cont_ventas: int): + """ + Muestra el saldo actual junto con el número de compras y ventas. + + Args: + saldo (float): El saldo actual. + cont_compras (int): Número total de compras realizadas. + cont_ventas (int): Número total de ventas realizadas. + """ + print(f"Saldo actual = {saldo:.2f} ({cont_compras} compras y {cont_ventas} ventas)") + + +def resetear_saldo(saldo: float, cont_compras: int, cont_ventas: int) -> tuple[float, int, int]: + """ + Resetea el saldo y las operaciones realizadas, mostrando los valores anteriores. + + Args: + saldo (float): El saldo actual. + cont_compras (int): Número total de compras realizadas. + cont_ventas (int): Número total de ventas realizadas. + + Returns: + tuple[float, int, int]: El nuevo saldo (0), número de compras (0) y número de ventas (0) después del reinicio. + """ + print(f"Saldo anterior = {saldo:.2f} ({cont_compras} compras y {cont_ventas} ventas)") + return 0, 0, 0 + + +def recuperar_comando_e_importe(linea: str) -> tuple[str, str]: + """ + Recupera el comando y, si lo hay, el importe de una línea de entrada. + + Args: + linea (str): Línea de texto introducida por el usuario. + + Returns: + tuple: El comando (str o None) y el importe (str o None). + + Ejemplos: + >>> recuperar_comando_e_importe("compra 100") + ('compra', '100') + + >>> recuperar_comando_e_importe("saldo") + ('saldo', None) + + >>> recuperar_comando_e_importe("") + (None, None) + """ + lista_palabras = linea.split() + + if len(lista_palabras) == 1: + return lista_palabras[0], None + elif len(lista_palabras) == 2: + return lista_palabras[0], lista_palabras[1] + else: + return None, None + + +def main(): + """ + Función principal que gestiona el flujo del programa. El programa permite al usuario realizar + operaciones de compra y venta, consultar el saldo, restablecer las operaciones y finalizar. + + Funciona a través de un bucle que sigue las instrucciones del usuario hasta que el comando "fin" es ingresado. + El saldo y las transacciones se actualizan según los comandos introducidos. + + Comandos disponibles: + - compra [importe]: Resta el importe del saldo. + - venta [importe]: Suma el importe al saldo. + - saldo: Muestra el saldo actual junto con el número de compras y ventas. + - reset: Restablece el saldo y las transacciones a cero. + - fin: Termina el programa. + + Ejemplos: + > compra 100 + > venta 50 + > saldo + Saldo actual = -50.00 (1 compras y 1 ventas) + > venta 200 + > reset + Saldo anterior = 150.00 (1 compras y 2 ventas) + > + Saldo actual = 0.00 (0 compras y 0 ventas) + > fin + """ + encuentra_fin = False + cont_compras = 0 + cont_ventas = 0 + saldo = 0 + + # Guardar los valores previos para deshacer + ultimo_saldo = 0 + ultimo_cont_compras = 0 + ultimo_cont_ventas = 0 + + while not encuentra_fin: + linea = input("> ").strip().lower() + comando, importe = recuperar_comando_e_importe(linea) + + if comando is None or not comprobar_comando(comando): + mostrar_mensaje_error() + elif comando in ("saldo", "reset", "fin") and importe is not None: + mostrar_mensaje_error() + elif comando == "saldo": + mostrar_saldo(saldo, cont_compras, cont_ventas) + elif comando == "reset": + saldo, cont_compras, cont_ventas = resetear_saldo(saldo, cont_compras, cont_ventas) + elif comando == "fin": + encuentra_fin = True + elif comando == "deshacer": + # Deshacer la última operación + saldo = ultimo_saldo + cont_compras = ultimo_cont_compras + cont_ventas = ultimo_cont_ventas + print("Última operación deshecha.") + elif importe is None or not comprobar_importe(importe): + mostrar_mensaje_error() + else: + importe = float(importe) + + # Guardar el estado previo para deshacer + ultimo_saldo = saldo + ultimo_cont_compras = cont_compras + ultimo_cont_ventas = cont_ventas + + if comando == "compra": + saldo = procesar_compra(saldo, importe) + cont_compras += 1 + elif comando == "venta": + saldo = procesar_venta(saldo, importe) + cont_ventas += 1 + + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/src/practicau2_1_alumnos.py b/src/practicau2_1_alumnos.py new file mode 100644 index 0000000..665171e --- /dev/null +++ b/src/practicau2_1_alumnos.py @@ -0,0 +1,181 @@ + +COMANDOS = ["compra", "venta", "saldo", "reset", "fin"] +MENSAJE_ERROR = "*ERROR* Entrada inválida" + + +def comprobar_importe(valor: str) -> bool: + """ + Verifica si el importe proporcionado es un número válido. + + Args: + valor (str): Cadena que representa el importe a verificar. + + Returns: + bool: True si el valor es un número válido (positivo, negativo o con punto decimal), False en caso contrario. + """ + + +def comprobar_comando(comando: str) -> bool: + """ + Verifica si el comando está dentro de la lista de comandos válidos. + + Args: + comando (str): Cadena que representa el comando ingresado por el usuario. + + Returns: + bool: True si el comando está en la lista de comandos válidos, False en caso contrario. + """ + + +def mostrar_mensaje_error(): + """ + Muestra el mensaje de error por entrada inválida. + """ + + +def procesar_compra(saldo: float, importe: float) -> float: + """ + Procesa una operación de compra y actualiza el saldo restando el importe. + + Args: + saldo (float): El saldo actual. + importe (float): El importe a restar por la compra. + + Returns: + float: El saldo actualizado después de realizar la compra. + """ + + +def procesar_venta(saldo: float, importe: float) -> float: + """ + Procesa una operación de venta y actualiza el saldo sumando el importe. + + Args: + saldo (float): El saldo actual. + importe (float): El importe a sumar por la venta. + + Returns: + float: El saldo actualizado después de realizar la venta. + """ + + +def mostrar_saldo(saldo: float, cont_compras: int, cont_ventas: int): + """ + Muestra el saldo actual junto con el número de compras y ventas. + + Args: + saldo (float): El saldo actual. + cont_compras (int): Número total de compras realizadas. + cont_ventas (int): Número total de ventas realizadas. + """ + + +def resetear_saldo(saldo: float, cont_compras: int, cont_ventas: int) -> tuple[float, int, int]: + """ + Resetea el saldo y las operaciones realizadas, mostrando antes el saldo anterior. + + Args: + saldo (float): El saldo actual. + cont_compras (int): Número total de compras realizadas. + cont_ventas (int): Número total de ventas realizadas. + + Returns: + tuple[float, int, int]: El nuevo saldo (0), número de compras (0) y número de ventas (0) después del reinicio. + """ + + +def recuperar_comando_e_importe(linea: str) -> tuple[str, str]: + """ + Recupera el comando y, si lo hay, el importe de una línea de entrada. + + Args: + linea (str): Línea de texto introducida por el usuario. + + Returns: + tuple: El comando (str o None) y el importe (str o None). + + Ejemplos: + >>> recuperar_comando_e_importe("compra 100") + ('compra', '100') + + >>> recuperar_comando_e_importe("saldo") + ('saldo', None) + + >>> recuperar_comando_e_importe("") + (None, None) + """ + lista_palabras = linea.split() + + if len(lista_palabras) == 1: + return lista_palabras[0], None + elif len(lista_palabras) == 2: + return lista_palabras[0], lista_palabras[1] + else: + return None, None + + +def main(): + """ + Función principal que gestiona el flujo del programa. El programa permite al usuario realizar + operaciones de compra y venta, consultar el saldo, restablecer las operaciones y finalizar. + + Funciona a través de un bucle que sigue las instrucciones del usuario hasta que el comando "fin" es ingresado. + El saldo y las transacciones se actualizan según los comandos introducidos. + + Comandos disponibles: + - compra [importe]: Resta el importe del saldo. + - venta [importe]: Suma el importe al saldo. + - saldo: Muestra el saldo actual junto con el número de compras y ventas. + - reset: Restablece el saldo y las transacciones a cero. + - fin: Termina el programa. + + Ejemplos: + > compra 100 + > venta 50 + > venta + *ERROR* Entrada inválida + > venta cincuenta euros + *ERROR* Entrada inválida + > compra 50€ + *ERROR* Entrada inválida + > saldo 666 + *ERROR* Entrada inválida + > saldo + Saldo actual = -50.00 (1 compras y 1 ventas) + > venta 200 + > reset + Saldo anterior = 150.00 (1 compras y 2 ventas) + > saldo + Saldo actual = 0.00 (0 compras y 0 ventas) + > fin + """ + cont_compras = 0 + cont_ventas = 0 + saldo = 0 + + while not encuentra_fin: + + comando, importe = recuperar_comando_e_importe(linea) + + if comando is None or not comprobar_comando(comando): + mostrar_mensaje_error() + elif comando in ("saldo", "reset", "fin") and importe is not None: + + elif comando == "saldo": + + elif comando == "reset": + + elif comando == "fin": + + elif importe is None or not comprobar_importe(importe): + + else: + + if comando == "compra": + + elif comando == "venta": + + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/tests/test_practicau2_1.py b/tests/test_practicau2_1.py new file mode 100644 index 0000000..84594da --- /dev/null +++ b/tests/test_practicau2_1.py @@ -0,0 +1,138 @@ +import pytest + +from src.practicau2_1 import ( + comprobar_importe, comprobar_comando, procesar_compra, procesar_venta, + mostrar_saldo, resetear_saldo, recuperar_comando_e_importe, mostrar_mensaje_error +) + +@pytest.mark.parametrize( + "valor, expected", + [ + ("100", True), + ("-50", True), + ("10.50", True), + ("10.5.0", False), + ("abc", False), + ("", False) + ] +) +def test_comprobar_importe(valor, expected): + """ + Prueba para la función comprobar_importe. + """ + assert comprobar_importe(valor) == expected + + +@pytest.mark.parametrize( + "comando, expected", + [ + ("compra", True), + ("venta", True), + ("saldo", True), + ("reset", True), + ("fin", True), + ("otro_comando", False) + ] +) +def test_comprobar_comando(comando, expected): + """ + Prueba para la función comprobar_comando. + """ + assert comprobar_comando(comando) == expected + + +@pytest.mark.parametrize( + "saldo, importe, expected", + [ + (100.0, 50.0, 50.0), + (200.0, 100.0, 100.0), + (0.0, 50.0, -50.0), + ] +) +def test_procesar_compra(saldo, importe, expected): + """ + Prueba para la función procesar_compra. + """ + assert procesar_compra(saldo, importe) == expected + + +@pytest.mark.parametrize( + "saldo, importe, expected", + [ + (100.0, 50.0, 150.0), + (200.0, 100.0, 300.0), + (0.0, 50.0, 50.0), + ] +) +def test_procesar_venta(saldo, importe, expected): + """ + Prueba para la función procesar_venta. + """ + assert procesar_venta(saldo, importe) == expected + + +@pytest.mark.parametrize( + "saldo, cont_compras, cont_ventas, expected_output", + [ + (100.0, 1, 2, "Saldo actual = 100.00 (1 compras y 2 ventas)\n"), + (-50.0, 0, 1, "Saldo actual = -50.00 (0 compras y 1 ventas)\n"), + (0.0, 3, 4, "Saldo actual = 0.00 (3 compras y 4 ventas)\n"), + ] +) +def test_mostrar_saldo(capsys, saldo, cont_compras, cont_ventas, expected_output): + """ + Prueba para la función mostrar_saldo. + """ + mostrar_saldo(saldo, cont_compras, cont_ventas) + captured = capsys.readouterr() + assert captured.out == expected_output + + +@pytest.mark.parametrize( + "saldo, cont_compras, cont_ventas, expected_saldo, expected_compras, expected_ventas, expected_output", + [ + (100.0, 1, 2, 0.0, 0, 0, "Saldo anterior = 100.00 (1 compras y 2 ventas)\n"), + (200.0, 3, 4, 0.0, 0, 0, "Saldo anterior = 200.00 (3 compras y 4 ventas)\n"), + ] +) +def test_resetear_saldo(capsys, saldo, cont_compras, cont_ventas, expected_saldo, expected_compras, expected_ventas, expected_output): + """ + Prueba para la función resetear_saldo. + """ + result_saldo, result_compras, result_ventas = resetear_saldo(saldo, cont_compras, cont_ventas) + captured = capsys.readouterr() + + assert captured.out == expected_output + assert result_saldo == expected_saldo + assert result_compras == expected_compras + assert result_ventas == expected_ventas + + +@pytest.mark.parametrize( + "linea, expected_comando, expected_importe", + [ + ("compra 100", "compra", "100"), + ("venta 50.5", "venta", "50.5"), + ("saldo", "saldo", None), + ("reset", "reset", None), + ("", None, None), + ("compra", "compra", None) # Cambiado None por 'compra' + ] +) +def test_recuperar_comando_e_importe(linea, expected_comando, expected_importe): + """ + Prueba para la función recuperar_comando_e_importe. + """ + comando, importe = recuperar_comando_e_importe(linea) + assert comando == expected_comando + assert importe == expected_importe + + +def test_mostrar_mensaje_error(capsys): + """ + Prueba para la función mostrar_mensaje_error. + Verifica si el mensaje de error se muestra correctamente. + """ + mostrar_mensaje_error() + captured = capsys.readouterr() + assert captured.out == "*ERROR* Entrada inválida\n"