Closed iqacevedo closed 5 years ago
cual seria la forma correcta de utilizar el try y except? señalando los posible errores?
@jalliende la forma correcta de usar try y except es señalando exactamente cual es el error que estás intentando capturar.
Éxito!
incluso está mal para hacer frontend.show()?
@isihirmas el problema en este caso es que si hacen frontend.show() en el Thread que escucha respuestas del servidor en el cliente, no funcionaría, por lo cual deben usar señales.
Éxito!
ok gracias!
Feedback Avance T03 :star: :bug:
A continuación se listan consejos y tips propuestos en base a lo entregado como avance para la T03. No duden en comentar dudas o postear issues con dudas relacionadas a esta. Pueden etiquetar issues al usar el signo gato (#) y el número de la issue.
Recuerden que el objetivo del avance de la tarea que se les pide no solo significa tener 2 décimas extras por hacer una entrega, sino que es una ayuda y oportunidad para que puedan pensar y modelar el problema planteado con anticipación. Así les resultará más fácil comenzar con el código de su programa.
Varios copiaron textualmente la ayudantía del 2018-2. Se recomienda fuertemente leer y entender el código antes de copiar porque esta presenta modelación circular. Se otorgó de todos modos las décimas, pero se debe arreglar eso para la entrega final.
Recuerden que los avances también son entregas formales del curso, por lo que no utilizar lenguaje vulgar (groserías) o inapropiado para el curso.
Recuerden seguir formato simple de entrega. Cada archivo a ejecutar se debe llamar
main.py
. Procuren además separar al cliente y al servidor como se indica en el enunciado, cada uno en una carpeta distinta. En cada una pueden haber más módulos además demain.py
, la idea es que dentro de cada una creen sus módulos y clases propias. En sí, la función de una claseServidor
y una claseCliente
es netamente mandar y recibir bytes. Pero por ejemploServidor
podría tener una instancia de una claseControladorChat
, que se encargue de verificar si a un jugador lo han expulsado. O, podría contener una instancia de una claseJuego
que se encargue de llevar el conteo del puntaje o verificar si una jugada es válida, de este modo tienen sus archivos de manera más ordenadas y se les facilita no superar el máximo de líneas permitido. Del mismo modo enCliente
tener una o más clases para la interfaz, etc...Llegaron algunos avances con el chat implementado por consola, sin interfaz gráfica asociada. Mucho ojo, que para la revisión de la tarea nuevamente NO se evaluará nada que no se pueda comprobar mediante una interfaz gráfica, sin importar si la consola printea alguna notificación de una funcionalidad o no. Finalmente, implementar networking a una interfaz gráfica no es tan trivial como parece, por lo que les recomiendo trabajar en ambas partes al mismo tiempo y no terminar una primero y luego incorporar la otra.
Algunas tareas ya tenían un ligero avance con la interfaz del juego, se recomienda que no se compliquen usando objetos rebuscados para el diseño del juego. Esta tarea no tiene como core la interfaz gráfica y está pensada para realizar con los contenidos del curso. Ejemplos más sencillos serían dejar las líneas precargadas como qlabel y cuando se hace click en ellas las “dibuja” (hay una issue al respecto) o hacer
QLabels
clickeables (conmousePressEvent
) que representan cada punto y así detectar queQLabel
son presionados y si son vecinos, poner una línea entre ellos.Recuerden utilizar señales siempre que quieran mostrar una nueva ventana, si intentan mostrar una señal directamente desde el thread que escucha al servidor, no va a funcionar.
La implementación de señales para comunicación entre el back-end y el front-end es necesaria para ambos lados. Esto quiere decir que, si el back-end tiene al front-end como atributo y llama a sus métodos a través de
self.front_end.realizar_accion()
, está mal porque no hace uso de señales. En este caso, se debe implementar una señal, seasenal_realizar_accion
conectada al método del front-end para llamar a ese método medianteemit
.Tengan cuidado con la referencia circular, si bien se aceptará referencia cruzada para simplificar el uso de las señales, deben de reconocer bien la diferencia de estas. En la cruzada se espera que el cliente y el servidor se conozcan mutuamente para poder enviar y recibir las señales necesarias para su funcionamiento. En una referencia circular se produce un llamado al parent para que ejecute una acción en un espacio que no le corresponde. Por ejemplo, que el servidor ejecute el dibujar la línea de un jugador en la interfaz gráfica es diferente a si manda una señal a los clientes involucrados para que estos envíen otra señal a sus propias interfaces y que así se ejecute el cambio.
Recuerden que en el chat de su tarea, debe haber una forma de identificar qué mensaje proviene de cada usuario (por ejemplo, poner
“user1 : Hola!”
). También recuerden que pueden haber más de dos usuarios jugando una partida, por lo que simplemente asignar en el chat a todos los otros usuarios con una única etiqueta genérica (como “Rival: Hola!”) estaría incorrecto.Por otro lado, consideren bien qué información sí hay que mostrar en el chat y cuál no, pensándolo como qué información necesita el usuario para poder jugar bien. Por ejemplo, un jugador no necesita saber la dirección de IP desde donde se conecta otro jugador, o el puerto, etc. Basta con avisar que alguien se conectó y mencionar su nombre.
Recuerden que al tener un método
send
no es necesario que envíen la información por otros medios, de esta manera evitan tener múltiples bugs de lo mismo, además de que se ahorran escribir mucho código y sólo deben debuguear una función.Mucho cuidado con el envío de datos con el servidor, si uno de los dos manda información muy seguida se les puede producir un error. Esto es porque cuando reciben lo hacen de la formar
self.recv(2048)
(por ejemplo), el problema de esto es que si mando dos mensajes al chat muy seguidos, entonces es posible que ambos mensajes se “mezclen”. Para solucionar esto, una vez que ustedes reciben el largo del arreglo de bytes que van a recibir pueden hacerself.recv(min(largo_de_bytes, 2048))
por ejemplo y meterlo en un loop que reciba solo hasta el lago de bytes (así cubren el caso en que el largo_de_bytes > 2048).Recuerden que en la realidad, un servidor envía todos los datos y elementos necesarios para la ejecución al cliente. Si bien no es necesario que le envíe la interfaz, toda información o elemento que el cliente quiera subir debe recibirla el servidor y este indicarle al cliente que actualice su interfaz.
Recuerden que
parametros.json
no debe ser uno compartido por cliente y servidor, sino que cada carpeta debe tener acceso sólo a lo que hay dentro de ella. No es correcto que cliente, por ejemplo, pueda acceder a algo dentro de la carpeta servidor.Además recuerden guardar en
parametros.json
los valores delHOST
y elPORT
. En el caso del que el cliente los obtenga a través de la interfaz no es necesario que los guarden, pero el servidor siempre deberá tener dichos valores en el archivoparametros.json
.Una vez que se cumplen los requisitos para echar a una persona se debe salir de la interfaz actual, no sirve solamente avisar por consola o dejar que se caiga la interfaz.
Fijense que cuando se cumpla la condición para hacer
\chao
de un usuario se cierre la ventana del usuario que corresponde y no la ventana del usuario que realizó el voto decisivo.Si un usuario hace múltiples veces
\chao
de un mismo usuario, su voto sólo se considerará una vez.El voto
\chao
sólo se considera si votaron más de la mitad de los jugadores, si hay dos jugadores y uno vota por echar al otro, entonces sigue faltando un voto para sacarlo.Queda a su criterio cómo manejar la existencia de múltiples
\chao
(que se trate de echar a distintos usuarios), ya sea:Les recomiendo que desarrollen el bonus de cliente y servidor robusto. De esta forma su programa podrá manejar correctamente errores y desconexiones, evitando que se caiga. Esto pueden hacerlo en paralelo a su trabajo de la tarea y les ayudará a probar mejor su código.
Para el bonus de las contraseñas se pueden utilizar distintos tipos de archivos para guardar la información sobre los usuarios registrados. Por ejemplo, pueden utilizar un archivo JSON, aplicando lo aprendido en la materia de serialización, o también pueden utilizar archivos CSV o TXT como han aprendido a lo largo del curso. No va a haber descuento por utilizar un archivo TXT en vez de materia más avanzada.
Revisen bien cuales son las funcionalidades del servidor y cuáles las del cliente. Algunos están realizando acciones correspondientes al servidor (por ejemplo chequeo de mensajes o usuarios) en el cliente. Esto es parte de lo que se evaluará en la tarea.
Recuerden instanciar sus objetos y llamar a los métodos necesarios para que su tarea parta. También adjuntar todos los archivos necesarios (no queremos 280 copias del enunciado) para la ejecución de la misma, ya que si no corre, no se revisa.
Trabajen mirando y seleccionando funcionalidades de la repartición de puntajes, así pueden priorizar de mejor manera los ítems que otorgan más puntaje, y no necesariamente con un esfuerzo mayor.
Recuerden respetar el máximo de caracteres por línea. Si quieren imprimir o escribir textos que superen los 80 caracteres, pueden guardarlos en un archivo aparte e importarlos para mostrar el texto relacionado, así evitan tener descuento por PEP8 y pueden reutilizar textos en caso de que sea necesario.
Recuerden hacer un correcto uso de
try
/except
, no deben hacer:ni deben hacer:
Ya que no se están manejando los distintos tipos de excepción, lo cual es una mala práctica.