DEV Community

Cover image for I Built a Complex Production Calculator for Arknights: Endfield using Astro & React (and solved circular dependency hell)
Causal Zap
Causal Zap

Posted on

I Built a Complex Production Calculator for Arknights: Endfield using Astro & React (and solved circular dependency hell)

πŸ‘‹ The Backstory
I'm a huge fan of Arknights: Endfield (the upcoming 3D RPG with factory building elements). During the technical test, I realized something: the industrial system (AIC) is surprisingly complex.

Unlike simple crafting trees, Endfield has Circular Production Loops.

Example: To make Bottled Water, you need an Empty Bottle. consuming the water returns the Empty Bottle.

The Problem: If you write a simple recursive calculator, it gets stuck in an infinite loop: Bottle -> Water -> Bottle -> Water... resulting in a RangeError: Maximum call stack size exceeded.

So, I decided to build Endfield DB, a dedicated wiki and production planner, to solve this. Here is how I built it using Astro, React, and Tailwind CSS.

(Replace this with your calculator screenshot url)

πŸ›  The Tech Stack
I needed something blazing fast for SEO (since it's a database) but highly interactive for the calculator.

Framework: Astro (Static Site Generation is perfect for Wiki-like content).

Interactivity: React (For the complex state management in the Calculator).

Styling: Tailwind CSS (To achieve the game's "Industrial Sci-Fi" aesthetic).

Data: JSON-based "CMS" (Lightweight and fast).

Optimization: Sharp (Node.js script to batch convert 1000+ assets to WebP).

🧩 The Challenge: Handling Circular Dependencies
The biggest technical hurdle was the calculator logic. A standard recursion would crash the browser when calculating items like "Amethyst Bottle" because the output feeds back into the input.

The Algorithm
I implemented a traverse function with cycle detection. By passing a Set of visited paths, the algorithm knows when it hits a loop and stops the recursion for that branch, treating it as a "solved" dependency.

Here is a simplified version of the logic:

TypeScript

// src/utils/calculator.ts

const traverse = (
itemId: string,
rate: number,
depth: number,
currentPath: Set // πŸ‘ˆ The breadcrumbs
) => {

// πŸ›‘ Cycle Detection: Stop if we've seen this item in the current chain
if (currentPath.has(itemId)) {
return;
}

const newPath = new Set(currentPath);
newPath.add(itemId);

const recipe = recipes.find(r => r.outputs.some(out => out.itemId === itemId));

// ... Calculate Facilities and Power ...

if (recipe) {
recipe.inputs.forEach(input => {
// Recursively calculate inputs
traverse(input.itemId, inputAmount, depth + 1, newPath);
});
}
};
This allows the calculator to accurately tell you: "To produce 60 Water/min, you need net 0 new bottles (if recycling) or X raw materials," without crashing.

⚑️ Performance Optimization
Since the database has over 1,700 items, performance was key.

Image Optimization: I wrote a custom Node.js script using sharp to convert all raw game assets (PNG) to WebP. This reduced the asset payload by ~70%.

Smart Fallbacks: Not all items have icons. I implemented a React component that tries to load the WebP image, and if it onError, it gracefully falls back to a CSS-styled initial (e.g., "A" for Amethyst) without breaking the layout.

Partial Hydration: Using Astro's client:load, the heavy React calculator only loads when needed, keeping the initial HTML payload tiny.

🎨 The "Industrial" UI Design
The game features a dark, gritty, high-tech interface. I used Tailwind's zinc color palette combined with vibrant orange-500 accents to mimic the in-game UI.

Glassmorphism: Used bg-zinc-950/80 backdrop-blur-md for sticky headers.

Data Tables: Built a custom responsive table to show Facility Counts, Power (kW), and raw material breakdowns.

(Replace this with your item list screenshot)

πŸš€ What's Next?
The site is now live at EndfieldDB.

I'm currently working on:

Visualizing the dependency tree (Node graph).

Multi-target planning (calculating for multiple outputs at once).

If you are into Arknights or just like building complex logic tools, I'd love to hear your feedback on the UX!

Thanks for reading!

Top comments (0)