Rename year directories to allow natural ordering
This commit is contained in:
Binary file not shown.
38
year3/semester1/CT326: Programming III/assignments/assignment2/assignment2/.gitignore
vendored
Normal file
38
year3/semester1/CT326: Programming III/assignments/assignment2/assignment2/.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
3
year3/semester1/CT326: Programming III/assignments/assignment2/assignment2/.idea/.gitignore
generated
vendored
Normal file
3
year3/semester1/CT326: Programming III/assignments/assignment2/assignment2/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
1
year3/semester1/CT326: Programming III/assignments/assignment2/assignment2/.idea/.name
generated
Normal file
1
year3/semester1/CT326: Programming III/assignments/assignment2/assignment2/.idea/.name
generated
Normal file
@ -0,0 +1 @@
|
||||
assignment2
|
7
year3/semester1/CT326: Programming III/assignments/assignment2/assignment2/.idea/encodings.xml
generated
Normal file
7
year3/semester1/CT326: Programming III/assignments/assignment2/assignment2/.idea/encodings.xml
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
13
year3/semester1/CT326: Programming III/assignments/assignment2/assignment2/.idea/misc.xml
generated
Normal file
13
year3/semester1/CT326: Programming III/assignments/assignment2/assignment2/.idea/misc.xml
generated
Normal file
@ -0,0 +1,13 @@
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
Binary file not shown.
After Width: | Height: | Size: 85 KiB |
Binary file not shown.
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>assignment2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -0,0 +1,138 @@
|
||||
// Name: Andrew Hayes
|
||||
// ID Number: 21321503
|
||||
import java.time.LocalDate;
|
||||
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.Money;
|
||||
|
||||
public class Expense {
|
||||
private LocalDate date;
|
||||
private String description;
|
||||
private ExpenseCategory category;
|
||||
private Money amount;
|
||||
private boolean approved; // defaults to false
|
||||
|
||||
/**
|
||||
* constructor that does not take the boolean "approved" - this should be set later
|
||||
* @param date
|
||||
* @param description
|
||||
* @param category
|
||||
* @param amount
|
||||
*/
|
||||
public Expense(LocalDate date, String description, ExpenseCategory category, Money amount) {
|
||||
this.date = date;
|
||||
this.description = description;
|
||||
this.category = category;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* constructor that takes the boolean "approved" in case you want to override it defaulting to false
|
||||
* @param date
|
||||
* @param description
|
||||
* @param category
|
||||
* @param amount
|
||||
* @param approved
|
||||
*/
|
||||
public Expense(LocalDate date, String description, ExpenseCategory category, Money amount, boolean approved) {
|
||||
this.date = date;
|
||||
this.description = description;
|
||||
this.category = category;
|
||||
this.amount = amount;
|
||||
this.approved = approved;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return date
|
||||
*/
|
||||
public LocalDate getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param date
|
||||
*/
|
||||
public void setDate(LocalDate date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param description
|
||||
*/
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return category
|
||||
*/
|
||||
public ExpenseCategory getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param category
|
||||
*/
|
||||
public void setCategory(ExpenseCategory category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return amount
|
||||
*/
|
||||
public Money getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param amount
|
||||
*/
|
||||
public void setAmount(Money amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* method to return the currency unit of the amount
|
||||
* @return the CurrencyUnit of the amount
|
||||
*/
|
||||
public CurrencyUnit getAmountCurrency() { return amount.getCurrencyUnit(); }
|
||||
|
||||
/**
|
||||
*
|
||||
* @return isApproved
|
||||
*/
|
||||
public boolean isApproved() {
|
||||
return approved;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param approved
|
||||
*/
|
||||
public void setApproved(boolean approved) {
|
||||
this.approved = approved;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"%s: %s - %s - %s %.2f", date.toString(), description, category, amount.getCurrencyUnit(), amount.getAmount().doubleValue()
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
// Name: Andrew Hayes
|
||||
// ID Number: 21321503
|
||||
public enum ExpenseCategory {
|
||||
TRAVEL_AND_SUBSISTENCE,
|
||||
SUPPLIES,
|
||||
ENTERTAINMENT,
|
||||
EQUIPMENT,
|
||||
OTHER
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
// Name: Andrew Hayes
|
||||
// ID Number: 21321503
|
||||
import java.util.ArrayList;
|
||||
|
||||
public interface ExpensePrinter {
|
||||
|
||||
/**
|
||||
* method to print the expenses
|
||||
* @param expenses
|
||||
*/
|
||||
public void print(ArrayList<Expense> expenses);
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
// Name: Andrew Hayes
|
||||
// ID Number: 21321503
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.IllegalCurrencyException;
|
||||
import org.joda.money.Money;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ExpensesPortal {
|
||||
private ArrayList<Expense> expenses = new ArrayList<Expense>();
|
||||
|
||||
/**
|
||||
* main method
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
ExpensesPortal ep = new ExpensesPortal();
|
||||
|
||||
// create sample expenses
|
||||
ep.addExpense(new Expense(LocalDate.of(2022, 9, 23), "FLight to Glasgow", ExpenseCategory.TRAVEL_AND_SUBSISTENCE, Money.parse("EUR 270.59")));
|
||||
ep.addExpense(new Expense(LocalDate.of(2022, 9, 23), "FLight to Dublin", ExpenseCategory.TRAVEL_AND_SUBSISTENCE, Money.parse("EUR 271.59")));
|
||||
ep.addExpense(new Expense(LocalDate.of(2022, 9, 20), "Dell 17-inch monitor", ExpenseCategory.EQUIPMENT, Money.parse("USD 540.00")));
|
||||
ep.addExpense(new Expense(LocalDate.of(2022, 9, 20), "Logitech Mouse", ExpenseCategory.EQUIPMENT, Money.parse("USD 40.00")));
|
||||
ep.addExpense(new Expense(LocalDate.of(2022, 9, 21), "Java for Dummies", ExpenseCategory.OTHER, Money.parse("EUR 17.99")));
|
||||
ep.addExpense(new Expense(LocalDate.of(2022, 9, 21), "Dinner", ExpenseCategory.OTHER, Money.parse("EUR 20.99")));
|
||||
ep.addExpense(new Expense(LocalDate.of(2022, 9, 21), "Whiteboard Marker", ExpenseCategory.SUPPLIES, Money.parse("EUR 4.99")));
|
||||
|
||||
// call the printExpenses method using a lambda expression to implement the ExpensePrinter parameter
|
||||
ep.printExpenses(expenses -> {
|
||||
for (Expense expense : expenses) {
|
||||
System.out.println(expense);
|
||||
}
|
||||
});
|
||||
System.out.printf("%n");
|
||||
|
||||
// call the printExpenses method using an anonymous inner class to implement the ExpensePrinter parameter
|
||||
ep.printExpenses(new ExpensePrinter() {
|
||||
/**
|
||||
* method to print a summary of the expenses
|
||||
* @param expenses
|
||||
*/
|
||||
@Override
|
||||
public void print(ArrayList<Expense> expenses) {
|
||||
System.out.println("There are " + expenses.toArray().length + " expenses in the system totalling to a value of " + sumExpenses(expenses));
|
||||
}
|
||||
});
|
||||
System.out.printf("%n");
|
||||
|
||||
// call the printExpense method using a PrinterByLabel instance as a parameter
|
||||
ep.printExpenses(new PrinterByLabel());
|
||||
}
|
||||
|
||||
/**
|
||||
* method to submit a new expense
|
||||
* @param expense
|
||||
*/
|
||||
public void addExpense(Expense expense) {
|
||||
expenses.add(expense);
|
||||
}
|
||||
|
||||
/**
|
||||
* method to print expenses
|
||||
* @param printer
|
||||
*/
|
||||
public void printExpenses(ExpensePrinter printer) {
|
||||
printer.print(expenses);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* method for summing the expenses that supports both EUR & USD
|
||||
* @param expenses
|
||||
* @return
|
||||
* @throws IllegalCurrencyException
|
||||
*/
|
||||
public static Money sumExpenses(ArrayList<Expense> expenses) throws IllegalCurrencyException {
|
||||
Money total = Money.parse("EUR 0");
|
||||
BigDecimal USDToEURConversionRate = BigDecimal.valueOf(0.95); // hardcoded conversion rate as of 2023-10-04 - clearly not ideal, but as a proof of concept
|
||||
|
||||
for (Expense expense : expenses) {
|
||||
// if currency is usd, converting to euro and adding to total
|
||||
if (expense.getAmountCurrency().equals(CurrencyUnit.of("USD"))) {
|
||||
total = total.plus(expense.getAmount().convertedTo(CurrencyUnit.EUR, USDToEURConversionRate, RoundingMode.HALF_UP));
|
||||
}
|
||||
// checking that the currency is of type euro before adding to total
|
||||
else if (expense.getAmountCurrency().equals(CurrencyUnit.of("EUR"))) {
|
||||
total = total.plus(expense.getAmount());
|
||||
}
|
||||
else {
|
||||
throw new IllegalCurrencyException("CurrencyUnity " + expense.getAmountCurrency() + " is not supported! USD or EUR only");
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
// Name: Andrew Hayes
|
||||
// ID Number: 21321503
|
||||
import java.util.ArrayList;
|
||||
//import java.util.Collections; // for use in commented out algorithm -- see below
|
||||
//import java.util.Comparator;
|
||||
|
||||
public class PrinterByLabel implements ExpensePrinter {
|
||||
/**
|
||||
* method to print all the expenses, grouped by category
|
||||
* @param expenses
|
||||
*/
|
||||
@Override
|
||||
public void print(ArrayList<Expense> expenses) {
|
||||
ExpenseCategory[] categories = ExpenseCategory.values();
|
||||
|
||||
for (ExpenseCategory category : categories) {
|
||||
System.out.println(category + ":");
|
||||
|
||||
for (Expense expense : expenses) {
|
||||
// printing out expense only if it's in the current category
|
||||
if (expense.getCategory().equals(category)) {
|
||||
System.out.println(expense);
|
||||
}
|
||||
}
|
||||
System.out.printf("%n");
|
||||
}
|
||||
|
||||
// below is a commented-out alternative to the above algorithm that doesn't match the output in the design spec
|
||||
// it doesn't print out every expense category as a title, just the ones that have an existing expense in the system
|
||||
// this allows the sorting to be done nicely using the enum, and allows the enum to be expanded or contracted without changing other code
|
||||
// this allows for slightly nicer sorting and does not print out categories which do not have extant expenses in them, which may or may not be desirable
|
||||
|
||||
// // sorting the ArrayList by category
|
||||
// Collections.sort(expenses, Comparator.comparing(Expense::getCategory));
|
||||
//
|
||||
// // variable to keep track of what category the last printed expense was so that a heading can be printed once and only once for each category
|
||||
// ExpenseCategory lastCategory = null;
|
||||
//
|
||||
// for (Expense expense : expenses) {
|
||||
// // if the current expense's category is different to the last, print it out as a heading
|
||||
// if (expense.getCategory() != lastCategory) {
|
||||
// System.out.println(expense.getCategory());
|
||||
// lastCategory = expense.getCategory();
|
||||
// }
|
||||
// System.out.println(expense);
|
||||
// }
|
||||
}
|
||||
}
|
Binary file not shown.
Reference in New Issue
Block a user