Skip to content

PromptNebula05/darkforge

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

226 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DARKFORGE v6.0

A Java 21 character/crew management system for the Coriolis: The Great Dark tabletop RPG.

What's New in Iteration 6

  • darkforge.database package — first relational persistence layer, built on JDBC + SQLite (jdbc:sqlite:), persisting the crew roster across three related tables. Complements (does not replace) the existing darkforge.persistence serialization.
    • DatabaseManager — owns the single jdbc:sqlite:darkforge.db Connection, sets PRAGMA foreign_keys = ON, and runs a hybrid bootstrap (verify tables via sqlite_master, create from schema.sql if missing)
    • ExplorerDao / CrewDao / CrewMembershipDao — all DML through PreparedStatement (inserts use RETURN_GENERATED_KEYS); provide the three required reads (ordered select, multi-table join, aggregation)
    • Row/result records — ExplorerRow, CrewRow, RosterEntry, CrewStat
  • 3-table schema (schema.sql) — crew · explorer · crew_membership, with full integrity constraints: PK + FK + NOT NULL + UNIQUE + CHECK, plus ON DELETE CASCADE on both foreign keys
    • Crew roles stored as enum-constant tokens (DELVER / SCOUT / BURROWER / GUARD / ARCHAEOLOGIST) with a CHECK list; round-trip via CrewRole.valueOf(...)
    • Professions stored as raw display name (no CHECK); validated on reload by ExplorerFactory
    • Six attributes (STR, AGL, LOG, PER, INS, EMP) CHECK-constrained to 2–6; derived stats (Health/Hope/Heart) computed in Java, not stored
  • FacadeDatabase — new subfacade wired by FacadeDarkforge.initialize() (same rhythm as FacadeConcurrency), exposed via databaseAccess(); DB connection closed on exit
  • CLI option [15] Crew Database — prompt-driven create-explorer / create-crew / assign-member / view-roster / crew-stats; nothing pre-seeded, all data entered at runtime
  • DatabaseException extends DarkForgeException — uniform error type for connection / SQL / constraint failures (mirrors ConcurrencyException)
  • JUnit 5 database tests — DAO round-trip, constraint enforcement (FK / composite PK / role + attribute CHECK / UNIQUE), ON DELETE CASCADE, and query correctness, each against a temp file DB or jdbc:sqlite::memory:
  • Main banner bumped v5.0 → v6.0

Requirements

  • Java 21+
  • lib/sqlite-jdbc-3.45.x.jar (Xerial SQLite JDBC driver) (NEW)
  • lib/slf4j-api-2.0.13.jar (required by sqlite-jdbc 3.43.2.0+ for its internal logging) (NEW)
  • lib/slf4j-nop-2.0.13.jar (no-op SLF4J provider; silences the startup "No SLF4J providers" warning) (NEW)
  • lib/json-20240303.jar (org.json)
  • lib/gson-2.10.1.jar (Google Gson)
  • lib/junit-platform-console-standalone-1.10.2.jar (testing)

Build & Run

Compile

javac -cp "lib/*" -d out \
    src/darkforge/*.java

Run CLI

java -cp "out:lib/*" darkforge.Main

Run GUI

java -cp "out:lib/*" darkforge.gui.DarkforgeGui

Run serialization benchmark

java -cp "out:lib/*" darkforge.persistence.SerializationBenchmark

Run dice probability simulator (CLI option [14])

java -cp "out:lib/*" darkforge.Main
# then choose [14] Dice Probability Simulator

Run crew database (CLI option [15])

java -cp "out:lib/*" darkforge.Main
# then choose [15] Crew Database
# tables auto-create in darkforge.db on first run

Run tests

java -jar lib/junit-platform-* -cp out --scan-classpath

Project Structure

src/darkforge/
├── collection/    # Inventory, generics
├── concurrency/   # ExecutorService, Callable, AtomicLong, SwingWorker adapter
├── cli/           # CLI menus (option [15] added)
├── crew/          # Crew, Vehicle, analytics
├── data/          # GameDataProvider, catalog
├── database/      # JDBC + SQLite: DatabaseManager, DAOs, row records (NEW)
├── display/       # Displayable, formatters
├── exception/     # DarkForgeException, ConcurrencyException, DatabaseException (NEW)
├── facade/        # Facade pattern (FacadeDatabase added)
├── gui/           # Swing GUI (DiceSimulatorPanel, background tasks)
├── model/         # GameEntity hierarchy
└── persistence/   # Serialization
src/resources/     # JSON catalog files + schema.sql (NEW)
test/darkforge/    # JUnit 5 test suite (database tests added)

Architecture

Hybrid composition + interfaces.

Explorer implements InventoryHolder<CharacterItem> and Equippable<Weapon>.

Vehicle implements InventoryHolder<CargoItem> and Equippable<VehicleModule>.

Facade pattern provides simplified access via FacadeDarkforgeFacadeCrew / FacadeCatalog / FacadeConcurrency / FacadeDatabase.

Database model

  • DatabaseManager owns the single jdbc:sqlite:darkforge.db Connection for the lifetime of the application; sets PRAGMA foreign_keys = ON (SQLite enforces FKs per-connection only when set) and is closed via FacadeDatabase.shutdown() from Main's finally block, alongside the concurrency shutdown.
  • Schema management is hybrid: schema.sql ships as a classpath resource and runs with CREATE TABLE IF NOT EXISTS, so re-running against an existing .db is a no-op. This is reproducible for graders and demonstrates JDBC DDL.
  • The relational↔OO mapping is isomorphic: Explorerexplorer rows, Crewcrew rows, and crew roles ↔ crew_membership.role. A 3-table join mirrors the lecture's researcher/journal/publication example.
  • All DML flows through PreparedStatement; inserts return generated keys. The three required reads are an ordered SELECT, a multi-table JOIN, and a GROUP BY aggregation (COUNT / AVG).

Concurrency model

  • DiceSimulator owns a fixed-size ExecutorService (one thread per available core) for the lifetime of the application; shut down via FacadeConcurrency.shutdown() from Main's finally block.
  • Roll batches are submitted as Callable<BatchResult> via invokeAll; each task owns its own seeded java.util.Random so no RNG is shared across threads.
  • Aggregation uses AtomicLong per counter, hit once per batch (not once per roll), keeping contention bounded by batch count.
  • GUI off-EDT work goes through BackgroundTask<T> (a SwingWorker<T, Integer> adapter); done() dispatches result/error back to the EDT.

Rulebook fidelity

Dice mechanics follow Coriolis: The Great Dark exactly: each 6 is a success, and pushing re-rolls any die not showing a 6 or a 1. Sixes lock as successes; ones lock as banes (Hope damage on Base dice, gear damage on Gear dice). The convergence test asserts a 3-die pool reaches the analytic targets within ±1%: unpushed ≈ 42.1% ($1 - (5/6)^3$), pushed ≈ 62.3% ($1 - (13/18)^3$).

About

An Explorer and Crew Management System for Coriolis: The Great Dark

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages