General Information

  • The topics are organized in a way that would make the code be most presentable and make the greatest sense
  • The order is not in the same order as presented in the FRQ but is numbered to allow for easy comparison

Question 4: Methods and Control Structures

In the fourth FRQ there was a focus on the use of interface and creation of interfaces that serves as a basic template for the all future similar occurrences of a class. We have a similar implementation within our own project representing a similar overall concept that we used an interface to define the basic structure of any crop and the methods that they would typically have, along with soil additives and the methods that they would typically have. Like as seen in the question where we made an interface for NumberGroup that is serves as a template for all future NumberGroup classes such as Range where the shared method contains is overridden. We also have a series of methods that are overridden in order to accomplish their unique attributes and methods.

public interface Crops {
    int econValue(int area);
    int growthStage();
    int calculateGrowingSeason();
    int profitValue(int area);
    int waterUsage(int area);
}


public interface SoilAdditives {
    int cost(int area);
    int ecoEffect(int area);
    int growthEffect(int area);
    int profitEffect(int area);
}

Question 2: Classes

In the second FRQ, there was a focus on the definition of classes and the constructor needed to initiate the class, like in HiddenWord class where we defined a constructor to take in the needed String and set it to the instance variable. We have a similar implementation within the Glyphosate class that we used a constructor to initiate the class and set the instance variable of area to perform the calculations to scale cost with the amount used. We can also see this in a general trend throughout other aspects of our project where we define the Inventory class, Corn class, Person class, etc.

// Uses the interface SoilAdditives element to implement the Glyphosate class like question 4
// The definition of the Glyphosate class similar to the concepts of question 2 
public class Glyphosate implements SoilAdditives {

    int cost = (int) (Math.random() * 13) + 1; // Glphosate cost's between 1 and 13 dollars per 
                                               // acre so we pick a random number in 
                                               // this range to get the cost
    int ecoEffect = -10;
    int growthEffect = 10;
    int profitEffect = 2;
    int area;

    public Glyphosate(area) {
        this.area = area;
    }

    @Override
    public int cost(int area) {
        int quantity = area;
        int unitCost = this.cost;
        int totalCost = unitCost * quantity;
        return totalCost;
    }

    @Override
    public int ecoEffect(int area) {
        int quantity = area;
        int unitEcoEffect = this.ecoEffect;
        int totalEcoEffect = unitEcoEffect * quantity;
        return totalEcoEffect;
    }

    @Override
    public int growthEffect(int area) {
        int quantity = area;
        int unitGrowthEffect = this.growthEffect;
        int totalGrowthEffect = unitGrowthEffect * quantity;
        return totalGrowthEffect;
    }

    @Override
    public int profitEffect(int area) {
        int quantity = area;
        int unitProfitEffect = this.profitEffect;
        int totalProfitEffect = unitProfitEffect * quantity;
        return totalProfitEffect;
    }
}

Question 1: 2D Arrays

In question 1 there was a focus on array and 2d array operations where we can use loops to be able to access the various elements from within the array. This was a very common theme regardless of the array was 2d or 1d as seen through parts A-C where we used them to perform calculations, like summing up the values in part a, or creating the array of row sums in part b, and the nested loops in part C. We have an implementation that also uses this mechanic of dealing with 2d arrays where we create a 2d array of the size growing season with the growing season amount of elements, where we then using nested for loops populate these arrays with values between the growth stage * water usage /2 and growth stage * water usage inclusive, then randomly select and index to create a price. This allows us to have an engaging and semi random experience for the user profits to be able to simulate some of the variability in crop prices which can depend on many factors like moisture content, and the amount of crops produced in this game setting.

import java.lang.Math;
import java.util.Random;

// Uses the interface element Crops to implement the Corn class like question 4
public class Corn implements Crops {

    int initialWeek;
    int week;
    int developmentStage;

    public Corn(int initialWeek, int week) {
        this.initialWeek = initialWeek;
        this.week = week;
    }

    @Override
    public int econValue(int area) {

        // creates a matrix of the size of the current week of the growing season then
        // populate it with random values between the growth state * waterusage/2 to
        // growth state * water usage and then pick a random value from the matrix.
        // Use of 2d arrays like question 1
        int growthStage = growthStage();
        int waterUsage = waterUsage(area);
        int growingSeason = calculateGrowingSeason();

        int[][] econValueMatrix = new int[growingSeason][growingSeason];

        Random random = new Random();

        for (int i = 0; i < growingSeason; i++) {
            for (int j = 0; j < growingSeason; j++) {
                int minValue = growthStage * waterUsage / 2;
                int maxValue = growthStage * waterUsage;
                econValueMatrix[i][j] = minValue + random.nextInt(maxValue - minValue + 1);
            }
        }

        int randomValue = econValueMatrix[random.nextInt(growingSeason)][random.nextInt(growingSeason)];
        return randomValue;
    }

    public int calculateGrowingSeason() {
        // Calculate growing season based on current week
        int currentWeek = getCurrentWeek(); // Replace with actual implementation
        int midPoint = 26; // Midpoint of the growing season
        int earlySeasonDebuff = 2; // Debuff for being too early in the season
        int lateSeasonDebuff = 1; // Debuff for being too late in the season

        if (currentWeek < midPoint) {
            return earlySeasonDebuff * (midPoint - currentWeek);
        } else {
            return lateSeasonDebuff * (currentWeek - midPoint);
        }
    }

