Technology stack
The application is built with the following technologies:Frontend
- React 16.2: Component-based UI library
- Redux 3.7: State management with thunk and logger middleware
- Material-UI 0.20: Component library for UI elements
- React Router 4: Client-side routing
- React Virtualized: Efficient rendering of large card lists
- Axios: HTTP client for API requests
Backend
- Express 4.16: Web server framework
- Sequelize 4.22: ORM for PostgreSQL
- PostgreSQL: Relational database for card storage
- Morgan: HTTP request logging
- Body Parser: Request body parsing middleware
Build tools
- Webpack 3: Module bundler
- Babel 6: JavaScript transpiler (React, ES2015, Stage-2)
- Nodemon: Auto-restart server during development
System architecture
Directory structure
Frontend architecture
Component hierarchy
The React application follows a container/presentational component pattern:- DeckBuilderContainer (
app/components/DeckBuilderContainer.jsx): Main container component that connects to Redux - DeckList (
app/components/DeckList.js): Displays the current deck composition - ProbabilityCell (
app/components/ProbabilityCell.js): Renders probability calculations for individual cards
Redux state management
The Redux store is configured inapp/store.js:7 with the following middleware:
- redux-thunk: Enables async action creators for API calls
- redux-logger: Logs all actions and state changes in development
Application entry point
The app bootstraps inapp/main.jsx:9 by rendering the main component wrapped in providers:
- Material-UI theming context
- Redux store access to all components
Backend architecture
Express server setup
The server is configured inserver/index.js with the following middleware stack:
- Morgan: HTTP request logging (
devformat) - Static files: Serves
public/directory - Body parser: Parses URL-encoded and JSON request bodies
- API routes: Mounted at
/api - SPA fallback: Serves
index.htmlfor all other routes - Error handler: Catches and formats errors
API routes
API routes are organized inserver/api/routes/:
/api/cards: Card CRUD operations (search, filter, retrieve card data)/api/alg: Probability calculation endpoints using the algorithm module
server/api/index.js:6 and mounted on the Express app.
Database models
Sequelize models are defined inserver/db/models/index.js:
Card model
Stores MTG card data with fields:- Basic info:
name,type,text,flavor - Mana:
manaCost,cmc(converted mana cost),colors - Stats:
power,toughness - Metadata:
set,multiverseid,mciNumber - Deck building:
ProducibleManaColors,fetchOptions
Deck model
Stores deck information:name: Deck name
cards_decks junction table
Links cards to decks with quantity:cardId: Reference to cardquantity: Number of copies in deck- Belongs to
Deck
Algorithm module
The__alg/ directory contains the core probability calculation engine.
Multichoose algorithm
The algorithm uses a multilayered multichoose approach to count valid hand combinations:-
Layer 1: Allocate cards into three bins:
- Target card bin (1 card minimum)
- Land bin (C cards, where C = converted mana cost)
- Other cards bin (remaining cards)
- Layer 2: Further break down the land bin by land types to account for color requirements
- Calculate all possible hand combinations that satisfy the constraints
Hypergeometric distribution
Once valid hand combinations are counted, the algorithm applies the hypergeometric distribution PMF (probability mass function) to calculate the probability of drawing each combination. The formula accounts for:- Population size (deck size)
- Number of success states (cards that satisfy conditions)
- Number of draws (opening hand + draw steps)
- Sample size (hand size)
Arithmetic helpers
Large combinatorial numbers (like60!) exceed JavaScript’s number precision. The ArithmaticHelpers.js module implements custom arithmetic functions to handle these calculations accurately.
Data flow
Typical request flow for calculating card probabilities:- User action: User builds a deck and selects a card to analyze
- Redux dispatch: Action creator dispatches async action
- API call: Axios sends POST request to
/api/algwith deck and card data - Algorithm processing: Server invokes multichoose algorithm with deck composition
- Probability calculation: Hypergeometric distribution computes probability
- Response: Server returns probability data as JSON
- Redux update: Reducer updates state with new probability data
- Re-render: React components re-render with updated probabilities
Design patterns
Separation of concerns
- Algorithm module is isolated in
__alg/and can be tested independently - API routes are modular and organized by domain
- Redux reducers manage distinct slices of state
- Components are separated into containers (logic) and presentational (UI)
Single-page application
The server servesindex.html for all non-API routes, allowing React Router to handle client-side routing without page reloads.
Middleware composition
Both Express and Redux use middleware patterns for composable, reusable functionality:- Express: logging, parsing, static files, error handling
- Redux: async actions (thunk), logging, DevTools
Performance considerations
- React Virtualized: Efficiently renders large lists of cards without performance degradation
- Algorithm optimization: Multichoose is O(m^n) but faster than Monte Carlo simulation
- Database indexing: Critical for card search queries
- Source maps: Enabled in development for debugging, should be disabled in production
Key files reference
| File | Purpose | Key features |
|---|---|---|
app/main.jsx:9 | React entry point | Renders app with Redux and Material-UI |
app/store.js:7 | Redux store | Configured with thunk, logger, DevTools |
server/index.js:30 | Server entry | Express setup, port 4000, DB sync |
server/api/index.js | API aggregator | Mounts card and algorithm routes |
server/db/models/index.js:2 | Database models | Sequelize models and associations |
__alg/ArithmaticHelpers.js | Algorithm core | Probability calculations |
webpack.config.js:8 | Build config | Bundles React app to public/bundle.js |
Next steps
Development setup
Set up your local development environment
Contributing
Learn how to contribute to the project
