๐ฃ Minesweeper Multiplayer + Dashboard
Un proyecto completo de programaciรณn de servicios y procesos
Juego de buscaminas competitivo en red + Panel de control integral
Caracterรญsticas โข
Arquitectura โข
Instalaciรณn โข
Uso โข
Mecรกnicas โข
Tecnologรญas
---
## ๐ธ Vista Previa
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ๐ฎ MINESWEEPER MULTIPLAYER DASHBOARD โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ โ โโโโโโโโโโโโโโโโโโโ โ
โ ACCIONES โ รREA DE RESULTADOS โ โ ๐ฃ MINESWEEPER โ โ
โ โโโโโโโโโโ โ โ โ MULTIPLAYER โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโโโโโโค โ
โ > Wallapop โ โ ๐ Monitor Sistema โ โ โ Ronda: 3 โ โ
โ > Scraping โ โ ๐ CPU: 45% โ โ โ ๐ฃ Bombas: 9 โ โ
โ > API Tiempo โ โ ๐พ RAM: 2.1GB โ โ โ โค๏ธ Vidas: 2 โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโโโโโโค โ
โ APPS โ โ โ โโโโโฌโโโโฌโโโโ โ โ
โ โโโโโโโโโโ โ Tabs: [Resultados][Navegador] โ โ โ โข โ โข โ โ โ โ โ
โ > VS Code โ [Correos][Bloc][Tareas] โ โ โโโโโผโโโโผโโโโค โ โ
โ > Camellos โ [Alarmas][Enlaces] โ โ โ ๐ฅโ โข โ โข โ โ โ
โ โ โ โ โโโโโดโโโโดโโโโ โ โ
โ BATCH โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโโโโโโค โ
โ โโโโโโโโโโ โ โ ๐ Panel de Notas โ โ โ [Iniciar Juego] โ โ
โ > Backups โ โ โ โ โ [Zona Despejada]โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโ
```
---
## โจ Caracterรญsticas
### ๐ฎ **Juego Minesweeper Multijugador**
| Caracterรญstica | Descripciรณn |
|----------------|-------------|
| ๐ฅ **Competitivo** | 2+ jugadores compiten en tiempo real |
| ๐ฃ **Colocaciรณn estratรฉgica** | Cada jugador coloca bombas para el rival |
| ๐ **Por turnos** | Sistema de turnos para colocar y buscar |
| ๐ **Dificultad progresiva** | 5 rondas con grids y bombas crecientes |
| โค๏ธ **Sistema de vidas** | 3 vidas por partida, ยกno las pierdas! |
### ๐ **Dashboard Integral**
- ๐ก **Monitor del sistema** en tiempo real (CPU, RAM, hilos)
- ๐ค๏ธ **API del tiempo** para Jรกvea (OpenWeather)
- ๐ **Anรกlisis de Wallapop** - Scraping de anuncios
- โฐ **Sistema de alarmas** programables
- ๐ **Bloc de notas** integrado
- ๐ **Gestor de enlaces** rรกpidos
- ๐ฒ **Minijuego de camellos** con animaciones
---
## ๐๏ธ Arquitectura
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ARQUITECTURA DEL SISTEMA โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SERVIDOR TCP โ
โ servidor.py โ
โ โโโโโโโโโโโโโโโโโโโโ โ
โ โ GameServer โ โ
โ โ - Estado juego โ โ
โ โ - Broadcast โ โ
โ โ - Turnos โ โ
โ โโโโโโโโโโโโโโโโโโโโ โ
โ Puerto 3333 โ
โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโ
โ Protocolo JSON โ
โ sobre TCP/IP โ
โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโ
โ โ โ
โผ โผ โผ
โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
โ CLIENTE 1 โ โ CLIENTE 2 โ โ CLIENTE N โ
โ โ โ โ โ โ
โ โโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโ โ
โ โ app.py โ โ โ โ app.py โ โ โ โ cliente_ โ โ
โ โ Dashboard โ โ โ โ Dashboard โ โ โ โ juego.py โ โ
โ โ + Juego โ โ โ โ + Juego โ โ โ โ Standalone โ โ
โ โโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
```
### ๐ Estructura del Proyecto
```
Proyecto1AVApsp/
โ
โโโ ๐ servidor.py # Servidor TCP del juego (371 lรญneas)
โ โโโ GameServer # Gestiona estado, turnos y broadcasts
โ
โโโ ๐ app.py # Dashboard principal (2566 lรญneas)
โ โโโ DashboardApp # Aplicaciรณn Tkinter completa
โ โโโ GameClient # Cliente TCP integrado
โ
โโโ ๐ cliente_juego.py # Cliente standalone (220 lรญneas)
โ โโโ GameClient # Versiรณn ligera para jugar
โ
โโโ ๐ requirements.txt # Dependencias Python
โโโ ๐ README.md # Este archivo
```
---
## ๐ Instalaciรณn
### Requisitos Previos
- **Python 3.8+**
- **pip** (gestor de paquetes)
### Paso 1: Clonar el Repositorio
```bash
git clone https://github.com/MarcosFerrandiz/Proyecto1AVApsp.git
cd Proyecto1AVApsp
```
### Paso 2: Crear Entorno Virtual (Recomendado)
```bash
python -m venv .venv
# Linux/macOS
source .venv/bin/activate
# Windows
.venv\Scripts\activate
```
### Paso 3: Instalar Dependencias
```bash
pip install -r requirements.txt
```
๐ฆ Ver dependencias detalladas
| Paquete | Versiรณn | Uso |
|---------|---------|-----|
| `psutil` | โฅ5.9.0 | Monitor de recursos del sistema |
| `matplotlib` | โฅ3.5.0 | Grรกficos en tiempo real |
| `pillow` | โฅ9.0.0 | Procesamiento de imรกgenes |
| `pygame` | โฅ2.1.0 | Reproducciรณn de audio (opcional) |
| `requests` | โฅ2.32.0 | Peticiones HTTP (API, Scraping) |
| `beautifulsoup4` | โฅ4.12.0 | Parsing HTML (Scraping) |
---
## ๐ฏ Uso
### ๐ฅ๏ธ Iniciar el Servidor
```bash
python servidor.py
```
> El servidor escucharรก en `0.0.0.0:3333`
### ๐ฎ Opciรณn A: Dashboard Completo
```bash
python app.py
```
Incluye el juego integrado + todas las funcionalidades del panel.
### ๐ฎ Opciรณn B: Cliente Standalone
```bash
python cliente_juego.py
```
Cliente ligero solo para jugar al Minesweeper.
### ๐ Conectar al Juego
1. Introduce el **Host** del servidor (por defecto: `127.0.0.1`)
2. Verifica el **Puerto** (por defecto: `3333`)
3. Pulsa **"Conectar"**
4. ยกEspera a otro jugador y pulsa **"Iniciar Juego"**!
---
## ๐ฃ Mecรกnicas del Juego
### ๐ Flujo de una Partida
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ FLUJO DEL JUEGO โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โ LOBBY โโโโโโถโ COLOCACIรN โโโโโโถโ BรSQUEDA โ โ
โ โ โ โ DE BOMBAS โ โ (PLAYING) โ โ
โ โโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโฌโโโโโโโ โ
โ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โ โผ โ
โ โ โโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโโโ โ
โ โ โ ยฟBOMBA? โโโโโถโ EXPLOSIรNโโโโโถโ ยฟVIDAS=0? โ โ
โ โ โโโโโโฌโโโโโ โโโโโโโโโโโโ โโโโโโโฌโโโโโโโ โ
โ โ โ NO โ โ
โ โ โผ Sร โผ โ
โ โ โโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โ โ SAFE โ โ GAME OVERโ โ
โ โ โ(casilla โ โโโโโโโโโโโโ โ
โ โ โ segura) โ โ
โ โ โโโโโโฌโโโโโ โ
โ โ โ โ
โ โ โผ โ
โ โ โฟโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ SIGUIENTE TURNO โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโถ (Nueva Partida) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
```
### ๐ Progresiรณn de Dificultad
| Ronda | Tamaรฑo Grid | Bombas/Jugador | Total Bombas* |
|:-----:|:-----------:|:--------------:|:-------------:|
| 1๏ธโฃ | 3ร3 | 3 | 6 |
| 2๏ธโฃ | 5ร5 | 5 | 10 |
| 3๏ธโฃ | 8ร8 | 9 | 18 |
| 4๏ธโฃ | 11ร11 | 12 | 24 |
| 5๏ธโฃ+ | 14ร14 | 15 | 30 |
*\*Para 2 jugadores*
### ๐ฏ Fases del Juego
#### 1. ๐ฃ Fase de Colocaciรณn (`PLACING`)
- Cada jugador coloca bombas **por turnos**
- Las bombas se muestran brevemente (1 segundo) a todos
- ยกMemoriza dรณnde pones TUS bombas y las del rival!
#### 2. ๐ Fase de Bรบsqueda (`PLAYING`)
- Excava casillas por turnos
- **Casilla segura** โ Se marca en verde โ
- **Bomba** โ ยกEXPLOSIรN! Pierdes 1 vida ๐
### ๐ Condiciones de Victoria
| Condiciรณn | Resultado |
|-----------|-----------|
| Rival pierde todas las vidas | **ยกGANASTE!** ๐ |
| Todas las casillas seguras reveladas | **ยกZona despejada!** |
| Superas la ronda 5 | **ยกVictoria total!** ๐ |
---
## ๐ก Protocolo de Comunicaciรณn
### Mensajes JSON Cliente โ Servidor
```javascript
// Iniciar partida
{ "type": "START_GAME" }
// Colocar bomba (fase PLACING)
{ "type": "PLACE_BOMB", "x": 2, "y": 1 }
// Excavar casilla (fase PLAYING)
{ "type": "CLICK_CELL", "x": 3, "y": 4 }
// Verificar zona despejada
{ "type": "CHECK_DUNGEON_CLEARED" }
```
### Mensajes JSON Servidor โ Clientes
```javascript
// Nueva ronda
{
"type": "NEW_ROUND",
"round": 1,
"grid_size": 3,
"total_bombs_per_player": 3
}
// Notificaciรณn de turno
{
"type": "TURN_NOTIFY",
"active_player": "('127.0.0.1', 54321)",
"msg": "Turno de ... para poner bombas."
}
// Flash de bomba (visible 1 segundo)
{
"type": "BOMB_flash",
"x": 1, "y": 2,
"who": "('127.0.0.1', 54321)"
}
// Explosiรณn
{
"type": "EXPLOSION",
"x": 1, "y": 2,
"who": "...",
"lives": 2
}
// Casilla segura
{ "type": "SAFE", "x": 0, "y": 0 }
// Game Over
{
"type": "GAME_OVER",
"loser": "...",
"msg": "๐ ยก... ha perdido todas sus vidas!"
}
```
---
## ๐ง Documentaciรณn Tรฉcnica Detallada
### ๐ Sistema de Identificaciรณn de Jugadores
El servidor **identifica a cada jugador mediante su direcciรณn de socket**, que es una tupla รบnica `(IP, Puerto)`:
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ IDENTIFICACIรN รNICA DE JUGADORES โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Cuando un cliente se conecta al servidor: โ
โ โ
โ Cliente 1 โโโโโโโบ sock.accept() โโโโโโโบ ('127.0.0.1', 49956) โ
โ Cliente 2 โโโโโโโบ sock.accept() โโโโโโโบ ('127.0.0.1', 49968) โ
โ โ
โ Aunque ambos clientes estรฉn en el MISMO ordenador (127.0.0.1) โ
โ el PUERTO es diferente y รบnico para cada conexiรณn. โ
โ โ
โ Esta tupla (IP, Puerto) actรบa como IDENTIFICADOR รNICO. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
```
#### ยฟCรณmo funciona en el mismo ordenador?
```python
# servidor.py - Al aceptar conexiรณn
conn, addr = s.accept() # addr = ('127.0.0.1', 49956)
# El sistema operativo asigna un puerto efรญmero รNICO
# a cada nueva conexiรณn de socket del cliente
```
| Cliente | IP | Puerto (asignado por SO) | Identificador Completo |
|---------|----|--------------------------|-----------------------|
| Dashboard 1 | 127.0.0.1 | 49956 | `('127.0.0.1', 49956)` |
| Dashboard 2 | 127.0.0.1 | 49968 | `('127.0.0.1', 49968)` |
| Cliente remoto | 192.168.1.50 | 52341 | `('192.168.1.50', 52341)` |
> **๐ก Clave:** El puerto del cliente es asignado automรกticamente por el sistema operativo y es **siempre diferente** para cada nueva conexiรณn, incluso desde el mismo ordenador.
---
### ๐ Gestiรณn de Turnos
El servidor mantiene **dos รญndices de turno** para controlar quiรฉn juega:
```python
# servidor.py - Variables de control de turnos
self.placing_turn_index = 0 # รndice en fase PLACING
self.playing_turn_index = 0 # รndice en fase PLAYING
self.client_list = [] # Lista ordenada de direcciones
```
#### Flujo de Verificaciรณn de Turno
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ VERIFICACIรN DE TURNO โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ client_list = [('127.0.0.1', 49956), ('127.0.0.1', 49968)] โ
โ โ โ โ
โ รญndice 0 รญndice 1 โ
โ โ
โ Si placing_turn_index = 0: โ
โ โ Solo ('127.0.0.1', 49956) puede poner bombas โ
โ โ
โ Cuando recibe PLACE_BOMB de un cliente: โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ if str(addr) != str(current_turn_addr): โ โ
โ โ return # No es su turno, ignorar โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
```
#### Cรณdigo de Verificaciรณn (servidor.py)
```python
elif msg_type == 'PLACE_BOMB':
if self.state == STATE_PLACING:
# Obtener quiรฉn tiene el turno actual
current_turn_addr = self.client_list[self.placing_turn_index]
# Comparar con quiรฉn enviรณ el mensaje
if str(addr) != str(current_turn_addr):
return # ยกNo es tu turno! Ignorar mensaje
# Procesar la bomba...
```
---
### ๐ค Cรณmo el Cliente Sabe si es su Turno
El cliente guarda su propia direcciรณn al conectarse y la compara con los mensajes del servidor:
```python
# app.py - Al conectarse
self.my_address = str(sock.getsockname()) # Ej: "('127.0.0.1', 49956)"
# Al recibir TURN_NOTIFY del servidor
def handle_message(self, msg):
if mtype == 'TURN_NOTIFY':
active_player = msg.get('active_player') # "('127.0.0.1', 49956)"
# Comparar con mi direcciรณn
if active_player == self.my_address:
self._log_game("๐ฏ ยกES TU TURNO!")
# Habilitar controles...
else:
self._log_game(f"โณ Turno de {active_player}")
# Deshabilitar controles...
```
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ FLUJO DE NOTIFICACIรN DE TURNO โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ SERVIDOR CLIENTES โ
โ โโโโโโโโ โโโโโโโโ โ
โ โ
โ broadcast({ Cliente 1 (49956): โ
โ "type": "TURN_NOTIFY", โโ my_address = 49956 โ
โ "active_player": โโ active_player = 49956 โ
โ "('127.0.0.1', 49956)" โโ โ ยกES MI TURNO! โ
โ }) โ
โ โ Cliente 2 (49968): โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโบ โโ my_address = 49968 โ
โ โโ active_player = 49956 โ
โ โโ โ No es mi turno โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
```
---
### ๐ Sincronizaciรณn con Threading Lock
El servidor usa un `threading.Lock` para evitar condiciones de carrera cuando mรบltiples clientes envรญan mensajes simultรกneamente:
```python
class GameServer:
def __init__(self):
self.lock = threading.Lock() # Mutex para sincronizaciรณn
self.clients = {} # Diccionario compartido
self.state = STATE_LOBBY # Estado compartido
def process_message(self, client, addr, msg):
with self.lock: # Adquirir lock antes de modificar estado
if msg_type == 'PLACE_BOMB':
# Solo un hilo puede ejecutar esto a la vez
self.bombs.add((x, y))
self._broadcast_unlocked(...)
```
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SINCRONIZACIรN CON LOCK โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Hilo Cliente 1 โโโโโโ โ
โ โโโโบ with self.lock: โโโบ Ejecuta primero โ
โ Hilo Cliente 2 โโโโโโ โ โ
โ โผ โ
โ (espera...) โ
โ โ โ
โ โผ โ
โ Hilo 2 ejecuta despuรฉs โ
โ โ
โ Esto evita que dos jugadores modifiquen el estado โ
โ del juego al mismo tiempo (condiciones de carrera). โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
```
---
### ๐ก Arquitectura de Hilos
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ARQUITECTURA DE HILOS โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ SERVIDOR (servidor.py) โ
โ โโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ Hilo Main โ โโโ Acepta conexiones (s.accept()) โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โ โ
โ โโโโบ Hilo Cliente 1 โโโบ handle_client(sock1) โ
โ โโโโบ Hilo Cliente 2 โโโบ handle_client(sock2) โ
โ โโโโบ Hilo Cliente N โโโบ handle_client(sockN) โ
โ โ
โ Cada cliente tiene su propio hilo daemon que: โ
โ 1. Lee mensajes del socket (recv) โ
โ 2. Procesa el mensaje (process_message) โ
โ 3. Puede hacer broadcast a todos los clientes โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ CLIENTE (app.py) โ
โ โโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ Hilo Main โ โ Hilo Recv โ โ
โ โ (Tkinter UI) โโโโโโ (_recv_loop) โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ โฒ โ
โ โ msg_queue.put() โ sock.recv() โ
โ โผ โ โ
โ โโโโโโโโโโโโโโโโโโโ โ โ
โ โ Cola de msgs โ โโโโโโโโโโโ โ
โ โ (thread-safe) โ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ
โ El hilo de recepciรณn pone mensajes en una cola. โ
โ El hilo principal (UI) los procesa con after(). โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
```
---
### ๐ฎ Resumen: Jugar en el Mismo Ordenador
| Paso | Quรฉ Sucede |
|------|------------|
| 1. Iniciar servidor | `python servidor.py` escucha en puerto 3333 |
| 2. Abrir Cliente 1 | Conecta โ SO asigna puerto 49956 |
| 3. Abrir Cliente 2 | Conecta โ SO asigna puerto 49968 |
| 4. Servidor registra | `clients = {sock1: ('127.0.0.1', 49956), sock2: ('127.0.0.1', 49968)}` |
| 5. Iniciar juego | `client_list = [addr1, addr2]` define orden de turnos |
| 6. Turno jugador 1 | Servidor envรญa `TURN_NOTIFY` con `active_player = addr1` |
| 7. Cliente 1 compara | `my_address == active_player` โ ยกEs mi turno! |
| 8. Cliente 2 compara | `my_address != active_player` โ Esperar |
| 9. Jugador 1 actรบa | Envรญa `PLACE_BOMB` o `CLICK_CELL` |
| 10. Servidor valida | `addr == current_turn_addr` โ Vรกlido, procesar |
| 11. Avanzar turno | `placing_turn_index += 1` โ Turno del siguiente |
---
## ๐ ๏ธ Tecnologรญas
Python 3
Lenguaje base
|
Tkinter
Interfaz grรกfica
|
TCP Sockets
Comunicaciรณn en red
|
Matplotlib
Grรกficos
|
JSON
Protocolo mensajes
|
Requests
APIs HTTP
|
### ๐งต Conceptos de PSP Aplicados
| Concepto | Implementaciรณn |
|----------|----------------|
| **Procesos** | Lanzamiento de aplicaciones externas (VS Code, Firefox) |
| **Threads** | Servidor multihilo, cliente con hilos de recepciรณn |
| **Sockets TCP** | Comunicaciรณn cliente-servidor en red |
| **Servicios** | API OpenWeather, scraping de Wallapop |
| **Sincronizaciรณn** | Locks para acceso concurrente a estado compartido |
---
## ๐จ Caracterรญsticas del Dashboard
### ๐ Monitor del Sistema
- Grรกfico de CPU en lรญnea temporal
- Grรกfico de memoria como รกrea
- Contador de hilos del proceso
### ๐ค๏ธ API del Tiempo (Jรกvea)
- Temperatura actual y sensaciรณn tรฉrmica
- Humedad y velocidad del viento
- Descripciรณn del clima
### ๐ Anรกlisis Wallapop
- Extracciรณn de informaciรณn de anuncios
- Headers personalizados para API
- Resultados formateados
### โฐ Sistema de Alarmas
- Programaciรณn en minutos
- Notificaciones visuales
- Gestiรณn de alarmas activas
---
## ๐ค Contribuir
1. **Fork** del proyecto
2. Crea tu **Feature Branch** (`git checkout -b feature/NuevaFuncion`)
3. **Commit** tus cambios (`git commit -m 'Add: Nueva funciรณn'`)
4. **Push** a la rama (`git push origin feature/NuevaFuncion`)
5. Abre un **Pull Request**
---
## ๐ Licencia
Este proyecto es de carรกcter **educativo** y fue desarrollado como parte del mรณdulo de **Programaciรณn de Servicios y Procesos**.
---
Desarrollado con โค๏ธ por Marcos Ferrandiz
Proyecto 1ยบ Evaluaciรณn - PSP (Programaciรณn de Servicios y Procesos)
---