    private int getCurrentWeek() {
        // Replace with actual implementation to get the current week
        return this.week;
    }

    @Override
    public int growthStage() {
        // get week via request from FE
        double randNum = 2 + (Math.random() * 4); // generates a random number between 2 and 5
        int weekGrowthFactor = (int) (randNum);
        int developmentStage = this.developmentStage;
        int initialWeek = this.initialWeek; // week when corn was placed
        int week = this.week;
        if (week - initialWeek == weekGrowthFactor) {
            developmentStage = developmentStage + 1;
        }
        return developmentStage;
    }

    @Override
    public int profitValue(int area) {
        int waterNeeded = waterUsage(area);
        int waterCost = 10; // 10 dollars allows for 1000 gallons of water
        int totalWaterCost = waterCost * waterNeeded;
        int baseCropProfit = 6134;
        int totalProfit = baseCropProfit - totalWaterCost;
        return totalProfit * area; // 134 dollars profit
    }

    @Override
    public int waterUsage(int area) {
        // 1 unit = 1000 gallons of water
        int waterNeeded = 600;
        return waterNeeded * area;
    }
}

Question 3: Array List

In question 3 there was a focus on arrayList through the SparseArray class which has an arrayList labeled entries which was full of SparseArrayEntry objects where we wanted to be able to operate on this arrayList to find the populated indices of the SparseArray represented and to be able to remove all elements of a given column and adjust the array size and indices of the remaining elements. We have a similar properties in our Inventory class where the class contains an ArrayList of either SoilAdditive or Crop objects representing the user’s use and quantity of these objects, the use of the arrayList allows us to similarly adjust the contents of the user’s inventory like we did in the problem like adding and removing the elements which would resize their inventory, and not being of a fixed size. From this we can then also perform operations based on the contents of their inventory and get read outs for their overall statistics from water usage, to total farm growth rate, etc. Which we then achieve by creating an Inventory object each user.

import java.util.ArrayList;
import java.util.List;

public class Inventory {
    private List<Crops> cropsList;
    private List<SoilAdditives> soilAdditivesList;
    private int farmArea;
    // Similar to FRQ 3 we have an array list that a player holds in their inventory
    // this also allows us for us to add and change elements as they
    // go through out the game ensuring more flexibility, we are also looping
    // through the various elements and being able to get a more
    // in-depth amount of player stats

    public Inventory(int farmArea) {
        cropsList = new ArrayList<>();
        soilAdditivesList = new ArrayList<>();
        this.farmArea = farmArea;
    }

    public void addCrop(Crops crop) {
        cropsList.add(crop);
    }

    public void removeCrop(Crops crop) {
        cropsList.remove(crop);
    }

    public void addSoilAdditive(SoilAdditives soilAdditive) {
        soilAdditivesList.add(soilAdditive);
    }

    public void removeSoilAdditive(SoilAdditives soilAdditive) {
        soilAdditivesList.remove(soilAdditive);
    }

    public int getEconValue() {
        int totalEconValue = 0;
        for (Crops crop : cropsList) {
            totalEconValue += crop.econValue(farmArea);
        }
        return totalEconValue;
    }

    public int getGrowthStage() {
        int totalGrowthStage = 0;
        for (Crops crop : cropsList) {
            totalGrowthStage += crop.growthStage();
        }
        return totalGrowthStage;
    }

    public int getProfitValue() {
        int totalProfitValue = 0;
        for (Crops crop : cropsList) {
            totalProfitValue += crop.profitValue(farmArea);
        }
        return totalProfitValue;
    }

    public int getWaterUsage() {
        int totalWaterUsage = 0;
        for (Crops crop : cropsList) {
            totalWaterUsage += crop.waterUsage(farmArea);
        }
        return totalWaterUsage;
    }

    public int getCost() {
        int totalCost = 0;
        for (SoilAdditives soilAdditive : soilAdditivesList) {
            totalCost += soilAdditive.cost(farmArea);
        }
        return totalCost;
    }

    public int getEcoEffect() {
        int totalEcoEffect = 0;
        for (SoilAdditives soilAdditive : soilAdditivesList) {
            totalEcoEffect += soilAdditive.ecoEffect(farmArea);
        }
        return totalEcoEffect;
    }

    public int getGrowthEffect() {
        int totalGrowthEffect = 0;
        for (SoilAdditives soilAdditive : soilAdditivesList) {
            totalGrowthEffect += soilAdditive.growthEffect(farmArea);
        }
        return totalGrowthEffect;
    }

    public int getProfitEffect() {
        int totalProfitEffect = 0;
        for (SoilAdditives soilAdditive : soilAdditivesList) {
            totalProfitEffect += soilAdditive.profitEffect(farmArea);
        }
        return totalProfitEffect;
    }

    public int userProfit() {
        return getProfitValue() * getProfitEffect() - getCost();
    }

    public int userEco() {
        return getEconValue() * getEcoEffect();
    }

    public int userGrowth() {
        return getGrowthStage() * getGrowthEffect();
    }

    public int userWater() {
        return getWaterUsage();
    }

}