diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
index 48a56c9..d58dfb7 100644
--- a/.mvn/wrapper/maven-wrapper.properties
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -16,4 +16,4 @@
 # under the License.
 wrapperVersion=3.3.2
 distributionType=only-script
-distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
diff --git a/src/main/java/com/appdev/allin/contract/BasketballContractGenerator.java b/src/main/java/com/appdev/allin/contract/BasketballContractGenerator.java
new file mode 100644
index 0000000..a1b500b
--- /dev/null
+++ b/src/main/java/com/appdev/allin/contract/BasketballContractGenerator.java
@@ -0,0 +1,105 @@
+package com.appdev.allin.contract;
+
+import java.time.LocalDate;
+import java.util.concurrent.ThreadLocalRandom;
+
+import com.appdev.allin.player.Player;
+import com.appdev.allin.playerData.PlayerDataRepo;
+import com.appdev.allin.user.User;
+
+public class BasketballContractGenerator extends ContractGenerator {
+
+    public BasketballContractGenerator(PlayerDataRepo playerDataRepo) {
+        super(playerDataRepo);
+    }
+
+    @Override
+    public Contract generateContract(User user, Player player, Double buyPrice, Rarity rarity) {
+        Event event = Event.getRandomEvent();
+        OpposingTeam opposingTeam = OpposingTeam.getRandomOpposingTeam();
+        Double eventProb = 0.5;
+        Double ratio = 2.0;
+
+        // Determine event probability and ratio based on rarity
+        switch (rarity) {
+            case Common:
+                // Probability of event hitting ranges from COMMON_PROB_LOWER_BOUND -
+                // COMMON_PROB_UPPER_BOUND
+                eventProb =
+                        ThreadLocalRandom.current().nextDouble()
+                                        * (COMMON_PROB_UPPER_BOUND - COMMON_PROB_LOWER_BOUND)
+                                + COMMON_PROB_LOWER_BOUND;
+                // Payout/buy_in ratio ranges from COMMON_PAYOUT_LOWER_BOUND -
+                // COMMON_PAYOUT_UPPER_BOUND
+                ratio =
+                        ThreadLocalRandom.current().nextDouble()
+                                        * (COMMON_PAYOUT_UPPER_BOUND - COMMON_PAYOUT_LOWER_BOUND)
+                                + COMMON_PAYOUT_LOWER_BOUND;
+                break;
+            case Rare:
+                // Probability of event hitting ranges from RARE_PROB_LOWER_BOUND -
+                // RARE_PROB_UPPER_BOUND
+                eventProb =
+                        ThreadLocalRandom.current().nextDouble()
+                                        * (RARE_PROB_UPPER_BOUND - RARE_PROB_LOWER_BOUND)
+                                + RARE_PROB_LOWER_BOUND;
+                // Payout/buy_in ratio ranges from RARE_PAYOUT_LOWER_BOUND -
+                // RARE_PAYOUT_UPPER_BOUND
+                ratio =
+                        ThreadLocalRandom.current().nextDouble()
+                                        * (RARE_PAYOUT_UPPER_BOUND - RARE_PAYOUT_LOWER_BOUND)
+                                + RARE_PAYOUT_LOWER_BOUND;
+                break;
+            case Epic:
+                // Probability of event hitting ranges from EPIC_PROB_LOWER_BOUND -
+                // EPIC_PROB_UPPER_BOUND
+                eventProb =
+                        ThreadLocalRandom.current().nextDouble()
+                                        * (EPIC_PROB_UPPER_BOUND - EPIC_PROB_LOWER_BOUND)
+                                + EPIC_PROB_LOWER_BOUND;
+                // Payout/buy_in ratio ranges from EPIC_PAYOUT_LOWER_BOUND -
+                // EPIC_PAYOUT_UPPER_BOUND
+                ratio =
+                        ThreadLocalRandom.current().nextDouble()
+                                        * (EPIC_PAYOUT_UPPER_BOUND - EPIC_PAYOUT_LOWER_BOUND)
+                                + EPIC_PAYOUT_LOWER_BOUND;
+                break;
+            case Legendary:
+                // Probability of event hitting ranges from LEGENDARY_PROB_LOWER_BOUND -
+                // LEGENDARY_PROB_UPPER_BOUND
+                eventProb =
+                        ThreadLocalRandom.current().nextDouble()
+                                        * (LEGENDARY_PROB_UPPER_BOUND - LEGENDARY_PROB_LOWER_BOUND)
+                                + LEGENDARY_PROB_LOWER_BOUND;
+                // Payout/buy_in ratio ranges from LEGENDARY_PAYOUT_LOWER_BOUND -
+                // LEGENDARY_PAYOUT_UPPER_BOUND
+                ratio =
+                        ThreadLocalRandom.current().nextDouble()
+                                        * (LEGENDARY_PAYOUT_UPPER_BOUND
+                                                - LEGENDARY_PAYOUT_LOWER_BOUND)
+                                + LEGENDARY_PAYOUT_LOWER_BOUND;
+                break;
+            default:
+                break;
+        }
+
+        Integer eventThreshold = normalizeEventThreshold(player, event, eventProb);
+
+        // Generate the basketball-specific contract
+        return new Contract(
+                player,
+                user,
+                buyPrice,
+                rarity,
+                opposingTeam,
+                "src/main/resources/static/images/teams/" + opposingTeam + ".png",
+                event,
+                eventThreshold,
+                LocalDate.now(),
+                buyPrice * ratio,
+                null,
+                false,
+                null
+        );
+    }
+}
diff --git a/src/main/java/com/appdev/allin/contract/ContractGenerator.java b/src/main/java/com/appdev/allin/contract/ContractGenerator.java
index 0d9b6ef..51fecea 100644
--- a/src/main/java/com/appdev/allin/contract/ContractGenerator.java
+++ b/src/main/java/com/appdev/allin/contract/ContractGenerator.java
@@ -1,17 +1,15 @@
 package com.appdev.allin.contract;
 
