I have this small simulation program simulating a toilet seat. The toilet seat may be in two positions: **up** or **down**. If a male arrives to the toilet to urinate, and notices that it is down, he must put it upwards. What we are measuring, are two strategies:

1. Each visitor leaves the seat in the same position as they used it.
2. Each visitor puts the seat **down**.

My code collows:

 package com.github.coderodde.simulation.toiletseat;

 import java.util.Objects;
 import java.util.Random;

 public final class ToiletSeatSimulator {

 private static final int MINIMUM_QUEUE_LENGTH = 1;

 private static enum Gender {
 FEMALE,
 MALE,
 }

 private static enum Operation {
 URINATE,
 POOP,
 }

 private static enum ToiletSeatPosition {
 UP,
 DOWN,
 }

 private final int queueLength;
 private final double femailProportion;
 private final double urinationProportion;
 private final boolean closeDown;
 private final Random random;
 private ToiletSeatPosition toiletSeatPosition;
 private int seatsMoved = 0;

 public ToiletSeatSimulator(int queueLength, 
 double femaileProportion, 
 double urinationProportion,
 boolean closeDown,
 Random random) {
 this.queueLength = checkQueueLength(queueLength);
 this.femailProportion = checkFemaleProportion(femaileProportion);
 this.urinationProportion = 
 checkUrinationProportion(urinationProportion);

 this.closeDown = closeDown;
 this.random = Objects.requireNonNull(random, "The Random is null.");
 this.toiletSeatPosition = ToiletSeatPosition.DOWN;
 }

 public int simulate() {
 for (int i = 0; i < queueLength; i++) {
 performOperation(getRandomGender(), 
 getRandomOperation());
 }

 return seatsMoved;
 }

 private void performOperation(Gender gender, Operation operation) {
 switch (operation) {
 case URINATE:
 performUrination(gender);
 break;

 case POOP:
 performPoop(gender);
 break;

 default:
 throw new IllegalStateException(
 "Unkwnown Gender enum: " + gender);
 }

 if (closeDown && toiletSeatPosition == ToiletSeatPosition.UP) {
 toiletSeatPosition = ToiletSeatPosition.DOWN;
 seatsMoved++;
 }
 }

 private void performUrination(Gender gender) {
 switch (gender) {
 case FEMALE:
 performFemaleUrination();
 break;

 case MALE:
 performMaleUrination();
 break;

 default:
 throw new IllegalStateException(
 "Unknown Gender enum: " + gender);
 }
 }

 private void performFemaleUrination() {
 if (toiletSeatPosition == ToiletSeatPosition.UP) {
 toiletSeatPosition = ToiletSeatPosition.DOWN;
 seatsMoved++;
 }
 }

 private void performMaleUrination() {
 if (toiletSeatPosition == ToiletSeatPosition.DOWN) {
 toiletSeatPosition = ToiletSeatPosition.UP;
 seatsMoved++;
 }
 }

 private void performPoop(Gender gender) {
 switch (gender) {
 case FEMALE:
 performFemalePoop();
 break;

 case MALE:
 performMalePoop();
 break;

 default:
 throw new IllegalStateException(
 "Unknown Gender enum: " + gender);
 }
 }

 private void performFemalePoop() {
 if (toiletSeatPosition == ToiletSeatPosition.UP) {
 toiletSeatPosition = ToiletSeatPosition.DOWN;
 seatsMoved++;
 }
 }

 private void performMalePoop() {
 if (toiletSeatPosition == ToiletSeatPosition.UP) {
 toiletSeatPosition = ToiletSeatPosition.DOWN;
 seatsMoved++;
 }
 }

 private Gender getRandomGender() {
 double coin = random.nextDouble(); // In the range [0, 1).
 return coin < femailProportion ? Gender.FEMALE : Gender.MALE;
 }

 private Operation getRandomOperation() {
 double coin = random.nextDouble();
 return coin < urinationProportion ? Operation.URINATE : Operation.POOP;
 }

 private static int checkQueueLength(int queueLength) {
 if (queueLength < MINIMUM_QUEUE_LENGTH) {
 throw new IllegalArgumentException(
 "Queue length is too small: " 
 + queueLength 
 + ". Must be at most " 
 + MINIMUM_QUEUE_LENGTH
 + ".");
 }

 return queueLength;
 }

 private static double checkFemaleProportion(double femaleProportion) {
 if (Double.isInfinite(femaleProportion)) {
 throw new IllegalArgumentException(
 "Female proportion is infinite in absolute value: " 
 + femaleProportion);
 }

 if (Double.isNaN(femaleProportion)) {
 throw new IllegalArgumentException("Female proportion is NaN.");
 }

 if (femaleProportion < 0.0 || femaleProportion > 1.0) {
 throw new IllegalArgumentException(
 "Female proportion is out of bounds: "
 + femaleProportion
 + ". Must be within closed range [0,1].");
 }

 return femaleProportion;
 }

 private static double checkUrinationProportion(double urinationProportion) {
 if (Double.isInfinite(urinationProportion)) {
 throw new IllegalArgumentException(
 "Urination proportion is infinite in absolute value: " 
 + urinationProportion);
 }

 if (Double.isNaN(urinationProportion)) {
 throw new IllegalArgumentException("Urination proportion is NaN.");
 }

 if (urinationProportion < 0.0 || urinationProportion > 1.0) {
 throw new IllegalArgumentException(
 "Urination proportion is out of bounds: "
 + urinationProportion
 + ". Must be within closed range [0,1].");
 }

 return urinationProportion;
 }
 }

The demo follows:

 package com.github.coderodde.simulation.toiletseat;

 import java.util.Random;

 public final class Demo {

 private static final int QUEUE_LENGTH = 1000;
 private static final double FEMALE_PROPORTION = 0.55;
 private static final double URINATION_PROPORTION = 0.2;

 public static void main(String[] args) {
 long seed = System.currentTimeMillis();
 System.out.println("<<< Seed = " + seed + ">>>");

 Random random1 = new Random(seed);
 Random random2 = new Random(seed);

 ToiletSeatSimulator simulator1 = 
 new ToiletSeatSimulator(
 QUEUE_LENGTH, 
 FEMALE_PROPORTION,
 URINATION_PROPORTION,
 false,
 random1);

 System.out.println(
 "Number of seat moves when changing seat position " 
 + "on demand: " 
 + simulator1.simulate());

 ToiletSeatSimulator simulator2 = 
 new ToiletSeatSimulator(
 QUEUE_LENGTH, 
 FEMALE_PROPORTION,
 URINATION_PROPORTION,
 true,
 random2);

 System.out.println(
 "Number of seat moves when changing seat position back to " 
 + "closed: " 
 + simulator2.simulate());
 }
 }

The typical output is:
```
<<< Seed = 1666884294029>>>
Number of seat moves when changing seat position on demand: 146
Number of seat moves when changing seat position back to closed: 162
```

**Critique request**

As always, I would like to hear any comments. Especially, I doubt the correctness of my implementation, since the above figures are rather optimistic to me.