| @ -0,0 +1,28 @@ | |||
| package uwstout.courses.cs144.examples; | |||
| import java.util.Scanner; | |||
| public class Loops { | |||
| public static void main(String[] args) { | |||
| Scanner sc = new Scanner(System.in); | |||
| System.out.println(createSimpleHistrogram(sc)); | |||
| sc.close(); | |||
| } | |||
| public static String createSimpleHistrogram(Scanner vals) { | |||
| String histoString = ""; | |||
| while (vals.hasNextInt()) { | |||
| int n = vals.nextInt(); | |||
| for (int i = 0; i <= n; i++) { | |||
| histoString += "*"; | |||
| } | |||
| histoString += "\n"; | |||
| } | |||
| return histoString; | |||
| } | |||
| } | |||
| @ -0,0 +1,48 @@ | |||
| package uwstout.courses.cs144.examples.characters; | |||
| public class Character { | |||
| private String name; | |||
| private int level; | |||
| private Item left; | |||
| private Item right; | |||
| public Character(String nName, int nLevel) { | |||
| name = nName; | |||
| level = nLevel; | |||
| left = null; | |||
| right = null; | |||
| } | |||
| public String getName() { | |||
| return name; | |||
| } | |||
| public int getLevel() { | |||
| return level; | |||
| } | |||
| public Item getLeftHand() { | |||
| return left; | |||
| } | |||
| public Item getRightHand() { | |||
| return right; | |||
| } | |||
| public void setName(String name) { | |||
| this.name = name; | |||
| } | |||
| public void setLevel(int level) { | |||
| this.level = level; | |||
| } | |||
| public void setLeftHand(Item left) { | |||
| this.left = left; | |||
| } | |||
| public void setRightHand(Item right) { | |||
| this.right = right; | |||
| } | |||
| } | |||
| @ -0,0 +1,54 @@ | |||
| package uwstout.courses.cs144.examples.characters; | |||
| public class CharacterList { | |||
| private Character[] actors; | |||
| private int count; | |||
| public CharacterList() { | |||
| actors = new Character[5]; | |||
| count = 0; | |||
| } | |||
| public int getCharacterCount() { | |||
| return count; | |||
| } | |||
| public Character getCharacter(int pos) { | |||
| if (pos >= 0 && pos < count) { | |||
| return actors[pos]; | |||
| } | |||
| return null; | |||
| } | |||
| public void addCharacter(Character person) { | |||
| if (count == actors.length) { | |||
| Character[] temp = new Character[actors.length + 5]; | |||
| for (int i = 0; i < actors.length; i++) { | |||
| temp[i] = actors[i]; | |||
| } | |||
| actors = temp; | |||
| } | |||
| actors[count++] = person; | |||
| } | |||
| public void removeCharacter(String name) { | |||
| int charPos = findCharacter(name); | |||
| if (charPos >= 0) { | |||
| for (int i = charPos; i < count - 1; i++) { | |||
| actors[i] = actors[i + 1]; | |||
| } | |||
| count--; | |||
| } | |||
| } | |||
| public int findCharacter(String name) { | |||
| for (int i = 0; i < count; i++) { | |||
| if (actors[i].getName().equals(name)) { | |||
| return i; | |||
| } | |||
| } | |||
| return -1; | |||
| } | |||
| } | |||
| @ -0,0 +1,29 @@ | |||
| package uwstout.courses.cs144.examples.characters; | |||
| public class Item { | |||
| private int type; | |||
| private String name; | |||
| public Item(int nType, String nName) { | |||
| type = nType; | |||
| name = nName; | |||
| } | |||
| public String getName() { | |||
| return name; | |||
| } | |||
| public int getType() { | |||
| return type; | |||
| } | |||
| public void setName(String name) { | |||
| this.name = name; | |||
| } | |||
| public void setType(int type) { | |||
| this.type = type; | |||
| } | |||
| } | |||
| @ -0,0 +1,15 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <classpath> | |||
| <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"> | |||
| <attributes> | |||
| <attribute name="module" value="true"/> | |||
| </attributes> | |||
| </classpathentry> | |||
| <classpathentry kind="src" path="src"/> | |||
| <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"> | |||
| <attributes> | |||
| <attribute name="module" value="true"/> | |||
| </attributes> | |||
| </classpathentry> | |||
| <classpathentry kind="output" path="bin"/> | |||
| </classpath> | |||
| @ -0,0 +1,17 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <projectDescription> | |||
| <name>LAB-6</name> | |||
| <comment></comment> | |||
| <projects> | |||
| </projects> | |||
| <buildSpec> | |||
| <buildCommand> | |||
| <name>org.eclipse.jdt.core.javabuilder</name> | |||
| <arguments> | |||
| </arguments> | |||
| </buildCommand> | |||
| </buildSpec> | |||
| <natures> | |||
| <nature>org.eclipse.jdt.core.javanature</nature> | |||
| </natures> | |||
| </projectDescription> | |||
| @ -0,0 +1,7 @@ | |||
| /** | |||
| * @author brett | |||
| * | |||
| */ | |||
| module uwstout.courses.cs144 { | |||
| requires junit; | |||
| } | |||
| @ -0,0 +1,197 @@ | |||
| package uwstout.courses.cs144.labs.lab6; | |||
| import java.text.DecimalFormat; | |||
| /** | |||
| * Represents information for a possible loan, specifically the credit score, | |||
| * desired amount, and number of years. | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.11.08 | |||
| */ | |||
| public class LoanInfo { | |||
| /* | |||
| * Constants | |||
| */ | |||
| // Initialization | |||
| private static final int MIN_VALID_CREDIT_SCORE = 300; | |||
| private static final int MAX_VALID_CREDIT_SCORE = 850; | |||
| private static final double MIN_LOAN_AMOUNT = 10000.00; | |||
| private static final int MIN_LOAN_YEARS = 5; | |||
| // Borders | |||
| /// Anything 300-579 is poor | |||
| private static final String POOR_CREDIT_STRING = "Poor"; | |||
| /// Anything 580-669 is fair | |||
| private static final int FAIR_CREDIT_BOUNDARY = 580; | |||
| private static final String FAIR_CREDIT_STRING = "Fair"; | |||
| /// Anything 670-739 is good | |||
| private static final int GOOD_CREDIT_BOUNDARY = 670; | |||
| private static final String GOOD_CREDIT_STRING = "Good"; | |||
| /// Anything 740-799 is very good | |||
| private static final int VGOOD_CREDIT_BOUNDARY = 740; | |||
| private static final String VGOOD_CREDIT_STRING = "Very Good"; | |||
| /// Anything 800-850 is exceptional | |||
| private static final int EXCEPTIONAL_CREDIT_BOUNDARY = 800; | |||
| private static final String EXCEPTIONAL_CREDIT_STRING = "Exceptional"; | |||
| // Approval Values | |||
| private static final int INSTANT_APPROVAL_CREDIT_SCORE = GOOD_CREDIT_BOUNDARY; | |||
| private static final int MIN_APPROVAL_CREDIT_SCORE = FAIR_CREDIT_BOUNDARY; | |||
| private static final double MAX_APPROVAL_LOAN_AMOUNT = 100000.00; | |||
| // Interest Rates | |||
| private static final double YEAR_10_IR = 0.06; | |||
| private static final double YEAR_15_IR = 0.05; | |||
| private static final double YEAR_30_IR = 0.04; | |||
| private static final double YEAR_OTHER_IR = 0.08; | |||
| /* | |||
| * Class Members | |||
| */ | |||
| private int creditScore; | |||
| private double amount; | |||
| private int years; | |||
| /** | |||
| * Creates a new instance of the LoanInfo class | |||
| * | |||
| * @param nCreditScore The credit score of the Loan applicant | |||
| * @param nAmount The dollar amount of the Loan | |||
| * @param nYears The number of years of the Loan | |||
| */ | |||
| public LoanInfo(int nCreditScore, double nAmount, int nYears) { | |||
| // Ensure credit score is between MIN and MAX, otherwise set it to 300. | |||
| creditScore = (nCreditScore >= MIN_VALID_CREDIT_SCORE | |||
| && nCreditScore <= MAX_VALID_CREDIT_SCORE) ? nCreditScore | |||
| : MIN_VALID_CREDIT_SCORE; | |||
| amount = (nAmount >= MIN_LOAN_AMOUNT) ? nAmount : MIN_LOAN_AMOUNT; | |||
| years = (nYears >= MIN_LOAN_YEARS) ? nYears : MIN_LOAN_YEARS; | |||
| } | |||
| /** | |||
| * Get the credit score of the Loan applicant | |||
| * | |||
| * @return The Loan applicant's credit score | |||
| */ | |||
| public int getCreditScore() { | |||
| return creditScore; | |||
| } | |||
| /** | |||
| * Get the dollar amount of the loan | |||
| * | |||
| * @return The dollar amount of the loan | |||
| */ | |||
| public double getAmount() { | |||
| return amount; | |||
| } | |||
| /** | |||
| * Get the number of years of the loan | |||
| * | |||
| * @return The number of years of the loan | |||
| */ | |||
| public int getYears() { | |||
| return years; | |||
| } | |||
| /** | |||
| * Determines if the loan should be approved based on the information | |||
| * provided. Is either approved immediately if the credit score is over the | |||
| * {@link #INSTANT_APPROVAL_CREDIT_SCORE} or if the credit score is over the | |||
| * {@link #MIN_APPROVAL_CREDIT_SCORE} and the loan amount is below the | |||
| * {@link #MAX_APPROVAL_LOAN_AMOUNT}. | |||
| * | |||
| * @return If the loan should be approved. | |||
| */ | |||
| public boolean canApprove() { | |||
| // Check if the credit score is above the instant approval credit score | |||
| if (creditScore >= INSTANT_APPROVAL_CREDIT_SCORE) { | |||
| return true; | |||
| } | |||
| // Check if the credit score is above the minimum approval, and the loan | |||
| // amount is below the maximum | |||
| if (creditScore >= MIN_APPROVAL_CREDIT_SCORE | |||
| && amount < MAX_APPROVAL_LOAN_AMOUNT) { | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| /** | |||
| * Gets the interest rate based on the number of years the loan is for. | |||
| * Either, {@link #YEAR_10_IR}, {@link #YEAR_15_IR}, {@link #YEAR_30_IR}, or | |||
| * {@link #YEAR_OTHER_IR}. | |||
| * | |||
| * @return The interest rate of the loan. | |||
| */ | |||
| public double getInterestRate() { | |||
| double result; | |||
| switch (years) { | |||
| case 10: | |||
| result = YEAR_10_IR; | |||
| break; | |||
| case 15: | |||
| result = YEAR_15_IR; | |||
| break; | |||
| case 30: | |||
| result = YEAR_30_IR; | |||
| break; | |||
| default: | |||
| result = YEAR_OTHER_IR; | |||
| break; | |||
| } | |||
| return result; | |||
| } | |||
| /** | |||
| * Gets the credit category of the loan based on the credit score of the | |||
| * applicant. | |||
| * | |||
| * @return The credit category | |||
| */ | |||
| public String getCreditCategory() { | |||
| String retString = ""; | |||
| if (creditScore >= EXCEPTIONAL_CREDIT_BOUNDARY) { | |||
| retString = EXCEPTIONAL_CREDIT_STRING; | |||
| } else if (creditScore >= VGOOD_CREDIT_BOUNDARY) { | |||
| retString = VGOOD_CREDIT_STRING; | |||
| } else if (creditScore >= GOOD_CREDIT_BOUNDARY) { | |||
| retString = GOOD_CREDIT_STRING; | |||
| } else if (creditScore >= FAIR_CREDIT_BOUNDARY) { | |||
| retString = FAIR_CREDIT_STRING; | |||
| } else { | |||
| retString = POOR_CREDIT_STRING; | |||
| } | |||
| return retString; | |||
| } | |||
| @Override | |||
| public String toString() { | |||
| StringBuilder builder = new StringBuilder(); | |||
| builder.append(DecimalFormat.getCurrencyInstance().format(amount)); | |||
| builder.append(" @ "); | |||
| builder.append( | |||
| DecimalFormat.getPercentInstance().format(getInterestRate())); | |||
| builder.append(" for "); | |||
| builder.append(years); | |||
| builder.append(" years, "); | |||
| builder.append(getCreditCategory()); | |||
| builder.append(" credit: "); | |||
| builder.append(canApprove() ? "Approved" : "Denied"); | |||
| return builder.toString(); | |||
| } | |||
| } | |||
| @ -0,0 +1,149 @@ | |||
| package uwstout.courses.cs144.labs.lab6; | |||
| import static org.junit.Assert.assertEquals; | |||
| import org.junit.Before; | |||
| import org.junit.Test; | |||
| /** | |||
| * Tests the {@link LoanInfo} class | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.11.08 | |||
| */ | |||
| public class LoanInfoTest { | |||
| private static final double DELTA = 0.01; | |||
| private LoanInfo l1; | |||
| private LoanInfo l2; | |||
| private LoanInfo l3; | |||
| private LoanInfo l4; | |||
| private LoanInfo l5; | |||
| private LoanInfo l6; | |||
| private LoanInfo l7; | |||
| /** | |||
| * Sets the LoanInfoTest class up for testing. | |||
| * | |||
| * @throws Exception | |||
| */ | |||
| @Before | |||
| public void setUp() throws Exception { | |||
| l1 = new LoanInfo(0, 0, 0); | |||
| l2 = new LoanInfo(600, 15000, 10); | |||
| l3 = new LoanInfo(900, 30000, 15); | |||
| l4 = new LoanInfo(850, 100000, 8); | |||
| l5 = new LoanInfo(580, 150000, 10); | |||
| l6 = new LoanInfo(600, 75000, 30); | |||
| l7 = new LoanInfo(580, 100000, 10); | |||
| } | |||
| /** | |||
| * Tests the LoanInfo constructor | |||
| */ | |||
| @Test | |||
| public void testLoanInfo() { | |||
| assertEquals(300, l1.getCreditScore()); | |||
| assertEquals(10000, l1.getAmount(), DELTA); | |||
| assertEquals(5, l1.getYears()); | |||
| assertEquals(600, l2.getCreditScore()); | |||
| assertEquals(15000, l2.getAmount(), DELTA); | |||
| assertEquals(10, l2.getYears()); | |||
| assertEquals(300, l3.getCreditScore()); | |||
| assertEquals(30000, l3.getAmount(), DELTA); | |||
| assertEquals(15, l3.getYears()); | |||
| assertEquals(850, l4.getCreditScore()); | |||
| assertEquals(100000, l4.getAmount(), DELTA); | |||
| assertEquals(8, l4.getYears()); | |||
| assertEquals(580, l5.getCreditScore()); | |||
| assertEquals(150000, l5.getAmount(), DELTA); | |||
| assertEquals(10, l5.getYears()); | |||
| assertEquals(600, l6.getCreditScore()); | |||
| assertEquals(75000, l6.getAmount(), DELTA); | |||
| assertEquals(30, l6.getYears()); | |||
| assertEquals(580, l7.getCreditScore()); | |||
| assertEquals(100000, l7.getAmount(), DELTA); | |||
| assertEquals(10, l7.getYears()); | |||
| } | |||
| /** | |||
| * Tests the canApprove method | |||
| */ | |||
| @Test | |||
| public void testCanApprove() { | |||
| assertEquals(false, l1.canApprove()); | |||
| assertEquals(true, l2.canApprove()); | |||
| assertEquals(false, l3.canApprove()); | |||
| assertEquals(true, l4.canApprove()); | |||
| assertEquals(false, l5.canApprove()); | |||
| assertEquals(true, l6.canApprove()); | |||
| assertEquals(false, l7.canApprove()); | |||
| } | |||
| /** | |||
| * Tests the getInterestRate method | |||
| */ | |||
| @Test | |||
| public void testGetInterestRate() { | |||
| assertEquals(0.08, l1.getInterestRate(), DELTA); | |||
| assertEquals(0.06, l2.getInterestRate(), DELTA); | |||
| assertEquals(0.05, l3.getInterestRate(), DELTA); | |||
| assertEquals(0.08, l4.getInterestRate(), DELTA); | |||
| assertEquals(0.06, l5.getInterestRate(), DELTA); | |||
| assertEquals(0.04, l6.getInterestRate(), DELTA); | |||
| assertEquals(0.06, l7.getInterestRate(), DELTA); | |||
| } | |||
| /** | |||
| * Tests the getCreditCategory method | |||
| */ | |||
| @Test | |||
| public void testGetCreditCategory() { | |||
| LoanInfo pCLoanInfo = new LoanInfo(300, 0, 0); | |||
| assertEquals("Poor", pCLoanInfo.getCreditCategory()); | |||
| LoanInfo fCLoanInfo = new LoanInfo(580, 0, 0); | |||
| assertEquals("Fair", fCLoanInfo.getCreditCategory()); | |||
| LoanInfo gCLoanInfo = new LoanInfo(670, 0, 0); | |||
| assertEquals("Good", gCLoanInfo.getCreditCategory()); | |||
| LoanInfo vgCLoanInfo = new LoanInfo(740, 0, 0); | |||
| assertEquals("Very Good", vgCLoanInfo.getCreditCategory()); | |||
| LoanInfo eCLoanInfo = new LoanInfo(800, 0, 0); | |||
| assertEquals("Exceptional", eCLoanInfo.getCreditCategory()); | |||
| } | |||
| /** | |||
| * Tests the toString method | |||
| */ | |||
| @Test | |||
| public void testToString() { | |||
| assertEquals("$10,000.00 @ 8% for 5 years, Poor credit: Denied", | |||
| l1.toString()); | |||
| assertEquals("$15,000.00 @ 6% for 10 years, Fair credit: Approved", | |||
| l2.toString()); | |||
| assertEquals("$30,000.00 @ 5% for 15 years, Poor credit: Denied", | |||
| l3.toString()); | |||
| assertEquals( | |||
| "$100,000.00 @ 8% for 8 years, Exceptional credit: Approved", | |||
| l4.toString()); | |||
| assertEquals("$150,000.00 @ 6% for 10 years, Fair credit: Denied", | |||
| l5.toString()); | |||
| assertEquals("$75,000.00 @ 4% for 30 years, Fair credit: Approved", | |||
| l6.toString()); | |||
| assertEquals("$100,000.00 @ 6% for 10 years, Fair credit: Denied", | |||
| l7.toString()); | |||
| } | |||
| } | |||
| @ -0,0 +1,15 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <classpath> | |||
| <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"> | |||
| <attributes> | |||
| <attribute name="module" value="true"/> | |||
| </attributes> | |||
| </classpathentry> | |||
| <classpathentry kind="src" path="src"/> | |||
| <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"> | |||
| <attributes> | |||
| <attribute name="module" value="true"/> | |||
| </attributes> | |||
| </classpathentry> | |||
| <classpathentry kind="output" path="bin"/> | |||
| </classpath> | |||
| @ -0,0 +1,17 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <projectDescription> | |||
| <name>LAB-7</name> | |||
| <comment></comment> | |||
| <projects> | |||
| </projects> | |||
| <buildSpec> | |||
| <buildCommand> | |||
| <name>org.eclipse.jdt.core.javabuilder</name> | |||
| <arguments> | |||
| </arguments> | |||
| </buildCommand> | |||
| </buildSpec> | |||
| <natures> | |||
| <nature>org.eclipse.jdt.core.javanature</nature> | |||
| </natures> | |||
| </projectDescription> | |||
| @ -0,0 +1,6 @@ | |||
| 6bw61YK7Bb [debits] 16 18 5 11 17 11 14 3 18 [debits] [uses] 13 19 14 16 2 [uses] [uses] 45.45 6.26 44.69 2.14 99.95 92.35 1.19 57.93 15.15 [uses] [returns] 17 16 0 14 8 3 [returns] [uses] 19 13 18 8 5 0 13 [uses] | |||
| H04GP8Y7DC returns 54.27 17.42 returns [debits] 7 10 14 [debits] income 60.29 96.40 7.21 16.78 37.25 income [debits] 59.23 32.09 [debits] | |||
| i51ZGQQ6g1 debits 16 17 3 12 0 6 9 debits debits 52.39 76.86 60.14 debits returns 13 12 15 17 0 returns income 64.74 11.76 41.06 income | |||
| dF6aW1--51 [debits] 19.19 5.33 91.10 [debits] [uses] 19 12 14 [uses] [returns] 82.80 17.24 [returns] interactions 17 18 3 7 19 interactions interactions 0 19 3 interactions [debits] 58.49 39.84 19.72 28.69 1.23 [debits] | |||
| XmqY743pr3 | |||
| @ -0,0 +1,16 @@ | |||
| 20#Tg0=OI6 [returns] 17 12 10 [returns] [uses] 1 8 [uses] [returns] 28.09 78.25 95.84 28.33 71.12 [returns] returns 2 3 14 0 4 16 15 1 returns | |||
| 68WTt10AZ5 [uses] 19 17 [uses] interactions 14 16 20 16 6 11 interactions income 45.90 71.70 98.27 80.55 31.32 income debits 16 8 17 2 8 5 3 4 debits | |||
| bm3D679n+m [returns] 39.60 96.77 64.52 64.80 70.38 46.81 84.05 67.88 6.05 [returns] uses 12 9 3 14 19 18 9 0 uses [interactions] 2 12 20 19 18 15 [interactions] | |||
| 9Yns4a9i5N returns 29.72 43.74 33.53 90.60 97.37 68.43 20.10 16.12 returns debits 3 6 15 16 11 7 debits returns 10 12 13 2 9 5 12 20 9 returns [income] 23.31 63.03 [income] interactions 7 7 11 20 14 1 interactions [uses] 18 0 11 0 15 5 2 [uses] | |||
| B407e5PDY0 returns 19 7 returns [returns] 24.21 85.33 44.85 45.20 43.83 40.31 10.30 98.19 [returns] | |||
| +9fA2h3U2l | |||
| aI8Ci9%18Z [debits] 21.23 59.68 19.85 49.44 14.94 45.33 10.34 22.56 [debits] income 13.09 83.16 75.74 51.15 22.35 91.03 28.40 income [returns] 4 20 14 3 6 15 [returns] [debits] 11.90 45.59 3.79 [debits] [debits] 42.29 15.47 84.80 88.71 41.90 [debits] | |||
| lvex52d110 [debits] 9 2 15 [debits] uses 74.82 82.98 96.95 81.61 14.77 82.69 24.71 35.64 uses [debits] 17.24 26.26 69.61 [debits] uses 48.97 0.95 uses | |||
| *xNr77h034 [debits] 4 5 0 [debits] [uses] 35.31 74.41 2.07 25.82 71.44 59.72 [uses] [uses] 11 20 19 10 12 12 0 3 17 [uses] [debits] 14.95 43.99 45.81 5.83 23.06 38.07 74.73 67.58 [debits] [uses] 66.46 16.19 69.98 57.36 4.92 [uses] returns 2 15 3 6 0 11 10 8 returns | |||
| 63Yl72Adc4 [uses] 16 1 6 18 6 7 3 0 [uses] debits 5 13 2 3 19 18 debits [debits] 59.62 95.24 26.35 52.61 34.09 0.62 9.89 6.27 16.72 [debits] | |||
| 1RHq52U783 returns 13.84 38.47 45.59 returns [uses] 11 13 18 6 18 [uses] returns 14 5 9 20 3 6 15 returns [income] 94.34 29.13 81.69 11.17 5.08 [income] [interactions] 7 14 5 0 [interactions] income 7.61 65.28 90.56 93.72 30.26 97.32 income interactions 10 0 17 17 interactions income 49.38 54.20 16.61 55.75 15.72 5.13 income | |||
| &m5876nKD( [debits] 19 4 9 2 3 6 8 0 [debits] [interactions] 7 2 5 [interactions] [uses] 38.14 39.76 [uses] | |||
| q5Uj)2U65@ income 57.93 41.45 income [interactions] 10 3 14 2 20 [interactions] [uses] 20 10 [uses] [returns] 60.25 69.45 40.95 60.48 34.32 15.74 59.19 55.31 [returns] [returns] 19 13 17 4 [returns] | |||
| p4C@NX9422 uses 65.43 4.42 92.60 12.60 9.53 uses [debits] 20 3 7 15 20 10 5 14 18 [debits] [returns] 83.67 44.87 99.39 15.32 48.07 99.70 11.94 [returns] interactions 0 16 14 interactions [income] 25.97 84.72 [income] returns 7.40 30.59 16.74 88.92 35.97 82.14 8.95 28.36 22.55 returns | |||
| 87W&66tt3q [interactions] 17 2 7 13 14 0 9 17 16 [interactions] uses 81.77 5.85 23.60 34.94 15.47 98.74 36.53 uses uses 19 4 9 16 4 13 uses | |||
| @ -0,0 +1,36 @@ | |||
| 0XlfA2Y21E [uses] 57.36 34.06 11.94 14.16 44.70 [uses] [debits] 71.66 12.84 14.25 57.75 56.44 71.61 33.24 15.48 [debits] [debits] 24.57 69.94 7.41 20.79 37.59 15.42 89.77 [debits] income 7.96 80.78 40.30 48.29 53.87 11.06 21.47 income | |||
| o80ve2yJ69 returns 6 14 12 7 2 8 3 returns [uses] 29.97 63.24 65.37 48.71 91.12 [uses] [uses] 2 4 20 4 4 0 6 16 11 [uses] [uses] 15 14 11 [uses] [debits] 52.68 78.95 63.40 16.51 72.03 97.23 60.62 14.71 16.55 [debits] uses 8 2 13 19 1 1 16 16 8 uses | |||
| 1wu5Rn5NF2 returns 23.24 48.99 12.59 returns uses 4 18 6 7 17 20 uses income 49.85 71.12 78.30 38.38 89.51 38.23 56.34 income returns 44.81 11.03 9.34 26.97 95.95 27.14 returns debits 92.86 95.33 68.83 82.44 93.17 37.82 debits | |||
| 23G1A210OF [debits] 15 15 15 13 12 2 [debits] income 97.30 0.59 94.92 35.63 16.31 income [interactions] 17 19 [interactions] debits 1 9 11 14 0 debits | |||
| xaj321J1BZ [debits] 8 14 [debits] [interactions] 6 18 18 7 8 [interactions] | |||
| Cr731Iii7I uses 87.86 63.43 70.21 87.20 88.97 60.50 76.81 18.42 uses uses 63.46 2.73 28.35 69.03 79.83 77.51 94.53 90.63 uses income 66.90 46.29 75.62 73.55 51.54 70.89 80.18 22.05 income [interactions] 13 2 20 9 0 19 [interactions] income 92.67 35.00 38.26 income income 20.75 22.31 38.63 66.89 74.26 10.71 income income 22.71 80.35 35.42 30.18 50.24 13.31 53.84 income | |||
| 6E3Fxj85yL returns 13 0 18 19 14 13 1 8 5 returns income 24.32 87.86 97.25 22.70 7.06 4.57 19.79 23.68 income interactions 9 15 19 16 interactions | |||
| wYs18i9m5k returns 3 11 6 2 returns [uses] 13 19 3 [uses] [interactions] 16 13 5 18 [interactions] | |||
| W8ANj6np26 [debits] 7 10 1 13 2 [debits] uses 72.59 17.42 81.22 17.96 93.96 95.85 63.51 75.19 98.87 uses [interactions] 7 12 17 20 2 10 [interactions] [income] 60.40 58.78 [income] interactions 1 14 15 14 20 1 interactions | |||
| b8W01cT5n8 interactions 0 16 4 3 interactions [income] 83.50 41.60 23.05 24.06 25.83 92.62 71.87 [income] | |||
| 338bJ687YD debits 10 12 8 5 2 4 17 9 2 debits | |||
| 8ft4ChT823 returns 15 14 returns [income] 7.81 95.19 16.07 91.16 89.42 24.06 [income] [income] 48.93 94.64 27.08 [income] [interactions] 8 0 5 8 19 13 12 15 [interactions] | |||
| i01&50ftN2 [uses] 1.20 2.67 [uses] [uses] 39.26 69.03 3.11 69.90 68.50 40.17 [uses] [interactions] 14 3 7 1 20 4 [interactions] [returns] 80.99 5.63 42.85 38.10 2.76 65.67 37.36 [returns] [uses] 83.26 69.03 [uses] | |||
| ocn2E9U02m [debits] 22.62 90.71 19.97 51.49 13.68 86.25 [debits] [uses] 26.53 78.68 46.65 [uses] [returns] 99.72 86.32 5.30 58.42 5.05 12.69 62.03 7.23 [returns] debits 20 11 18 1 0 8 10 9 11 debits | |||
| At90OL089h [returns] 19 19 8 4 8 0 2 7 16 [returns] [uses] 59.72 97.33 8.67 [uses] [uses] 19 10 16 11 9 [uses] income 22.74 97.53 income returns 1 12 7 17 1 2 15 3 returns returns 18 5 6 9 18 3 15 10 4 returns returns 5 10 4 8 7 returns | |||
| eo0n0Z62wq [uses] 3 5 11 1 14 1 11 19 13 [uses] [uses] 14 10 [uses] income 25.97 25.06 58.94 18.99 69.62 4.73 26.77 income [income] 26.69 92.09 12.96 27.95 72.97 [income] returns 11 11 3 20 5 12 13 3 3 returns | |||
| 6sVk7528rZ [returns] 16 20 13 8 7 15 [returns] [interactions] 3 13 10 17 15 [interactions] [income] 20.17 48.83 97.01 [income] [debits] 55.54 57.08 [debits] [income] 1.45 69.59 60.61 41.25 74.95 65.20 77.76 64.14 86.07 [income] | |||
| O@2C3Y5Oe6 [debits] 80.98 74.85 83.88 25.76 33.65 31.69 93.79 91.78 38.96 [debits] [debits] 15 14 9 0 [debits] uses 13.61 51.04 29.17 6.43 uses | |||
| 99L0MmmK60 [returns] 36.56 98.19 72.40 47.40 16.82 58.52 7.37 33.99 11.17 [returns] returns 91.67 76.87 67.45 26.60 91.27 94.31 60.00 3.24 58.90 returns [returns] 94.99 2.55 79.16 [returns] | |||
| M5N$p8C823 income 30.79 33.35 88.69 income [interactions] 12 15 [interactions] | |||
| 8r80725tqY debits 4 11 14 0 debits returns 4 2 19 returns [uses] 8 6 2 6 9 0 20 20 [uses] [interactions] 20 2 11 [interactions] income 11.96 51.60 12.41 31.54 46.24 52.49 96.30 3.58 income | |||
| Qb7gA5M10H [uses] 5 0 3 20 16 0 7 2 6 [uses] debits 52.74 39.02 67.73 95.93 debits | |||
| 0Y-o506P%b [uses] 6.01 89.11 76.96 88.11 74.98 27.75 2.27 [uses] [interactions] 1 3 16 6 3 [interactions] | |||
| 9Lc160L30C uses 1 10 12 12 6 10 2 14 uses [interactions] 17 13 11 18 12 8 20 16 [interactions] income 62.32 89.46 62.95 49.40 42.38 78.53 income [uses] 1 4 10 6 7 4 18 [uses] | |||
| E%q847=v2d [returns] 47.88 76.44 50.37 45.13 [returns] | |||
| 23L9Jgx7yt returns 92.18 68.29 18.09 returns uses 14 17 11 18 14 15 8 0 uses returns 0 11 returns | |||
| BH51tz93s5 [uses] 7 7 9 7 [uses] returns 15.34 63.27 71.81 3.52 23.05 12.82 52.33 returns [interactions] 7 6 2 3 7 [interactions] income 4.03 67.32 87.56 65.24 22.91 income [uses] 10 18 20 17 8 1 13 8 [uses] | |||
| f71O-^D5k9 interactions 13 18 2 interactions income 42.37 89.94 75.14 12.04 income [returns] 6.50 80.41 69.37 35.66 [returns] [debits] 61.39 47.20 28.31 15.98 30.56 81.34 89.15 9.94 [debits] | |||
| o4bbw3q524 uses 10 13 11 4 15 11 1 uses returns 19 18 15 0 20 14 8 11 16 returns interactions 16 10 17 14 5 4 17 interactions interactions 10 11 9 4 2 interactions | |||
| x60iC7015a [uses] 16 0 [uses] returns 31.19 2.89 44.83 20.84 44.40 65.63 returns debits 10 15 18 debits [interactions] 4 17 18 18 15 19 [interactions] income 98.69 68.25 17.93 28.21 53.36 8.78 75.31 34.99 income [income] 39.25 12.78 64.77 14.10 74.76 27.78 [income] debits 12 7 11 3 17 debits | |||
| 578q3cOi4L uses 9 9 15 16 uses debits 99.02 5.76 14.89 69.11 80.06 2.97 19.95 91.74 debits [debits] 17 7 [debits] income 43.22 81.33 94.52 88.67 32.87 63.32 income [interactions] 3 6 5 15 0 6 20 18 [interactions] income 85.06 66.61 22.98 77.44 income | |||
| t8W7R&45s3 [debits] 11 17 [debits] income 6.35 30.91 22.44 29.06 53.71 49.69 87.38 23.27 35.04 income interactions 0 12 11 17 17 18 interactions [uses] 40.87 87.47 47.98 28.70 32.46 65.56 41.49 96.47 68.70 [uses] | |||
| 53h2xKa8P1 [debits] 9 13 0 0 [debits] returns 52.56 50.71 94.78 32.58 returns returns 67.72 37.34 44.23 33.35 returns [uses] 15 8 12 15 2 9 [uses] | |||
| 9=4(L4kF8b uses 10 5 18 15 1 6 15 9 16 uses returns 8.39 15.71 99.57 returns [returns] 18 10 20 12 [returns] [debits] 9 0 9 2 17 4 9 4 [debits] debits 18 12 4 3 7 debits | |||
| 12TGf5$u)3 [uses] 19.01 21.42 7.07 33.85 2.58 86.49 68.91 [uses] debits 18 2 debits [income] 74.02 8.65 [income] | |||
| @ -0,0 +1,5 @@ | |||
| 6bw61YK7Bb .00 | |||
| H04GP8Y7DC 217.93 | |||
| i51ZGQQ6g1 117.56 | |||
| dF6aW1--51 .00 | |||
| XmqY743pr3 .00 | |||
| @ -0,0 +1,5 @@ | |||
| 6bw61YK7Bb 0 | |||
| H04GP8Y7DC 217.93 | |||
| i51ZGQQ6g1 117.56 | |||
| dF6aW1--51 0 | |||
| XmqY743pr3 0 | |||
| @ -0,0 +1,5 @@ | |||
| 6bw61YK7Bb 0 | |||
| H04GP8Y7DC 0 | |||
| i51ZGQQ6g1 0 | |||
| dF6aW1--51 12 | |||
| XmqY743pr3 0 | |||
| @ -0,0 +1,5 @@ | |||
| 6bw61YK7Bb true | |||
| H04GP8Y7DC true | |||
| i51ZGQQ6g1 true | |||
| dF6aW1--51 false | |||
| XmqY743pr3 true | |||
| @ -0,0 +1,15 @@ | |||
| 20#Tg0=OI6 .00 | |||
| 68WTt10AZ5 327.74 | |||
| bm3D679n+m .00 | |||
| 9Yns4a9i5N 86.34 | |||
| B407e5PDY0 .00 | |||
| +9fA2h3U2l .00 | |||
| aI8Ci9%18Z 364.92 | |||
| lvex52d110 .00 | |||
| *xNr77h034 .00 | |||
| 63Yl72Adc4 .00 | |||
| 1RHq52U783 221.41 | |||
| &m5876nKD( .00 | |||
| q5Uj)2U65@ 99.38 | |||
| p4C@NX9422 110.69 | |||
| 87W&66tt3q .00 | |||
| @ -0,0 +1,15 @@ | |||
| 20#Tg0=OI6 0 | |||
| 68WTt10AZ5 327.74 | |||
| bm3D679n+m 0 | |||
| 9Yns4a9i5N 86.34 | |||
| B407e5PDY0 0 | |||
| +9fA2h3U2l 0 | |||
| aI8Ci9%18Z 364.92 | |||
| lvex52d110 0 | |||
| *xNr77h034 0 | |||
| 63Yl72Adc4 0 | |||
| 1RHq52U783 221.41 | |||
| &m5876nKD( 0 | |||
| q5Uj)2U65@ 99.38 | |||
| p4C@NX9422 110.69 | |||
| 87W&66tt3q 0 | |||
| @ -0,0 +1,15 @@ | |||
| 20#Tg0=OI6 0 | |||
| 68WTt10AZ5 13 | |||
| bm3D679n+m 14 | |||
| 9Yns4a9i5N 10 | |||
| B407e5PDY0 0 | |||
| +9fA2h3U2l 0 | |||
| aI8Ci9%18Z 0 | |||
| lvex52d110 0 | |||
| *xNr77h034 0 | |||
| 63Yl72Adc4 0 | |||
| 1RHq52U783 6 | |||
| &m5876nKD( 4 | |||
| q5Uj)2U65@ 9 | |||
| p4C@NX9422 10 | |||
| 87W&66tt3q 10 | |||
| @ -0,0 +1,15 @@ | |||
| 20#Tg0=OI6 false | |||
| 68WTt10AZ5 false | |||
| bm3D679n+m false | |||
| 9Yns4a9i5N true | |||
| B407e5PDY0 false | |||
| +9fA2h3U2l false | |||
| aI8Ci9%18Z false | |||
| lvex52d110 false | |||
| *xNr77h034 false | |||
| 63Yl72Adc4 false | |||
| 1RHq52U783 false | |||
| &m5876nKD( false | |||
| q5Uj)2U65@ false | |||
| p4C@NX9422 false | |||
| 87W&66tt3q false | |||
| @ -0,0 +1,35 @@ | |||
| 0XlfA2Y21E 263.73 | |||
| o80ve2yJ69 .00 | |||
| 1wu5Rn5NF2 421.73 | |||
| 23G1A210OF 244.75 | |||
| xaj321J1BZ .00 | |||
| Cr731Iii7I 487.02 | |||
| 6E3Fxj85yL 287.23 | |||
| wYs18i9m5k .00 | |||
| W8ANj6np26 119.18 | |||
| b8W01cT5n8 362.53 | |||
| 338bJ687YD .00 | |||
| 8ft4ChT823 323.71 | |||
| i01&50ftN2 .00 | |||
| ocn2E9U02m .00 | |||
| At90OL089h 120.27 | |||
| eo0n0Z62wq 230.08 | |||
| 6sVk7528rZ 166.01 | |||
| O@2C3Y5Oe6 .00 | |||
| 99L0MmmK60 .00 | |||
| M5N$p8C823 152.83 | |||
| 8r80725tqY 306.12 | |||
| Qb7gA5M10H .00 | |||
| 0Y-o506P%b .00 | |||
| 9Lc160L30C 385.04 | |||
| E%q847=v2d .00 | |||
| 23L9Jgx7yt .00 | |||
| BH51tz93s5 247.06 | |||
| f71O-^D5k9 219.49 | |||
| o4bbw3q524 .00 | |||
| x60iC7015a 385.52 | |||
| 578q3cOi4L 403.93 | |||
| t8W7R&45s3 337.85 | |||
| 53h2xKa8P1 .00 | |||
| 9=4(L4kF8b .00 | |||
| 12TGf5$u)3 82.67 | |||
| @ -0,0 +1,35 @@ | |||
| 0XlfA2Y21E 263.73 | |||
| o80ve2yJ69 0 | |||
| 1wu5Rn5NF2 421.73 | |||
| 23G1A210OF 244.75 | |||
| xaj321J1BZ 0 | |||
| Cr731Iii7I 487.02 | |||
| 6E3Fxj85yL 287.23 | |||
| wYs18i9m5k 0 | |||
| W8ANj6np26 119.18 | |||
| b8W01cT5n8 362.53 | |||
| 338bJ687YD 0 | |||
| 8ft4ChT823 323.71 | |||
| i01&50ftN2 0 | |||
| ocn2E9U02m 0 | |||
| At90OL089h 120.27 | |||
| eo0n0Z62wq 230.08 | |||
| 6sVk7528rZ 166.01 | |||
| O@2C3Y5Oe6 0 | |||
| 99L0MmmK60 0 | |||
| M5N$p8C823 152.83 | |||
| 8r80725tqY 306.12 | |||
| Qb7gA5M10H 0 | |||
| 0Y-o506P%b 0 | |||
| 9Lc160L30C 385.04 | |||
| E%q847=v2d 0 | |||
| 23L9Jgx7yt 0 | |||
| BH51tz93s5 247.06 | |||
| f71O-^D5k9 219.49 | |||
| o4bbw3q524 0 | |||
| x60iC7015a 385.52 | |||
| 578q3cOi4L 403.93 | |||
| t8W7R&45s3 337.85 | |||
| 53h2xKa8P1 0 | |||
| 9=4(L4kF8b 0 | |||
| 12TGf5$u)3 82.67 | |||
| @ -0,0 +1,35 @@ | |||
| 0XlfA2Y21E 0 | |||
| o80ve2yJ69 0 | |||
| 1wu5Rn5NF2 0 | |||
| 23G1A210OF 18 | |||
| xaj321J1BZ 11 | |||
| Cr731Iii7I 10 | |||
| 6E3Fxj85yL 14 | |||
| wYs18i9m5k 13 | |||
| W8ANj6np26 11 | |||
| b8W01cT5n8 5 | |||
| 338bJ687YD 0 | |||
| 8ft4ChT823 10 | |||
| i01&50ftN2 8 | |||
| ocn2E9U02m 0 | |||
| At90OL089h 0 | |||
| eo0n0Z62wq 0 | |||
| 6sVk7528rZ 11 | |||
| O@2C3Y5Oe6 0 | |||
| 99L0MmmK60 0 | |||
| M5N$p8C823 13 | |||
| 8r80725tqY 11 | |||
| Qb7gA5M10H 0 | |||
| 0Y-o506P%b 5 | |||
| 9Lc160L30C 14 | |||
| E%q847=v2d 0 | |||
| 23L9Jgx7yt 0 | |||
| BH51tz93s5 5 | |||
| f71O-^D5k9 11 | |||
| o4bbw3q524 11 | |||
| x60iC7015a 15 | |||
| 578q3cOi4L 9 | |||
| t8W7R&45s3 12 | |||
| 53h2xKa8P1 0 | |||
| 9=4(L4kF8b 0 | |||
| 12TGf5$u)3 0 | |||
| @ -0,0 +1,35 @@ | |||
| 0XlfA2Y21E true | |||
| o80ve2yJ69 false | |||
| 1wu5Rn5NF2 true | |||
| 23G1A210OF false | |||
| xaj321J1BZ true | |||
| Cr731Iii7I true | |||
| 6E3Fxj85yL true | |||
| wYs18i9m5k true | |||
| W8ANj6np26 true | |||
| b8W01cT5n8 false | |||
| 338bJ687YD false | |||
| 8ft4ChT823 false | |||
| i01&50ftN2 false | |||
| ocn2E9U02m true | |||
| At90OL089h false | |||
| eo0n0Z62wq true | |||
| 6sVk7528rZ false | |||
| O@2C3Y5Oe6 false | |||
| 99L0MmmK60 false | |||
| M5N$p8C823 false | |||
| 8r80725tqY false | |||
| Qb7gA5M10H true | |||
| 0Y-o506P%b false | |||
| 9Lc160L30C false | |||
| E%q847=v2d false | |||
| 23L9Jgx7yt true | |||
| BH51tz93s5 false | |||
| f71O-^D5k9 false | |||
| o4bbw3q524 false | |||
| x60iC7015a false | |||
| 578q3cOi4L false | |||
| t8W7R&45s3 false | |||
| 53h2xKa8P1 false | |||
| 9=4(L4kF8b false | |||
| 12TGf5$u)3 false | |||
| @ -0,0 +1,7 @@ | |||
| /** | |||
| * @author brett | |||
| * | |||
| */ | |||
| module uwstout.courses.cs144 { | |||
| requires junit; | |||
| } | |||
| @ -0,0 +1,184 @@ | |||
| package uwstout.courses.cs144.labs.lab7; | |||
| import java.io.File; | |||
| import java.io.FileNotFoundException; | |||
| import java.io.PrintWriter; | |||
| import java.text.DecimalFormat; | |||
| import java.util.Scanner; | |||
| /** | |||
| * Stores the name of the input file that the data is in and the name of the | |||
| * output file where the report will be written. Contains a number of methods to | |||
| * find, filter, and process the data. | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.11.28 | |||
| */ | |||
| public class DataAnalytic { | |||
| private String inputFileName; | |||
| private String outputFileName; | |||
| /** | |||
| * Creates a new DataAnalytic class to analyze and process data. Takes data | |||
| * from input (filename), and outputs the report to output (filename). | |||
| * | |||
| * @param input The name of the input file | |||
| * @param output The name of the output file | |||
| */ | |||
| public DataAnalytic(String input, String output) { | |||
| inputFileName = (input == null) ? "" : input; | |||
| outputFileName = (output == null) ? "" : output; | |||
| } | |||
| /** | |||
| * Get the input filename | |||
| * | |||
| * @return The input filename | |||
| */ | |||
| public String getInputName() { | |||
| return inputFileName; | |||
| } | |||
| /** | |||
| * Get the output filename | |||
| * | |||
| * @return The output filename | |||
| */ | |||
| public String getOutputName() { | |||
| return outputFileName; | |||
| } | |||
| /** | |||
| * Skips to a field definition | |||
| * | |||
| * @param sc The input scanner | |||
| * @param fieldName The field we are searching for | |||
| */ | |||
| public void skipToField(Scanner sc, String fieldName) { | |||
| String readString; | |||
| do { | |||
| if (sc.hasNext()) { | |||
| readString = sc.next(); | |||
| } else { | |||
| break; | |||
| } | |||
| } while (!readString.matches("(\\[?)" + fieldName + "(\\]?)")); | |||
| } | |||
| /** | |||
| * Gets the sum of an income field | |||
| * | |||
| * @param sc The input scanner | |||
| * @return The total income | |||
| */ | |||
| public double getIncome(Scanner sc) { | |||
| skipToField(sc, "income"); | |||
| double total = 0; | |||
| while (sc.hasNextDouble()) { | |||
| total += sc.nextDouble(); | |||
| } | |||
| return total; | |||
| } | |||
| /** | |||
| * Get the average of an interactions field | |||
| * | |||
| * @param sc The input scanner | |||
| * @return The average interactions | |||
| */ | |||
| public int getFrequency(Scanner sc) { | |||
| skipToField(sc, "interactions"); | |||
| int total = 0; | |||
| int num = 0; | |||
| while (sc.hasNextDouble()) { | |||
| total += sc.nextInt(); | |||
| num++; | |||
| } | |||
| try { | |||
| return total / num; | |||
| } catch (Exception e) { | |||
| return 0; | |||
| } | |||
| } | |||
| /** | |||
| * Checks if an input ID is valid | |||
| * | |||
| * @param id The ID to check | |||
| * @return If the ID is valid | |||
| */ | |||
| public boolean isValid(String id) { | |||
| int numDigits = 0; | |||
| int numLetters = 0; | |||
| int numOtherChars = 0; | |||
| for (int i = 0; i < id.length(); i++) { | |||
| char c = id.charAt(i); | |||
| if ('0' <= c && c <= '9') { | |||
| numDigits++; | |||
| } else if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) { | |||
| numLetters++; | |||
| } else { | |||
| numOtherChars++; | |||
| } | |||
| } | |||
| return numOtherChars == 0 && numDigits < numLetters; | |||
| } | |||
| /** | |||
| * Processes the input file, and outputs the given reportType to the output | |||
| * file specified at class creation. Returns true if the file was processed, | |||
| * false if one of the files can't be opened. | |||
| * | |||
| * @param reportType The type of report to be created. | |||
| * @return If the processing occurred. | |||
| */ | |||
| public boolean processFile(ProcessType reportType) { | |||
| DecimalFormat df = new DecimalFormat("#,###.00"); | |||
| try { | |||
| File inFile = new File(inputFileName); | |||
| Scanner fileScanner = new Scanner(inFile); | |||
| PrintWriter outWriter = new PrintWriter(outputFileName); | |||
| while (fileScanner.hasNext()) { | |||
| String readLine = fileScanner.nextLine(); | |||
| Scanner lineScanner = new Scanner(readLine); | |||
| String id = lineScanner.next(); | |||
| switch (reportType) { | |||
| case COST: | |||
| double income = getIncome(lineScanner); | |||
| outWriter.println(id + " " + df.format(income)); | |||
| break; | |||
| case FREQUENCY: | |||
| int freq = getFrequency(lineScanner); | |||
| outWriter.println(id + " " + freq); | |||
| break; | |||
| default: | |||
| boolean valid = isValid(id); | |||
| outWriter.println(id + " " + valid); | |||
| break; | |||
| } | |||
| } | |||
| fileScanner.close(); | |||
| outWriter.close(); | |||
| return true; | |||
| } catch (FileNotFoundException e) { | |||
| return false; | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,251 @@ | |||
| package uwstout.courses.cs144.labs.lab7; | |||
| import static org.junit.Assert.assertEquals; | |||
| import static org.junit.Assert.assertFalse; | |||
| import static org.junit.Assert.assertTrue; | |||
| import static org.junit.Assert.fail; | |||
| import java.io.File; | |||
| import java.util.Scanner; | |||
| import org.junit.Before; | |||
| import org.junit.Test; | |||
| /** | |||
| * Tests the DataAnalytic Class | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.11.28 | |||
| */ | |||
| public class DataAnalyticTest { | |||
| private static final double DELTA = 0.01; | |||
| private DataAnalytic da1; | |||
| private DataAnalytic da2; | |||
| private DataAnalytic da3; | |||
| /** | |||
| * Set up the shared DataAnalytic Classes | |||
| * | |||
| * @throws Exception | |||
| */ | |||
| @Before | |||
| public void setUp() throws Exception { | |||
| da1 = new DataAnalytic("input1.txt", "output1.txt"); | |||
| da2 = new DataAnalytic("input2.txt", "output2.txt"); | |||
| da3 = new DataAnalytic("input3.txt", "output3.txt"); | |||
| } | |||
| /** | |||
| * Tests the default constructor | |||
| */ | |||
| @Test | |||
| public void testDataAnalytic() { | |||
| DataAnalytic t1 = new DataAnalytic(null, null); | |||
| assertEquals("", t1.getInputName()); | |||
| assertEquals("", t1.getOutputName()); | |||
| DataAnalytic t2 = new DataAnalytic("testin1.txt", "testout1.txt"); | |||
| assertEquals("testin1.txt", t2.getInputName()); | |||
| assertEquals("testout1.txt", t2.getOutputName()); | |||
| } | |||
| /** | |||
| * Tests the getIncome method | |||
| */ | |||
| @Test | |||
| public void testGetIncome() { | |||
| // create a line of input (taken from one of the data files) | |||
| // this should find the interactions field and average the numbers. | |||
| Scanner input = new Scanner("[uses] 10 5 8 [uses] " | |||
| + "[uses] 86.26 10.48 98.26 55.51 28.41 61.26 [uses] " | |||
| + "income 32.35 51.31 70.99 98.72 40.78 65.53 income " | |||
| + "[interactions] 8 20 1 1 6 3 17 3 18 [interactions] "); | |||
| assertEquals(359.68, da1.getIncome(input), DELTA); | |||
| input = new Scanner("[income] [income]"); | |||
| assertEquals(0, da1.getIncome(input), DELTA); | |||
| input = new Scanner(""); | |||
| assertEquals(0, da1.getIncome(input), DELTA); | |||
| input = new Scanner("income 10 10 10 income"); | |||
| assertEquals(30, da1.getIncome(input), DELTA); | |||
| } | |||
| /** | |||
| * Tests the getFrequency method | |||
| */ | |||
| @Test | |||
| public void testGetFrequency() { | |||
| // create a line of input (taken from one of the data files) | |||
| // this should find the interactions field and average the numbers. | |||
| Scanner input = new Scanner("[uses] 10 5 8 [uses] " | |||
| + "[uses] 86.26 10.48 98.26 55.51 28.41 61.26 [uses] " | |||
| + "income 32.35 51.31 70.99 98.72 40.78 65.53 income " | |||
| + "[interactions] 8 20 1 1 6 3 17 3 18 [interactions] "); | |||
| assertEquals(8, da1.getFrequency(input)); | |||
| input = new Scanner("[interactions] [interactions]"); | |||
| assertEquals(0, da1.getFrequency(input)); | |||
| input = new Scanner(""); | |||
| assertEquals(0, da1.getFrequency(input)); | |||
| input = new Scanner("interactions 10 10 interactions"); | |||
| assertEquals(10, da1.getFrequency(input)); | |||
| } | |||
| /** | |||
| * Tests the isValid method | |||
| */ | |||
| @Test | |||
| public void testIsValid() { | |||
| // create object - file names don't matter | |||
| // since they are not being used | |||
| assertTrue(da1.isValid("9Yns4a9i5N")); | |||
| assertTrue(da1.isValid("H04GP8Y7DC")); | |||
| assertFalse(da1.isValid("dF6aW1--51")); | |||
| assertFalse(da1.isValid("20#Tg0=OI6")); | |||
| assertFalse(da1.isValid("23G1A210OF")); | |||
| assertFalse(da1.isValid("23G1a?]Z`z")); | |||
| } | |||
| /** | |||
| * Test processFile with the VALIDATE value | |||
| */ | |||
| @Test | |||
| public void testProcessFileValidate() { | |||
| // create the report | |||
| assertTrue(da1.processFile(ProcessType.VALIDATE)); | |||
| // this will only return true if everything else worked. | |||
| assertTrue(testFile("output1.txt", "output1Valid.txt")); | |||
| // create the report | |||
| assertTrue(da2.processFile(ProcessType.VALIDATE)); | |||
| // this will only return true if everything else worked. | |||
| assertTrue(testFile("output2.txt", "output2Valid.txt")); | |||
| // create the report | |||
| assertTrue(da3.processFile(ProcessType.VALIDATE)); | |||
| // this will only return true if everything else worked. | |||
| assertTrue(testFile("output3.txt", "output3Valid.txt")); | |||
| } | |||
| /** | |||
| * Test processFile with the FREQUENCY value | |||
| */ | |||
| @Test | |||
| public void testProcessFileFrequency() { | |||
| // create the report | |||
| assertTrue(da1.processFile(ProcessType.FREQUENCY)); | |||
| // this will only return true if everything else worked. | |||
| assertTrue(testFile("output1.txt", "output1Frequency.txt")); | |||
| // create the report | |||
| assertTrue(da2.processFile(ProcessType.FREQUENCY)); | |||
| // this will only return true if everything else worked. | |||
| assertTrue(testFile("output2.txt", "output2Frequency.txt")); | |||
| // create the report | |||
| assertTrue(da3.processFile(ProcessType.FREQUENCY)); | |||
| // this will only return true if everything else worked. | |||
| assertTrue(testFile("output3.txt", "output3Frequency.txt")); | |||
| } | |||
| /** | |||
| * Test processFile with the COST value | |||
| */ | |||
| @Test | |||
| public void testProcessFileCost() { | |||
| // create the report | |||
| assertTrue(da1.processFile(ProcessType.COST)); | |||
| // this will only return true if everything else worked. | |||
| assertTrue(testFile("output1.txt", "output1Cost.txt")); | |||
| // create the report | |||
| assertTrue(da2.processFile(ProcessType.COST)); | |||
| // this will only return true if everything else worked. | |||
| assertTrue(testFile("output2.txt", "output2Cost.txt")); | |||
| // create the report | |||
| assertTrue(da3.processFile(ProcessType.COST)); | |||
| // this will only return true if everything else worked. | |||
| assertTrue(testFile("output3.txt", "output3Cost.txt")); | |||
| } | |||
| /** | |||
| * Test processFile with an invalid file | |||
| */ | |||
| @Test | |||
| public void testProcessFileInvalid() { | |||
| DataAnalytic data = new DataAnalytic(null, null); | |||
| // create the report | |||
| assertFalse(data.processFile(ProcessType.COST)); | |||
| } | |||
| private boolean testFile(String fileName, String expectedFileName) { | |||
| String id; | |||
| String value; | |||
| String line; | |||
| int lineCount = 0; | |||
| // Test if the output file exists | |||
| File inputFile = new File(fileName); | |||
| File expectedFile = new File(expectedFileName); | |||
| assertTrue("Could not find file " + fileName, inputFile.exists()); | |||
| try { | |||
| // create scanners for the file and the string | |||
| // of expected results | |||
| Scanner inputScan = new Scanner(inputFile); | |||
| Scanner expScan = new Scanner(expectedFile); | |||
| // read until one of the two ends (hopefully both) | |||
| while (inputScan.hasNext() && expScan.hasNext()) { | |||
| // read in a line from the file | |||
| line = inputScan.nextLine(); | |||
| // assuming that the expected data has two values | |||
| // per line: the id and the value - should work | |||
| // for all three types of reports | |||
| id = expScan.next(); | |||
| value = expScan.next(); | |||
| // check if line has id and value | |||
| assertTrue( | |||
| "Could not find the id on line " + lineCount | |||
| + ". The id was supposed to be " + id + ".", | |||
| line.indexOf(id) >= 0); | |||
| assertTrue("Could not find the value on line " + lineCount | |||
| + ". The id was supposed to be " + id + " and the " | |||
| + "value should be " + value + ".", | |||
| line.indexOf(value) >= 0); | |||
| lineCount++; | |||
| } | |||
| // check if there is more data in either scanner | |||
| assertFalse("The output file had more lines than it should.", | |||
| inputScan.hasNext()); | |||
| assertFalse("There was not as much data in the output " | |||
| + "file as expected.", expScan.hasNext()); | |||
| inputScan.close(); | |||
| expScan.close(); | |||
| } catch (Exception e) { | |||
| fail("processFile crashed trying to read from " + inputFile); | |||
| } | |||
| return true; | |||
| } | |||
| } | |||
| @ -0,0 +1,39 @@ | |||
| package uwstout.courses.cs144.labs.lab7; | |||
| /** | |||
| * Represents the kind of analysis being ran on the input file. | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.11.28 | |||
| */ | |||
| public enum ProcessType { | |||
| /** | |||
| * Calculate total income | |||
| */ | |||
| COST, | |||
| /** | |||
| * Calculate average interactions | |||
| */ | |||
| FREQUENCY, | |||
| /** | |||
| * Validate IDs | |||
| */ | |||
| VALIDATE; | |||
| @Override | |||
| public String toString() { | |||
| String retString; | |||
| switch (this) { | |||
| case COST: | |||
| retString = "Total Income"; | |||
| break; | |||
| case FREQUENCY: | |||
| retString = "Average Interactions"; | |||
| break; | |||
| default: | |||
| retString = "Validation"; | |||
| break; | |||
| } | |||
| return retString; | |||
| } | |||
| } | |||
| @ -0,0 +1,25 @@ | |||
| package uwstout.courses.cs144.labs.lab7; | |||
| import static org.junit.Assert.assertEquals; | |||
| import org.junit.Test; | |||
| /** | |||
| * Tests the ProcessType enum | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.11.28 | |||
| */ | |||
| public class ProcessTypeTest { | |||
| /** | |||
| * Tests the toString method on ProcessType | |||
| */ | |||
| @Test | |||
| public void testToString() { | |||
| assertEquals("Total Income", ProcessType.COST.toString()); | |||
| assertEquals("Average Interactions", ProcessType.FREQUENCY.toString()); | |||
| assertEquals("Validation", ProcessType.VALIDATE.toString()); | |||
| } | |||
| } | |||
| @ -0,0 +1,15 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <classpath> | |||
| <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"> | |||
| <attributes> | |||
| <attribute name="module" value="true"/> | |||
| </attributes> | |||
| </classpathentry> | |||
| <classpathentry kind="src" path="src"/> | |||
| <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"> | |||
| <attributes> | |||
| <attribute name="module" value="true"/> | |||
| </attributes> | |||
| </classpathentry> | |||
| <classpathentry kind="output" path="bin"/> | |||
| </classpath> | |||
| @ -0,0 +1,17 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <projectDescription> | |||
| <name>LAB-8</name> | |||
| <comment></comment> | |||
| <projects> | |||
| </projects> | |||
| <buildSpec> | |||
| <buildCommand> | |||
| <name>org.eclipse.jdt.core.javabuilder</name> | |||
| <arguments> | |||
| </arguments> | |||
| </buildCommand> | |||
| </buildSpec> | |||
| <natures> | |||
| <nature>org.eclipse.jdt.core.javanature</nature> | |||
| </natures> | |||
| </projectDescription> | |||
| @ -0,0 +1 @@ | |||
| 0.25 0.20 0.18 0.05 29999999.95 | |||
| @ -0,0 +1,7 @@ | |||
| /** | |||
| * @author Brett Bender | |||
| * @version 2022.12.05 | |||
| */ | |||
| module uwstout.courses.cs144 { | |||
| requires junit; | |||
| } | |||
| @ -0,0 +1,162 @@ | |||
| package uwstout.courses.cs144.labs.lab8; | |||
| import java.io.File; | |||
| import java.io.FileNotFoundException; | |||
| import java.util.Scanner; | |||
| /** | |||
| * Stores the prices of an item over time, and provides access to the current, | |||
| * maximum, and average price. | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.12.05 | |||
| */ | |||
| public class PriceHistory { | |||
| private static final int INITIAL_SIZE = 5; | |||
| private String name; | |||
| private double[] prices; | |||
| private int count; | |||
| /** | |||
| * Create a new PriceHistory that is tracking the item named nName. | |||
| * Initializes the internal array to {@link #INITIAL_SIZE}, and the count to | |||
| * 0. | |||
| * | |||
| * @param nName The name of the item. | |||
| */ | |||
| public PriceHistory(String nName) { | |||
| name = nName; | |||
| prices = new double[INITIAL_SIZE]; | |||
| count = 0; | |||
| } | |||
| /** | |||
| * Get the name of the item | |||
| * | |||
| * @return The item name. | |||
| */ | |||
| public String getName() { | |||
| return name; | |||
| } | |||
| /** | |||
| * Get the current (last) price. Returns 0 if no price history stored. | |||
| * | |||
| * @return The current price | |||
| */ | |||
| public double getCurrentPrice() { | |||
| if (count > 0) { | |||
| return prices[count - 1]; | |||
| } | |||
| return 0; | |||
| } | |||
| /** | |||
| * Get the number of prices in the history. | |||
| * | |||
| * @return The number of prices | |||
| */ | |||
| public int getNumberOfPrices() { | |||
| return count; | |||
| } | |||
| /** | |||
| * Get the price at a certain point. Returns 0 if pos out of bounds. | |||
| * | |||
| * @param pos The position of the price you'd like to retrieve. | |||
| * @return The price at that position | |||
| */ | |||
| public double getPrice(int pos) { | |||
| if (0 <= pos && pos < count) { | |||
| return prices[pos]; | |||
| } | |||
| return 0; | |||
| } | |||
| /** | |||
| * Add a price to the history. Will only add if positive, and will | |||
| * automatically expand the array if needed. | |||
| * | |||
| * @param price The price to add | |||
| */ | |||
| public void addPrice(double price) { | |||
| if (price > 0) { | |||
| if (count == prices.length) { | |||
| double[] temp = new double[prices.length + 3]; | |||
| for (int i = 0; i < prices.length; i++) { | |||
| temp[i] = prices[i]; | |||
| } | |||
| prices = temp; | |||
| } | |||
| prices[count++] = price; | |||
| } | |||
| } | |||
| /** | |||
| * Add prices from an input scanner | |||
| * | |||
| * @param sc The input scanner | |||
| */ | |||
| public void addPrices(Scanner sc) { | |||
| while (sc.hasNextDouble()) { | |||
| addPrice(sc.nextDouble()); // Since addPrice already checks if the | |||
| // value is positive/negative, we can | |||
| // directly pass in the input | |||
| } | |||
| } | |||
| /** | |||
| * Add prices from an input file | |||
| * | |||
| * @param fileName The input file name | |||
| */ | |||
| public void addPrices(String fileName) { | |||
| try { | |||
| Scanner sc = new Scanner(new File(fileName)); | |||
| addPrices(sc); | |||
| sc.close(); | |||
| } catch (FileNotFoundException e) { | |||
| // Do nothing | |||
| } | |||
| } | |||
| /** | |||
| * Get the maximum price of an item | |||
| * | |||
| * @return The maximum price | |||
| */ | |||
| public double getMaximumPrice() { | |||
| double max = 0; | |||
| if (count > 0) { | |||
| max = prices[0]; | |||
| for (int i = 1; i < count; i++) { | |||
| double x = prices[i]; | |||
| if (x > max) { | |||
| max = x; | |||
| } | |||
| } | |||
| } | |||
| return max; | |||
| } | |||
| /** | |||
| * Get the average price of the item | |||
| * | |||
| * @return The average price | |||
| */ | |||
| public double getAveragePrice() { | |||
| double avg = 0; | |||
| if (count > 0) { | |||
| for (int i = 0; i < count; i++) { | |||
| avg += prices[i]; | |||
| } | |||
| avg = avg / count; | |||
| } | |||
| return avg; | |||
| } | |||
| } | |||
| @ -0,0 +1,235 @@ | |||
| package uwstout.courses.cs144.labs.lab8; | |||
| import static org.junit.Assert.assertEquals; | |||
| import static org.junit.Assert.fail; | |||
| import java.io.PrintWriter; | |||
| import java.util.Scanner; | |||
| import org.junit.Test; | |||
| /** | |||
| * Tests the PriceHistory class | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.12.05 | |||
| */ | |||
| public class PriceHistoryTest { | |||
| private static final double DELTA = 0.001; | |||
| /** | |||
| * Tests the constructor | |||
| */ | |||
| @Test | |||
| public void testPriceHistory() { | |||
| PriceHistory ph1 = new PriceHistory("Test Item"); | |||
| assertEquals("Test Item", ph1.getName()); | |||
| assertEquals(0, ph1.getNumberOfPrices()); | |||
| PriceHistory ph2 = new PriceHistory("Wooot"); | |||
| assertEquals("Wooot", ph2.getName()); | |||
| assertEquals(0, ph2.getNumberOfPrices()); | |||
| } | |||
| /** | |||
| * Tests the getCurrentPrice method | |||
| */ | |||
| @Test | |||
| public void testGetCurrentPrice() { | |||
| PriceHistory ph1 = new PriceHistory("Pizza"); | |||
| assertEquals(0, ph1.getCurrentPrice(), DELTA); | |||
| ph1.addPrice(7.99); | |||
| assertEquals(7.99, ph1.getCurrentPrice(), DELTA); | |||
| ph1.addPrice(28.99); | |||
| assertEquals(28.99, ph1.getCurrentPrice(), DELTA); | |||
| } | |||
| /** | |||
| * Tests the getNumberOfPrices method | |||
| */ | |||
| @Test | |||
| public void testGetNumberOfPrices() { | |||
| PriceHistory ph1 = new PriceHistory("Pizza"); | |||
| assertEquals(0, ph1.getNumberOfPrices()); | |||
| ph1.addPrice(7.99); | |||
| assertEquals(1, ph1.getNumberOfPrices()); | |||
| ph1.addPrice(21.99); | |||
| assertEquals(2, ph1.getNumberOfPrices()); | |||
| ph1.addPrice(21.99); | |||
| assertEquals(3, ph1.getNumberOfPrices()); | |||
| ph1.addPrice(16.99); | |||
| assertEquals(4, ph1.getNumberOfPrices()); | |||
| ph1.addPrice(28.99); | |||
| assertEquals(5, ph1.getNumberOfPrices()); | |||
| ph1.addPrice(27.99); | |||
| assertEquals(6, ph1.getNumberOfPrices()); | |||
| } | |||
| /** | |||
| * Tests the getPrice method | |||
| */ | |||
| @Test | |||
| public void testGetPrice() { | |||
| PriceHistory ph1 = new PriceHistory("Pizza"); | |||
| assertEquals(0, ph1.getPrice(1), DELTA); | |||
| assertEquals(0, ph1.getPrice(0), DELTA); | |||
| assertEquals(0, ph1.getPrice(-1), DELTA); | |||
| ph1.addPrice(7.99); // 0 | |||
| ph1.addPrice(21.99); // 1 | |||
| ph1.addPrice(21.99); // 2 | |||
| ph1.addPrice(16.99); // 3 | |||
| ph1.addPrice(28.99); // 4 | |||
| ph1.addPrice(27.99); // 5 | |||
| assertEquals(7.99, ph1.getPrice(0), DELTA); | |||
| assertEquals(21.99, ph1.getPrice(1), DELTA); | |||
| assertEquals(21.99, ph1.getPrice(2), DELTA); | |||
| assertEquals(16.99, ph1.getPrice(3), DELTA); | |||
| assertEquals(0, ph1.getPrice(6), DELTA); | |||
| } | |||
| /** | |||
| * Tests the addPrice method | |||
| */ | |||
| @Test | |||
| public void testAddPrice() { | |||
| PriceHistory ph1 = new PriceHistory("Pizza"); | |||
| assertEquals(0, ph1.getCurrentPrice(), DELTA); | |||
| ph1.addPrice(-5.99); | |||
| assertEquals(0, ph1.getNumberOfPrices()); | |||
| assertEquals(0, ph1.getCurrentPrice(), DELTA); | |||
| ph1.addPrice(5.99); | |||
| assertEquals(1, ph1.getNumberOfPrices()); | |||
| assertEquals(5.99, ph1.getCurrentPrice(), DELTA); | |||
| ph1.addPrice(8.99); | |||
| assertEquals(2, ph1.getNumberOfPrices()); | |||
| assertEquals(8.99, ph1.getCurrentPrice(), DELTA); | |||
| ph1.addPrice(10.99); | |||
| assertEquals(3, ph1.getNumberOfPrices()); | |||
| assertEquals(10.99, ph1.getCurrentPrice(), DELTA); | |||
| ph1.addPrice(0); | |||
| assertEquals(3, ph1.getNumberOfPrices()); | |||
| assertEquals(10.99, ph1.getCurrentPrice(), DELTA); | |||
| ph1.addPrice(-5.99); | |||
| assertEquals(3, ph1.getNumberOfPrices()); | |||
| assertEquals(10.99, ph1.getCurrentPrice(), DELTA); | |||
| ph1.addPrice(11.99); // 4 | |||
| ph1.addPrice(15.99); // 5 | |||
| ph1.addPrice(14.99); // 6 | |||
| assertEquals(6, ph1.getNumberOfPrices()); | |||
| assertEquals(14.99, ph1.getCurrentPrice(), DELTA); | |||
| ph1.addPrice(11.99); // 7 | |||
| ph1.addPrice(15.99); // 8 | |||
| ph1.addPrice(14.99); // 9 | |||
| assertEquals(9, ph1.getNumberOfPrices()); | |||
| assertEquals(14.99, ph1.getCurrentPrice(), DELTA); | |||
| } | |||
| /** | |||
| * Tests the addPrices(Scanner) method | |||
| */ | |||
| @Test | |||
| public void testAddPricesScanner() { | |||
| String input = "0.25 0.20 0.18 0.05 29999999.95"; | |||
| PriceHistory ph = new PriceHistory("GME"); | |||
| ph.addPrices(new Scanner(input)); | |||
| assertEquals(5, ph.getNumberOfPrices()); | |||
| assertEquals(0.25, ph.getPrice(0), DELTA); | |||
| assertEquals(0.2, ph.getPrice(1), DELTA); | |||
| assertEquals(0.18, ph.getPrice(2), DELTA); | |||
| assertEquals(0.05, ph.getPrice(3), DELTA); | |||
| assertEquals(29999999.95, ph.getPrice(4), DELTA); | |||
| } | |||
| /** | |||
| * Tests the addPrices(String) method | |||
| */ | |||
| @Test | |||
| public void testAddPricesString() { | |||
| String filename = "input1.txt"; | |||
| try { | |||
| PrintWriter out = new PrintWriter(filename); | |||
| out.println("0.25 0.20 0.18 0.05 29999999.95"); | |||
| out.close(); | |||
| } catch (Exception e) { | |||
| fail("Couldn't write file!"); | |||
| } | |||
| PriceHistory ph = new PriceHistory("Apple Stock"); | |||
| ph.addPrices(filename); | |||
| assertEquals(5, ph.getNumberOfPrices()); | |||
| assertEquals(0.25, ph.getPrice(0), DELTA); | |||
| assertEquals(0.2, ph.getPrice(1), DELTA); | |||
| assertEquals(0.18, ph.getPrice(2), DELTA); | |||
| assertEquals(0.05, ph.getPrice(3), DELTA); | |||
| assertEquals(29999999.95, ph.getPrice(4), DELTA); | |||
| PriceHistory ph2 = new PriceHistory("GME Stock"); | |||
| ph.addPrices("invalid"); | |||
| assertEquals(0, ph2.getNumberOfPrices()); | |||
| } | |||
| /** | |||
| * Tests the getMaximumPrice method | |||
| */ | |||
| @Test | |||
| public void testGetMaximumPrice() { | |||
| PriceHistory ph1 = new PriceHistory("Woo"); | |||
| assertEquals(0, ph1.getMaximumPrice(), DELTA); | |||
| String input2 = "0.25 0.20 0.18 0.05 29999999.95"; | |||
| PriceHistory ph2 = new PriceHistory("GME"); | |||
| ph2.addPrices(new Scanner(input2)); | |||
| assertEquals(29999999.95, ph2.getMaximumPrice(), DELTA); | |||
| String input3 = "0.25 100 0.20 0.18 0.05"; | |||
| PriceHistory ph3 = new PriceHistory("APPL"); | |||
| ph3.addPrices(new Scanner(input3)); | |||
| assertEquals(100, ph3.getMaximumPrice(), DELTA); | |||
| } | |||
| /** | |||
| * Tests the getAveragePrice method | |||
| */ | |||
| @Test | |||
| public void testGetAveragePrice() { | |||
| PriceHistory ph1 = new PriceHistory("Woo"); | |||
| assertEquals(0, ph1.getAveragePrice(), DELTA); | |||
| String input2 = "0.25 0.20 0.18 0.05 29999999.95"; | |||
| PriceHistory ph2 = new PriceHistory("GME"); | |||
| ph2.addPrices(new Scanner(input2)); | |||
| assertEquals(6000000.126, ph2.getAveragePrice(), DELTA); | |||
| String input3 = "0.25 100 0.20 0.18 0.05"; | |||
| PriceHistory ph3 = new PriceHistory("APPL"); | |||
| ph3.addPrices(new Scanner(input3)); | |||
| assertEquals(20.136, ph3.getAveragePrice(), DELTA); | |||
| } | |||
| } | |||
| @ -0,0 +1,15 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <classpath> | |||
| <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"> | |||
| <attributes> | |||
| <attribute name="module" value="true"/> | |||
| </attributes> | |||
| </classpathentry> | |||
| <classpathentry kind="src" path="src"/> | |||
| <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"> | |||
| <attributes> | |||
| <attribute name="module" value="true"/> | |||
| </attributes> | |||
| </classpathentry> | |||
| <classpathentry kind="output" path="bin"/> | |||
| </classpath> | |||
| @ -0,0 +1,17 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <projectDescription> | |||
| <name>LAB-9</name> | |||
| <comment></comment> | |||
| <projects> | |||
| </projects> | |||
| <buildSpec> | |||
| <buildCommand> | |||
| <name>org.eclipse.jdt.core.javabuilder</name> | |||
| <arguments> | |||
| </arguments> | |||
| </buildCommand> | |||
| </buildSpec> | |||
| <natures> | |||
| <nature>org.eclipse.jdt.core.javanature</nature> | |||
| </natures> | |||
| </projectDescription> | |||
| @ -0,0 +1,10 @@ | |||
| /** | |||
| * | |||
| */ | |||
| /** | |||
| * @author brett | |||
| * | |||
| */ | |||
| module uwstout.courses.cs144 { | |||
| requires junit; | |||
| } | |||
| @ -0,0 +1,61 @@ | |||
| package uwstout.courses.cs144.projects.project3.orders; | |||
| /** | |||
| * Represents a menu item in an Order. | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.12.08 | |||
| */ | |||
| public class MenuItem { | |||
| private static final double DEFAULT_COST = 9.99; | |||
| private MenuItemType type; | |||
| private String name; | |||
| private double cost; | |||
| /** | |||
| * Create a MenuItem with the given name, cost, and type. If name is null or | |||
| * empty, will be replaced with the type + " of the Day". If type is null, | |||
| * will be replaced with {@link MenuItemType#SIDE}. If cost is less than | |||
| * $3.50, will be set to {@link #DEFAULT_COST}. | |||
| * | |||
| * @param nName Name of the item | |||
| * @param nCost Cost of the item | |||
| * @param nType Type of the item | |||
| */ | |||
| public MenuItem(String nName, double nCost, MenuItemType nType) { | |||
| type = (nType != null) ? nType : MenuItemType.SIDE; | |||
| name = (nName != null && !nName.isEmpty()) ? nName | |||
| : (type.toString() + " of the Day"); | |||
| cost = (nCost >= 3.50) ? nCost : DEFAULT_COST; | |||
| } | |||
| /** | |||
| * Get the type of the item | |||
| * | |||
| * @return The item type | |||
| */ | |||
| public MenuItemType getType() { | |||
| return type; | |||
| } | |||
| /** | |||
| * Get the name of the item | |||
| * | |||
| * @return The item name | |||
| */ | |||
| public String getName() { | |||
| return name; | |||
| } | |||
| /** | |||
| * Get the cost of the item | |||
| * | |||
| * @return The item cost | |||
| */ | |||
| public double getCost() { | |||
| return cost; | |||
| } | |||
| } | |||
| @ -0,0 +1,39 @@ | |||
| package uwstout.courses.cs144.projects.project3.orders; | |||
| import static org.junit.Assert.assertEquals; | |||
| import org.junit.Test; | |||
| /** | |||
| * Tests the MenuItem class | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.12.09 | |||
| */ | |||
| public class MenuItemTest { | |||
| private static final double DELTA = 0.001; | |||
| /** | |||
| * Test the MenuItem(String, double, MenuItemType), as a result, also tests | |||
| * the getters. | |||
| */ | |||
| @Test | |||
| public void testMenuItem() { | |||
| MenuItem mi1 = new MenuItem(null, 0, null); | |||
| assertEquals(9.99, mi1.getCost(), DELTA); | |||
| assertEquals(MenuItemType.SIDE, mi1.getType()); | |||
| assertEquals("Side Dish of the Day", mi1.getName()); | |||
| MenuItem mi2 = new MenuItem("Steak", 12.99, MenuItemType.ENTREE); | |||
| assertEquals(12.99, mi2.getCost(), DELTA); | |||
| assertEquals(MenuItemType.ENTREE, mi2.getType()); | |||
| assertEquals("Steak", mi2.getName()); | |||
| MenuItem mi3 = new MenuItem("", 3.49, MenuItemType.DESSERT); | |||
| assertEquals(9.99, mi3.getCost(), DELTA); | |||
| assertEquals(MenuItemType.DESSERT, mi3.getType()); | |||
| assertEquals("Dessert of the Day", mi3.getName()); | |||
| } | |||
| } | |||
| @ -0,0 +1,67 @@ | |||
| package uwstout.courses.cs144.projects.project3.orders; | |||
| /** | |||
| * Represents the various types of Menu Items. | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.12.08 | |||
| */ | |||
| public enum MenuItemType { | |||
| /** | |||
| * The main course | |||
| */ | |||
| ENTREE, | |||
| /** | |||
| * A bowl of soup | |||
| */ | |||
| SOUP, | |||
| /** | |||
| * A side salad | |||
| */ | |||
| SALAD, | |||
| /** | |||
| * A drink | |||
| */ | |||
| DRINK, | |||
| /** | |||
| * A side dish | |||
| */ | |||
| SIDE, | |||
| /** | |||
| * A dessert item | |||
| */ | |||
| DESSERT; | |||
| @Override | |||
| public String toString() { | |||
| String out = ""; | |||
| switch (this) { | |||
| case ENTREE: | |||
| out = "Main Course"; | |||
| break; | |||
| case SOUP: | |||
| out = "Bowl of Soup"; | |||
| break; | |||
| case SALAD: | |||
| out = "Side Salad"; | |||
| break; | |||
| case DRINK: | |||
| out = "Drink"; | |||
| break; | |||
| case SIDE: | |||
| out = "Side Dish"; | |||
| break; | |||
| case DESSERT: | |||
| default: | |||
| out = "Dessert"; | |||
| break; | |||
| } | |||
| return out; | |||
| } | |||
| } | |||
| @ -0,0 +1,28 @@ | |||
| package uwstout.courses.cs144.projects.project3.orders; | |||
| import static org.junit.Assert.assertEquals; | |||
| import org.junit.Test; | |||
| /** | |||
| * Tests the MenuItemType enum | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.12.08 | |||
| */ | |||
| public class MenuItemTypeTest { | |||
| /** | |||
| * Tests the toString method | |||
| */ | |||
| @Test | |||
| public void testToString() { | |||
| assertEquals("Main Course", MenuItemType.ENTREE.toString()); | |||
| assertEquals("Bowl of Soup", MenuItemType.SOUP.toString()); | |||
| assertEquals("Side Salad", MenuItemType.SALAD.toString()); | |||
| assertEquals("Drink", MenuItemType.DRINK.toString()); | |||
| assertEquals("Side Dish", MenuItemType.SIDE.toString()); | |||
| assertEquals("Dessert", MenuItemType.DESSERT.toString()); | |||
| } | |||
| } | |||
| @ -0,0 +1,216 @@ | |||
| package uwstout.courses.cs144.projects.project3.orders; | |||
| import java.text.DecimalFormat; | |||
| import java.text.NumberFormat; | |||
| /** | |||
| * Represents an Order with a variety of items. | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.12.08 | |||
| */ | |||
| public class Order { | |||
| private static final int INITIAL_SIZE = 5; | |||
| private static final int LABEL_WIDTH = 20; | |||
| private static final int VALUE_WIDTH = 10; | |||
| private static final NumberFormat DF = DecimalFormat.getCurrencyInstance(); | |||
| private int orderNum; | |||
| private MenuItem[] items; | |||
| private int count; | |||
| /** | |||
| * Create an order with a given order number | |||
| * | |||
| * @param nOrderNum The number of the order | |||
| */ | |||
| public Order(int nOrderNum) { | |||
| orderNum = nOrderNum; | |||
| items = new MenuItem[INITIAL_SIZE]; | |||
| } | |||
| public Order(Order other) { | |||
| orderNum = other.orderNum; | |||
| count = other.count; | |||
| items = other.items.clone(); | |||
| } | |||
| /** | |||
| * Get the order number | |||
| * | |||
| * @return The order number | |||
| */ | |||
| public int getOrderNumber() { | |||
| return orderNum; | |||
| } | |||
| /** | |||
| * Get the number of items in the order | |||
| * | |||
| * @return Number of items | |||
| */ | |||
| public int getItemCount() { | |||
| return count; | |||
| } | |||
| /** | |||
| * Get an item at a given position. Returns null if outside of bounds. | |||
| * | |||
| * @param pos The position to pull from | |||
| * @return The item | |||
| */ | |||
| public MenuItem getItem(int pos) { | |||
| if (pos >= 0 && pos < count) { | |||
| return items[pos]; | |||
| } | |||
| return null; | |||
| } | |||
| /** | |||
| * Iterates over the items in the order, and counts the number of the given | |||
| * type. | |||
| * | |||
| * @param type The type of item we are searching for. | |||
| * @return The number of items of the given type | |||
| */ | |||
| public int countItems(MenuItemType type) { | |||
| int c = 0; | |||
| for (int i = 0; i < count; i++) { | |||
| if (items[i].getType() == type) { | |||
| c++; | |||
| } | |||
| } | |||
| return c; | |||
| } | |||
| /** | |||
| * Attempt to add an item to the order. Only allows 5 items per order. Will | |||
| * only allow one of each item type (allows two of SIDE). | |||
| * | |||
| * @param item The item to add to the order | |||
| * @return If the item was added | |||
| */ | |||
| public boolean addItem(MenuItem item) { | |||
| if (count < items.length) { | |||
| MenuItemType type = item.getType(); | |||
| int iCount = countItems(type); | |||
| if ((type == MenuItemType.SIDE && iCount < 2) | |||
| || (type != MenuItemType.SIDE && iCount < 1)) { | |||
| items[count++] = item; | |||
| return true; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| /** | |||
| * Loops over the items in the order and sums the cost of each item. | |||
| * | |||
| * @return The total cost of the order. | |||
| */ | |||
| public double getTotalCost() { | |||
| double c = 0; | |||
| for (int i = 0; i < count; i++) { | |||
| c += items[i].getCost(); | |||
| } | |||
| return c; | |||
| } | |||
| /** | |||
| * Calculates tax at a 5.56% rate. | |||
| * | |||
| * @return The amount of tax | |||
| */ | |||
| public double getTax() { | |||
| return getTotalCost() * 0.056; | |||
| } | |||
| /** | |||
| * Get the tip amount for a given percentage | |||
| * | |||
| * @param percentage The percent tip you'd like to give | |||
| * @return The tip amount | |||
| */ | |||
| public double getTipAmount(double percentage) { | |||
| return getTotalCost() * percentage; | |||
| } | |||
| @Override | |||
| public String toString() { | |||
| StringBuilder builder = new StringBuilder(); | |||
| double tax = getTax(); | |||
| double total = getTotalCost() + tax; | |||
| // Order # 100 | |||
| builder.append("Order # " + orderNum); | |||
| builder.append("\n"); | |||
| // | |||
| for (int i = 0; i < count; i++) { | |||
| MenuItem item = items[i]; | |||
| builder.append(formatLabel(LABEL_WIDTH, VALUE_WIDTH, item.getCost(), | |||
| item.getName())); | |||
| builder.append("\n"); | |||
| } | |||
| // Tax | |||
| builder.append( | |||
| formatLabel(LABEL_WIDTH, VALUE_WIDTH, tax, "Tax") + "\n"); | |||
| // Total | |||
| builder.append( | |||
| formatLabel(LABEL_WIDTH, VALUE_WIDTH, total, "Total") + "\n"); | |||
| builder.append("\n"); | |||
| // Tips | |||
| builder.append(formatLabel(LABEL_WIDTH, VALUE_WIDTH, getTipAmount(0.18), | |||
| "18% Tip") + "\n"); | |||
| builder.append(formatLabel(LABEL_WIDTH, VALUE_WIDTH, getTipAmount(0.20), | |||
| "20% Tip") + "\n"); | |||
| builder.append(formatLabel(LABEL_WIDTH, VALUE_WIDTH, getTipAmount(0.25), | |||
| "25% Tip") + "\n"); | |||
| return builder.toString(); | |||
| } | |||
| public boolean substituteItem(MenuItem subItem, String replacementItem) { | |||
| boolean substituted = false; | |||
| for (int i = 0; i < count; i++) { | |||
| MenuItem item = items[i]; | |||
| if (item.getCost() == subItem.getCost() | |||
| && item.getName().equals(subItem.getName())) { | |||
| items[i] = new MenuItem(replacementItem, item.getCost(), | |||
| item.getType()); | |||
| substituted = true; | |||
| } | |||
| } | |||
| return substituted; | |||
| } | |||
| /** | |||
| * Formats a value such that it lines everything up. Formats the value with | |||
| * a currency formatter. | |||
| * | |||
| * @param labelWidth The width of the label | |||
| * @param valueWidth The width of the value | |||
| * @param value The value we're printing | |||
| * @param label The label of the value | |||
| * @return A formatted string | |||
| */ | |||
| private String formatLabel(int labelWidth, int valueWidth, double value, | |||
| String label) { | |||
| String retString = label + " ".repeat(labelWidth - label.length()); | |||
| String valString = DF.format(value); | |||
| retString += " ".repeat(Math.max(valueWidth - valString.length(), 0)) | |||
| + valString; | |||
| return retString; | |||
| } | |||
| } | |||
| @ -0,0 +1,87 @@ | |||
| package uwstout.courses.cs144.projects.project3.orders; | |||
| public class OrderList { | |||
| private static final int INITIAL_SIZE = 3; | |||
| private Order[] orders; | |||
| private int count; | |||
| public OrderList() { | |||
| orders = new Order[INITIAL_SIZE]; | |||
| count = 0; | |||
| } | |||
| public OrderList(OrderList other) { | |||
| count = other.count; | |||
| orders = new Order[other.orders.length]; | |||
| for (int i = 0; i < count; i++) { | |||
| orders[i] = new Order(other.orders[i]); | |||
| } | |||
| } | |||
| public int getOrderCount() { | |||
| return count; | |||
| } | |||
| public Order getOrder(int pos) { | |||
| if (pos >= 0 && pos < count) { | |||
| return orders[pos]; | |||
| } | |||
| return null; | |||
| } | |||
| public void addOrder(Order other) { | |||
| if (count == orders.length) { | |||
| growArray(); | |||
| } | |||
| orders[count++] = other; | |||
| } | |||
| public Order findOrder(int orderNumber) { | |||
| Order found = null; | |||
| for (int i = 0; i < count; i++) { | |||
| Order potOrder = orders[i]; | |||
| if (potOrder.getOrderNumber() == orderNumber) { | |||
| found = potOrder; | |||
| break; | |||
| } | |||
| } | |||
| return found; | |||
| } | |||
| public double getGrandTotal() { | |||
| double sum = 0; | |||
| for (int i = 0; i < count; i++) { | |||
| Order o = orders[i]; | |||
| sum += o.getTotalCost(); | |||
| sum += o.getTax(); | |||
| } | |||
| return sum; | |||
| } | |||
| public int substituteItems(MenuItem subItem, String replacementName) { | |||
| int replaced = 0; | |||
| for (int i = 0; i < 0; i++) { | |||
| if (orders[i].substituteItem(subItem, replacementName)) { | |||
| replaced++; | |||
| } | |||
| } | |||
| return replaced; | |||
| } | |||
| public void clearList() { | |||
| count = 0; | |||
| } | |||
| private void growArray() { | |||
| Order[] temp = new Order[orders.length + 3]; | |||
| for (int i = 0; i < count; i++) { | |||
| temp[i] = orders[i]; | |||
| } | |||
| orders = temp; | |||
| } | |||
| } | |||
| @ -0,0 +1,7 @@ | |||
| package uwstout.courses.cs144.projects.project3.orders; | |||
| public class OrderProcessor { | |||
| private OrderList oList; | |||
| } | |||
| @ -0,0 +1,302 @@ | |||
| package uwstout.courses.cs144.projects.project3.orders; | |||
| import static org.junit.Assert.assertEquals; | |||
| import static org.junit.Assert.assertFalse; | |||
| import static org.junit.Assert.assertNotEquals; | |||
| import static org.junit.Assert.assertNull; | |||
| import static org.junit.Assert.assertTrue; | |||
| import org.junit.Before; | |||
| import org.junit.Test; | |||
| /** | |||
| * Tests the Order class | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.12.09 | |||
| */ | |||
| public class OrderTest { | |||
| private static final double DELTA = 0.01; | |||
| /** | |||
| * Some standard menu items to be used in tests. TODO add more if needed | |||
| */ | |||
| private static final MenuItem[] MENU_ITEMS = { | |||
| new MenuItem("Steak", 25.45, MenuItemType.ENTREE), | |||
| new MenuItem("Tofu", 35.95, MenuItemType.ENTREE), | |||
| new MenuItem("Chicken Noodle", 3.75, MenuItemType.SOUP), | |||
| new MenuItem("Hot Seasoned Water", 10.10, MenuItemType.SOUP), | |||
| new MenuItem("All Lettuce", 7.15, MenuItemType.SALAD), | |||
| new MenuItem("Taco Salad", 5.65, MenuItemType.SALAD), | |||
| new MenuItem("Water", 3.50, MenuItemType.DRINK), | |||
| new MenuItem("Cold Water", 5.50, MenuItemType.DRINK), | |||
| new MenuItem("Fries", 6.95, MenuItemType.SIDE), | |||
| new MenuItem("Bacon Fries", 8.95, MenuItemType.SIDE), | |||
| new MenuItem("Fried Bacon", 10.95, MenuItemType.SIDE), | |||
| new MenuItem("Mixed Vegetables", 5.50, MenuItemType.SIDE), | |||
| new MenuItem("Unmixed Vegetables", 6.50, MenuItemType.SIDE), | |||
| new MenuItem("Pie", 7.25, MenuItemType.DESSERT), | |||
| new MenuItem("Cake", 6.10, MenuItemType.DESSERT), }; | |||
| private Order order1; | |||
| private Order order2; | |||
| /** | |||
| * Sets up some orders for testing | |||
| * | |||
| * @throws Exception Not used | |||
| */ | |||
| @Before | |||
| public void setUp() throws Exception { | |||
| order1 = new Order(531); | |||
| order1.addItem(MENU_ITEMS[0]); | |||
| order1.addItem(MENU_ITEMS[8]); | |||
| order1.addItem(MENU_ITEMS[14]); | |||
| order2 = new Order(97645); | |||
| order2.addItem(MENU_ITEMS[3]); | |||
| order2.addItem(MENU_ITEMS[6]); | |||
| order2.addItem(MENU_ITEMS[11]); | |||
| order2.addItem(MENU_ITEMS[12]); | |||
| } | |||
| /** | |||
| * Test the Order(int) constructor | |||
| */ | |||
| @Test | |||
| public void testOrder() { | |||
| Order o1 = new Order(1000); | |||
| assertEquals(1000, o1.getOrderNumber()); | |||
| assertEquals(531, order1.getOrderNumber()); | |||
| assertEquals(97645, order2.getOrderNumber()); | |||
| } | |||
| /** | |||
| * Test the {@link Order#getItemCount()} method | |||
| */ | |||
| @Test | |||
| public void testGetItemCount() { | |||
| assertEquals(3, order1.getItemCount()); | |||
| assertEquals(4, order2.getItemCount()); | |||
| } | |||
| /** | |||
| * Test the {@link Order#countItems(MenuItemType)} method | |||
| */ | |||
| @Test | |||
| public void testCountItems() { | |||
| assertEquals(1, order1.countItems(MenuItemType.ENTREE)); | |||
| assertEquals(1, order1.countItems(MenuItemType.SIDE)); | |||
| assertEquals(1, order1.countItems(MenuItemType.DESSERT)); | |||
| assertEquals(1, order2.countItems(MenuItemType.SOUP)); | |||
| assertEquals(1, order2.countItems(MenuItemType.DRINK)); | |||
| assertEquals(2, order2.countItems(MenuItemType.SIDE)); | |||
| } | |||
| /** | |||
| * Test the addItem method (and thus some of the getItem method) | |||
| */ | |||
| @Test | |||
| public void testAddItem() { | |||
| Order o1 = new Order(100); | |||
| assertEquals(0, o1.getItemCount()); | |||
| assertTrue(o1.addItem(MENU_ITEMS[0])); | |||
| assertFalse(o1.addItem(MENU_ITEMS[0])); | |||
| assertTrue(checkMenuItem(MENU_ITEMS[0], o1.getItem(0))); | |||
| assertEquals(1, o1.getItemCount()); | |||
| assertTrue(o1.addItem(MENU_ITEMS[2])); | |||
| assertFalse(o1.addItem(MENU_ITEMS[2])); | |||
| assertTrue(checkMenuItem(MENU_ITEMS[2], o1.getItem(1))); | |||
| assertEquals(2, o1.getItemCount()); | |||
| assertTrue(o1.addItem(MENU_ITEMS[8])); | |||
| assertTrue(o1.addItem(MENU_ITEMS[9])); | |||
| assertFalse(o1.addItem(MENU_ITEMS[8])); | |||
| assertTrue(checkMenuItem(MENU_ITEMS[8], o1.getItem(2))); | |||
| assertTrue(checkMenuItem(MENU_ITEMS[9], o1.getItem(3))); | |||
| assertEquals(4, o1.getItemCount()); | |||
| assertTrue(o1.addItem(MENU_ITEMS[13])); | |||
| assertFalse(o1.addItem(MENU_ITEMS[13])); | |||
| assertTrue(checkMenuItem(MENU_ITEMS[13], o1.getItem(4))); | |||
| assertEquals(5, o1.getItemCount()); | |||
| } | |||
| /** | |||
| * Tests the {@link Order#getItem(int)} method | |||
| */ | |||
| @Test | |||
| public void testGetItem() { | |||
| assertNull(order1.getItem(-1)); | |||
| assertTrue(checkMenuItem(MENU_ITEMS[0], order1.getItem(0))); | |||
| assertTrue(checkMenuItem(MENU_ITEMS[8], order1.getItem(1))); | |||
| assertTrue(checkMenuItem(MENU_ITEMS[14], order1.getItem(2))); | |||
| assertNull(order1.getItem(3)); | |||
| assertNull(order2.getItem(-1)); | |||
| assertTrue(checkMenuItem(MENU_ITEMS[3], order2.getItem(0))); | |||
| assertTrue(checkMenuItem(MENU_ITEMS[6], order2.getItem(1))); | |||
| assertTrue(checkMenuItem(MENU_ITEMS[11], order2.getItem(2))); | |||
| assertTrue(checkMenuItem(MENU_ITEMS[12], order2.getItem(3))); | |||
| assertNull(order2.getItem(4)); | |||
| } | |||
| /** | |||
| * Tests the {@link Order#getTotalCost()} method | |||
| */ | |||
| @Test | |||
| public void testGetTotalCost() { | |||
| Order blankOrder = new Order(0); | |||
| assertEquals(0, blankOrder.getTotalCost(), DELTA); | |||
| assertEquals(38.50, order1.getTotalCost(), DELTA); | |||
| assertEquals(25.60, order2.getTotalCost(), DELTA); | |||
| } | |||
| /** | |||
| * Tests the {@link Order#getTax()} method | |||
| */ | |||
| @Test | |||
| public void testGetTax() { | |||
| assertEquals(2.16, order1.getTax(), DELTA); | |||
| assertEquals(1.43, order2.getTax(), DELTA); | |||
| } | |||
| /** | |||
| * Tests the {@link Order#getTipAmount(double)} method | |||
| */ | |||
| @Test | |||
| public void testGetTipAmount() { | |||
| assertEquals(6.93, order1.getTipAmount(0.18), DELTA); | |||
| assertEquals(7.70, order1.getTipAmount(0.20), DELTA); | |||
| assertEquals(9.62, order1.getTipAmount(0.25), DELTA); | |||
| assertEquals(4.61, order2.getTipAmount(0.18), DELTA); | |||
| assertEquals(5.12, order2.getTipAmount(0.20), DELTA); | |||
| assertEquals(6.40, order2.getTipAmount(0.25), DELTA); | |||
| } | |||
| /** | |||
| * Tests the {@link Order#toString()} method | |||
| */ | |||
| @Test | |||
| public void testToString() { | |||
| // get the string | |||
| String order1Str = order1.toString(); | |||
| // for debugging | |||
| // System.out.println(order1Str); | |||
| // Check if order number is in string | |||
| // indexOf returns the position in the String where | |||
| // the parameter is found. It returns -1 if | |||
| // it is not there. | |||
| assertNotEquals("No order number found", -1, order1Str.indexOf("531")); | |||
| // May have to adjust if formatting is different | |||
| // Check for names and prices are in string | |||
| assertNotEquals("Item name missing", -1, order1Str.indexOf("Steak")); | |||
| assertNotEquals("Item name missing", -1, order1Str.indexOf("Fries")); | |||
| assertNotEquals("Item name missing", -1, order1Str.indexOf("Cake")); | |||
| assertNotEquals("Item cost missing", -1, order1Str.indexOf("25.45")); | |||
| assertNotEquals("Item cost missing", -1, order1Str.indexOf("6.95")); | |||
| assertNotEquals("Item cost missing", -1, order1Str.indexOf("6.10")); | |||
| // Check for tax | |||
| assertNotEquals("Tax missing", -1, order1Str.indexOf("2.16")); | |||
| // Check for total | |||
| assertNotEquals("Total (with tax) missing", -1, | |||
| order1Str.indexOf("40.66")); | |||
| // Check for tips | |||
| assertNotEquals("18% Tip missing", -1, order1Str.indexOf("6.93")); | |||
| assertNotEquals("20% Tip missing", -1, order1Str.indexOf("7.70")); | |||
| assertNotEquals("25% Tip missing", -1, order1Str.indexOf("9.62")); | |||
| // get the string | |||
| String order2Str = order2.toString(); | |||
| // for debugging | |||
| System.out.println(order2Str); | |||
| // Check if order number is in string | |||
| // indexOf returns the position in the String where | |||
| // the parameter is found. It returns -1 if | |||
| // it is not there. | |||
| assertNotEquals("No order number found", -1, | |||
| order2Str.indexOf("97645")); | |||
| // May have to adjust if formatting is different | |||
| // Check for names and prices are in string | |||
| assertNotEquals("Item name missing", -1, | |||
| order2Str.indexOf("Hot Seasoned Water")); | |||
| assertNotEquals("Item name missing", -1, order2Str.indexOf("Water")); | |||
| assertNotEquals("Item name missing", -1, | |||
| order2Str.indexOf("Mixed Vegetables")); | |||
| assertNotEquals("Item name missing", -1, | |||
| order2Str.indexOf("Unmixed Vegetables")); | |||
| assertNotEquals("Item cost missing", -1, order2Str.indexOf("10.10")); | |||
| assertNotEquals("Item cost missing", -1, order2Str.indexOf("3.50")); | |||
| assertNotEquals("Item cost missing", -1, order2Str.indexOf("5.50")); | |||
| assertNotEquals("Item cost missing", -1, order2Str.indexOf("6.50")); | |||
| // Check for tax | |||
| assertNotEquals("Tax missing", -1, order2Str.indexOf("1.43")); | |||
| // Check for total | |||
| assertNotEquals("Total (with tax) missing", -1, | |||
| order2Str.indexOf("27.03")); | |||
| // Check for tips | |||
| assertNotEquals("18% Tip missing", -1, order2Str.indexOf("4.61")); | |||
| assertNotEquals("20% Tip missing", -1, order2Str.indexOf("5.12")); | |||
| assertNotEquals("25% Tip missing", -1, order2Str.indexOf("6.40")); | |||
| } | |||
| /** | |||
| * Compares two MenuItems | |||
| * | |||
| * @param expected The MenuItem you expect to have | |||
| * @param actual The actual MenuItem | |||
| * @return true if they are the same | |||
| */ | |||
| private boolean checkMenuItem(MenuItem expected, MenuItem actual) { | |||
| // if both are null or the same object | |||
| if (expected == actual) { | |||
| return true; | |||
| } | |||
| // one of them is null | |||
| if (expected == null || actual == null) { | |||
| return false; | |||
| } | |||
| // check if all of the values match | |||
| return expected.getName().equals(actual.getName()) | |||
| && Math.abs(expected.getCost() - actual.getCost()) < 0.01 | |||
| && expected.getType() == actual.getType(); | |||
| } | |||
| /** | |||
| * Checks if an Order is as expected | |||
| * | |||
| * @param ord Order to check | |||
| * @param eOrderNumber Expected order number | |||
| * @param items Array of MenuItems that should be in the array. | |||
| * Should have the same length as the number of items in | |||
| * the order. | |||
| * @return True if it matches the order number and items. | |||
| */ | |||
| private boolean checkOrder(Order ord, int eOrderNumber, MenuItem[] items) { | |||
| // check if the order number of number of items | |||
| // is wrong | |||
| if (ord == null || ord.getOrderNumber() != eOrderNumber | |||
| || ord.getItemCount() != items.length) { | |||
| return false; | |||
| } | |||
| // check if each menu item is the same | |||
| for (int i = 0; i < ord.getItemCount(); i++) { | |||
| if (!checkMenuItem(items[i], ord.getItem(i))) { | |||
| return false; | |||
| } | |||
| } | |||
| // must be equal if we are here. | |||
| return true; | |||
| } | |||
| } | |||
| @ -0,0 +1,15 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <classpath> | |||
| <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"> | |||
| <attributes> | |||
| <attribute name="module" value="true"/> | |||
| </attributes> | |||
| </classpathentry> | |||
| <classpathentry kind="src" path="src"/> | |||
| <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"> | |||
| <attributes> | |||
| <attribute name="module" value="true"/> | |||
| </attributes> | |||
| </classpathentry> | |||
| <classpathentry kind="output" path="bin"/> | |||
| </classpath> | |||
| @ -0,0 +1,17 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <projectDescription> | |||
| <name>PROJECT-2</name> | |||
| <comment></comment> | |||
| <projects> | |||
| </projects> | |||
| <buildSpec> | |||
| <buildCommand> | |||
| <name>org.eclipse.jdt.core.javabuilder</name> | |||
| <arguments> | |||
| </arguments> | |||
| </buildCommand> | |||
| </buildSpec> | |||
| <natures> | |||
| <nature>org.eclipse.jdt.core.javanature</nature> | |||
| </natures> | |||
| </projectDescription> | |||
| @ -0,0 +1,7 @@ | |||
| /** | |||
| * @author brett | |||
| * | |||
| */ | |||
| module courses.uwstout.cs144 { | |||
| requires junit; | |||
| } | |||
| @ -0,0 +1,150 @@ | |||
| package uwstout.courses.cs144.projects.project2.companion; | |||
| /** | |||
| * Represents a Player's companion. | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.11.15 | |||
| */ | |||
| public class Companion { | |||
| /* | |||
| * Constants | |||
| */ | |||
| private static final int DEF_COOLDOWN = 0; | |||
| private static final int MIN_COOLDOWN = 0; | |||
| private static final int BASE_DAMAGE = 15; | |||
| // Sayings | |||
| private static final String VERY_NEGATIVE_SAYING = "Maybe I should take my money and go."; | |||
| private static final String NEGATIVE_SAYING = "I'm bored."; | |||
| private static final String NEUTRAL_SAYING = "Now what?"; | |||
| private static final String POSITIVE_SAYING = "Is that free gold I see?"; | |||
| private static final String VERY_POSITIVE_SAYING = "Woohoo! More stuff!"; | |||
| /* | |||
| * Class Members | |||
| */ | |||
| private Player player; | |||
| private Relationship relationship; | |||
| private int cooldown; | |||
| /** | |||
| * Create a new Companion for a Player | |||
| * | |||
| * @param nPlayer The Player this Companion is for | |||
| */ | |||
| public Companion(Player nPlayer) { | |||
| player = nPlayer; | |||
| cooldown = DEF_COOLDOWN; | |||
| relationship = new Relationship(); | |||
| } | |||
| /** | |||
| * Get the Player for this Companion | |||
| * | |||
| * @return The Player | |||
| */ | |||
| public Player getPlayer() { | |||
| return player; | |||
| } | |||
| /** | |||
| * Get the Relationship for this Companion | |||
| * | |||
| * @return The Relationship | |||
| */ | |||
| public Relationship getRelationship() { | |||
| return relationship; | |||
| } | |||
| /** | |||
| * Get the cooldown of actions | |||
| * | |||
| * @return The current cooldown | |||
| */ | |||
| public int getCooldown() { | |||
| return cooldown; | |||
| } | |||
| /** | |||
| * Returns a saying based on the status of the relationship | |||
| * | |||
| * @return The saying | |||
| */ | |||
| public String getSaying() { | |||
| String retString = ""; | |||
| switch (relationship.getRelationshipStatus()) { | |||
| case "Very Negative": | |||
| retString = VERY_NEGATIVE_SAYING; | |||
| break; | |||
| case "Negative": | |||
| retString = NEGATIVE_SAYING; | |||
| break; | |||
| case "Neutral": | |||
| retString = NEUTRAL_SAYING; | |||
| break; | |||
| case "Positive": | |||
| retString = POSITIVE_SAYING; | |||
| break; | |||
| case "Very Positive": | |||
| retString = VERY_POSITIVE_SAYING; | |||
| break; | |||
| } | |||
| return retString; | |||
| } | |||
| /** | |||
| * Heals the player depending on the strength of the relationship | |||
| * | |||
| * @return The amount healed | |||
| */ | |||
| public int heal() { | |||
| int healAmount = 0; | |||
| if (cooldown == 0) { | |||
| // Set the cooldown | |||
| cooldown = 4; | |||
| int rStrength = relationship.getRelationshipStrength(); | |||
| if (rStrength != 0) { | |||
| healAmount = (Math.abs(rStrength) + 2) / 3 * 10; | |||
| } else { | |||
| healAmount = 5; | |||
| } | |||
| } | |||
| return healAmount; | |||
| } | |||
| /** | |||
| * Attacks | |||
| * | |||
| * @return The damage of the attack | |||
| */ | |||
| public int attack() { | |||
| int attackAmount = 0; | |||
| if (cooldown == 0) { | |||
| // Set the cooldown | |||
| cooldown = 4; | |||
| attackAmount = 5 * player.getLevel() | |||
| + relationship.getRelationshipStrength() + BASE_DAMAGE; | |||
| } | |||
| return attackAmount; | |||
| } | |||
| /** | |||
| * Called when time is passed | |||
| */ | |||
| public void tick() { | |||
| // Decrease the cooldown | |||
| if (cooldown > MIN_COOLDOWN) { | |||
| cooldown--; | |||
| } | |||
| // Heal the player if need be | |||
| if (cooldown == 0 | |||
| && (player.getCurrentHealth() < player.getMaxHealth() / 2)) { | |||
| player.adjustHealth(heal()); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,207 @@ | |||
| package uwstout.courses.cs144.projects.project2.companion; | |||
| import static org.junit.Assert.assertEquals; | |||
| import org.junit.Before; | |||
| import org.junit.Test; | |||
| /** | |||
| * Tests the Companion class | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.11.15 | |||
| */ | |||
| public class CompanionTest { | |||
| private Player p1; | |||
| private Player p2; | |||
| private Companion c1; | |||
| private Companion c2; | |||
| /** | |||
| * Sets the Test class up, creates default Players and Companions | |||
| * | |||
| * @throws Exception | |||
| */ | |||
| @Before | |||
| public void setUp() throws Exception { | |||
| p1 = new Player("Player1", 0, 10); | |||
| p2 = new Player("Player2", 5, 15); | |||
| c1 = new Companion(p1); | |||
| c2 = new Companion(p2); | |||
| } | |||
| /** | |||
| * Tests the Companion(Player) constructor) | |||
| */ | |||
| @Test | |||
| public void testCompanion() { | |||
| assertEquals(p1, c1.getPlayer()); | |||
| assertEquals(0, c1.getCooldown()); | |||
| assertEquals(1, c1.getRelationship().getRelationshipStrength()); | |||
| assertEquals(false, c1.getRelationship().wasQuestCompleted()); | |||
| assertEquals(p2, c2.getPlayer()); | |||
| assertEquals(0, c2.getCooldown()); | |||
| assertEquals(1, c2.getRelationship().getRelationshipStrength()); | |||
| assertEquals(false, c2.getRelationship().wasQuestCompleted()); | |||
| } | |||
| /** | |||
| * Tests the {@link Companion#getSaying()} method. | |||
| */ | |||
| @Test | |||
| public void testGetSaying() { | |||
| setRelationshipStrength(c1.getRelationship(), -10); | |||
| assertEquals("Maybe I should take my money and go.", c1.getSaying()); | |||
| setRelationshipStrength(c1.getRelationship(), -5); | |||
| assertEquals("I'm bored.", c1.getSaying()); | |||
| setRelationshipStrength(c1.getRelationship(), 0); | |||
| assertEquals("Now what?", c1.getSaying()); | |||
| setRelationshipStrength(c1.getRelationship(), 5); | |||
| assertEquals("Is that free gold I see?", c1.getSaying()); | |||
| setRelationshipStrength(c1.getRelationship(), 19); | |||
| assertEquals("Woohoo! More stuff!", c1.getSaying()); | |||
| } | |||
| /** | |||
| * Tests the {@link Companion#heal()} method. | |||
| */ | |||
| @Test | |||
| public void testHeal() { | |||
| assertEquals(10, c1.heal()); | |||
| assertEquals(4, c1.getCooldown()); | |||
| assertEquals(0, c1.heal()); | |||
| doTicks(c1, 4); | |||
| setRelationshipStrength(c1.getRelationship(), 5); | |||
| assertEquals(20, c1.heal()); | |||
| assertEquals(4, c1.getCooldown()); | |||
| doTicks(c1, 4); | |||
| setRelationshipStrength(c1.getRelationship(), -5); | |||
| assertEquals(20, c1.heal()); | |||
| assertEquals(4, c1.getCooldown()); | |||
| doTicks(c1, 4); | |||
| setRelationshipStrength(c1.getRelationship(), -2); | |||
| assertEquals(10, c1.heal()); | |||
| assertEquals(4, c1.getCooldown()); | |||
| } | |||
| /** | |||
| * Tests the {@link Companion#attack()} method. | |||
| */ | |||
| @Test | |||
| public void testAttack() { | |||
| // Level 1 Values | |||
| setRelationshipStrength(c1.getRelationship(), 0); | |||
| assertEquals(20, c1.attack()); | |||
| assertEquals(4, c1.getCooldown()); | |||
| assertEquals(0, c1.attack()); | |||
| doTicks(c1, 4); | |||
| setRelationshipStrength(c1.getRelationship(), 5); | |||
| assertEquals(25, c1.attack()); | |||
| assertEquals(4, c1.getCooldown()); | |||
| doTicks(c1, 4); | |||
| setRelationshipStrength(c1.getRelationship(), -5); | |||
| assertEquals(15, c1.attack()); | |||
| assertEquals(4, c1.getCooldown()); | |||
| // Level 5 Values | |||
| setRelationshipStrength(c2.getRelationship(), 0); | |||
| assertEquals(0, c1.attack()); | |||
| doTicks(c2, 1); | |||
| assertEquals(40, c2.attack()); | |||
| assertEquals(4, c2.getCooldown()); | |||
| doTicks(c2, 4); | |||
| setRelationshipStrength(c2.getRelationship(), 5); | |||
| assertEquals(45, c2.attack()); | |||
| assertEquals(4, c2.getCooldown()); | |||
| doTicks(c2, 4); | |||
| setRelationshipStrength(c2.getRelationship(), -5); | |||
| assertEquals(35, c2.attack()); | |||
| assertEquals(4, c2.getCooldown()); | |||
| } | |||
| /** | |||
| * Tests the {@link Companion#tick()} method. | |||
| */ | |||
| @Test | |||
| public void testTick() { | |||
| // Set the cooldown to 4 | |||
| c1.attack(); | |||
| // Ensure it decreases cooldown by one each time | |||
| c1.tick(); | |||
| assertEquals(3, c1.getCooldown()); | |||
| c1.tick(); | |||
| assertEquals(2, c1.getCooldown()); | |||
| c1.tick(); | |||
| assertEquals(1, c1.getCooldown()); | |||
| c1.tick(); | |||
| assertEquals(0, c1.getCooldown()); | |||
| // Make sure it heals | |||
| c1.getPlayer().adjustHealth(-6); | |||
| c1.tick(); | |||
| assertEquals(10, c1.getPlayer().getCurrentHealth()); | |||
| // Making sure heal amount is correct overall | |||
| doTicks(c1, 4); | |||
| c1.getPlayer().adjustHealth(-10); | |||
| setRelationshipStrength(c1.getRelationship(), 0); | |||
| c1.tick(); | |||
| assertEquals(5, c1.getPlayer().getCurrentHealth()); | |||
| } | |||
| /** | |||
| * Increases/decreases a relationship's strength to match a certain level. | |||
| * | |||
| * @param rel Relationship to modify | |||
| * @param str New strength level | |||
| */ | |||
| private void setRelationshipStrength(Relationship rel, int str) { | |||
| int currentStr = rel.getRelationshipStrength(); | |||
| int adjustment = str - currentStr; | |||
| if (adjustment < 0) { | |||
| for (int i = 0; i < Math.abs(adjustment); i++) { | |||
| rel.decreaseRelationship(); | |||
| } | |||
| } else { | |||
| for (int i = 0; i < adjustment; i++) { | |||
| rel.increaseRelationship(); | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * Calls the Companion's tick method count times. | |||
| * | |||
| * @param comp Companion to call tick on | |||
| * @param count Number of times to call tick | |||
| */ | |||
| private void doTicks(Companion comp, int count) { | |||
| for (int i = 0; i < count; i++) { | |||
| comp.tick(); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,109 @@ | |||
| package uwstout.courses.cs144.projects.project2.companion; | |||
| /** | |||
| * Represents a player in a game. | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.11.15 | |||
| */ | |||
| public class Player { | |||
| /* | |||
| * Constants | |||
| */ | |||
| private static final int DEF_MAX_HEALTH = 10; | |||
| private static final int DEF_LEVEL = 1; | |||
| private static final int MIN_POSSIBLE_HEALTH = 0; | |||
| /* | |||
| * Class Members | |||
| */ | |||
| private int level; | |||
| private int maxHealth; | |||
| private int curHealth; | |||
| private boolean alive; | |||
| private String name; | |||
| /** | |||
| * Create a new player with a name, level, and a given max health. Will | |||
| * ensure level is at least 1, and if max health is less than or equal to 0, | |||
| * it will be 10. | |||
| * | |||
| * @param nName The name of the player | |||
| * @param nLevel The level of the player | |||
| * @param nMaxHealth The maximum health of the player | |||
| */ | |||
| public Player(String nName, int nLevel, int nMaxHealth) { | |||
| maxHealth = (nMaxHealth > 0) ? nMaxHealth : DEF_MAX_HEALTH; | |||
| level = (nLevel >= 1) ? nLevel : DEF_LEVEL; | |||
| curHealth = maxHealth; | |||
| name = nName; | |||
| alive = true; | |||
| } | |||
| /** | |||
| * Get the level of the Player | |||
| * | |||
| * @return The level | |||
| */ | |||
| public int getLevel() { | |||
| return level; | |||
| } | |||
| /** | |||
| * Get the name of the Player | |||
| * | |||
| * @return The name | |||
| */ | |||
| public String getName() { | |||
| return name; | |||
| } | |||
| /** | |||
| * Get the max health of the Player | |||
| * | |||
| * @return The maximum health | |||
| */ | |||
| public int getMaxHealth() { | |||
| return maxHealth; | |||
| } | |||
| /** | |||
| * Get the current health of the Player | |||
| * | |||
| * @return The current health | |||
| */ | |||
| public int getCurrentHealth() { | |||
| return curHealth; | |||
| } | |||
| /** | |||
| * Check if the Player is alive | |||
| * | |||
| * @return Player's alive status | |||
| */ | |||
| public boolean isAlive() { | |||
| return alive; | |||
| } | |||
| /** | |||
| * Adjust the health of the player. Will mark as not-alive if the change | |||
| * causes the current health to drop below 0. Will also cap to max health. | |||
| * | |||
| * @param change The amount that the health should be changed. | |||
| */ | |||
| public void adjustHealth(int change) { | |||
| if (alive) { | |||
| curHealth += change; | |||
| if (curHealth > maxHealth) { | |||
| curHealth = maxHealth; | |||
| } | |||
| if (curHealth < MIN_POSSIBLE_HEALTH) { | |||
| curHealth = MIN_POSSIBLE_HEALTH; | |||
| alive = false; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,88 @@ | |||
| package uwstout.courses.cs144.projects.project2.companion; | |||
| import static org.junit.Assert.assertEquals; | |||
| import org.junit.Before; | |||
| import org.junit.Test; | |||
| /** | |||
| * Tests the Player class | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.11.15 | |||
| */ | |||
| public class PlayerTest { | |||
| private Player p1; | |||
| private Player p2; | |||
| /** | |||
| * Sets the Test class up, creates default players | |||
| * | |||
| * @throws Exception | |||
| */ | |||
| @Before | |||
| public void setUp() throws Exception { | |||
| p1 = new Player("Player1", 0, 10); | |||
| p2 = new Player("Player2", 5, 15); | |||
| } | |||
| /** | |||
| * Tests the Player(String, int, int) constructor. (Including all get | |||
| * methods) | |||
| */ | |||
| @Test | |||
| public void testPlayer() { | |||
| Player t1 = new Player("player", 0, 0); | |||
| assertEquals("player", t1.getName()); | |||
| assertEquals(1, t1.getLevel()); | |||
| assertEquals(10, t1.getMaxHealth()); | |||
| assertEquals(true, t1.isAlive()); | |||
| assertEquals(10, t1.getCurrentHealth()); | |||
| Player t2 = new Player("player2", -10, -10); | |||
| assertEquals("player2", t2.getName()); | |||
| assertEquals(1, t2.getLevel()); | |||
| assertEquals(10, t2.getMaxHealth()); | |||
| assertEquals(true, t2.isAlive()); | |||
| assertEquals(10, t2.getCurrentHealth()); | |||
| Player t3 = new Player("player3", 2, 15); | |||
| assertEquals("player3", t3.getName()); | |||
| assertEquals(2, t3.getLevel()); | |||
| assertEquals(15, t3.getMaxHealth()); | |||
| assertEquals(true, t3.isAlive()); | |||
| assertEquals(15, t3.getCurrentHealth()); | |||
| } | |||
| /** | |||
| * Tests the {@link Player#adjustHealth(int)} method. | |||
| */ | |||
| @Test | |||
| public void testAdjustHealth() { | |||
| p1.adjustHealth(-10); | |||
| assertEquals(true, p1.isAlive()); | |||
| assertEquals(0, p1.getCurrentHealth()); | |||
| p1.adjustHealth(-1); | |||
| assertEquals(false, p1.isAlive()); | |||
| assertEquals(0, p1.getCurrentHealth()); | |||
| p1.adjustHealth(1); | |||
| assertEquals(false, p1.isAlive()); | |||
| assertEquals(0, p1.getCurrentHealth()); | |||
| p2.adjustHealth(10); | |||
| assertEquals(true, p2.isAlive()); | |||
| assertEquals(15, p2.getCurrentHealth()); | |||
| p2.adjustHealth(-1); | |||
| assertEquals(true, p2.isAlive()); | |||
| assertEquals(14, p2.getCurrentHealth()); | |||
| p2.adjustHealth(-16); | |||
| assertEquals(false, p2.isAlive()); | |||
| assertEquals(0, p2.getCurrentHealth()); | |||
| } | |||
| } | |||
| @ -0,0 +1,128 @@ | |||
| package uwstout.courses.cs144.projects.project2.companion; | |||
| /** | |||
| * Represents a relationship between a player and a companion. | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.11.15 | |||
| */ | |||
| public class Relationship { | |||
| /* | |||
| * Constants | |||
| */ | |||
| // Relationship Strength | |||
| private static final int MAX_RELATIONSHIP_STRENGTH = 10; | |||
| private static final int MIN_RELATIONSHIP_STRENGTH = -10; | |||
| // Relationship Statuses | |||
| /// Very Negative | |||
| private static final String STATUS_VERY_NEGATIVE = "Very Negative"; | |||
| /// Negative | |||
| private static final int STATUS_NEGATIVE_BOUNDARY = -6; | |||
| private static final String STATUS_NEGATIVE = "Negative"; | |||
| /// Neutral | |||
| private static final int STATUS_NEUTRAL_BOUNDARY = -2; | |||
| private static final String STATUS_NEUTRAL = "Neutral"; | |||
| /// Positive | |||
| private static final int STATUS_POSITIVE_BOUNDARY = 3; | |||
| private static final String STATUS_POSITIVE = "Positive"; | |||
| /// Very Positive | |||
| private static final int STATUS_VERY_POSITIVE_BOUNDARY = 7; | |||
| private static final String STATUS_VERY_POSITIVE = "Very Positive"; | |||
| /* | |||
| * Class Members | |||
| */ | |||
| private boolean questCompleted; | |||
| private int strength; | |||
| /** | |||
| * Create a new Relationship. Defaults to an uncompleted quest and a | |||
| * strength of 1. | |||
| */ | |||
| public Relationship() { | |||
| questCompleted = false; | |||
| strength = 1; | |||
| } | |||
| /** | |||
| * Get the strength of the Relationship. | |||
| * | |||
| * @return The relationship strength | |||
| */ | |||
| public int getRelationshipStrength() { | |||
| return strength; | |||
| } | |||
| /** | |||
| * Checks if the quest was completed. | |||
| * | |||
| * @return The quest completion status | |||
| */ | |||
| public boolean wasQuestCompleted() { | |||
| return questCompleted; | |||
| } | |||
| /** | |||
| * Increases the strength of the relationship, if the quest is not | |||
| * completed. Will be maxed to 10. | |||
| */ | |||
| public void increaseRelationship() { | |||
| if (strength < MAX_RELATIONSHIP_STRENGTH && !questCompleted) { | |||
| strength++; | |||
| } | |||
| } | |||
| /** | |||
| * Decreases the strength of the relationship, if the quest is not | |||
| * completed. Will keep at or above -10. | |||
| */ | |||
| public void decreaseRelationship() { | |||
| if (strength > MIN_RELATIONSHIP_STRENGTH && !questCompleted) { | |||
| strength--; | |||
| } | |||
| } | |||
| /** | |||
| * Mark a quest as completed, setting the strength based on if it was | |||
| * successful or not. | |||
| * | |||
| * @param successful If the quest was successful or not | |||
| */ | |||
| public void questCompleted(boolean successful) { | |||
| if (!questCompleted) { | |||
| questCompleted = true; | |||
| if (successful) { | |||
| strength = MAX_RELATIONSHIP_STRENGTH; | |||
| } else { | |||
| strength = MIN_RELATIONSHIP_STRENGTH; | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * Get a string representation of the relationship status. | |||
| * | |||
| * @return The status of the relationship | |||
| */ | |||
| public String getRelationshipStatus() { | |||
| String retString; | |||
| if (strength < STATUS_NEGATIVE_BOUNDARY) { | |||
| retString = STATUS_VERY_NEGATIVE; | |||
| } else if (strength < STATUS_NEUTRAL_BOUNDARY) { | |||
| retString = STATUS_NEGATIVE; | |||
| } else if (strength < STATUS_POSITIVE_BOUNDARY) { | |||
| retString = STATUS_NEUTRAL; | |||
| } else if (strength < STATUS_VERY_POSITIVE_BOUNDARY) { | |||
| retString = STATUS_POSITIVE; | |||
| } else { // It is above the very positive boundary | |||
| retString = STATUS_VERY_POSITIVE; | |||
| } | |||
| return retString; | |||
| } | |||
| } | |||
| @ -0,0 +1,162 @@ | |||
| package uwstout.courses.cs144.projects.project2.companion; | |||
| import static org.junit.Assert.assertEquals; | |||
| import org.junit.Before; | |||
| import org.junit.Test; | |||
| /** | |||
| * Tests the Relationship class | |||
| * | |||
| * @author Brett Bender | |||
| * @version 2022.11.15 | |||
| */ | |||
| public class RelationshipTest { | |||
| private Relationship r1; | |||
| private Relationship r2; | |||
| /** | |||
| * Sets the Test class up, creating default relationships | |||
| * | |||
| * @throws Exception | |||
| */ | |||
| @Before | |||
| public void setUp() throws Exception { | |||
| r1 = new Relationship(); | |||
| r2 = new Relationship(); | |||
| } | |||
| /** | |||
| * Tests the default constructor | |||
| */ | |||
| @Test | |||
| public void testRelationship() { | |||
| assertEquals(1, r1.getRelationshipStrength()); | |||
| assertEquals(false, r1.wasQuestCompleted()); | |||
| } | |||
| /** | |||
| * Tests the {@link Relationship#increaseRelationship()} method. | |||
| */ | |||
| @Test | |||
| public void testIncreaseRelationship() { | |||
| r1.increaseRelationship(); | |||
| assertEquals(2, r1.getRelationshipStrength()); | |||
| setRelationshipStrength(r1, 10); | |||
| assertEquals(10, r1.getRelationshipStrength()); | |||
| setRelationshipStrength(r1, 15); | |||
| assertEquals(10, r1.getRelationshipStrength()); | |||
| r1.questCompleted(false); | |||
| setRelationshipStrength(r1, 15); | |||
| assertEquals(-10, r1.getRelationshipStrength()); | |||
| } | |||
| /** | |||
| * Tests the {@link Relationship#decreaseRelationship()} method. | |||
| */ | |||
| @Test | |||
| public void testDecreaseRealtionship() { | |||
| r1.decreaseRelationship(); | |||
| assertEquals(0, r1.getRelationshipStrength()); | |||
| setRelationshipStrength(r1, -10); | |||
| assertEquals(-10, r1.getRelationshipStrength()); | |||
| setRelationshipStrength(r1, -15); | |||
| assertEquals(-10, r1.getRelationshipStrength()); | |||
| r1.questCompleted(true); | |||
| setRelationshipStrength(r1, -15); | |||
| assertEquals(10, r1.getRelationshipStrength()); | |||
| } | |||
| /** | |||
| * Tests the {@link Relationship#questCompleted()} method. | |||
| */ | |||
| @Test | |||
| public void testQuestCompleted() { | |||
| assertEquals(false, r1.wasQuestCompleted()); | |||
| r1.questCompleted(true); | |||
| assertEquals(true, r1.wasQuestCompleted()); | |||
| assertEquals(10, r1.getRelationshipStrength()); | |||
| r1.questCompleted(false); | |||
| assertEquals(true, r1.wasQuestCompleted()); | |||
| assertEquals(10, r1.getRelationshipStrength()); | |||
| assertEquals(false, r2.wasQuestCompleted()); | |||
| r2.questCompleted(false); | |||
| assertEquals(true, r2.wasQuestCompleted()); | |||
| assertEquals(-10, r2.getRelationshipStrength()); | |||
| r2.questCompleted(true); | |||
| assertEquals(true, r2.wasQuestCompleted()); | |||
| assertEquals(-10, r2.getRelationshipStrength()); | |||
| } | |||
| /** | |||
| * Tests the {@link Relationship#getRelationshipStatus()} method. | |||
| */ | |||
| @Test | |||
| public void testGetRelationshipStatus() { | |||
| // Very Negative | |||
| setRelationshipStrength(r1, -10); | |||
| assertEquals("Very Negative", r1.getRelationshipStatus()); | |||
| setRelationshipStrength(r1, -7); | |||
| assertEquals("Very Negative", r1.getRelationshipStatus()); | |||
| // Negative | |||
| setRelationshipStrength(r1, -6); | |||
| assertEquals("Negative", r1.getRelationshipStatus()); | |||
| setRelationshipStrength(r1, -3); | |||
| assertEquals("Negative", r1.getRelationshipStatus()); | |||
| // Neutral | |||
| setRelationshipStrength(r1, -2); | |||
| assertEquals("Neutral", r1.getRelationshipStatus()); | |||
| setRelationshipStrength(r1, 2); | |||
| assertEquals("Neutral", r1.getRelationshipStatus()); | |||
| // Positive | |||
| setRelationshipStrength(r1, 3); | |||
| assertEquals("Positive", r1.getRelationshipStatus()); | |||
| setRelationshipStrength(r1, 6); | |||
| assertEquals("Positive", r1.getRelationshipStatus()); | |||
| // Very Positive | |||
| setRelationshipStrength(r1, 7); | |||
| assertEquals("Very Positive", r1.getRelationshipStatus()); | |||
| setRelationshipStrength(r1, 10); | |||
| assertEquals("Very Positive", r1.getRelationshipStatus()); | |||
| } | |||
| /** | |||
| * Increases/decreases a relationship's strength to match a certain level. | |||
| * | |||
| * @param rel Relationship to modify | |||
| * @param str New strength level | |||
| */ | |||
| private void setRelationshipStrength(Relationship rel, int str) { | |||
| int currentStr = rel.getRelationshipStrength(); | |||
| int adjustment = str - currentStr; | |||
| if (adjustment < 0) { | |||
| for (int i = 0; i < Math.abs(adjustment); i++) { | |||
| rel.decreaseRelationship(); | |||
| } | |||
| } else { | |||
| for (int i = 0; i < adjustment; i++) { | |||
| rel.increaseRelationship(); | |||
| } | |||
| } | |||
| } | |||
| } | |||