Skip to content

Commit 7359726

Browse files
authored
Merge pull request #7506 from Kenysdev/36_40.js
#36 - javascript -> #40
2 parents 2cd3259 + ae8f8d4 commit 7359726

File tree

5 files changed

+773
-0
lines changed

5 files changed

+773
-0
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
_____________________________________
3+
https://github.com/kenysdev
4+
2024 - JavaScript
5+
_______________________________________________________
6+
# 36 EL SOMBRERO SELECCIONADOR
7+
-------------------------------------------------------
8+
* EJERCICIO:
9+
* Cada 1 de septiembre, el Hogwarts Express parte hacia la escuela
10+
* de programación de Hogwarts para magos y brujas del código.
11+
* En ella, su famoso sombrero seleccionador ayuda a los programadores
12+
* a encontrar su camino...
13+
* Desarrolla un programa que simule el comportamiento del sombrero.
14+
* Requisitos:
15+
* 1. El sombrero realizará 10 preguntas para determinar la casa del alumno.
16+
* 2. Deben existir 4 casas. Por ejemplo: Frontend, Backend, Mobile y Data.
17+
* (Puedes elegir las que quieras)
18+
* Acciones:
19+
* 1. Crea un programa que solicite el nombre del alumno y realice 10
20+
* preguntas, con cuatro posibles respuestas cada una.
21+
* 2. Cada respuesta asigna puntos a cada una de las casas (a tu elección).
22+
* 3. Una vez finalizado, el sombrero indica el nombre del alumno
23+
* y a qué casa pertenecerá (resuelve el posible empate de manera aleatoria,
24+
* pero indicándole al alumno que la decisión ha sido complicada).
25+
*/
26+
// ________________________________________________________
27+
28+
const readline = require("readline");
29+
const rl = readline.createInterface({
30+
input: process.stdin,
31+
output: process.stdout,
32+
});
33+
34+
const getInput = (prompt) => {
35+
return new Promise((resolve) => {
36+
rl.question(prompt, (input) => {
37+
resolve(input.trim());
38+
});
39+
});
40+
};
41+
42+
const HOUSES = ["Frontend", "Backend", "Mobile", "Data"];
43+
44+
const QUESTIONS = [
45+
"¿Qué te atrae más?",
46+
"¿Qué superhéroe de la programación te gustaría ser?",
47+
"En un proyecto de software, ¿qué rol te emociona más?",
48+
"Si tu código fuera una obra de arte, ¿qué estilo tendría?",
49+
"¿Qué animal de programación serías?",
50+
"En una hackathon, ¿qué tipo de proyecto propondrías?",
51+
"Si tu carrera en tech fuera una película, ¿de qué género sería?",
52+
"¿Qué herramienta de programación no puede faltar en tu caja de herramientas digital?",
53+
"Si pudieras resolver un gran problema en tech, ¿cuál elegirías?",
54+
"¿Qué tipo de equipo prefieres?",
55+
];
56+
57+
const ANSWERS = [
58+
["Crear experiencias visuales.", "Solucionar problemas de funcionamiento.", "Innovar en dispositivos portátiles.", "Descubrir tendencias ocultas."],
59+
["Diseñador de Interfaces, creando experiencias asombrosas", "Arquitecto de Sistemas, construyendo estructuras robustas", "Mago de Apps, conjurando soluciones móviles", "Explorador de Datos, descubriendo tesoros ocultos"],
60+
["Director de UX, orquestando la sinfonía visual", "Ingeniero de Backend, dominando la lógica del servidor", "Desarrollador de Apps, llevando la potencia al bolsillo", "Científico de Datos, descifrando los secretos de la información"],
61+
["Minimalismo elegante, como una landing page perfecta", "Arquitectura compleja, como un sistema distribuido", "Diseño adaptativo, fluyendo en diferentes dispositivos", "Visualización de datos, pintando historias con números"],
62+
["Un camaleón, adaptándome a diferentes frameworks", "Un pulpo, manejando múltiples servicios a la vez", "Un colibrí, ágil y siempre en movimiento", "Una lechuza, analizando datos con sabiduría"],
63+
["Una web app que revolucione la experiencia del usuario", "Un sistema de IA que optimice procesos backend", "Una app móvil que cambie la forma de interactuar con el mundo", "Un proyecto de big data que prediga tendencias futuras"],
64+
["Comedia romántica con JavaScript y CSS", "Thriller de ciencia ficción con microservicios", "Aventura de acción en el mundo de las apps", "Documental profundo sobre el universo de los datos"],
65+
["Un editor de código con plugins para diseño visual", "Una robusta suite de testing y depuración", "Un emulador multi-dispositivo de última generación", "Una plataforma de análisis de datos en tiempo real"],
66+
["Hacer que la accesibilidad web sea universal", "Crear una arquitectura de software autorreparable", "Desarrollar una plataforma de AR/VR para educación móvil", "Construir un modelo de IA ético y transparente"],
67+
["Creativos enfocados en diseño.", "Técnicos que construyen sistemas.", "Especialistas en aplicaciones móviles.", "Expertos en datos y análisis."],
68+
];
69+
70+
class SortingHat {
71+
constructor(name) {
72+
this.name = name;
73+
this.scores = HOUSES.reduce((acc, house) => {
74+
acc[house] = 0;
75+
return acc;
76+
}, {});
77+
}
78+
79+
async askQuestion(qNum, question, answers) {
80+
console.log(`\n#${qNum}: ${question}`);
81+
answers.forEach((answer, index) => {
82+
console.log(`${index + 1}) ${answer}`);
83+
});
84+
85+
while (true) {
86+
const input = await getInput("Elige tu respuesta (1-4): ");
87+
const choice = parseInt(input, 10) - 1;
88+
89+
if (!isNaN(choice) && choice >= 0 && choice < HOUSES.length) {
90+
this.scores[HOUSES[choice]] += 1;
91+
break;
92+
} else {
93+
console.log("Por favor, elige un número entre 1 y 4.");
94+
}
95+
}
96+
}
97+
98+
selectHouse() {
99+
const maxScore = Math.max(...Object.values(this.scores));
100+
const topHouses = Object.keys(this.scores).filter(
101+
(house) => this.scores[house] === maxScore
102+
);
103+
104+
if (topHouses.length > 1) {
105+
console.log("\nLa decisión ha sido complicada.");
106+
return topHouses[Math.floor(Math.random() * topHouses.length)];
107+
}
108+
109+
return topHouses[0];
110+
}
111+
}
112+
113+
const main = async () => {
114+
console.log("EL SOMBRERO SELECCIONADOR");
115+
const name = await getInput("¿Cuál es tu nombre? : ");
116+
const hat = new SortingHat(name);
117+
118+
for (let i = 0; i < QUESTIONS.length; i++) {
119+
await hat.askQuestion(i + 1, QUESTIONS[i], ANSWERS[i]);
120+
}
121+
122+
const selectedHouse = hat.selectHouse();
123+
console.log(`\n'${name}' pertenecerá a la casa '${selectedHouse}'\n`);
124+
rl.close();
125+
};
126+
127+
main();
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
/*
2+
_____________________________________
3+
https://github.com/kenysdev
4+
2024 - JavaScript
5+
_______________________________________________________
6+
#37 OASIS VS LINKIN PARK
7+
-------------------------------------------------------
8+
* ¡Dos de las bandas más grandes de la historia están de vuelta!
9+
* Oasis y Linkin Park han anunciado nueva gira, pero, ¿quién es más popular?
10+
* Desarrolla un programa que se conecte al API de Spotify y los compare.
11+
* Requisitos:
12+
* 1. Crea una cuenta de desarrollo en https://developer.spotify.com.
13+
* 2. Conéctate al API utilizando tu lenguaje de programación.
14+
* 3. Recupera datos de los endpoint que tú quieras.
15+
* Acciones:
16+
* 1. Accede a las estadísticas de las dos bandas.
17+
* Por ejemplo: número total de seguidores, escuchas mensuales,
18+
* canción con más reproducciones...
19+
* 2. Compara los resultados de, por lo menos, 3 endpoint.
20+
* 3. Muestra todos los resultados por consola para notificar al usuario.
21+
* 4. Desarrolla un criterio para seleccionar qué banda es más popular.
22+
*/
23+
// ________________________________________________________
24+
require('dotenv').config();
25+
const https = require('https');
26+
27+
const SPOTIFY_CLIENT_ID = process.env.SPOTIFY_CLIENT_ID;
28+
const SPOTIFY_CLIENT_SECRET = process.env.SPOTIFY_CLIENT_SECRET;
29+
30+
const getSpotifyAccessToken = async () => {
31+
const options = {
32+
hostname: "accounts.spotify.com",
33+
path: "/api/token",
34+
method: "POST",
35+
headers: {
36+
"Content-Type": "application/x-www-form-urlencoded",
37+
Authorization: `Basic ${Buffer.from(
38+
`${SPOTIFY_CLIENT_ID}:${SPOTIFY_CLIENT_SECRET}`
39+
).toString("base64")}`,
40+
},
41+
};
42+
43+
return new Promise((resolve, reject) => {
44+
const req = https.request(options, (res) => {
45+
let data = "";
46+
47+
res.on("data", (chunk) => {
48+
data += chunk;
49+
});
50+
51+
res.on("end", () => {
52+
const response = JSON.parse(data);
53+
resolve(response.access_token);
54+
});
55+
});
56+
57+
req.on("error", (e) => {
58+
reject(e);
59+
});
60+
61+
req.write("grant_type=client_credentials");
62+
req.end();
63+
});
64+
};
65+
66+
const spotifyAPIRequest = async (endpoint, accessToken) => {
67+
const options = {
68+
hostname: "api.spotify.com",
69+
path: endpoint,
70+
method: "GET",
71+
headers: {
72+
Authorization: `Bearer ${accessToken}`,
73+
},
74+
};
75+
76+
return new Promise((resolve, reject) => {
77+
const req = https.request(options, (res) => {
78+
let data = "";
79+
80+
res.on("data", (chunk) => {
81+
data += chunk;
82+
});
83+
84+
res.on("end", () => {
85+
resolve(JSON.parse(data));
86+
});
87+
});
88+
89+
req.on("error", (e) => {
90+
reject(e);
91+
});
92+
93+
req.end();
94+
});
95+
};
96+
97+
class Spotify {
98+
constructor() {
99+
this.accessToken = null;
100+
}
101+
102+
async authenticate() {
103+
this.accessToken = await getSpotifyAccessToken();
104+
}
105+
106+
async getArtists(name) {
107+
const results = await spotifyAPIRequest(
108+
`/v1/search?q=artist:${encodeURIComponent(name)}&type=artist&limit=3`,
109+
this.accessToken
110+
);
111+
return results.artists ? results.artists.items : [];
112+
}
113+
114+
async getMostPopularArtist(name) {
115+
const artists = await this.getArtists(name);
116+
if (artists.length === 0) return null;
117+
118+
return artists.sort((a, b) => b.popularity - a.popularity)[0];
119+
}
120+
121+
async artistTopTracks(artistId) {
122+
const results = await spotifyAPIRequest(
123+
`/v1/artists/${artistId}/top-tracks?market=US`,
124+
this.accessToken
125+
);
126+
return results.tracks || [];
127+
}
128+
129+
async artistAlbums(artistId) {
130+
const results = await spotifyAPIRequest(
131+
`/v1/artists/${artistId}/albums?album_type=album`,
132+
this.accessToken
133+
);
134+
return results.items || [];
135+
}
136+
}
137+
138+
// Clase Versus
139+
class Versus {
140+
constructor(artist1, artist2, spotifyInstance) {
141+
this.a1 = artist1;
142+
this.a2 = artist2;
143+
this.sp = spotifyInstance;
144+
this.a1Score = 0;
145+
this.a2Score = 0;
146+
}
147+
148+
popularity() {
149+
console.log(`Popularidad: ${this.a1.popularity} vs ${this.a2.popularity}`);
150+
if (this.a1.popularity > this.a2.popularity) this.a1Score++;
151+
else if (this.a2.popularity > this.a1.popularity) this.a2Score++;
152+
}
153+
154+
followers() {
155+
console.log(
156+
`Seguidores: ${this.a1.followers.total} vs ${this.a2.followers.total}`
157+
);
158+
if (this.a1.followers.total > this.a2.followers.total) this.a1Score++;
159+
else if (this.a2.followers.total > this.a1.followers.total) this.a2Score++;
160+
}
161+
162+
async top3Tracks() {
163+
const a1Tracks = await this.sp.artistTopTracks(this.a1.id);
164+
const a2Tracks = await this.sp.artistTopTracks(this.a2.id);
165+
166+
const a1Popularity = a1Tracks.slice(0, 3).reduce((sum, track) => sum + track.popularity, 0);
167+
const a2Popularity = a2Tracks.slice(0, 3).reduce((sum, track) => sum + track.popularity, 0);
168+
169+
console.log(`Popularidad Top 3 canciones: ${a1Popularity} vs ${a2Popularity}`);
170+
if (a1Popularity > a2Popularity) this.a1Score++;
171+
else if (a2Popularity > a1Popularity) this.a2Score++;
172+
}
173+
174+
async albumsAndActiveYears() {
175+
const a1Albums = await this.sp.artistAlbums(this.a1.id);
176+
const a2Albums = await this.sp.artistAlbums(this.a2.id);
177+
178+
console.log(`Número de álbumes: ${a1Albums.length} vs ${a2Albums.length}`);
179+
if (a1Albums.length > a2Albums.length) this.a1Score++;
180+
else if (a2Albums.length > a1Albums.length) this.a2Score++;
181+
182+
const a1Years = new Set(a1Albums.map((album) => album.release_date.slice(0, 4)));
183+
const a2Years = new Set(a2Albums.map((album) => album.release_date.slice(0, 4)));
184+
185+
console.log(`Años activos: ${a1Years.size} vs ${a2Years.size}`);
186+
if (a1Years.size > a2Years.size) this.a1Score++;
187+
else if (a2Years.size > a1Years.size) this.a2Score++;
188+
}
189+
190+
finalResult() {
191+
console.log("\nRESULTADO FINAL:");
192+
console.log(`${this.a1.name}: ${this.a1Score} puntos`);
193+
console.log(`${this.a2.name}: ${this.a2Score} puntos`);
194+
195+
if (this.a1Score > this.a2Score) {
196+
console.log(`\n¡'${this.a1.name}' gana el versus!`);
197+
} else if (this.a2Score > this.a1Score) {
198+
console.log(`\n¡'${this.a2.name}' gana el versus!`);
199+
} else {
200+
console.log("\n¡Es un empate!");
201+
}
202+
}
203+
204+
async start() {
205+
console.log(`${this.a1.name} vs ${this.a2.name}`);
206+
this.popularity();
207+
this.followers();
208+
await this.top3Tracks();
209+
await this.albumsAndActiveYears();
210+
this.finalResult();
211+
}
212+
}
213+
214+
const main = async () => {
215+
const spotify = new Spotify();
216+
await spotify.authenticate();
217+
218+
const artist1 = await spotify.getMostPopularArtist("Oasis");
219+
const artist2 = await spotify.getMostPopularArtist("Linkin Park");
220+
221+
if (!artist1 || !artist2) {
222+
console.log("Artistas no encontrados");
223+
return;
224+
}
225+
226+
const versus = new Versus(artist1, artist2, spotify);
227+
await versus.start();
228+
};
229+
230+
main();

0 commit comments

Comments
 (0)