+import java.util.List;
+
+import org.apache.commons.math3.distribution.NormalDistribution;
+
 import com.appdev.allin.player.Player;
 import com.appdev.allin.playerData.PlayerData;
 import com.appdev.allin.playerData.PlayerDataRepo;
 import com.appdev.allin.user.User;
 
-import org.apache.commons.math3.distribution.NormalDistribution;
-
-import java.time.LocalDate;
-import java.util.List;
-import java.util.concurrent.ThreadLocalRandom;
-
-public class ContractGenerator {
+public abstract class ContractGenerator {
 
     PlayerDataRepo playerDataRepo;
 
@@ -106,144 +104,7 @@ public static void generateBounds() {
         LEGENDARY_PAYOUT_LOWER_BOUND = legendary_payout_center - legendary_payout_radius;
     }
 
-    public Contract generateContract(User user, Player player, Double buyPrice, Rarity rarity) {
-        Event event = Event.getRandomEvent();
-        OpposingTeam opposingTeam = OpposingTeam.getRandomOpposingTeam();
-        Double eventProb = 0.5;
-        Double ratio = 2.0;
-        generateBounds();
-
-        switch (rarity) {
-            case Common:
-                // Probability of event hitting ranges from COMMON_PROB_LOWER_BOUND -
-                // COMMON_PROB_UPPER_BOUND
-                eventProb =
-                        ThreadLocalRandom.current().nextDouble()
-                                        * (COMMON_PROB_UPPER_BOUND - COMMON_PROB_LOWER_BOUND)
-                                + COMMON_PROB_LOWER_BOUND;
-                // Payout/buy_in ratio ranges from COMMON_PAYOUT_LOWER_BOUND -
-                // COMMON_PAYOUT_UPPER_BOUND
-                ratio =
-                        ThreadLocalRandom.current().nextDouble()
-                                        * (COMMON_PAYOUT_UPPER_BOUND - COMMON_PAYOUT_LOWER_BOUND)
-                                + COMMON_PAYOUT_LOWER_BOUND;
-                break;
-            case Rare:
-                // Probability of event hitting ranges from RARE_PROB_LOWER_BOUND -
-                // RARE_PROB_UPPER_BOUND
-                eventProb =
-                        ThreadLocalRandom.current().nextDouble()
-                                        * (RARE_PROB_UPPER_BOUND - RARE_PROB_LOWER_BOUND)
-                                + RARE_PROB_LOWER_BOUND;
-                // Payout/buy_in ratio ranges from RARE_PAYOUT_LOWER_BOUND -
-                // RARE_PAYOUT_UPPER_BOUND
-                ratio =
-                        ThreadLocalRandom.current().nextDouble()
-                                        * (RARE_PAYOUT_UPPER_BOUND - RARE_PAYOUT_LOWER_BOUND)
-                                + RARE_PAYOUT_LOWER_BOUND;
-                break;
-            case Epic:
-                // Probability of event hitting ranges from EPIC_PROB_LOWER_BOUND -
-                // EPIC_PROB_UPPER_BOUND
-                eventProb =
-                        ThreadLocalRandom.current().nextDouble()
-                                        * (EPIC_PROB_UPPER_BOUND - EPIC_PROB_LOWER_BOUND)
-                                + EPIC_PROB_LOWER_BOUND;
-                // Payout/buy_in ratio ranges from EPIC_PAYOUT_LOWER_BOUND -
-                // EPIC_PAYOUT_UPPER_BOUND
-                ratio =
-                        ThreadLocalRandom.current().nextDouble()
-                                        * (EPIC_PAYOUT_UPPER_BOUND - EPIC_PAYOUT_LOWER_BOUND)
-                                + EPIC_PAYOUT_LOWER_BOUND;
-                break;
-            case Legendary:
-                // Probability of event hitting ranges from LEGENDARY_PROB_LOWER_BOUND -
-                // LEGENDARY_PROB_UPPER_BOUND
-                eventProb =
-                        ThreadLocalRandom.current().nextDouble()
-                                        * (LEGENDARY_PROB_UPPER_BOUND - LEGENDARY_PROB_LOWER_BOUND)
-                                + LEGENDARY_PROB_LOWER_BOUND;
-                // Payout/buy_in ratio ranges from LEGENDARY_PAYOUT_LOWER_BOUND -
-                // LEGENDARY_PAYOUT_UPPER_BOUND
-                ratio =
-                        ThreadLocalRandom.current().nextDouble()
-                                        * (LEGENDARY_PAYOUT_UPPER_BOUND
-                                                - LEGENDARY_PAYOUT_LOWER_BOUND)
-                                + LEGENDARY_PAYOUT_LOWER_BOUND;
-                break;
-            default:
-                break;
-        }
-
-        Integer eventThreshold = normalizeEventThreshold(player, event, eventProb);
-
-        return new Contract(
-                player,
-                user,
-                buyPrice,
-                rarity,
-                opposingTeam,
-                "src/main/resources/static/images/teams/" + opposingTeam + ".png",
-                event,
-                eventThreshold,
-                LocalDate.now(),
-                buyPrice * ratio,
-                null,
-                false,
-                null);
-    }
-
-    // public Contract generateContract(User user, Player player, Double buyPrice,
-    // Rarity rarity) {
-    // // event and opposing_team is randomly picked
-    // // Value should be greater than the buy_price (each rarity has a different
-    // // multiplier with legendary being the highest)
-    // // event_threshold will be determined from player averages
-
-    // Event event = Event.getRandomEvent();
-    // OpposingTeam opposingTeam = OpposingTeam.getRandomOpposingTeam();
-
-    // // Probability of event happening * payout/buy_in ratio = alpha
-    // // Lower alpha means more profit for us, higher alpha means more profit for
-    // the
-    // // users
-    // Double alpha = 0.95;
-    // Double eventProb = 1.0;
-    // Double ratio = 1.0;
-
-    // switch (rarity) {
-    // case Common:
-    // // Probability of event hitting ranges from 60-80%
-    // eventProb = Math.random() * 0.2 + 0.6;
-    // ratio = alpha / eventProb;
-    // break;
-    // case Rare:
-    // // Probability of event hitting ranges from 45-65%
-    // eventProb = Math.random() * 0.2 + 0.45;
-    // ratio = alpha / eventProb;
-    // break;
-    // case Epic:
-    // // Probability of event hitting ranges from 30-50%
-    // eventProb = Math.random() * 0.2 + 0.3;
-    // ratio = alpha / eventProb;
-    // break;
-    // case Legendary:
-    // // Probability of event hitting ranges from 15-35%
-    // eventProb = Math.random() * 0.2 + 0.15;
-    // ratio = alpha / eventProb;
-    // break;
-    // default:
-    // break;
-    // }
-
-    // Integer eventThreshold = normalizeEventThreshold(player, event, eventProb);
-
-    // return new Contract(player, user, buyPrice, rarity, opposingTeam,
-    // "src/main/resources/static/images/teams/" + opposingTeam + ".png", event,
-    // eventThreshold, LocalDate.now(),
-    // buyPrice * ratio, null,
-    // false, null);
-    // }
+    public abstract Contract generateContract(User user, Player player, Double buyPrice, Rarity rarity);
 
     public Double[] getPlayerDataByEvent(Player player, Event event) {
         List<PlayerData> playerData = playerDataRepo.findByPlayer(player);
@@ -273,4 +134,4 @@ public Integer normalizeEventThreshold(Player player, Event event, Double eventP
         Integer threshold = (int) Math.ceil(X.inverseCumulativeProbability(1 - eventProb));
         return threshold;
     }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/appdev/allin/contract/ContractService.java b/src/main/java/com/appdev/allin/contract/ContractService.java
index f5af8c2..bc392f9 100644
--- a/src/main/java/com/appdev/allin/contract/ContractService.java
+++ b/src/main/java/com/appdev/allin/contract/ContractService.java
@@ -94,7 +94,7 @@ public Contract createContract(
             throw new OverdrawnException("User balance is too low.");
         }
 
-        ContractGenerator contractGenerator = new ContractGenerator(playerDataRepo);
+        ContractGenerator contractGenerator = new BasketballContractGenerator(playerDataRepo);
         Contract contract = contractGenerator.generateContract(user, player, buyPrice, rarity);
         contractRepo.save(contract);
 
diff --git a/src/test/java/com/appdev/allin/AllInApplicationTests.java b/src/test/java/com/appdev/allin/AllInApplicationTests.java
index c6b557b..3fa5041 100644
--- a/src/test/java/com/appdev/allin/AllInApplicationTests.java
+++ b/src/test/java/com/appdev/allin/AllInApplicationTests.java
@@ -12,13 +12,15 @@
 
 import org.junit.jupiter.api.Test;
 
+import com.appdev.allin.contract.BasketballContractGenerator;
+
 class AllInApplicationTests {
 
     @Test
     public void testGenerateContract() {
 
         PlayerDataRepo playerDataRepo = mock(PlayerDataRepo.class);
-        ContractGenerator contractGenerator = new ContractGenerator(playerDataRepo);
+        ContractGenerator contractGenerator = new BasketballContractGenerator(playerDataRepo);
 
         System.out.println("Testing ContractGenerator.generateContract()");
         System.out.println(
diff --git a/src/test/java/com/appdev/allin/ContractGeneratorTest.java b/src/test/java/com/appdev/allin/ContractGeneratorTest.java
index 55798c1..1f60749 100644
--- a/src/test/java/com/appdev/allin/ContractGeneratorTest.java
+++ b/src/test/java/com/appdev/allin/ContractGeneratorTest.java
@@ -12,13 +12,15 @@
 
 import org.junit.jupiter.api.Test;
 
+import com.appdev.allin.contract.BasketballContractGenerator;
+
 class ContractGeneratorTest {
 
     @Test
     public void testGenerateContract() {
 
         PlayerDataRepo playerDataRepo = mock(PlayerDataRepo.class);
-        ContractGenerator contractGenerator = new ContractGenerator(playerDataRepo);
+        ContractGenerator contractGenerator = new BasketballContractGenerator(playerDataRepo);
 
         System.out.println("Testing ContractGenerator.generateContract()");
         System.out.println(