├── 01-Fundamentos-JS ├── async.md ├── dom.md ├── eventos.md ├── fundamentos-js.md ├── tarea-calculadora.md ├── poo.md ├── fundamentos-backend.md └── proyecto-el-amarre.md ├── 03-Node.js ├── estructura-proyectos.md ├── npm-package.md ├── Introduccion-nodejs.md └── proyecto-barcos.md ├── 00-Prework ├── mongo.md ├── mysql.md ├── node-npm.md └── git-ssh.md ├── README.md └── 02-Fundamentos-React └── proyecto-todo.md /01-Fundamentos-JS/async.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /01-Fundamentos-JS/dom.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /01-Fundamentos-JS/eventos.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /01-Fundamentos-JS/fundamentos-js.md: -------------------------------------------------------------------------------- 1 | # Fundamentos de JavaScript 2 | 3 | 4 | -------------------------------------------------------------------------------- /03-Node.js/estructura-proyectos.md: -------------------------------------------------------------------------------- 1 | # Estructura de proyectos de Node.js 2 | 3 | ```gitignore 4 | node_modules 5 | package-lock.json 6 | ``` 7 | 8 | /modules/retrievedate.js 9 | ```JavaScript 10 | // Este módulo lo creamos y solo devuelve la fecha actual DEL SERVER 11 | exports.RetrieveDate = function() { 12 | return Date(); 13 | } 14 | ``` -------------------------------------------------------------------------------- /03-Node.js/npm-package.md: -------------------------------------------------------------------------------- 1 | # NPM y Package JSON 2 | 3 | ```JSON 4 | { 5 | "name": "holamundo", 6 | "version": "1.0.0", 7 | "description": "Es mi primer hola mundo", 8 | "main": "index.js", 9 | "scripts": { 10 | "start": "node index.js", 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/Launch-X-Latam/MisionBackend" 16 | }, 17 | "author": "josejesusguzman", 18 | "license": "ISC", 19 | "dependencies": { 20 | 21 | }, 22 | "devDependencies": { 23 | 24 | }, 25 | "homepage": "https://github.com/Launch-X-Latam/MisionBackend" 26 | } 27 | 28 | ``` -------------------------------------------------------------------------------- /01-Fundamentos-JS/tarea-calculadora.md: -------------------------------------------------------------------------------- 1 | # Tarea 2 | 3 | ## Calculadora 4 | 5 | Uno de los primeros ejercicios de todo curso de programación es hacer una calculadora ya que te permite aprender: 6 | 7 | - Concatenación 8 | - Operaciones matemáticas 9 | - Uso de variables 10 | - Entrada del usuario 11 | - Muestra de resultados al usuario 12 | 13 | Para esta tarea debes hacer una calculadora con las siguientes operaciones: 14 | - Suma 15 | - Resta 16 | - Multiplicación 17 | - División 18 | - Raiz cuiadrada 19 | - Potencia al número qe el usuario te diga 20 | - Residuo de una división 21 | - Borrar todos los datos de la calculadora 22 | 23 | - Todo debe ser con botones e inputs HTML. Nada en consola. 24 | 25 | Mucho éxito ✨ -------------------------------------------------------------------------------- /00-Prework/mongo.md: -------------------------------------------------------------------------------- 1 | # Instalación de MongoDB 2 | 3 | MongoDB es un sistema de base de datos NoSQL, orientado a documentos y de código abierto. 4 | 5 | En lugar de guardar los datos en tablas, tal y como se hace en las bases de datos relacionales, MongoDB guarda estructuras de datos BSON (algo similar a JSON) con un esquema dinámico, haciendo que la integración de los datos en ciertas aplicaciones sea más fácil y rápida. 6 | 7 | ## Instalación 8 | 9 | 1. Descarga el instalador desde el siguiente enlace -> https://www.mongodb.com/try/download/community 10 | 11 | 2. Selecciona: Windows como Plataforma y **msi** como paquete. 12 | 13 | 3. Ejecuta el instalador y sigue las instrucciones. 14 | 15 | En el caso de MacOS si tu equipo tiene un procesador de Apple en plataforma selecciona MacOs ARM 64. 16 | 17 | Para el caso de Linux, selecciona la distro que tienes y en package selecciona **mongos**. 18 | 19 | 20 | -------------------------------------------------------------------------------- /03-Node.js/Introduccion-nodejs.md: -------------------------------------------------------------------------------- 1 | # Introducción a Node.js 2 | 3 | App.js 4 | ```JavaScript 5 | const http = require('http'); // Cargando un módulo de Node.js 6 | const url = require('url'); 7 | 8 | const rd = require('./modules/retrievedate') ; //Cargamos un módulo propio que esta en ./modules/retrievedate.js 9 | 10 | http.createServer((req, res) => { 11 | res.writeHead(200, {'Content-Type': 'text/html'}); 12 | //res.write("La fecha y hora es: "+ rd.RetrieveDate()); 13 | const query = url.parse(req.url, true).query; 14 | const text = query.year + " " + query.month 15 | //res.end("Holaaaa Mundo!!!!"); 16 | res.end(text); 17 | }).listen(8080); 18 | ``` 19 | 20 | index.js 21 | ```JavaScript 22 | const http = require('http'); 23 | const fs = require('fs'); 24 | 25 | http.createServer((req, res) => { 26 | fs.readFile('./html/demo.html', function(err, data) { 27 | res.writeHead(200, {'Content-Type': 'text/html'}); 28 | res.write(data); 29 | return res.end(); 30 | }); 31 | }).listen(3200); 32 | ``` 33 | 34 | /html/demo.html 35 | ````HTML 36 | 37 | 38 | 39 | 40 | MI PÁGINA EN NODE 41 | 42 | 43 |

MIRA MAMÁ ESTOY PROGRAMANDO EN NODE

44 |

45 | Estoy aprendiendo Node.js en vez de hacerme wey. 46 |

47 | 48 | 49 | 50 | ```` -------------------------------------------------------------------------------- /00-Prework/mysql.md: -------------------------------------------------------------------------------- 1 | # Instalación de MySQL 2 | 3 | MySQL es un sistema de gestión de bases de datos relacionales (RDBMS) de código abierto respaldado por Oracle y basado en el lenguaje de consulta estructurado (SQL). 4 | 5 | ## Instalación en Windows 6 | 7 | Descarga el instalador y ejecutalo. Lo puedes descargar desde la siguiente liga: 8 | https://dev.mysql.com/downloads/installer/ 9 | 10 | Solo sigue los pasos y provee todos los permisos necesarios y listo. 11 | 12 | **NOTA:** Trata de descargar el archivo más pesado e instalar MySQL Workbench. Lo utilizaremos después. 13 | 14 | ## Instalación en Mac 15 | 16 | 17 | Descarga el instalador y ejecutalo. Lo puedes descargar desde la siguiente liga: 18 | https://dev.mysql.com/downloads/mysql/ seleccionando MacOS como sistema operativo. 19 | 20 | **NOTA:** Selecciona las versiones ARM, 64-bit si tienes una Mac con procesador de Apple (M1 o variantes y M2). SI tienes Una Mac con procesador de Intel, descargar las versiones x86, 64-bit. 21 | 22 | Descarga los archivos DMG para que la instalación sea más fácil. 23 | 24 | ## Instalación En Linux 25 | 26 | ### Ubuntu/Debian 27 | 28 | Si tienes una distro basada en debian instala el .deb descargandolo desde aquí: https://dev.mysql.com/downloads/repo/apt/ 29 | 30 | ### Oracle, Fedora, Red Hat 31 | Si tienes una distro de estas o basada en estas descarga el RPM package -> https://dev.mysql.com/downloads/repo/yum/ 32 | 33 | Para otras distros de Linux selecciona tu sistema opereativo desde la opción **Select Operating System:** en esta página -> https://dev.mysql.com/downloads/mysql/ -------------------------------------------------------------------------------- /00-Prework/node-npm.md: -------------------------------------------------------------------------------- 1 | # Instalación de Node.js 2 | 3 | Node. js sirve para crear sitios web dinámicos muy eficientes, escritos con el lenguaje de programación JavaScript. 4 | 5 | ## Instalación en Windows 6 | 7 | Instala Node.js desde el instalador de Windows [-> da clic aquí <-](https://nodejs.org/en/#home-downloadhead) 8 | 9 | ## Instalación en MacOS 10 | 11 | - Puedes instalar directamente node.js con el siguiente comando ejecutandolo desde la terminal: 12 | 13 | ```bash 14 | curl "https://nodejs.org/dist/latest/node-${VERSION:-$(wget -qO- https://nodejs.org/dist/latest/ | sed -nE 's|.*>node-(.*)\.pkg.*|\1|p')}.pkg" > "$HOME/Downloads/node-latest.pkg" && sudo installer -store -pkg "$HOME/Downloads/node-latest.pkg" -target "/" 15 | ``` 16 | 17 | - También peudes instalar [Homebrew](https://brew.sh/index_es) que es un instalador de paquetes de Mac. Para ello puedes ejecutar el siguiente comando en la terminal: 18 | 19 | ```bash 20 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 21 | ``` 22 | 23 | Sigue las instrucciones finales del instalador de Homebrew. 24 | 25 | ```bash 26 | brew install node 27 | ``` 28 | 29 | ## Instalación en Linux 30 | 31 | Así puedes Instalar Node.js dependiedo de tu distro: 32 | 33 | Arch Linux 34 | 35 | ```bash 36 | pacman -S nodejs npm 37 | ``` 38 | 39 | CentOS, Fedora y Red Hat Enterprise Linux 40 | ```bash 41 | dnf module install nodejs:18/common 42 | ``` 43 | 44 | Ubuntu 45 | ```bash 46 | curl -fsSL https://deb.nodesource.com/setup_19.x | sudo -E bash - &&\ 47 | 48 | sudo apt-get install -y nodejs 49 | ``` 50 | 51 | Debian 52 | ```bash 53 | curl -fsSL https://deb.nodesource.com/setup_19.x | bash - &&\ 54 | 55 | apt-get install -y nodejs 56 | ``` 57 | FreeBSD 58 | ```bash 59 | pkg install node 60 | ``` 61 | Gentoo 62 | ```bash 63 | emerge nodejs 64 | ``` 65 | 66 | -------------------------------------------------------------------------------- /01-Fundamentos-JS/poo.md: -------------------------------------------------------------------------------- 1 | # Programación Orientada a Objetos con JavaScript 2 | 3 | index.html 4 | ```HTML 5 | 6 | 7 | 8 | POO en JavaScript 9 | 10 | 11 | 12 | 13 | 14 |

