<h2 id="intro">Intro</h2>
<p>Every spaceship in game needs a crew to operate it. Smaller ships with fewer components require less crew than huge ones with lots of components.</p>
<h2 id="types">Types</h2>
<p>Unit stats lists amount of crew required to operate a spaceship and if they need sleeping quarters.</p>
<pre><code>data UnitStats = UnitStats
    { unitStatsMinimumCrew :: ![CrewRequirement]
    , unitStatsNominalCrew :: ![CrewRequirement]
    , unitStatsCrewSpace :: !TotalCrewSpace
    , unitStatsCrewSpaceRequired :: !CrewSpaceReq
    } deriving (Show, Read, Eq)</code></pre>
<p>Different positions a crew can have is an enumeration:</p>
<pre><code>data CrewPosition =
    Commander
    | Navigator
    | Signaler
    | SensorOperator
    | Gunner
    | Doctor
    | Nurse
    | Driver
    | Helmsman
    | Artificer
    | Crew
    | Passenger
    deriving (Show, Read, Eq, Enum, Bounded)
derivePersistField &quot;CrewPosition&quot;</code></pre>
<p>Rank of a crew member isn’t a military rank, but rather their position in ship’s internal hierarchy:</p>
<pre><code>data CrewRank =
    SecondClass
    | FirstClass
    | Senior
    | Chief
    deriving (Show, Read, Eq, Enum, Bounded)
derivePersistField &quot;CrewRank&quot;</code></pre>
<p>Amount of crew is newtype that helps me not to mix different types of numbers with each other.</p>
<pre><code>newtype CrewAmount = CrewAmount { unCrewAmount :: Int }
    deriving (Show, Read, Eq, Ord, Num)</code></pre>
<p>Total crew space of a ship is divided to three different types: steerage, standard and luxury.</p>
<pre><code>data TotalCrewSpace = TotalCrewSpace
    { totalCrewSpaceSteerage :: !(CrewSpace SteerageQuarters)
    , totalCrewSpaceStandard :: !(CrewSpace StandardQuarters)
    , totalCrewSpaceLuxury :: !(CrewSpace LuxuryQuarters)
    } deriving (Show, Read, Eq)</code></pre>
<p>Again, crew space is newtype so I don’t mix different types of numbers with each other.</p>
<pre><code>data CrewSpace a =
    CrewSpace { unCrewSpace :: CrewAmount }
    deriving (Show, Read, Eq)</code></pre>
<p>I could have modeled fact that vehicle might need crew space with <code>Bool</code>, but having a descriptive name and type is more to my liking.</p>
<pre><code>data CrewSpaceReq =
    CrewSpaceRequired
    | CrewSpaceOptional
    deriving (Show, Read, Eq)
derivePersistField &quot;CrewSpaceReq&quot;</code></pre>
<p>The fact that single person could manage multiple components is reflected by <code>ComponentCrewReq</code> having <code>Double</code> instead of <code>Integer</code></p>
<pre><code>-- | Crew requirements for a component
data ComponentCrewReq =
    ComponentCrewReq CrewPosition Double
    deriving (Show, Read, Eq)</code></pre>
<h2 id="in-closing">In closing</h2>
<p>If you have questions, comments or feedback, easiest way to catch me nowdays is by email or in fediverse where I’m <code>Tuula@mastodon.social</code></p>
