Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 147 additions & 0 deletions 4001_juan-orozco_v1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import fs from 'fs'
import path from 'path'

class LocalDB {
constructor() {
const dirName = path.dirname(new URL(import.meta.url).pathname)

this.filePath = path.join(dirName, 'users.json')
this.tempFilePath = path.join(dirName, 'users_temp.json')

this.data = this.loadData()
}

loadData() {
if (!fs.existsSync(this.filePath)) {
fs.writeFileSync(this.filePath, JSON.stringify([]))
}

const data = fs.readFileSync(this.filePath, 'utf-8')
return JSON.parse(data)
}

saveData() {
fs.writeFileSync(this.tempFilePath, JSON.stringify(this.data))
fs.renameSync(this.tempFilePath, this.filePath)
}
}

function addUser() {
const db = new LocalDB()

const [id, name, email, role] = process.argv.slice(3).join(' ').split(',')

if (!id || !name || !email || !role) {
console.error('Faltan argumentos. Uso: node 4001_juan-orozco_v1.js ADD <id>,<nombre>,<email>,<rol>')
return
}

if (db.data.find(user => user.id === id)) {
console.error('ERROR:DUP_ID')
return
}

if (db.data.find(user => user.email === email)) {
console.error('ERROR:DUP_EMAIL')
return
}

db.data.push({ id, name, email, role })
db.saveData()
}

function getUser() {
const db = new LocalDB()

const id = process.argv[3]

if (!id) {
console.error('Faltan argumentos. Uso: node 4001_juan-orozco_v1.js GET <id>')
return
}

const user = db.data.find(user => user.id === id)

if (!user) {
console.error('ERROR:USUARIO_NO_ENCONTRADO')
return
}

const { id: uid, name, email, role } = user

console.log(`\nID\t| Nombre\t| Email\t\t| Rol`)
console.log(`${uid}\t| ${name}\t| ${email}\t| ${role}`)
}

function deleteUser() {
const db = new LocalDB()

const id = process.argv[3]

if (!id) {
console.error('Faltan argumentos. Uso: node 4001_juan-orozco_v1.js DEL <id>')
return
}

const userIndex = db.data.findIndex(user => user.id === id)

if (userIndex === -1) {
console.error('ERROR:USUARIO_NO_ENCONTRADO')
return
}

db.data = db.data.filter(user => user.id !== id)
db.saveData()
}

function listUsers() {
const db = new LocalDB()

console.log(`\nID\t\tNombre\t\tEmail\t\t\tRol`)

db.data
.sort((a, b) => a.id - b.id)
.forEach(({ id, name, email, role }) => {
console.log(`${id}\t${name}\t${email}\t${role}`)
})
}

const commands = {
add: addUser,
get: getUser,
del: deleteUser,
list: listUsers
}

function main() {
const args = process.argv.slice(2);
const command = args[0].toLocaleLowerCase();

if (commands[command]) {
commands[command]()
} else {
console.error('Comando no reconocido. Use ADD, GET, DEL o LIST.')
}
}

main()


/*

# Pruebas
1) Agregar usuario:
terminal: node 4001_juan-orozco_v1.js ADD 1,Juan,juan@example.com,admin
salida:
- Ninguna salida en terminal
- users.json se actualiza con el nuevo usuario

2) Obtener usuario existente:
terminal: node 4001_juan-orozco_v1.js GET 1
salida:
ID | Nombre | Email | Rol
1 | Juan | juan@example.com | admin
3) Obtener usuario no existente:
terminal: node 4001_juan-orozco_v1.js GET 99
salida: ERROR:USUARIO_NO_ENCONTRADO
*/
136 changes: 136 additions & 0 deletions 4002_juan-orozco_v1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import fs from 'fs'
import path from 'path'

function generateSeed() {
const rates = {
USD: {
EUR: 0.94,
GBP: 0.81,
JPY: 149.52,
MXN: 18.23,
COP: 4185.50
},
EUR: {
USD: 1.06,
GBP: 0.86,
JPY: 159.12,
MXN: 19.40,
COP: 4450.75
},
GBP: {
USD: 1.23,
EUR: 1.16,
JPY: 185.02,
MXN: 22.53,
COP: 5170.40
},
JPY: {
USD: 0.0067,
EUR: 0.0063,
GBP: 0.0054,
MXN: 0.12,
COP: 28.00
},
MXN: {
USD: 0.055,
EUR: 0.052,
GBP: 0.044,
JPY: 8.33,
COP: 229.50
},
COP: {
USD: 0.00024,
EUR: 0.00022,
GBP: 0.00019,
JPY: 0.036,
MXN: 0.0044
}
};


const dirName = path.dirname(new URL(import.meta.url).pathname)
const filePath = path.join(dirName, 'rates.json')
fs.writeFileSync(filePath, JSON.stringify(rates))
}

async function fetchWithBackoffJitter(url, retries = 5, delay = 500) {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url)

if (!response.ok) throw new Error(response.status)

return await response.json()
} catch (error) {
if (i === retries - 1) throw error

if (error.status != 429 || error.status != 503) {
throw error
}

console.log(`Reintento ${i + 1} en ${delay}ms...`)

const jitter = Math.random() * 100
await new Promise(res => setTimeout(res, delay + jitter))

delay *= 2
}
}
}

async function main() {
if (process.argv[2] == "--seed") {
generateSeed()
return
}

const [amount, fromCurrency, toCurrency, fileName] = process.argv.slice(2)

if (!amount || !fromCurrency || !toCurrency || !fileName) {
console.error('Faltan argumentos. Uso: node 4002_juan-orozco_v1.js <cantidad> <de> <a> <archivo>')
return
}

try {
const data = await fetchWithBackoffJitter(`http://localhost:8000/${fileName}`)

if (!data[fromCurrency] || !data[fromCurrency][toCurrency]) {
console.error(`No se encontró la tasa de cambio de ${fromCurrency} a ${toCurrency}.`)
return
}

const rate = data[fromCurrency][toCurrency]
const convertedAmount = (parseFloat(amount) * rate).toFixed(2)

console.log(`\n${amount} ${fromCurrency} → ${toCurrency} = ${convertedAmount}`)
} catch (error) {
if (error.status === 404) {
console.error(`ERROR:NO_SE_ENCONTRO_EL_ARCHIVO`)
} else {
console.error(`ERROR: ${error.message}`)
}
}
}

main()


/*
# Pruebas

1) Generar archivo de tasas:
terminal: node 4002_juan-orozco_v1.js --seed
salida:
- Ninguna salida en terminal
- rates.json se crea con las tasas de cambio

2) Convertir moneda (archivo existe y tasa existe):
terminal: node 4002_juan-orozco_v1.js 100 USD EUR rates.json
salida esperada en terminal:
100 USD → EUR = 94.00

3) Convertir moneda (archivo no existe):
terminal: node 4002_juan-orozco_v1.js 100 USD EUR nonexistent.json
salida esperada en terminal:
ERROR:NO_SE_ENCONTRO_EL_ARCHIVO
*/
Loading