From ce8262cafbbe88fc9140c0d283ad0b900bdd2d5d Mon Sep 17 00:00:00 2001 From: luisgulo Date: Tue, 28 Apr 2026 13:24:44 +0200 Subject: [PATCH] Subida inicial. Chequeada --- README.md | 61 ++++++++++++++ morse.png | Bin 0 -> 30501 bytes morse.py | 201 +++++++++++++++++++++++++++++++++++++++++++++++ morse2text.py | 25 ++++++ requeriments.txt | 1 + text2morse.py | 22 ++++++ 6 files changed, 310 insertions(+) create mode 100644 README.md create mode 100644 morse.png create mode 100755 morse.py create mode 100755 morse2text.py create mode 100644 requeriments.txt create mode 100755 text2morse.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..2082c34 --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +# Codificador visual de Morse + +Este programa está realizado en python. + +## Dependencias e instalación + +El programa unicamente tiene como dependencia `Pygame` y lo puedes instalar de la siguiente forma: + +1. Sistemas basados en Debian + +Si usas **Debian**, Ubuntu, Linux Mint o Raspberry Pi debes usar el gestor +de paquetes para evitar conflictos: + +```bash +sudo apt update +sudo apt -y install python3-pygame +``` + +2. Otros Sistemas Operativos + +Si usas Windows, macOS u otras distros tienes que instalar las dependencias +mediante el comando `pip` + +``` +pip install pygame +``` + +O usar el fichero requeriments.txt para resolver dependencias: + +``` +pip install -r requeriments.txt +``` + +## Ejecutar el programa + +``` +python morse.py +``` + +Captura de programa tras *codificar* en morse "SoloConLinux": + +![](morse.png) + + +Al finalizar la ejecución se muestra el texto y el código morse: + +```bash + +$ python morse.py + +======================================== +CODIFICADOR MORSE +TEXTO: SOLOCONLINUX +MORSE: ... --- ... --- ... --- ... ... --- .-.. --- -.-. --- -. .-.. .. -. ..- -..- +======================================== +``` + + + + + diff --git a/morse.png b/morse.png new file mode 100644 index 0000000000000000000000000000000000000000..2a069683aae599069cd1c8316cf0983a132cbfd2 GIT binary patch literal 30501 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 AbN~PV literal 0 HcmV?d00001 diff --git a/morse.py b/morse.py new file mode 100755 index 0000000..108534c --- /dev/null +++ b/morse.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python3 +import os +import warnings + +# Ignorar el aviso de AVX2 y otros avisos de ejecución +warnings.filterwarnings("ignore", category=RuntimeWarning) +# Silenciar el saludo de "Hello from the pygame community" +os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide" + +import pygame +import sys + +# Inicialización +pygame.init() + +# Configuración de ventana +ANCHO, ALTO = 1000, 850 +ventana = pygame.display.set_mode((ANCHO, ALTO)) +pygame.display.set_caption("Codificador Morse - SoloConLinux") + +# Colores +COLOR_FONDO = (245, 245, 245) +COLOR_PUNTO = (70, 70, 160) +COLOR_RAYA = (180, 50, 50) +COLOR_LINEA = (210, 210, 210) +COLOR_RESALTE = (0, 200, 0) +COLOR_TEXTO = (20, 20, 20) +COLOR_BARRA = (40, 40, 40) +COLOR_LEYENDA = (220, 220, 220) +COLOR_HISTORIAL = (50, 50, 100) + +# Fuentes +fuente_nodos = pygame.font.SysFont("Arial", 20, bold=True) +fuente_leyenda = pygame.font.SysFont("Monospace", 16) +fuente_preview = pygame.font.SysFont("Arial", 40, bold=True) +fuente_mensaje = pygame.font.SysFont("Courier New", 36, bold=True) + +class NodoMorse: + def __init__(self, letra, x, y, es_raya=False): + self.letra = letra + self.x = x + self.y = y + self.es_raya = es_raya + self.punto = None + self.raya = None + self.padre = None + + def dibujar_lineas(self, superficie, nodo_actual): + es_camino_activo = self.es_parte_del_camino(nodo_actual) + color = COLOR_RESALTE if es_camino_activo else COLOR_LINEA + ancho = 4 if es_camino_activo else 2 + + if self.punto: + pygame.draw.line(superficie, color, (self.x, self.y), (self.punto.x, self.punto.y), ancho) + self.punto.dibujar_lineas(superficie, nodo_actual) + if self.raya: + pygame.draw.line(superficie, color, (self.x, self.y), (self.raya.x, self.raya.y), ancho) + self.raya.dibujar_lineas(superficie, nodo_actual) + + def dibujar_nodo(self, superficie, nodo_actual): + activo = (self == nodo_actual) + color = COLOR_RESALTE if activo else (COLOR_RAYA if self.es_raya else COLOR_PUNTO) + + if self.es_raya: + pygame.draw.rect(superficie, color, (self.x - 22, self.y - 11, 44, 22)) + else: + pygame.draw.circle(superficie, color, (self.x, self.y), 16) + + if self.letra: + color_letra = (255, 255, 255) if activo else COLOR_TEXTO + # Ajustar texto si no tiene fuente Arial instalada + # Generamos la superficie del texto + texto_surf = fuente_nodos.render(self.letra, True, color_letra) + + # Creamos un rectángulo con el tamaño del texto y lo centramos en (self.x, self.y) + texto_rect = texto_surf.get_rect(center=(self.x, self.y)) + + # Dibujamos la superficie en las coordenadas del rectángulo calculado + superficie.blit(texto_surf, texto_rect) + + def es_parte_del_camino(self, destino): + temp = destino + while temp is not None: + if temp == self: return True + temp = temp.padre + return False + +# --- CONSTRUCCIÓN DEL ÁRBOL --- +nodos_lista = [] +def crear_nodo(letra, x, y, es_raya=False): + nuevo = NodoMorse(letra, x, y, es_raya) + nodos_lista.append(nuevo) + return nuevo + +raiz = crear_nodo("", 500, 150) # Bajado un poco para dar espacio al texto arriba +# Derecha (Puntos) +e = crear_nodo("E", 700, 250); e.padre = raiz; raiz.punto = e +i = crear_nodo("I", 800, 250); i.padre = e; e.punto = i +s = crear_nodo("S", 900, 250); s.padre = i; i.punto = s +h = crear_nodo("H", 970, 250); h.padre = s; s.punto = h +v = crear_nodo("V", 900, 330, True); v.padre = s; s.raya = v +u = crear_nodo("U", 800, 330, True); u.padre = i; i.raya = u +f = crear_nodo("F", 800, 410); f.padre = u; u.punto = f +a = crear_nodo("A", 700, 450, True); a.padre = e; e.raya = a +r = crear_nodo("R", 800, 530); r.padre = a; a.punto = r +l = crear_nodo("L", 900, 530); l.padre = r; r.punto = l +w = crear_nodo("W", 700, 610, True); w.padre = a; a.raya = w +p = crear_nodo("P", 800, 610); p.padre = w; w.punto = p +j = crear_nodo("J", 700, 690, True); j.padre = w; w.raya = j +# Izquierda (Rayas) +t = crear_nodo("T", 300, 250, True); t.padre = raiz; raiz.raya = t +m = crear_nodo("M", 200, 250, True); m.padre = t; t.raya = m +o = crear_nodo("O", 100, 250, True); o.padre = m; m.raya = o +g = crear_nodo("G", 200, 330); g.padre = m; m.punto = g +q = crear_nodo("Q", 100, 410, True); q.padre = g; g.raya = q +z = crear_nodo("Z", 200, 410); z.padre = g; g.punto = z +n = crear_nodo("N", 300, 450); n.padre = t; t.punto = n +k = crear_nodo("K", 200, 530, True); k.padre = n; n.raya = k +y = crear_nodo("Y", 100, 530, True); y.padre = k; k.raya = y +c = crear_nodo("C", 200, 610); c.padre = k; k.punto = c +d = crear_nodo("D", 300, 610); d.padre = n; n.punto = d +x = crear_nodo("X", 200, 690, True); x.padre = d; d.raya = x +b = crear_nodo("B", 300, 690); b.padre = d; d.punto = b + +# --- VARIABLES DE ESTADO --- +nodo_actual = raiz +mensaje_completo = "" # El mensaje final que se imprimirá +codigo_morse_total = "" # El código final que se imprimirá +morse_actual = "" # Lo que se va pulsando para la letra actual +ejecutando = True +reloj = pygame.time.Clock() + +while ejecutando: + ventana.fill(COLOR_FONDO) + + # 1. Dibujar Cabecera (Mensaje generado) + pygame.draw.rect(ventana, (230, 230, 230), (0, 0, ANCHO, 80)) + pygame.draw.line(ventana, COLOR_BARRA, (0, 80), (ANCHO, 80), 2) + img_msg = fuente_mensaje.render(mensaje_completo + "_", True, COLOR_HISTORIAL) + ventana.blit(img_msg, (20, 20)) + + # 2. Dibujar Árbol + raiz.dibujar_lineas(ventana, nodo_actual) + for n in nodos_lista: + n.dibujar_nodo(ventana, nodo_actual) + + # 3. Dibujar Barra de Leyenda + pygame.draw.rect(ventana, COLOR_BARRA, (0, ALTO - 60, ANCHO, 60)) + texto_leyenda = ". (Punto) - (Raya) SPACE (Confirmar) BACKSPACE (Borrar) ESC (Salir)" + img_leyenda = fuente_leyenda.render(texto_leyenda, True, COLOR_LEYENDA) + ventana.blit(img_leyenda, (20, ALTO - 38)) + + # 4. Previsualización de letra actual + if nodo_actual.letra: + # Ajuste texto si no tiene fuente Arial + pygame.draw.circle(ventana, COLOR_RESALTE, (ANCHO - 60, ALTO - 120), 35, 3) + img_prev = fuente_preview.render(nodo_actual.letra, True, COLOR_TEXTO) + # Centrado dinámico: + rect_prev = img_prev.get_rect(center=(ANCHO - 60, ALTO - 120)) + ventana.blit(img_prev, rect_prev) + + for evento in pygame.event.get(): + if evento.type == pygame.QUIT: + ejecutando = False + if evento.type == pygame.KEYDOWN: + if evento.key == pygame.K_PERIOD: + if nodo_actual.punto: + nodo_actual = nodo_actual.punto + morse_actual += "." + elif evento.key in [pygame.K_MINUS, pygame.K_SLASH, pygame.K_KP_MINUS]: + if nodo_actual.raya: + nodo_actual = nodo_actual.raya + morse_actual += "-" + elif evento.key == pygame.K_SPACE: + if nodo_actual.letra: + mensaje_completo += nodo_actual.letra + codigo_morse_total += morse_actual + " " + else: + mensaje_completo += " " + codigo_morse_total += " " + # resetarar para siguiente letra + nodo_actual = raiz + morse_actual = "" + elif evento.key == pygame.K_BACKSPACE: + mensaje_completo = mensaje_completo[:-1] + morse_actual = "" + elif evento.key == pygame.K_ESCAPE: + ejecutando = False + + pygame.display.flip() + reloj.tick(30) + +# -- Al Salir imprimimos todo el texto -- +print("\n" + "="*40) +print("CODIFICADOR MORSE") +print(f"TEXTO: {mensaje_completo}") +print(f"MORSE: {codigo_morse_total.strip()}") +print("="*40 + "\n") + +pygame.quit() +sys.exit() diff --git a/morse2text.py b/morse2text.py new file mode 100755 index 0000000..c72ef66 --- /dev/null +++ b/morse2text.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +import sys + +MORSE_MAP = {'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.', 'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..', 'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.', 'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-', 'Y': '-.--', 'Z': '--..', '1': '.----', '2': '..---', '3': '...--', '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', '9': '----.', '0': '-----'} +# Invertimos el diccionario: { '.-': 'A', ... } +REVERSE_MAP = {v: k for k, v in MORSE_MAP.items()} + +def decode(): + if len(sys.argv) < 2: + print("Uso: python3 morse2text.py \".... --- .-.. .-\"") + return + + # El input es la cadena morse + input_morse = sys.argv[1] + palabras_morse = input_morse.split(" ") # Separamos por doble espacio + frase_final = [] + + for palabra in palabras_morse: + letras = [REVERSE_MAP.get(cod, "?") for cod in palabra.split(" ")] + frase_final.append("".join(letras)) + + print(" ".join(frase_final)) + +if __name__ == "__main__": + decode() diff --git a/requeriments.txt b/requeriments.txt new file mode 100644 index 0000000..9a4d8c4 --- /dev/null +++ b/requeriments.txt @@ -0,0 +1 @@ +pygame>=2.6.0 diff --git a/text2morse.py b/text2morse.py new file mode 100755 index 0000000..95f4242 --- /dev/null +++ b/text2morse.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +import sys + +MORSE_MAP = {'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.', 'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..', 'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.', 'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-', 'Y': '-.--', 'Z': '--..', '1': '.----', '2': '..---', '3': '...--', '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', '9': '----.', '0': '-----'} + +def encode(): + if len(sys.argv) < 2: + print("Uso: python3 text2morse.py \"TEXTO A CONVERTIR\"") + return + + texto = " ".join(sys.argv[1:]).upper() + resultado = [] + + for palabra in texto.split(" "): + codificado = [MORSE_MAP.get(letra, "") for letra in palabra] + resultado.append(" ".join(codificado)) + + # Unimos las palabras con 2 espacios + print(" ".join(resultado)) + +if __name__ == "__main__": + encode()