Underground 2 Revived
Play Need for Speed: Underground 2 (2004) in Chrome and Firefox with WebGPU graphics, Web Audio, up to 120 fps widescreen, controller support, free roam and Online races with friends. Fan project, not
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Ranking de crafteo en Albion Online por plata realizable por dia (margen x volumen x cuota de mercado), no por margen unitario.
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
Ranking de crafteo en Albion Online por plata realizable por día, no por margen unitario. Cubre alquimia, refinado, cocina, armas y armaduras, y monturas, y suma una calculadora con planificaciones guardadas y avisos por Discord. Casi todas las herramientas de mercado de Albion responden "¿cuánta ganancia deja una unidad de este ítem?". Esa es la pregunta equivocada: si crafteás 400 pociones y el mercado absorbe 12 por día, un 200% de ROI vale menos que un 40% sobre algo que mueve 5.000 unidades diarias.查看完整 README ↗
Ranking de crafteo en Albion Online por plata realizable por día, no por margen unitario. Cubre alquimia, refinado, cocina, armas y armaduras, y monturas, y suma una calculadora con planificaciones guardadas y avisos por Discord.
Casi todas las herramientas de mercado de Albion responden "¿cuánta ganancia deja una unidad de este ítem?". Esa es la pregunta equivocada: si crafteás 400 pociones y el mercado absorbe 12 por día, un 200% de ROI vale menos que un 40% sobre algo que mueve 5.000 unidades diarias.
PlataRank mete el volumen diario de ventas (expuesto desde siempre por la API pública, casi nunca usado) dentro de la matemática del crafteo: ganancia unitaria × volumen diario de ventas × la cuota que asumís llevarte. El resto del producto se ordena alrededor de tres cosas:
fee = valor de ítem × tarifa × 0,001125 (plata por cada 100 de nutrición consumida, no un porcentaje plano), con el valor de ítem sacado de los datos del juego.| Ruta | Qué es |
|---|---|
/es | Inicio: las mejores recetas del momento y la frescura del dato |
/es/alquimia · /refinado · /cocina | Rankings de 174 / 115 / 183 recetas |
/es/equipo | Armas y armaduras (5.711 recetas, calidades Q1-Q5) |
/es/monturas | Monturas (29 recetas), con opción de criar el animal base en vez de comprarlo |
/es/calculadora | Calculadora de un ítem, planificaciones guardadas, avisos por Discord y la pestaña Transporte (peso a cargar contra bolsa, montura y capa de recolección) |
/es/receta/[itemId] | Página indexable de una receta concreta: costo, ganancia y plata por día |
/es/metodologia | Cómo se calcula cada número |
/es/acerca | Qué es PlataRank y de dónde salen los datos |
Entrar con Discord es opcional: solo hace falta para guardar planificaciones y avisos. Los rankings y la calculadora funcionan sin cuenta.
retorno = 1 − 1/(1 + bono). Los artefactos nunca reciben retorno.craftingCategory (parseado de craftingmodifiers.xml) y un único selector "ciudad donde craftea" resuelve el bono correcto en todos los rubros.src/lib/formulas/market-tax.ts.items.json, sin estimar. Quedan afuera el dragón (Draco Ala de Fuego) y el conejo de Pascua, que no tienen un costo honesto para calcular (src/lib/formulas/breeding.ts).Todo supuesto es un control visible: ciudades de compra y de venta por separado, cuota, foco, tarifa de estación (500 por defecto), antigüedad máxima y volumen mínimo. El estado del ranking vive en la URL y se puede compartir; la calculadora comparte sus supuestos con un enlace.
fixtures/golden-cases.json, tests/golden-cases.test.ts).gamedata.xml) no se parsea; "craftear Q3 y rerollear" no se calcula.Next.js 15 (App Router) + TypeScript · Tailwind + shadcn/ui · TanStack Virtual · Supabase (Postgres y Auth con Discord) + Drizzle ORM · GitHub Actions (cron del ingester y del aviso diario) · fast-xml-parser (solo en build time) · tar-stream (lee el volcado diario de AODP en streaming) · Vitest.
El brief original pedía TanStack Table, pero su versión instalable (v9) es una reescritura pre-release con una API inestable: se optó por un sort manual más TanStack Virtual, que sí es estable.
El sitio está en español (/es), inglés (/en) y portugués de Brasil (/pt) con next-intl, sin middleware. Los textos viven en src/messages/{es,en,pt}/<namespace>.json (los tres idiomas con las mismas claves; legal es solo servidor) y las páginas largas (metodología, acerca, privacidad, términos) en content/{es,en,pt}.tsx. Las carpetas de src/app/[locale]/ conservan los nombres en español; los slugs traducidos (/en/artifacts, /pt/artefatos, /pt/receita/...) son rewrites definidos en next.config.ts a partir de la tabla ROUTES de src/i18n/config.ts. Los enlaces se arman siempre con localePath, y / elige idioma según Accept-Language (src/app/route.ts). Para elegir un valor por idioma usá byLocale/intlLocale en vez de locale === "en" ? … : … (que le daba el español al portugués). Los nombres de ítems salen del volcado del juego (nameEs/nameEn/namePt; itemName cae al inglés si falta el portugués). Para agregar una página: carpeta en [locale], entrada en ROUTES, textos en los tres JSON y pageMetadata({ locale, route, ... }).
pnpm install
pnpm dev
Variables de entorno (ver .env.example):
| Variable | Para qué |
|---|---|
DATABASE_URL | Conexión a Postgres (web e ingester) |
DATABASE_URL_READONLY | Rol de solo lectura para el aviso diario (opcional, cae a DATABASE_URL) |
AODP_SERVER | west (Américas), europe o east |
AODP_CONTACT | Contacto que se envía a AODP en el User-Agent |
NEXT_PUBLIC_SITE_URL | Dominio absoluto para metadata, sitemap y enlaces de avisos |
NEXT_PUBLIC_SUPABASE_URL · NEXT_PUBLIC_SUPABASE_ANON_KEY | Auth y datos de usuario desde el navegador |
DISCORD_DAILY_WEBHOOK | Webhook del canal del aviso diario (solo en GitHub) |
REVALIDATE_SECRET | Mismo valor en Vercel y en los secrets de GitHub: el ingest llama a POST /api/revalidate al terminar para tirar la caché de mercado y que los precios nuevos salgan enseguida (opcional; sin él la caché vence sola en una hora) |
pnpm test # fórmulas, matemática de recetas, agregados y outliers
pnpm lint
pnpm fetch-game-data # regenera recipes.json + city-specialties.json + quality-mechanics.json desde ao-bin-dumps
pnpm tsx scripts/fetch-transport-data.ts # pesos de ítems y capas de recolección para Transporte
pnpm tsx scripts/fetch-hideout-data.ts # bonos de escondites (nivel de poder, calidad de zona, biomas)
pnpm ingest # corre el ingester (precios + volumen + agregados + avisos) una vez
pnpm db:generate # genera migraciones de Drizzle a partir de src/lib/db/schema.ts
scripts/ingest.ts, cron cada hora en .github/workflows/ingest.yml): trae los precios de todos los ítems de las recetas más el forraje y las crías del toggle de crianza, y calcula un agregado por ítem + ciudad + calidad en market_aggregates (precio, antigüedad, volumen diario, precio histórico ponderado). Las filas sin precio ni volumen no se guardan: eran el 70% de la tabla y viajaban en cada carga de ranking. No se persisten filas crudas de precio ni de historial (con la calidad de equipo llenarían el free tier de Supabase en horas).db_backup_*.tgz de AODP y, si es nuevo, lo procesa en streaming para recalcular el volumen de 30 días. En las demás corridas solo refresca precios. ingest_state guarda la URL del último volcado procesado.rank_snapshots, src/lib/server/top-recipes.ts) para no leer decenas de miles de filas en cada visita. Supabase free tiene 5 GB de egress por mes, así que cualquier cambio que amplíe lo que una página lee de la base tiene que contarlo.src/lib/server/shared-cache.ts): la web lee el mercado a través de la caché de datos de Next (unstable_cache, una hora), compartida entre instancias, idiomas y deploys; el de equipo va en 8 pedazos para no pasar los 2 MB por entrada de Vercel. Las recetas salen de recipes.json (src/lib/recipes-data.ts), no de la tabla. El ingester no puede usar esa caché (corre fuera de Next) y llama a station-data directo; al terminar, la invalida con POST /api/revalidate (tag market), así los precios nuevos aparecen apenas termina en vez de hasta una hora después.src/lib/recipe-math.ts y corre en el navegador para rubros chicos; equipo se rankea en el servidor (rankStation) para el orden y los filtros elegidos.src/lib/ingest/alerts.ts) y se avisa al webhook de Discord del usuario solo cuando la ganancia cruza el umbral desde abajo./es/metodologia: la explicación de cara al usuario.Datos de mercado cortesía de The Albion Online Data Project, un proyecto sostenido por la comunidad. Recetas y mecánicas extraídas del dump oficial del cliente (ao-data/ao-bin-dumps): items.json para recetas, valores y pesos, craftingmodifiers.xml para especialidades de ciudad, gamedata.xml para la distribución de calidad de crafteo.
supabase/