Skip to content

Commit 3d56850

Browse files
authored
Merge pull request #6633 from oriaj3/main
#39, #40, #41, #42 - Python
2 parents 6032a63 + 77e77d8 commit 3d56850

File tree

4 files changed

+476
-0
lines changed

4 files changed

+476
-0
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
"""
2+
3+
/*
4+
* EJERCICIO:
5+
* Cada año se celebra el Batman Day durante la tercera semana de septiembre...
6+
* ¡Y este año cumple 85 años! Te propongo un reto doble:
7+
*
8+
* RETO 1:
9+
* Crea un programa que calcule cuándo se va a celebrar el Batman Day hasta
10+
* su 100 aniversario.
11+
*
12+
* RETO 2:
13+
* Crea un programa que implemente el sistema de seguridad de la Batcueva.
14+
* Este sistema está diseñado para monitorear múltiples sensores distribuidos
15+
* por Gotham, detectar intrusos y activar respuestas automatizadas.
16+
* Cada sensor reporta su estado en tiempo real, y Batman necesita un programa
17+
* que procese estos datos para tomar decisiones estratégicas.
18+
* Requisitos:
19+
* - El mapa de Gotham y los sensores se representa con una cuadrícula 20x20.
20+
* - Cada sensor se identifica con una coordenada (x, y) y un nivel
21+
* de amenaza entre 0 a 10 (número entero).
22+
* - Batman debe concentrar recursos en el área más crítica de Gotham.
23+
* - El programa recibe un listado de tuplas representando coordenadas de los
24+
* sensores y su nivel de amenaza. El umbral de activación del protocolo de
25+
* seguridad es 20 (sumatorio de amenazas en una cuadrícula 3x3).
26+
* Acciones:
27+
* - Identifica el área con mayor concentración de amenazas
28+
* (sumatorio de amenazas en una cuadrícula 3x3).
29+
* - Si el sumatorio de amenazas es mayor al umbral, activa el
30+
* protocolo de seguridad.
31+
* - Calcula la distancia desde la Batcueva, situada en (0, 0). La distancia es
32+
* la suma absoluta de las coordenadas al centro de la cuadrícula amenazada.
33+
* - Muestra la coordenada al centro de la cuadrícula más amenazada, la suma de
34+
* sus amenazas, la distancia a la Batcueva y si se debe activar el
35+
* protocolo de seguridad.
36+
*/
37+
38+
"""
39+
40+
# Reto 1
41+
from datetime import datetime, timedelta
42+
43+
year_of_creation = 1939
44+
anniversary_year = year_of_creation + 85
45+
46+
batman_day_anniversary_dates = []
47+
48+
while anniversary_year <= year_of_creation + 100:
49+
50+
september = datetime(anniversary_year, 9, 1)
51+
#Resto 5 para que sea el primer sábado de septiembre
52+
#Si el primer día de la semana es 6 (sábado) entonces el primer sábado es el mismo día
53+
first_saturday = 5 - september.weekday() if september.weekday() <= 5 else 12 - september.weekday()
54+
55+
third_saturday = september + timedelta(days=first_saturday + 14)
56+
57+
batman_day_anniversary_dates.append(
58+
(
59+
anniversary_year,
60+
anniversary_year - year_of_creation,
61+
third_saturday.strftime("%Y-%m-%d")
62+
)
63+
)
64+
anniversary_year += 1
65+
66+
for year, anniversary, date in batman_day_anniversary_dates:
67+
print(f"Batman Day {year} - {anniversary}º Aniversario: {date}")
68+
69+
"""
70+
* RETO 2:
71+
* Crea un programa que implemente el sistema de seguridad de la Batcueva.
72+
* Este sistema está diseñado para monitorear múltiples sensores distribuidos
73+
* por Gotham, detectar intrusos y activar respuestas automatizadas.
74+
* Cada sensor reporta su estado en tiempo real, y Batman necesita un programa
75+
* que procese estos datos para tomar decisiones estratégicas.
76+
* Requisitos:
77+
* - El mapa de Gotham y los sensores se representa con una cuadrícula 20x20.
78+
* - Cada sensor se identifica con una coordenada (x, y) y un nivel
79+
* de amenaza entre 0 a 10 (número entero).
80+
* - Batman debe concentrar recursos en el área más crítica de Gotham.
81+
* - El programa recibe un listado de tuplas representando coordenadas de los
82+
* sensores y su nivel de amenaza. El umbral de activación del protocolo de
83+
* seguridad es 20 (sumatorio de amenazas en una cuadrícula 3x3).
84+
* Acciones:
85+
* - Identifica el área con mayor concentración de amenazas
86+
* (sumatorio de amenazas en una cuadrícula 3x3).
87+
* - Si el sumatorio de amenazas es mayor al umbral, activa el
88+
* protocolo de seguridad.
89+
* - Calcula la distancia desde la Batcueva, situada en (0, 0). La distancia es
90+
* la suma absoluta de las coordenadas al centro de la cuadrícula amenazada.
91+
* - Muestra la coordenada al centro de la cuadrícula más amenazada, la suma de
92+
* sus amenazas, la distancia a la Batcueva y si se debe activar el
93+
* protocolo de seguridad.
94+
*/
95+
96+
"""
97+
def sum_subgrib_alerts(sensors, center_x, center_y) -> int:
98+
total = 0
99+
for x in range(center_x-1, center_x+2):
100+
for y in range(center_y-1, center_y+2):
101+
for sensor in sensors:
102+
if sensor[0] == x and sensor[1] == y:
103+
total += sensor[2]
104+
return total
105+
106+
def batcave_security_system(sensors):
107+
max_alert_level = 0
108+
max_alert_center = (0, 0)
109+
110+
for x in range(1,19):
111+
for y in range(1,19):
112+
alert_level = sum_subgrib_alerts(sensors, x, y)
113+
if alert_level > max_alert_level:
114+
max_alert_level = alert_level
115+
max_alert_center = (x, y)
116+
activate_protocol = max_alert_level > 20
117+
distance = abs(max_alert_center[0]) + abs(max_alert_center[1])
118+
119+
return max_alert_center, max_alert_level, distance, activate_protocol
120+
121+
# Function draw grid, with the lvl of alert of each sensor
122+
def draw_grid(sensors):
123+
grid = [["-" for x in range(20)] for y in range(20)]
124+
for sensor in sensors:
125+
grid[sensor[0]][sensor[1]] = sensor[2]
126+
for row in grid:
127+
print(row)
128+
129+
sensors = [
130+
(2, 3, 5),
131+
(4, 5, 8),
132+
(6, 7, 3),
133+
(8, 9, 1),
134+
(10, 11, 2),
135+
(12, 13, 10),
136+
(14, 15, 7),
137+
(14, 14, 8),
138+
(16, 17, 4),
139+
(18, 19, 9),
140+
(19, 19, 6)
141+
]
142+
143+
result = batcave_security_system(sensors)
144+
draw_grid(sensors)
145+
146+
print(f"Centro cuadrícula más amenzada: {result[0]}.")
147+
print(f"Máximo nivel de alerta: {result[1]}.")
148+
print(f"Distancia a la Batcueva: {result[2]}.")
149+
print(f"Activar protocolo de seguridad: {'Sí' if result[3] else 'No'}.")
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
"""
2+
/*
3+
* EJERCICIO:
4+
* ¡Rubius tiene su propia skin en Fortnite!
5+
* Y va a organizar una competición para celebrarlo.
6+
* Esta es la lista de participantes:
7+
* https://x.com/Rubiu5/status/1840161450154692876
8+
*
9+
* Desarrolla un programa que obtenga el número de seguidores en
10+
* Twitch de cada participante, la fecha de creación de la cuenta
11+
* y ordene los resultados en dos listados.
12+
* - Usa el API de Twitch: https://dev.twitch.tv/docs/api/reference
13+
* (NO subas las credenciales de autenticación)
14+
* - Crea un ranking por número de seguidores y por antigüedad.
15+
* - Si algún participante no tiene usuario en Twitch, debe reflejarlo.
16+
*/
17+
"""
18+
import requests
19+
import os
20+
from dotenv import load_dotenv
21+
22+
load_dotenv()
23+
24+
CLIENT_ID = os.getenv("TWITCH_CLIENT_ID")
25+
CLIENT_SECRET = os.getenv("TWITCH_CLIENT_SECRET")
26+
27+
"""
28+
curl -X POST 'https://id.twitch.tv/oauth2/token' \
29+
-H 'Content-Type: application/x-www-form-urlencoded' \
30+
-d 'client_id=<your client id goes here>&client_secret=<your client secret goes here>&grant_type=client_credentials'
31+
"""
32+
def get_access_token(client_id: str, client_secret: str) -> str:
33+
url = "https://id.twitch.tv/oauth2/token"
34+
data = {
35+
"client_id": client_id,
36+
"client_secret": client_secret,
37+
"grant_type": "client_credentials"
38+
}
39+
40+
response = requests.post(url=url, data=data)
41+
42+
#Verificar si la respuesta es correcta, se puede hacer con response.raise_for_status() también
43+
if response.status_code == 200:
44+
token_data = response.json()
45+
return token_data.get("access_token")
46+
else:
47+
print(f"Error: Unable to get access token. Status Code {response.status_code}.")
48+
return None
49+
"""
50+
curl -X GET 'https://api.twitch.tv/helix/users?id=141981764' \
51+
-H 'Authorization: Bearer cfabdegwdoklmawdzdo98xt2fo512y' \
52+
-H 'Client-Id: uo6dggojyb8d6soh92zknwmi5ej1q2'
53+
"""
54+
def get_user_info(token: str, client_id: str, login: str):
55+
url = "https://api.twitch.tv/helix/users"
56+
headers = {
57+
"Authorization": f"Bearer {token}",
58+
"Client-Id": client_id
59+
}
60+
params = {"login": login}
61+
62+
response = requests.get(url=url, headers=headers, params=params)
63+
response.raise_for_status()
64+
data = response.json().get("data", []) #Si no hay data, devolver lista vacía, lo hace el ", [])"
65+
if not data:
66+
return None
67+
68+
return data[0]
69+
70+
"""
71+
curl -X GET 'https://api.twitch.tv/helix/channels/followers?broadcaster_id=123456' \
72+
-H 'Authorization: Bearer kpvy3cjboyptmiacwr0c19hotn5s' \
73+
-H 'Client-Id: hof5gwx0su6owfn0nyan9c87zr6t'
74+
"""
75+
def get_user_followers(token: str, client_id: str, user_id: str) -> int:
76+
url = "https://api.twitch.tv/helix/channels/followers"
77+
headers = {
78+
"Authorization": f"Bearer {token}",
79+
"Client-Id": client_id
80+
}
81+
params = {"broadcaster_id": user_id}
82+
response = requests.get(url=url, headers=headers, params=params)
83+
response.raise_for_status()
84+
return response.json().get("total", 0)
85+
86+
users = [
87+
"littleragergirl", "ache", "adricontreras4", "agustin51", "alexby11", "ampeterby7", "tvander",
88+
"arigameplays", "arigeli_", "auronplay", "axozer", "beniju03", "bycalitos",
89+
"byviruzz", "carreraaa", "celopan", "srcheeto", "crystalmolly", "darioemehache",
90+
"dheylo", "djmariio", "doble", "elvisayomastercard", "elyas360", "folagorlives", "thegrefg",
91+
"guanyar", "hika", "hiperop", "ibai", "ibelky_", "illojuan", "imantado",
92+
"irinaissaia", "jesskiu", "jopa", "jordiwild", "kenaivsouza", "mrkeroro10",
93+
"thekiddkeo95", "kikorivera", "knekro", "kokoop", "kronnozomberoficial", "leviathan",
94+
"litkillah", "lolalolita", "lolitofdez", "luh", "luzu", "mangel", "mayichi",
95+
"melo", "missasinfonia", "mixwell", "jaggerprincesa", "nategentile7", "nexxuz",
96+
"lakshartnia", "nilojeda", "nissaxter", "olliegamerz", "orslok", "outconsumer", "papigavitv",
97+
"paracetamor", "patica1999", "paulagonu", "pausenpaii", "perxitaa", "nosoyplex",
98+
"polispol1", "quackity", "recuerd0p", "reventxz", "rivers_gg", "robertpg", "roier",
99+
"ceuvebrokenheart", "rubius", "shadoune666", "silithur", "spok_sponha", "elspreen", "spursito",
100+
"bystaxx", "suzyroxx", "vicens", "vitu", "werlyb", "xavi", "xcry", "elxokas",
101+
"thezarcort", "zeling", "zormanworld", "mouredev"
102+
]
103+
users_data = []
104+
not_found_users = []
105+
106+
TOKEN = get_access_token(CLIENT_ID, CLIENT_SECRET)
107+
108+
for user_name in users:
109+
user = get_user_info(TOKEN, CLIENT_ID, user_name)
110+
if user is None:
111+
not_found_users.append(user_name)
112+
else:
113+
114+
followers = get_user_followers(TOKEN, CLIENT_ID, user.get("id"))
115+
users_data.append({
116+
"username": user_name,
117+
"created_at": user.get("created_at"),
118+
"followers": followers
119+
})
120+
121+
#Usuarios no encontrados
122+
print (not_found_users)
123+
124+
#Ordenar por seguidores
125+
users_data.sort(key=lambda x: x["followers"], reverse=True)
126+
127+
print("Ranking por seguidores:")
128+
for id, user, in enumerate(users_data):
129+
print(f"{id + 1} - {user['username']}: {user['followers']} seguidores")
130+
131+
#Ordenar por antigüedad
132+
users_data.sort(key=lambda x: x["created_at"])
133+
134+
print("Ranking por antigüedad:")
135+
for id, user, in enumerate(users_data):
136+
print(f"{id + 1} - {user['username']}: {user['created_at']}")
137+
138+
139+
140+
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""
2+
/*
3+
* EJERCICIO:
4+
* ¿Has visto la camiseta.rar?
5+
* https://x.com/MoureDev/status/1841531938961592740
6+
*
7+
* Crea un programa capaz de comprimir un archivo
8+
* en formato .zip (o el que tú quieras).
9+
* - No subas el archivo o el zip.
10+
*/
11+
"""
12+
13+
import zipfile
14+
import os
15+
16+
def compress_file(file_path: str, zip_path: str):
17+
18+
if os.path.exists(file_path):
19+
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
20+
zipf.write(file_path, os.path.basename(file_path))
21+
print(f"Archivo {file_path} comprimido como {zip_path}.")
22+
return zip_path
23+
else:
24+
print(f"El archivo {file_path} no existe.")
25+
return None
26+
27+
def decompress_file(zip_path: str, dest_path: str):
28+
29+
if os.path.exists(zip_path):
30+
with zipfile.ZipFile(zip_path) as zipf:
31+
zipf.extractall(dest_path)
32+
print(f"Archivo {zip_path} descomprimido en {dest_path}.")
33+
else:
34+
print(f"El archivo {zip_path} no existe.")
35+
36+
path = os.path.dirname(os.path.abspath(__file__)) # Directorio actual
37+
file = "prueba.txt"
38+
zip_file = f"{file}.zip"
39+
40+
zip = compress_file(os.path.join(path, file), os.path.join(path, zip_file))
41+
42+
if zip != None:
43+
decompress_file(os.path.join(path, zip), path)
44+
#os.remove(os.path.join(path, zip))
45+
46+

0 commit comments

Comments
 (0)