15 | POO en JavaScript 16 |

17 | 18 | 19 | ``` 20 | 21 | Animales.js 22 | ```JavaScript 23 | // Herencia 24 | class Animales { 25 | 26 | #especie = ""; 27 | #nombre = ""; 28 | #edad = 0; 29 | #terrenosAbuela = "Terreno"; 30 | 31 | constructor(nombre, edad) { 32 | this.nombre = nombre; 33 | this.edad = edad; 34 | } 35 | 36 | canta() { 37 | return `${this.nombre} puede cantar`; 38 | } 39 | 40 | correr() { 41 | return `${this.nombre} puede correr`; 42 | } 43 | 44 | getEspecie() { 45 | return this.#especie; 46 | } 47 | 48 | setEspecie(especie) { 49 | this.#especie = especie 50 | } 51 | } 52 | 53 | class Gatos extends Animales { 54 | 55 | constructor(nombre, edad, colorBigotes) { 56 | super(nombre, edad); 57 | this.colorBigotes = colorBigotes; 58 | } 59 | 60 | bigotes() { 61 | return `Tengo bigotes color ${this.colorBigotes}`; 62 | } 63 | 64 | anios() { 65 | return `Tengo ${this.edad} años`; 66 | } 67 | 68 | especiegato() { 69 | return `Soy un ${this.getEspecie()}`; 70 | } 71 | 72 | } 73 | 74 | let animal = new Animales("gato", 5); 75 | animal.setEspecie("Felis Catus"); 76 | 77 | 78 | let gato = new Gatos("gato", 5, "blanco"); 79 | 80 | gato.setEspecie("Felis Catus"); 81 | 82 | console.log(gato.anios()); 83 | //console.log(animal.especie); 84 | console.log(gato); 85 | ``` 86 | 87 | index.js 88 | ```JavaScript 89 | // Intro a objetos y POO 90 | let nombres = { 91 | nombre: "Jesús", 92 | apellido: "Guzmán" 93 | }; 94 | 95 | console.log(nombres.nombre); 96 | console.log(nombres.hasOwnProperty("telefono")); 97 | 98 | console.log(nombres); 99 | 100 | function perro(nombre, edad) { 101 | perro.nombre = nombre; 102 | perro.edad = edad; 103 | } 104 | 105 | perro.prototype.habla = function() { 106 | return "Wof Wof Soy un perro"; 107 | } 108 | 109 | let firulais = new perro("Firulais", 9); 110 | console.log(firulais.habla()); 111 | ``` 112 | 113 | Persona.js 114 | ```JavaScript 115 | // Polimorfismo 116 | function Persona(nombre) { 117 | this.nombre = nombre; 118 | this.caminar = function() { 119 | console.log("CAMINANDO"); 120 | } 121 | } 122 | 123 | function Alumno(nombre, llorandoSangre) { 124 | Persona.call(this, nombre); 125 | 126 | this.llorandoSangre = llorandoSangre; 127 | this.caminar = function() { 128 | console.log("CAMINANDO Y LLORANDO SANGRE"); 129 | } 130 | } 131 | 132 | Alumno.prototype = Object.create(Persona.prototype); 133 | Alumno.prototype.constructor = Alumno 134 | 135 | let estudiante1 = new Alumno('Jesús Guzmán', "React"); 136 | let persona1 = new Persona("Memo Ochoa"); 137 | 138 | console.log(estudiante1.caminar()); 139 | console.log(persona1.caminar()); 140 | 141 | ``` 142 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Misión Backend 2 | 3 | 4 | ## Bienvenid@ a una nueva etapa misión!! 5 | 6 | 7 | En esta misión veremos la lógica y la técnica detrás de lo que mueve las aplicaciones y al Frontend, el Backend. Sin el Backend, el Frontend no funciona y sin el Frontend, el Backend no puede ser usado. Este ying y yang se llama FullStack developer. 8 | 9 | ![GIF](https://c.tenor.com/gI1CoSP-3R8AAAAM/front.gif) 10 | 11 | # Temario de la misión Backend 12 | 13 | Esta misión tiene 7 módulos que tienen varios subtemas que iremos viendo conforme avancemos con el curso. 14 | 15 | **Las diferentes ligas se irán desbloqueando durante el curso conforme pasen las semanas para que no se me adelanten** 16 | 17 | ### -1. Las Playlist oficiales autorizadas 18 | - [Música pa jakiar](https://open.spotify.com/playlist/6K5Ot9oBJA2wnP5GiN2Vcj?si=dac276877959418e) 19 | - [Cumbias pa jakiar el pentagono](https://open.spotify.com/playlist/7vNuXU1vaXmbWIAcoDLSMJ?si=787c3b4a77ba41ae) 20 | - [Perreo puerco pa jakiar más puerco](https://open.spotify.com/playlist/2URfkpVmGNoShqgU2aVONc?si=a134d105880a47c0) 21 | - [LoFi for programming](https://open.spotify.com/playlist/3TxfEUkuXd0FNiiczwII0e?si=51df479eb7634f2c) 22 | - [Música para programar con odio](https://open.spotify.com/playlist/0BEi0kOdkpWKdzqm7V7Wfc?si=9993d36cd223458f) 23 | 24 | ### 0. Prework - Instalación 25 | - [Git y SSH keys](/00-Prework/git-ssh.md) 26 | - [Node.js y NPM](/00-Prework/node-npm.md) 27 | - [MySQL](/00-Prework/mysql.md) 28 | - [MongoDB](/00-Prework/mongo.md) 29 | 30 | ### 1. Fundamentos de JavaScript 31 | - [Fundamentos de programación backend](/01-Fundamentos-JS/fundamentos-backend.md) 32 | - [Fundamentos de JavaScript](/01-Fundamentos-JS/fundamentos-js.md) 33 | - [Manejo de DOM](/01-Fundamentos-JS/dom.md) 34 | - [Manejo de eventos](/01-Fundamentos-JS/eventos.md) 35 | - [Programación orientada a objetos con JavaScript](/01-Fundamentos-JS/poo.md) 36 | - [Procesos asincronos con JavaScript](/01-Fundamentos-JS/async.md) 37 | 38 | #### El Proyecto 39 | - ["El amarre"](/01-Fundamentos-JS/proyecto-el-amarre.md) 40 | 41 | #### La Tarea 42 | - [Calculadora en JavaScript](/01-Fundamentos-JS/tarea-calculadora.md) 43 | 44 | ### 2. Fundamentos de React.js 45 | - [Introducción a React]() 46 | - [Estructura de un proyecto en React]() 47 | - [Syntactically Awesome Style Sheets (Sass)]() 48 | - [Componentes de React]() 49 | - [Estado en React]() 50 | - [Contexto en React]() 51 | - [React Hooks]() 52 | - [Consumo de API REST]() 53 | - [Hosting de una applicación de React]() 54 | 55 | #### El Proyecto 56 | - [ToDo App](/02-Fundamentos-React/proyecto-todo.md) 57 | 58 | #### La Tarea 59 | - [Pokédex]() 60 | 61 | 62 | ### 3. Backend con Node.js 63 | - [Introducción a Node.js](/03-Node.js/Introduccion-nodejs.md) 64 | - [NPM y package.json](/03-Node.js/npm-package.md) 65 | - [Estructura de proyectos en Node.js](/03-Node.js/estructura-proyectos.md) 66 | - [Consumo de API REST]() 67 | - [Fundamentos de Express]() 68 | - [Peticiones Get y Create]() 69 | - [Peticiones Post, Put y Delete]() 70 | - [CORS Middleware]() 71 | - [Manejo de headers]() 72 | - [Websockets y Socket.io]() 73 | - [Hosting de una applicación de Node.js]() 74 | 75 | #### El Proyecto 76 | - [Barcos multijugador](/03-Node.js/proyecto-barcos.md) 77 | 78 | #### La Tarea 79 | - [Aplicación de chat en tiempo real]() 80 | 81 | ### 4. Testing con Node.js 82 | - [Git avanzado]() 83 | - [Desarrollo TDD]() 84 | - [Pruebas unitarias]() 85 | - [Fundamentos de Mocha]() 86 | - [Code coverage]() 87 | - [Refactorización de código]() 88 | - [Performance, profiling y debugging]() 89 | 90 | #### El Proyecto 91 | - [Automatizador de emails (Testing)]() 92 | 93 | #### La Tarea 94 | - [Aplicación de chat en tiempo real (Testing)]() 95 | 96 | ### 5. Bases de datos MySQL 97 | - [Introducción a SQL y conceptos]() 98 | - [Joins en SQL]() 99 | - [Vistas en SQL]() 100 | - [Transacciones en SQL]() 101 | - [Node.js meets Mysql]() 102 | - [Bases de datos en la nube]() 103 | 104 | #### El Proyecto 105 | - [Base de datos de empleados]() 106 | 107 | #### La Tarea 108 | - [API REST de lenguajes de programación]() 109 | 110 | ### 6. Bases de NoSQL 111 | - [Principios de NoSQL]() 112 | - [Fundamentos de MongoDB]() 113 | - [Filtrado y busqueda de datos]() 114 | - [Insertar, eliminar y actualizar]() 115 | - [CRUD con MongoDB y Node.js]() 116 | - [MongoDB y Azure Cosmos DB]() 117 | 118 | #### El Proyecto 119 | - [Estadisticas de Futbol]() 120 | 121 | #### La Tarea 122 | - [Chat en tiempo real con MongoB]() 123 | 124 | ### 7. Cloud Infraestructure 125 | - [Introducción a Azure VM]() 126 | - [Introducción a Contenedores]() 127 | - [Primeros pasos en Kubernetes]() 128 | - [Logging y seguridad]() 129 | - [Empleabilidad y consejos finales]() 130 | 131 | Recuerda que la práctica hace al maestro, recuerda que no hay preguntas tontas, lo tonto es no preguntar y Recuerda que esto no es Brujería, es Tecnología. 🪄 132 | 133 | -------------------------------------------------------------------------------- /01-Fundamentos-JS/fundamentos-backend.md: -------------------------------------------------------------------------------- 1 | # Fundamentos de programación BackEnd 2 | 3 | El backend es la parte del desarrollo web que se encarga de que toda la lógica de una página web funcione. Se trata del conjunto de acciones que pasan en una web pero que no vemos como, por ejemplo, la comunicación con el servidor. 4 | 5 | En otras palabras, el Backend serían tus organos como tu corazón o pulmones. El Frontend sería tu piel, ojos, dientes... 6 | 7 | Algunas de las funciones que se gestionan en la parte del Backend son: 8 | 9 | - El Desarrollo de funciones que simplifiquen el proceso de desarrollo. 10 | Acciones de lógica 11 | - Conexión con bases de datos 12 | - Uso de librerías del servidor web (por ejemplo para implementar temas de caché o para comprimir las imágenes de la web) 13 | - Seguridad de conexión entre la base de datos y la solución 14 | 15 | Algunos lenguajes de Backend son los siguientes: 16 | - Java (Con JAVA EE o Spring) 17 | - Python (Solo o con Django o Flask) 18 | - JavaScript (Con Node.js) 19 | - PHP (Solo o con Laravel, Codeigniter o Yii2) 20 | - C# 21 | 22 | # Tips para ser buen Backend 23 | 24 | 1. **AUTOMATIZACIÓN**: antomatiza todo lo que haces repetidamente, incluida la línea de comandos (scripts bash), manipulaciones de texto y registros, refactorización, construcción, implementación, integración, prueba, etc 25 | 26 | 2. **NO OPTIMIZAR AÚN**: El impulso de optimizar suele ser prematuro. Las soluciones inteligentes para exprimir el rendimiento aumentan la complejidad y socavan el objetivo final 27 | 28 | 3. **QUÉ OPTIMIZAR**: puedes optimizar la velocidad, pero lo más preciado que debe optimizar es tu propio tiempo. Optimiza la legibilidad y la claridad. Si tienes que parar y preguntarte, ¿cómo funciona esto? ¿O por qué esto no está haciendo lo que debería hacer? Acabas de perder el tiempo. No uses muchas estructuras de datos complejas y algoritmos o funciones de lenguaje avanzado como una forma de demostrar tu habilidad a menos que el proyecto lo necesite 29 | 30 | 4. **KYT (Know Your Tools -Conoce tus herramientas-)**: uno de los mejores trucos de productividad de todos los tiempos es este: familiarizate con las herramientas y el entorno con el que estás trabajando 31 | 32 | 5. **PROYECTOS PARALELOS/APRENDER COSAS NUEVAS**: esto podría mejorar enormemente tu productividad y confianza. Tener un proyecto paralelo que podrías hacer si estás aburrido con un proyecto en particular podría ser excelente, pero ten en cuenta que depende en gran medida de la duración de tu proyecto principal. Además, siempre aprender y mejorar tus habilidades leyendo el código fuente de otras personas, viendo videos de YouTube, leyendo documentación oficial o leyendo artículos de blog... podría ser una gran fuente de motivación para mantenerte productivo como Backend developer. 33 | 34 | 6. **COLABORACIÓN**: Otra gran fuente de productividad es la colaboración, mira que nadie es una isla de conocimiento, necesitas colaborar con la gente para poder pedir ayuda, trabajar en proyectos juntos y aprender a formar y/o gestionar equipos 35 | 36 | 7. **PRIORIZA TU TAREA Y COMPROMÉTETE CON ELLA**: Esto requerirá un poco de disciplina, no es suficiente programar algo que hacer, debes desempeñarte bien activamente en aquellas actividades que son más valiosas para ti y/o tu equipo. Esto requiere mantener la mente enfocada en la tarea en cuestión. Realmente no puedes escribir un buen código o resolver un problema difícil cuando estás pensando en muchas cosas al mismo tiempo. 37 | 38 | 8. **ELIMINA LAS DISTRACCIONES**: mantente alejado de las redes sociales por un tiempo en el trabajo. Las redes sociales podrían ser una de las principales distracciones para los BackEnd developer, incluidos YouTube, Quora, StackOverflow... Solo requiere cierto grado de disciplina de su parte para mantenerse comprometido con su trabajo y ser productivo.} 39 | - Si te cuesta mucho trabajo, pon tu celular en no molestar y en blanco y negro (Investigalo por tu cuenta, recuerda que hay que aprender cosas nuevas) 40 | 41 | 9. **ENCUENTRA UN MENTOR**: Esta podría ser una gran fuente de motivación para much@s developers porque donde tu fuerza no puede llegar, tu mentor puede ayudarte. Por lo tanto, encontrar un buen mentor puede aumentar tu nivel de productividad 42 | 43 | 10. **ENTIENDE EL NEGOCIO**: Una cosa crucial que podría acabar con tu productividad es no entender el proyecto, el negocio o incluso los requisitos correctamente. Entonces, para mejorar la productividad en un proyecto o empresa, debes tener una comprensión adecuada de los procesos, la cultura, el proyecto y los requisitos 44 | 45 | 11. **TOMA DESCANSOS, DUERME, DESCANSA, NO TE CHINGUES DEMASIADO**: Escuché a much@s developers decir que no duermen o que les encanta trabajar de noche o cuando eso les quita el sueño o el descanso. Quiero decirte hoy que para que seas productivo como Backend developer necesitas tiempo para descansar y dormir, por lo menos descansos para calmarte los nervios antes de continuar. 46 | 47 | 12. **APRENDE A DEPURAR Y LIMPIAR CÓDIGO**: una habilidad importante que cualquier Backend Developer debe saber es la depuración. Puede ahorrarte mucho tiempo averiguando algo en sus programas. Así que aprende habilidades de depuración y también aprende a escribir código limpio. Una recomendación de lectura es [-> The Clean Code Blog](https://blog.cleancoder.com/) 48 | -------------------------------------------------------------------------------- /01-Fundamentos-JS/proyecto-el-amarre.md: -------------------------------------------------------------------------------- 1 | # Proyecto 2 | ## El amarre 3 | 4 | Desde tiempos inmemoriables los animales han ideado formas diferentes de atraer pareja. 5 | 6 | Tenemos al pavo real macho con su ya conocido plumaje exotico 7 | 8 | ![Pavo Real](https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Pavo_cristatus_Campo_Grande.jpg/250px-Pavo_cristatus_Campo_Grande.jpg) 9 | 10 | Pasando por la hembra Mantis Religiosa comiendose la cabeza de su enamorado. 11 | 12 | ![Mantis](https://www.sopitas.com/wp-content/uploads/2016/07/mantis-comida-1.jpg) 13 | 14 | Hasta tu **"amig@"** esperando el momento perfecto para saltar. 15 | 16 | ![Chapulin](https://static.wixstatic.com/media/8c78bb_338ea1ef9cca4d8689c41327432b266f~mv2.jpg/v1/crop/x_154,y_0,w_717,h_740/fill/w_337,h_348,al_c,q_80,usm_0.66_1.00_0.01,enc_auto/zxcdc.jpg) 17 | 18 | Es por ello que te tengo una forma en la que tu crush literalmente, no te podrá decir que NO. El Amarre. 19 | 20 | ## Lo que aprendes 21 | - HTML 22 | - CSS 23 | - Reproduicción de audio y video 24 | - Funciones de JS 25 | - Manejo del DOM 26 | - Manejo de eventos 27 | 28 | **Te recomiendo leer muy bien los comentarios del codigo.** 29 | 30 | Archivo: index.html 31 | ```html 32 | 33 | 34 | 35 | 36 | 37 | 38 | ¿Quieres ser mi Sempai/Waifu? 39 | 40 | 41 | 42 | 47 | 48 | 49 | 50 | 51 | 54 |
55 |

MODO SEXO ACTIVADO :3

56 | 57 |
58 | 59 | 63 | 67 | 68 |

DI QUE SÍ POR FAVOR

69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | ``` 79 | 80 | **NOTA:** Al cargar el JS antes del HTML podríamos asegurar, por ejemplo, que un usuario no loggeado vea algo del contenido. Al cargarlo después, podemos colocarle eventos a los botones. Por ejemplo, que mande una notificación al presionar un botón. 81 | 82 | ```css 83 | button:hover { 84 | cursor: pointer; 85 | } 86 | 87 | h1 { 88 | color: blueviolet; 89 | font-family: Arial, Helvetica, sans-serif; 90 | } 91 | 92 | .modo_sexo { 93 | height: 2000px; 94 | position: absolute; 95 | display: none; 96 | width: 100%; 97 | background-color: red; 98 | z-index: 1000; 99 | } 100 | 101 | #btn_si { 102 | background-color: cadetblue; 103 | border-color: cadetblue; 104 | color: azure; 105 | font-size: xx-large; 106 | padding: 32px; 107 | text-align: center; 108 | border-radius: 2px; 109 | } 110 | ``` 111 | 112 | ```JavaScript 113 | function moverPosicionRandom(elm) { 114 | elm.style.position = 'absolute'; 115 | elm.style.top = Math.random() * (window.innerHeight - elm.offsetHeight) + 'px'; 116 | elm.style.left = Math.random() * (window.innerWidth - elm.offsetWidth) + 'px'; 117 | } 118 | 119 | let btnSi = document.getElementById("btn_si"); 120 | let btnNo = document.getElementById("btn_no"); 121 | let divModoSexo = document.getElementsByClassName("modo_sexo")[0]; 122 | 123 | btnNo.addEventListener('mouseenter', function(e) { moverPosicionRandom(e.target) }); 124 | 125 | btnSi.addEventListener('click', function(e) { 126 | alert('Sabía que dirías que SÍ. Casemonos ya y tengamos hijos. TE AMO!!!! ❤️'); 127 | 128 | divModoSexo.style.display = 'block'; 129 | const cancion = new Audio('img\\modo_hot.mp3'); 130 | //cancion.play(); 131 | }); 132 | 133 | divModoSexo.addEventListener('click', function(e) { 134 | const img = document.createElement("img"); 135 | img.src = "https://i.pinimg.com/originals/c5/e3/c9/c5e3c9b5260daa31f5a4ab03ff048ece.png"; 136 | console.log(img) 137 | divModoSexo.appendChild(img) 138 | }); 139 | 140 | botones = document.getElementsByTagName("button") 141 | console.log(botones) 142 | 143 | window.addEventListener('beforeunload', (event) => { 144 | event.preventDefault(); 145 | event.returnValue = ""; 146 | }); 147 | ``` 148 | -------------------------------------------------------------------------------- /00-Prework/git-ssh.md: -------------------------------------------------------------------------------- 1 | # Instalación de Git y configuración de GitHub 2 | 3 | Git es un sistema de control de versiones distribuido, lo que significa que un clon local del proyecto es un repositorio de control de versiones completo. Estos repositorios locales plenamente funcionales permiten trabajar sin conexión o de forma remota con facilidad. 4 | 5 | ## Instalación de Git en Windows 6 | 7 | 1. Descargar Git para Windows [-> dando clic aquí <-](https://git-scm.com/download/win) 8 | - Verifica que tipo de sistema operativo tienes, de 32 o 64 bits. Eso lo puedes verificar en **Configuración > Sistema > Información del sistema** y selecciona la opción correcta 9 | 10 | 2. Sigue todos los pasos predeterminados del instalador 11 | 3. Comprueba que se instalo Git correctamente abriendo un cmd simbolo de sistema ejecutando el comando ``git`` en la terminal. Si tienes como resultado lo siguiente: 12 | 13 | ![Git error](https://www.partitionwizard.com/images/uploads/articles/2021/05/git-is-not-recognized/git-is-not-recognized-1.png) 14 | 15 | Habrá que colocar la ruta de Git en las variables de entorno de Windows. Puedes seguir este tutorial para resolver esto [-> da clic aquí <-](https://programmerclick.com/article/44141352196/). 16 | 17 | ## Instalación de Git en Mac 18 | 19 | 1. Instala [Homebrew](https://brew.sh/index_es) que es un instalador de paquetes de Mac. Para ello puedes ejecutar el siguiente comando en la terminal: 20 | 21 | ```bash 22 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 23 | ``` 24 | 25 | Sigue las instrucciones finales del instalador de Homebrew 26 | 27 | 2. Instala Git con Homebrew usando el siguiente comando: 28 | 29 | ```bash 30 | brew install git 31 | ``` 32 | 33 | 3. Comprueba que se instalo Git correctamente en la terminal ejecutando el comando ``git``. 34 | 35 | ## Instalación en Linux 36 | 37 | Hay algunas distros de Linux como Kali Linux que ya tienen preinstalado Git. Sin embargo, así puedes instalarlo dependiedo de tu distro: 38 | 39 | Debian/Ubuntu 40 | 41 | ```bash 42 | sudo apt-get install git 43 | ``` 44 | 45 | Para Ubuntu, este PPA proporciona la última versión Git 46 | 47 | ```bash 48 | sudo add-apt-repository ppa:git-core/ppa 49 | sudo apt update 50 | sudo apt install git 51 | ``` 52 | 53 | Fedora 54 | 55 | ```bash 56 | dnf install git 57 | ``` 58 | 59 | Gentoo 60 | ```bash 61 | emerge --ask --verbose dev-vcs/git 62 | ``` 63 | 64 | Arch Linux 65 | ```bash 66 | pacman -S git 67 | ``` 68 | 69 | openSUSE 70 | ```bash 71 | zypper install git 72 | ``` 73 | 74 | Mageia 75 | ```bash 76 | urpmi git 77 | ``` 78 | 79 | Nix/NixOS 80 | ```bash 81 | nix-env -i git 82 | ``` 83 | 84 | FreeBSD 85 | ```bash 86 | pkg install git 87 | ``` 88 | 89 | ## Instalación del SSH en tu cuenta de GitHub 90 | 91 | 1. Crea una cuenta de GitHub -> https://github.com/ 92 | 2. Ve a Settings > SSH and GPG Keys 93 | 3. Sigue las instrucciones de acuerdo a tu sistema operativo: 94 | 1. [Windows](#para-windows) 95 | 2. [MacOs](#para-mac) 96 | 3. [Linux](#para-linux) 97 | 98 | ### Para Windows 99 | 100 | 1. Abre Git Bash 101 | 2. Ejecuta `ls -al ~/.ssh` Para ver si hay llaves SSH presentes 102 | 3. checa la lista del directorio para ver si ya tienes una clave SSH pública. De forma predeterminada, los nombres de archivo de las claves públicas admitidas para GitHub son uno de los siguientes. 103 | - id_rsa.pub 104 | - id_ecdsa.pub 105 | - id_ed25519.pub 106 | 107 | Si tienes una llave ve al paso 8 108 | 109 | 4. Si no tienes una llave generala con el siguiente comando sustituyendo el email ejemplo por el que tienes con tu cuenta de GitHub: 110 | 111 | ```cmd 112 | ssh-keygen -t ed25519 -C "your_email@example.com" 113 | ``` 114 | 115 | 5. Sigue las instrucciones y si te pide una contraseña puedes crear una o solo darle Enter para seguir sin contraseña. 116 | 6. Inicia el agente SSH con el siguiente comando: 117 | ```cmd 118 | eval "$(ssh-agent -s)" 119 | ``` 120 | 7. Añade tu clave privada al agente SSH con el siguiente comando: 121 | ```cmd 122 | ssh-add ~/.ssh/id_ed25519 123 | ``` 124 | 125 | 8. Copia en tu portapapeles la clave publica SSH con el siguiente comando: 126 | ```cmd 127 | clip < ~/.ssh/id_ed25519.pub 128 | ``` 129 | 130 | 9. Pegalo en la sección Settings > SSH and GPG Keys de GitHub y guarda los cambios. 131 | 132 | ### Para Mac 133 | 134 | 1. Abre Git Bash 135 | 2. Ejecuta `ls -al ~/.ssh` Para ver si hay llaves SSH presentes 136 | 3. checa la lista del directorio para ver si ya tienes una clave SSH pública. De forma predeterminada, los nombres de archivo de las claves públicas admitidas para GitHub son uno de los siguientes. 137 | - id_rsa.pub 138 | - id_ecdsa.pub 139 | - id_ed25519.pub 140 | 141 | Si tienes una llave ve al paso 8 142 | 143 | 4. Si no tienes una llave generala con el siguiente comando sustituyendo el email ejemplo por el que tienes con tu cuenta de GitHub: 144 | 145 | ```bash 146 | ssh-keygen -t ed25519 -C "your_email@example.com" 147 | ``` 148 | 149 | 5. Sigue las instrucciones y si te pide una contraseña puedes crear una o solo darle Enter para seguir sin contraseña. 150 | 6. Inicia el agente SSH con el siguiente comando: 151 | ```bash 152 | eval "$(ssh-agent -s)" 153 | ``` 154 | 7. Añade tu clave privada al agente SSH con el siguiente comando: 155 | ```bash 156 | ssh-add ~/.ssh/id_ed25519 157 | ``` 158 | 159 | 8. Copia en tu portapapeles la clave publica SSH con el siguiente comando: 160 | ```bash 161 | pbcopy < ~/.ssh/id_ed25519.pub 162 | ``` 163 | 164 | 9. Pegalo en la sección Settings > SSH and GPG Keys de GitHub y guarda los cambios. 165 | 166 | ### Para Linux 167 | 168 | 1. Abre Git Bash 169 | 2. Ejecuta `ls -al ~/.ssh` Para ver si hay llaves SSH presentes 170 | 3. checa la lista del directorio para ver si ya tienes una clave SSH pública. De forma predeterminada, los nombres de archivo de las claves públicas admitidas para GitHub son uno de los siguientes. 171 | - id_rsa.pub 172 | - id_ecdsa.pub 173 | - id_ed25519.pub 174 | 175 | Si tienes una llave ve al paso 8 176 | 177 | 4. Si no tienes una llave generala con el siguiente comando sustituyendo el email ejemplo por el que tienes con tu cuenta de GitHub: 178 | 179 | ```bash 180 | ssh-keygen -t ed25519 -C "your_email@example.com" 181 | ``` 182 | 183 | 5. Sigue las instrucciones y si te pide una contraseña puedes crear una o solo darle Enter para seguir sin contraseña. 184 | 6. Inicia el agente SSH con el siguiente comando: 185 | ```bash 186 | eval "$(ssh-agent -s)" 187 | ``` 188 | 7. Añade tu clave privada al agente SSH con el siguiente comando: 189 | ```bash 190 | ssh-add ~/.ssh/id_ed25519 191 | ``` 192 | 193 | 8. Copia en tu portapapeles la clave publica SSH con el siguiente comando: 194 | ```bash 195 | cat ~/.ssh/id_ed25519.pub 196 | ``` 197 | 198 | 9. Pegalo en la sección Settings > SSH and GPG Keys de GitHub y guarda los cambios. -------------------------------------------------------------------------------- /02-Fundamentos-React/proyecto-todo.md: -------------------------------------------------------------------------------- 1 | # Proyecto 2 | 3 | ## TODO APP 4 | 5 | # Pendiente 6 | 7 | Solo hice cambie/cree los siguuientes de un proyecto en blanco de React.js 8 | 9 | App.js 10 | ```JavaScript 11 | import './App.scss'; 12 | import Container from './components/Container' 13 | 14 | function App() { 15 | return ( 16 |
17 | 18 |
19 | ); 20 | } 21 | 22 | export default App; 23 | 24 | ``` 25 | 26 | /components/Checkbox.jsx 27 | ```JavaScript 28 | import React, { Fragment } from "react"; 29 | 30 | const Checkbox = props => { 31 | 32 | const { 33 | onChange, 34 | data: {id, description, done} 35 | } = props; 36 | 37 | return ( 38 | 39 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 75 | ); 76 | } 77 | 78 | export default Checkbox; 79 | ``` 80 | 81 | /components/Container.jsx 82 | ```JavaScript 83 | import React, { useState } from "react"; 84 | import FormTodo from './FormTodo'; 85 | import TaskList from './TaskList'; 86 | 87 | const Container = () => { 88 | const [list, setList] = useState([]); 89 | 90 | const addItem = addItem => { 91 | setList([...list, addItem]) 92 | }; 93 | 94 | return ( 95 |
96 | 97 | 98 |
99 | ); 100 | } 101 | 102 | export default Container 103 | ``` 104 | 105 | /components/FormTodo.jsx 106 | ```JavaScript 107 | import React, { useState } from "react"; 108 | 109 | const FormTodo = props => { 110 | const [description, setDescription] = useState(""); 111 | const {addItem} = props; 112 | 113 | const handleSubmit = e => { 114 | e.preventDefault(); 115 | console.log(description) 116 | 117 | addItem({ 118 | done: false, 119 | id: (new Date()).toString(), 120 | description 121 | }); 122 | 123 | setDescription(""); 124 | } 125 | 126 | return ( 127 |
128 |
129 |
130 | setDescription(e.target.value)} 135 | /> 136 | 150 |
151 |
152 |
153 | ); 154 | } 155 | 156 | export default FormTodo; 157 | ``` 158 | 159 | /components/TaskList.jsx 160 | ```JavaScript 161 | import React from "react"; 162 | import Checkbox from "./Checkbox"; 163 | 164 | const TaskList = props => { 165 | const {list, setList} = props; 166 | 167 | const onChangeStatus = e => { 168 | const {name, checked} = e.target; 169 | const updateList = list.map(item => ({ 170 | ...item, 171 | done: item.id === name ? checked : item.done 172 | })); 173 | setList(updateList); 174 | }; 175 | 176 | const onClickRemoveItem = e => { 177 | const updateList = list.filter(item => !item.done); 178 | setList(updateList) 179 | }; 180 | 181 | const checkbox = list.map(item => ( 182 | 183 | )); 184 | 185 | return ( 186 |
187 | {list.length ? checkbox : "No hay tareas"} 188 | {list.length ? ( 189 |

190 | 191 |

192 | ) : null} 193 |
194 | ) 195 | } 196 | 197 | export default TaskList; 198 | ``` 199 | 200 | ```scss 201 | html { 202 | background: #ddd; 203 | height: 100%; 204 | display: flex; 205 | } 206 | body { 207 | width: 100%; 208 | margin: auto; 209 | } 210 | 211 | .App { 212 | font-family: sans-serif; 213 | text-align: center; 214 | } 215 | 216 | .todo-list { 217 | background: #fff; 218 | font-size: 18px; 219 | max-width: 300px; 220 | margin: auto; 221 | margin-bottom: 24px; 222 | padding: 8px 16px; 223 | box-shadow: 0 5px 30px rgba(0,0,0,0.2); 224 | } 225 | 226 | $colorRosa: #C2185B; 227 | $colorRosaHover: #E91E63; 228 | 229 | $colorAzul: #1976D2; 230 | $colorAzulHover: #03A9F4; 231 | 232 | @mixin button($class, $color, $colorHover) { 233 | .button.#{$class}{background: $color;} 234 | .button.#{$class}:hover{background: $colorHover;} 235 | .button.#{$class}:active{background: $color;} 236 | } 237 | 238 | .button { 239 | outline: none; 240 | padding: 8px; 241 | border: 1px solid white; 242 | border-radius: 15px; 243 | color: white; 244 | } 245 | 246 | @include button ('pink', $colorRosa, $colorRosaHover); 247 | @include button ('blue', $colorAzul, $colorAzulHover); 248 | 249 | .file_input { 250 | padding: 2px; 251 | background: #f8f8f8; 252 | } 253 | 254 | .file_input > .text { 255 | outline: none; 256 | padding: 0px, 10px; 257 | font-size: 18px; 258 | width: 230px; 259 | height: 43; 260 | background: transparent; 261 | border: 0px solid; 262 | } 263 | 264 | $duracion: 0.4s; 265 | $stroke: #34eb9f; 266 | $colorText: #222222; 267 | $colorTextChecked: #85e6e4; 268 | 269 | .todo { 270 | display: block; 271 | position: relative; 272 | padding: 1em 1em 1em 16%; 273 | margin: 0 auto; 274 | cursor: pointer; 275 | border-bottom: solid 1px #ddd; 276 | &:last-child {border-bottom: none;} 277 | } 278 | 279 | .todo.new-item { 280 | opacity: 0; 281 | transform: translateX(100px); 282 | animation: fadeIn .3s linear forwards; 283 | } 284 | 285 | @keyframes fadeIn { 286 | to { 287 | transform: translateX(0px); 288 | opacity: 1; 289 | } 290 | } 291 | 292 | .todo_state { 293 | position: absolute; 294 | top: 0; 295 | left: 0; 296 | opacity: 0; 297 | } 298 | 299 | .todo_text { 300 | color: $colorText; 301 | text-align: right; 302 | transition: all $duracion/2 linear $duracion/2; 303 | } 304 | 305 | .todo_icon { 306 | position: absolute; 307 | top: 0; 308 | bottom: 0; 309 | left: 0; 310 | width: 100%; 311 | height: auto; 312 | margin: auto; 313 | 314 | fill: none; 315 | stroke: $stroke; 316 | stroke-width: 2; 317 | stroke-linejoin: round; 318 | stroke-linecap: round; 319 | } 320 | 321 | .todo_line, .todo_box, .todo_check { 322 | transition: stroke-dashoffset $duracion cubic-bezier(0.075, 0.82, 0.165, 1) 323 | } 324 | 325 | .todo_circle { 326 | stroke: $stroke; 327 | stroke-dasharray: 1 6; 328 | stroke-width: 0; 329 | 330 | transform-origin: 13.5px 12.5px; 331 | transform: scale(0.4) rotate(0deg); 332 | animation: none $duracion linear; 333 | 334 | @keyframes explode { 335 | 30% { 336 | stroke-width: 3; 337 | stroke-opacity: 1; 338 | transform: scale(0.8) rotate(40deg); 339 | } 340 | 341 | 100% { 342 | stroke-width: 0; 343 | stroke-opacity: 0; 344 | transform: scale(1.1) rotate(60deg); 345 | } 346 | } 347 | 348 | } 349 | 350 | .todo_box { 351 | stroke-dasharray: 56, 56; 352 | stroke-dashoffset: 0; 353 | transition-delay: $duracion * 0.2; 354 | } 355 | 356 | .todo_check { 357 | stroke: $stroke; 358 | stroke-dasharray: 9.8 9.8; 359 | stroke-dashoffset: 9; 360 | transition-delay: $duracion * 0.4; 361 | } 362 | 363 | .todo_line { 364 | stroke-dasharray: 168, 168; 365 | stroke-dashoffset: 168; 366 | } 367 | 368 | .todo_circle { 369 | animation-delay: $duracion * 0.7; 370 | animation-duration: $duracion * 0.7; 371 | } 372 | 373 | .todo_state:checked { 374 | ~ .todo_text { transition-delay: 0s; color: $colorTextChecked; opacity: 0.6;} 375 | ~ .todo_icon .todo_box { stroke-dashoffset: 56; transition-delay: 0s; } 376 | ~ .todo_icon .todo_line { stroke-dashoffset: -8; } 377 | ~ .todo_icon .todo_check { stroke-dashoffset: 0; transition-delay: $duracion * 0.6; } 378 | ~ .todo_icon .todo_circle { animation-name: explode;} 379 | } 380 | ``` -------------------------------------------------------------------------------- /03-Node.js/proyecto-barcos.md: -------------------------------------------------------------------------------- 1 | # Proyecto 2 | ## Barcos multijugador 3 | 4 | Repositorio para fork en -> https://github.com/josejesusguzman/Batalla-naval-Ejercicio-Node 5 | 6 | Package.json 7 | ```JSON 8 | { 9 | "name": "barcos-multijugador", 10 | "version": "1.0.0", 11 | "description": "", 12 | "main": "server.js", 13 | "scripts": { 14 | "start": "node server", 15 | "test": "nodemon server" 16 | }, 17 | "keywords": [], 18 | "author": "", 19 | "license": "ISC", 20 | "devDependencies": { 21 | "nodemon": "^2.0.20" 22 | }, 23 | "dependencies": { 24 | "express": "^4.18.2", 25 | "socket.io": "^4.5.4" 26 | } 27 | } 28 | 29 | ``` 30 | 31 | Server.js 32 | ```JavaScript 33 | 34 | const express = require('express'); 35 | const path = require('path'); 36 | const http = require('http'); 37 | const PORT = process.env.PORT || 3000; 38 | const socket = require('socket.io'); 39 | const app = express(); 40 | const server = http.createServer(app); 41 | const io = socket(server); 42 | 43 | app.use(express.static('public')); 44 | 45 | server.listen(PORT, () => console.log("El servidor esta corriendo")); 46 | 47 | const connections = [null, null]; 48 | 49 | io.on('connection', socket => { 50 | let playerIndex = -1; 51 | for (const i in connections) { 52 | if (connections[i] === null) { 53 | playerIndex = i; 54 | break; 55 | } 56 | } 57 | 58 | socket.emit("player-number", playerIndex); 59 | 60 | console.log(`Jugador ${playerIndex} se ha conectado`); 61 | 62 | if (playerIndex === -1) return; 63 | connections[playerIndex] = false; 64 | 65 | socket.broadcast.emit('player-connection', playerIndex); 66 | 67 | socket.on('disconnect', () => { 68 | console.log(`Jugador ${playerIndex} se ha desconectado`); 69 | connections[playerIndex] = null; 70 | socket.broadcast.emit('player-connection', playerIndex); 71 | }); 72 | 73 | socket.on('player-ready', () => { 74 | socket.broadcast.emit('enemy-ready', playerIndex); 75 | connections[playerIndex] = true; 76 | }); 77 | 78 | socket.on('check-players', () => { 79 | const players = []; 80 | for (const i in connections) { 81 | connections[i] === null ? 82 | players.push({connected: false, ready: false}) : 83 | players.push({connected: true, ready: connections[i]}); 84 | } 85 | socket.emit('check-players', players); 86 | }); 87 | 88 | socket.on('fire', id => { 89 | console.log(`Disparo de ${playerIndex}`, id); 90 | socket.broadcast.emit('fire', id); 91 | }); 92 | 93 | socket.on('fire-reply', square =>{ 94 | console.log(square); 95 | socket.broadcast.emit('fire-reply', square); 96 | }); 97 | 98 | setTimeout(() => { 99 | connections[playerIndex] = null; 100 | socket.emit('timeout'); 101 | socket.disconnect(); 102 | }, 600000); 103 | 104 | }); 105 | 106 | ``` 107 | 108 | public/index.html 109 | ```HTML 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | Batalla naval 118 | 119 | 120 | 121 | 122 |
123 |

Batalla naval

124 |
125 | Un solo jugador 126 | 127 | Multiplayer 128 |
129 |
130 | 131 | 132 | 133 | 134 | 135 | 136 | ``` 137 | 138 | public/singleplayer.html 139 | ```HTML 140 | 141 | 142 | 143 | 144 | 145 | 146 | Batalla naval 147 | 148 | 151 | 152 | 153 | 154 |
155 |
156 |
157 |
158 | 159 |
160 |
161 | 162 | 163 |
164 |

Tu turno

165 |

166 |
167 | 168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 | 200 | 201 | 202 | ``` 203 | 204 | public/multiplayer.html 205 | ```HTML 206 | 207 | 208 | 209 | 210 | 211 | 212 | Batalla naval 213 | 214 | 215 | 218 | 219 | 220 | 221 | 222 | 223 |
224 |
225 | Player 1 226 |
Connected
227 |
Ready
228 |
229 | 230 |
231 | Player 2 232 |
Connected
233 |
Ready
234 |
235 |
236 | 237 |
238 |
239 |
240 |
241 | 242 |
243 |
244 | 245 | 246 |
247 |

Your Go

248 |

249 |
250 | 251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 | 283 | 284 | 285 | 286 | ``` 287 | 288 | public/cliente.js 289 | 290 | ```JavaScript 291 | 292 | document.addEventListener('DOMContentLoaded', () => { 293 | const userGrid = document.querySelector('.grid-user') 294 | const computerGrid = document.querySelector('.grid-computer') 295 | const displayGrid = document.querySelector('.grid-display') 296 | const ships = document.querySelectorAll('.ship') 297 | const destroyer = document.querySelector('.destroyer-container') 298 | const submarine = document.querySelector('.submarine-container') 299 | const cruiser = document.querySelector('.cruiser-container') 300 | const battleship = document.querySelector('.battleship-container') 301 | const carrier = document.querySelector('.carrier-container') 302 | const startButton = document.querySelector('#start') 303 | const rotateButton = document.querySelector('#rotate') 304 | const turnDisplay = document.querySelector('#whose-go') 305 | const infoDisplay = document.querySelector('#info') 306 | const setupButtons = document.getElementById('setup-buttons') 307 | const userSquares = [] 308 | const computerSquares = [] 309 | let isHorizontal = true 310 | let isGameOver = false 311 | let currentPlayer = 'user' 312 | const width = 10 313 | let playerNum = 0 314 | let ready = false 315 | let enemyReady = false 316 | let allShipsPlaced = false 317 | let shotFired = -1 318 | // Los barcos 319 | const shipArray = [ 320 | { 321 | name: 'destroyer', 322 | directions: [ 323 | [0, 1], 324 | [0, width] 325 | ] 326 | }, 327 | { 328 | name: 'submarine', 329 | directions: [ 330 | [0, 1, 2], 331 | [0, width, width * 2] 332 | ] 333 | }, 334 | { 335 | name: 'cruiser', 336 | directions: [ 337 | [0, 1, 2], 338 | [0, width, width * 2] 339 | ] 340 | }, 341 | { 342 | name: 'battleship', 343 | directions: [ 344 | [0, 1, 2, 3], 345 | [0, width, width * 2, width * 3] 346 | ] 347 | }, 348 | { 349 | name: 'carrier', 350 | directions: [ 351 | [0, 1, 2, 3, 4], 352 | [0, width, width * 2, width * 3, width * 4] 353 | ] 354 | }, 355 | ] 356 | 357 | createBoard(userGrid, userSquares) 358 | createBoard(computerGrid, computerSquares) 359 | 360 | // Seleccion del modo de juego 361 | if (gameMode === 'singlePlayer') { 362 | startSinglePlayer() 363 | } else { 364 | startMultiPlayer() 365 | } 366 | 367 | // Multijugador 368 | function startMultiPlayer() { 369 | const socket = io(); 370 | 371 | // Obten tu número de jugador del server 372 | socket.on('player-number', num => { 373 | if (num === -1) { 374 | infoDisplay.innerHTML = "El servidor esta lleno" 375 | } else { 376 | playerNum = parseInt(num) 377 | if (playerNum === 1) currentPlayer = "enemy" 378 | 379 | console.log(playerNum) 380 | 381 | // Revisa el status de los otros jugadores 382 | socket.emit('check-players') 383 | } 384 | }) 385 | 386 | // Si el otro jugador se ha desconectado o conectado 387 | socket.on('player-connection', num => { 388 | console.log(`Jugador ${num} se fue`) 389 | playerConnectedOrDisconnected(num) 390 | }) 391 | 392 | // Cuando el enemigo esta listo 393 | socket.on('enemy-ready', num => { 394 | enemyReady = true 395 | playerReady(num) 396 | if (ready) { 397 | playGameMulti(socket) 398 | setupButtons.style.display = 'none' 399 | } 400 | }) 401 | 402 | // Revisa el status del jugador 403 | socket.on('check-players', players => { 404 | players.forEach((p, i) => { 405 | if (p.connected) playerConnectedOrDisconnected(i) 406 | if (p.ready) { 407 | playerReady(i) 408 | if (i !== playerReady) enemyReady = true 409 | } 410 | }) 411 | }) 412 | 413 | // cuando se acaba el tiempo 414 | socket.on('timeout', () => { 415 | infoDisplay.innerHTML = '¿Sigues ahí? se te acabo el tiempo' 416 | }) 417 | 418 | // Clic para el boton ready 419 | startButton.addEventListener('click', () => { 420 | if (allShipsPlaced) playGameMulti(socket) 421 | else infoDisplay.innerHTML = "Debes poner TODOS los barcos primero" 422 | }) 423 | 424 | // Configurar listeners para disparar 425 | computerSquares.forEach(square => { 426 | square.addEventListener('click', () => { 427 | if (currentPlayer === 'user' && ready && enemyReady) { 428 | shotFired = square.dataset.id 429 | socket.emit('fire', shotFired) 430 | } 431 | }) 432 | }) 433 | 434 | // Cuando recibes un disparo 435 | socket.on('fire', id => { 436 | enemyGo(id) 437 | const square = userSquares[id] 438 | socket.emit('fire-reply', square.classList) 439 | playGameMulti(socket) 440 | }) 441 | 442 | // Cuando se recibe una replica de disparo 443 | socket.on('fire-reply', classList => { 444 | revealSquare(classList) 445 | playGameMulti(socket) 446 | }) 447 | 448 | function playerConnectedOrDisconnected(num) { 449 | let player = `.p${parseInt(num) + 1}` 450 | document.querySelector(`${player} .connected`).classList.toggle('active') 451 | if (parseInt(num) === playerNum) document.querySelector(player).style.fontWeight = 'bold' 452 | } 453 | } 454 | 455 | // Modo un solo jugador 456 | function startSinglePlayer() { 457 | generate(shipArray[0]) 458 | generate(shipArray[1]) 459 | generate(shipArray[2]) 460 | generate(shipArray[3]) 461 | generate(shipArray[4]) 462 | 463 | startButton.addEventListener('click', () => { 464 | setupButtons.style.display = 'none' 465 | playGameSingle() 466 | }) 467 | } 468 | 469 | // Creamos el tablero de juego 470 | function createBoard(grid, squares) { 471 | for (let i = 0; i < width * width; i++) { 472 | const square = document.createElement('div') 473 | square.dataset.id = i 474 | grid.appendChild(square) 475 | squares.push(square) 476 | } 477 | } 478 | 479 | // Dibuja los barcos de las computadoras en ubicaciones aleatorias. 480 | function generate(ship) { 481 | let randomDirection = Math.floor(Math.random() * ship.directions.length) 482 | let current = ship.directions[randomDirection] 483 | if (randomDirection === 0) direction = 1 484 | if (randomDirection === 1) direction = 10 485 | let randomStart = Math.abs(Math.floor(Math.random() * computerSquares.length - (ship.directions[0].length * direction))) 486 | 487 | const isTaken = current.some(index => computerSquares[randomStart + index].classList.contains('taken')) 488 | const isAtRightEdge = current.some(index => (randomStart + index) % width === width - 1) 489 | const isAtLeftEdge = current.some(index => (randomStart + index) % width === 0) 490 | 491 | if (!isTaken && !isAtRightEdge && !isAtLeftEdge) current.forEach(index => computerSquares[randomStart + index].classList.add('taken', ship.name)) 492 | 493 | else generate(ship) 494 | } 495 | 496 | 497 | // Rotación de los barcos 498 | function rotate() { 499 | if (isHorizontal) { 500 | destroyer.classList.toggle('destroyer-container-vertical') 501 | submarine.classList.toggle('submarine-container-vertical') 502 | cruiser.classList.toggle('cruiser-container-vertical') 503 | battleship.classList.toggle('battleship-container-vertical') 504 | carrier.classList.toggle('carrier-container-vertical') 505 | isHorizontal = false 506 | // console.log(isHorizontal) 507 | return 508 | } 509 | if (!isHorizontal) { 510 | destroyer.classList.toggle('destroyer-container-vertical') 511 | submarine.classList.toggle('submarine-container-vertical') 512 | cruiser.classList.toggle('cruiser-container-vertical') 513 | battleship.classList.toggle('battleship-container-vertical') 514 | carrier.classList.toggle('carrier-container-vertical') 515 | isHorizontal = true 516 | // console.log(isHorizontal) 517 | return 518 | } 519 | } 520 | rotateButton.addEventListener('click', rotate) 521 | 522 | // moverse por el barco del jugador 523 | ships.forEach(ship => ship.addEventListener('dragstart', dragStart)) 524 | userSquares.forEach(square => square.addEventListener('dragstart', dragStart)) 525 | userSquares.forEach(square => square.addEventListener('dragover', dragOver)) 526 | userSquares.forEach(square => square.addEventListener('dragenter', dragEnter)) 527 | userSquares.forEach(square => square.addEventListener('dragleave', dragLeave)) 528 | userSquares.forEach(square => square.addEventListener('drop', dragDrop)) 529 | userSquares.forEach(square => square.addEventListener('dragend', dragEnd)) 530 | 531 | let selectedShipNameWithIndex 532 | let draggedShip 533 | let draggedShipLength 534 | 535 | ships.forEach(ship => ship.addEventListener('mousedown', (e) => { 536 | selectedShipNameWithIndex = e.target.id 537 | // console.log(selectedShipNameWithIndex) 538 | })) 539 | 540 | function dragStart() { 541 | draggedShip = this 542 | draggedShipLength = this.childNodes.length 543 | // console.log(draggedShip) 544 | } 545 | 546 | function dragOver(e) { 547 | e.preventDefault() 548 | } 549 | 550 | function dragEnter(e) { 551 | e.preventDefault() 552 | } 553 | 554 | function dragLeave() { 555 | // console.log('drag leave') 556 | } 557 | 558 | function dragDrop() { 559 | let shipNameWithLastId = draggedShip.lastChild.id 560 | let shipClass = shipNameWithLastId.slice(0, -2) 561 | // console.log(shipClass) 562 | let lastShipIndex = parseInt(shipNameWithLastId.substr(-1)) 563 | let shipLastId = lastShipIndex + parseInt(this.dataset.id) 564 | // console.log(shipLastId) 565 | const notAllowedHorizontal = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 1, 11, 21, 31, 41, 51, 61, 71, 81, 91, 2, 22, 32, 42, 52, 62, 72, 82, 92, 3, 13, 23, 33, 43, 53, 63, 73, 83, 93] 566 | const notAllowedVertical = [99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60] 567 | 568 | let newNotAllowedHorizontal = notAllowedHorizontal.splice(0, 10 * lastShipIndex) 569 | let newNotAllowedVertical = notAllowedVertical.splice(0, 10 * lastShipIndex) 570 | 571 | selectedShipIndex = parseInt(selectedShipNameWithIndex.substr(-1)) 572 | 573 | shipLastId = shipLastId - selectedShipIndex 574 | // console.log(shipLastId) 575 | 576 | if (isHorizontal && !newNotAllowedHorizontal.includes(shipLastId)) { 577 | for (let i = 0; i < draggedShipLength; i++) { 578 | let directionClass 579 | if (i === 0) directionClass = 'start' 580 | if (i === draggedShipLength - 1) directionClass = 'end' 581 | userSquares[parseInt(this.dataset.id) - selectedShipIndex + i].classList.add('taken', 'horizontal', directionClass, shipClass) 582 | } 583 | // Siempre que el índice de la nave que está arrastrando no esté en la matriz newNotAllowedVertical. Esto significa que a veces si arrastras el barco por su index-1 , index-2 y así sucesivamente, el barco regresará a displayGrid. 584 | } else if (!isHorizontal && !newNotAllowedVertical.includes(shipLastId)) { 585 | for (let i = 0; i < draggedShipLength; i++) { 586 | let directionClass 587 | if (i === 0) directionClass = 'start' 588 | if (i === draggedShipLength - 1) directionClass = 'end' 589 | userSquares[parseInt(this.dataset.id) - selectedShipIndex + width * i].classList.add('taken', 'vertical', directionClass, shipClass) 590 | } 591 | } else return 592 | 593 | displayGrid.removeChild(draggedShip) 594 | if (!displayGrid.querySelector('.ship')) allShipsPlaced = true 595 | } 596 | 597 | function dragEnd() { 598 | // console.log('dragend') 599 | } 600 | 601 | // Logica para el Mukltijugador 602 | function playGameMulti(socket) { 603 | setupButtons.style.display = 'none' 604 | if (isGameOver) return 605 | if (!ready) { 606 | socket.emit('player-ready') 607 | ready = true 608 | playerReady(playerNum) 609 | } 610 | 611 | if (enemyReady) { 612 | if (currentPlayer === 'user') { 613 | turnDisplay.innerHTML = 'Tu turno' 614 | } 615 | if (currentPlayer === 'enemy') { 616 | turnDisplay.innerHTML = "Turno enemigo" 617 | } 618 | } 619 | } 620 | 621 | function playerReady(num) { 622 | let player = `.p${parseInt(num) + 1}` 623 | document.querySelector(`${player} .ready`).classList.toggle('active') 624 | } 625 | 626 | // Game Logic for Single Player 627 | function playGameSingle() { 628 | if (isGameOver) return 629 | if (currentPlayer === 'user') { 630 | turnDisplay.innerHTML = 'Tu turno' 631 | computerSquares.forEach(square => square.addEventListener('click', function (e) { 632 | shotFired = square.dataset.id 633 | revealSquare(square.classList) 634 | })) 635 | } 636 | if (currentPlayer === 'enemy') { 637 | turnDisplay.innerHTML = 'Computers Go' 638 | setTimeout(enemyGo, 1000) 639 | } 640 | } 641 | 642 | let destroyerCount = 0 643 | let submarineCount = 0 644 | let cruiserCount = 0 645 | let battleshipCount = 0 646 | let carrierCount = 0 647 | 648 | function revealSquare(classList) { 649 | const enemySquare = computerGrid.querySelector(`div[data-id='${shotFired}']`) 650 | const obj = Object.values(classList) 651 | if (!enemySquare.classList.contains('boom') && currentPlayer === 'user' && !isGameOver) { 652 | if (obj.includes('destroyer')) destroyerCount++ 653 | if (obj.includes('submarine')) submarineCount++ 654 | if (obj.includes('cruiser')) cruiserCount++ 655 | if (obj.includes('battleship')) battleshipCount++ 656 | if (obj.includes('carrier')) carrierCount++ 657 | } 658 | if (obj.includes('taken')) { 659 | enemySquare.classList.add('boom') 660 | } else { 661 | enemySquare.classList.add('miss') 662 | } 663 | checkForWins() 664 | currentPlayer = 'enemy' 665 | if (gameMode === 'singlePlayer') playGameSingle() 666 | } 667 | 668 | let cpuDestroyerCount = 0 669 | let cpuSubmarineCount = 0 670 | let cpuCruiserCount = 0 671 | let cpuBattleshipCount = 0 672 | let cpuCarrierCount = 0 673 | 674 | 675 | function enemyGo(square) { 676 | if (gameMode === 'singlePlayer') square = Math.floor(Math.random() * userSquares.length) 677 | if (!userSquares[square].classList.contains('boom')) { 678 | const hit = userSquares[square].classList.contains('taken') 679 | userSquares[square].classList.add(hit ? 'boom' : 'miss') 680 | if (userSquares[square].classList.contains('destroyer')) cpuDestroyerCount++ 681 | if (userSquares[square].classList.contains('submarine')) cpuSubmarineCount++ 682 | if (userSquares[square].classList.contains('cruiser')) cpuCruiserCount++ 683 | if (userSquares[square].classList.contains('battleship')) cpuBattleshipCount++ 684 | if (userSquares[square].classList.contains('carrier')) cpuCarrierCount++ 685 | checkForWins() 686 | } else if (gameMode === 'singlePlayer') enemyGo() 687 | currentPlayer = 'user' 688 | turnDisplay.innerHTML = 'Tu turno' 689 | } 690 | 691 | function checkForWins() { 692 | let enemy = 'computer' 693 | if (gameMode === 'multiPlayer') enemy = 'enemy' 694 | if (destroyerCount === 2) { 695 | infoDisplay.innerHTML = `Hundiste el destructor de ${enemy}` 696 | destroyerCount = 10 697 | } 698 | if (submarineCount === 3) { 699 | infoDisplay.innerHTML = `Hundiste el submarino de ${enemy}` 700 | submarineCount = 10 701 | } 702 | if (cruiserCount === 3) { 703 | infoDisplay.innerHTML = `Hundiste el bote de${enemy}` 704 | cruiserCount = 10 705 | } 706 | if (battleshipCount === 4) { 707 | infoDisplay.innerHTML = `Hundiste el barco de ${enemy}` 708 | battleshipCount = 10 709 | } 710 | if (carrierCount === 5) { 711 | infoDisplay.innerHTML = `Hundiste el carguero de${enemy}` 712 | carrierCount = 10 713 | } 714 | if (cpuDestroyerCount === 2) { 715 | infoDisplay.innerHTML = `${enemy} hundio tu destructor` 716 | cpuDestroyerCount = 10 717 | } 718 | if (cpuSubmarineCount === 3) { 719 | infoDisplay.innerHTML = `${enemy} hundio tu submarino` 720 | cpuSubmarineCount = 10 721 | } 722 | if (cpuCruiserCount === 3) { 723 | infoDisplay.innerHTML = `${enemy} hundio tu bote` 724 | cpuCruiserCount = 10 725 | } 726 | if (cpuBattleshipCount === 4) { 727 | infoDisplay.innerHTML = `${enemy} hundio tu barco` 728 | cpuBattleshipCount = 10 729 | } 730 | if (cpuCarrierCount === 5) { 731 | infoDisplay.innerHTML = `${enemy} hundio tu carguero` 732 | cpuCarrierCount = 10 733 | } 734 | 735 | if ((destroyerCount + submarineCount + cruiserCount + battleshipCount + carrierCount) === 50) { 736 | infoDisplay.innerHTML = "GANASTE" 737 | gameOver() 738 | } 739 | if ((cpuDestroyerCount + cpuSubmarineCount + cpuCruiserCount + cpuBattleshipCount + cpuCarrierCount) === 50) { 740 | infoDisplay.innerHTML = `${enemy.toUpperCase()} GANA` 741 | gameOver() 742 | } 743 | } 744 | 745 | function gameOver() { 746 | isGameOver = true 747 | startButton.removeEventListener('click', playGameSingle) 748 | } 749 | }) 750 | 751 | ``` --------------------------------------------------------------------------------