diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f7896d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/README.md b/README.md index 2cae075..a20c7a6 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -Branch test \ No newline at end of file +Branch test 3 \ No newline at end of file diff --git a/src/main/java/Exchange.java b/src/main/java/Exchange.java new file mode 100644 index 0000000..afbde59 --- /dev/null +++ b/src/main/java/Exchange.java @@ -0,0 +1,114 @@ +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +public class Exchange { + + private final String name; + private int week; + private final Map stockMap; + private final Random random; + + public Exchange(String name, List stocks) { + this.name = name; + this.week = 1; + this.stockMap = new HashMap<>(); + this.random = new Random(); + + for (Stock stock : stocks) { + stockMap.put(stock.getSymbol(), stock); + } + + } + + public String getName() { + return name; + } + + public int getWeek() { + return week; + } + + public boolean hasStock(String symbol) { + return stockMap.containsKey(symbol); + } + + public Stock getStock(String symbol) { + return stockMap.get(symbol); + } + + public List findStocks(String searchTerm) { + List result = new ArrayList<>(); + String lowerSearch = searchTerm.toLowerCase(); + + for (Stock stock : stockMap.values()) { + if (stock.getSymbol().toLowerCase().contains(lowerSearch) + || stock.getCompany().toLowerCase().contains(lowerSearch)) { + result.add(stock); + } + } + + return result; + } + + public Transaction buy(String symbol, BigDecimal quantity, Player player) { + Stock stock = getStock(symbol); + + // unngå nullpointerexception + if (stock == null) { + return null; + } + + // lager en ny "andel" basert på nåværende salgspris + Share shareToBuy = new Share(stock, quantity, stock.getSalesPrice()); + + // oppretter kjøpstransaksjonen for den uka + Purchase purchase = new Purchase(shareToBuy, this.week); + + // committer til player + purchase.commit(player); + + return purchase; + } + + public Transaction sell(Share share, Player player) { + // unngå nullpointerexception + if (share == null) { + return null; + } + + // oppretter salgstransaksjonen for den uka + Sale sale = new Sale(share, this.week); + + // commiter til player + sale.commit(player); + + return sale; + } + + public void advance() { + + week++; + + for (Stock stock : stockMap.values()) { // henter stock-objektene + + BigDecimal currentPrice = stock.getSalesPrice(); // henter siste pris fra Stock + + double changePercent = (random.nextDouble() - 0.5) * 0.1; + + BigDecimal change = currentPrice.multiply(BigDecimal.valueOf(changePercent)); + + BigDecimal newPrice = currentPrice.add(change); + + if (newPrice.compareTo(BigDecimal.ZERO) > 0) { // unngå negativ pris + stock.addNewSalesPrice(newPrice); + } + } + } + + + +} diff --git a/src/main/java/Player.java b/src/main/java/Player.java new file mode 100644 index 0000000..59b4f72 --- /dev/null +++ b/src/main/java/Player.java @@ -0,0 +1,43 @@ +import java.math.BigDecimal; + +public class Player { + private String name; + private BigDecimal startingMoney; + private BigDecimal money; + private Portfolio portfolio; + private TransactionArchive transactionArchive; + + public Player(String name, BigDecimal startingMoney) { + this.name = name; + this.startingMoney = startingMoney; + this.money = startingMoney; + this.portfolio = new Portfolio(); + this.transactionArchive = new TransactionArchive(); + } + + public String getName() { + return this.name; + } + + public BigDecimal getMoney() { + return this.money; + } + + public void addMoney(BigDecimal amount) { + this.money = this.money.add(amount); + } + + public void withdrawMoney(BigDecimal amount) { + this.money = this.money.subtract(amount); + } + + public Portfolio getPortfolio() { + return this.portfolio; + } + + public TransactionArchive getTransactionArchive() { + return this.transactionArchive; + } + + +} diff --git a/src/main/java/Portfolio.java b/src/main/java/Portfolio.java new file mode 100644 index 0000000..a25561f --- /dev/null +++ b/src/main/java/Portfolio.java @@ -0,0 +1,38 @@ +import java.util.ArrayList; +import java.util.List; + +public class Portfolio { + + private final List shares; + + public Portfolio() { + this.shares = new ArrayList<>(); + } + + public boolean addShare(Share share) { + return shares.add(share); + } + + public boolean removeShare(Share share) { + return shares.remove(share); + } + + public List getShares() { + return new ArrayList<>(shares); + } + + public List getShares(String symbol) { + List result = new ArrayList<>(); + for (Share share : shares) { + if (share.getStock().getSymbol().equals(symbol)) { + result.add(share); + } + } + return result; + } + + public boolean contains(Share share) { + return shares.contains(share); + } + +} diff --git a/src/main/java/Purchase.java b/src/main/java/Purchase.java new file mode 100644 index 0000000..67b1049 --- /dev/null +++ b/src/main/java/Purchase.java @@ -0,0 +1,22 @@ +import java.math.BigDecimal; + +public class Purchase extends Transaction { + public Purchase(Share share, int week) { + super(share, week, new PurchaseCalculator(share)); + } + + @Override + public void commit(Player player) { + BigDecimal price = this.getCalculator().calculateTotal(); + + if (isCommitted() || (player.getMoney().compareTo(price) < 0)) { + return; + } + + player.withdrawMoney(price); + player.getPortfolio().addShare(this.getShare()); + player.getTransactionArchive().add(this); + + this.committed = true; + } +} diff --git a/src/main/java/PurchaseCalculator.java b/src/main/java/PurchaseCalculator.java new file mode 100644 index 0000000..78f8e90 --- /dev/null +++ b/src/main/java/PurchaseCalculator.java @@ -0,0 +1,29 @@ +import java.math.BigDecimal; + +public class PurchaseCalculator implements TransactionCalculator { + private BigDecimal purchasePrice; + private BigDecimal quantity; + + public PurchaseCalculator(Share share) { + this.purchasePrice = share.getPurchasePrice(); + this.quantity = share.getQuantity(); + } + + public BigDecimal calculateGross() { + return this.purchasePrice.multiply(this.quantity); + } + + public BigDecimal calculateCommission() { + BigDecimal rate = new BigDecimal("0.005"); + return calculateGross().multiply(rate); + } + + public BigDecimal calculateTax() { + BigDecimal tax = new BigDecimal("0"); + return tax; + } + + public BigDecimal calculateTotal() { + return calculateGross().add(calculateCommission()).add(calculateTax()); + } +} diff --git a/src/main/java/Sale.java b/src/main/java/Sale.java new file mode 100644 index 0000000..7a3efc2 --- /dev/null +++ b/src/main/java/Sale.java @@ -0,0 +1,21 @@ +import java.math.BigDecimal; + +public class Sale extends Transaction { + public Sale(Share share, int week) { + super(share, week, new SaleCalculator(share)); + } + + public void commit(Player player) { + BigDecimal price = getCalculator().calculateTotal(); + + if (isCommitted() || !player.getPortfolio().contains(this.getShare())) { + return; + } + + player.addMoney(price); + player.getPortfolio().removeShare(this.getShare()); + player.getTransactionArchive().add(this); + + this.committed = true; + } +} diff --git a/src/main/java/SaleCalculator.java b/src/main/java/SaleCalculator.java new file mode 100644 index 0000000..f868729 --- /dev/null +++ b/src/main/java/SaleCalculator.java @@ -0,0 +1,36 @@ +import java.math.BigDecimal; + +public class SaleCalculator implements TransactionCalculator{ + private BigDecimal purchasePrice; + private BigDecimal salesPrice; + private BigDecimal quantity; + + public SaleCalculator(Share share) { + this.purchasePrice = share.getPurchasePrice(); + this.salesPrice = share.getStock().getSalesPrice(); + this.quantity = share.getQuantity(); + } + + public BigDecimal calculateGross() { + return this.salesPrice.multiply(this.quantity); + } + + public BigDecimal calculateCommission() { + BigDecimal rate = new BigDecimal("0.01"); + return calculateGross().multiply(rate); + } + + public BigDecimal calculateTax() { + BigDecimal sellingCost = this.purchasePrice.multiply(this.quantity); + BigDecimal profit = calculateGross().subtract(calculateCommission()).subtract(sellingCost); + BigDecimal rate = new BigDecimal("0.3"); + return profit.multiply(rate); + } + + public BigDecimal calculateTotal() { + return calculateGross().subtract(calculateCommission()).subtract(calculateTax()); + } + + + +} diff --git a/src/main/java/Share.java b/src/main/java/Share.java new file mode 100644 index 0000000..0ab76b5 --- /dev/null +++ b/src/main/java/Share.java @@ -0,0 +1,27 @@ +import java.math.BigDecimal; + +public class Share { + + private final Stock stock; + private final BigDecimal quantity; + private final BigDecimal purchasePrice; + + public Share(Stock stock, BigDecimal quantity, BigDecimal purchasePrice) { + this.stock = stock; + this.quantity = quantity; + this.purchasePrice = purchasePrice; + } + + public Stock getStock() { + return stock; + } + + public BigDecimal getQuantity() { + return quantity; + } + + public BigDecimal getPurchasePrice() { + return purchasePrice; + } + +} diff --git a/src/main/java/Stock.java b/src/main/java/Stock.java new file mode 100644 index 0000000..e650b01 --- /dev/null +++ b/src/main/java/Stock.java @@ -0,0 +1,33 @@ +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +public class Stock { + + private final String symbol; + private final String company; + private final List prices; + + public Stock(String symbol, String company, BigDecimal salesPrice) { + this.symbol = symbol; + this.company = company; + this.prices = new ArrayList<>(); + this.prices.add(salesPrice); + } + + public String getSymbol() { + return symbol; + } + + public String getCompany() { + return company; + } + + public BigDecimal getSalesPrice() { + return prices.get(prices.size() - 1); + } + + public void addNewSalesPrice(BigDecimal price) { + prices.add(price); + } +} diff --git a/src/main/java/Transaction.java b/src/main/java/Transaction.java new file mode 100644 index 0000000..18d07ed --- /dev/null +++ b/src/main/java/Transaction.java @@ -0,0 +1,31 @@ +public abstract class Transaction { + private Share share; + private int week; + private TransactionCalculator calculator; + protected boolean committed; + + protected Transaction(Share share, int week, TransactionCalculator calculator) { + this.share = share; + this.week = week; + this.calculator = calculator; + } + + public Share getShare() { + return this.share; + } + + public int getWeek() { + return this.week; + } + + public TransactionCalculator getCalculator() { + return this.calculator; + } + + public boolean isCommitted() { + return this.committed; + } + + public abstract void commit(Player player); + +} diff --git a/src/main/java/TransactionArchive.java b/src/main/java/TransactionArchive.java new file mode 100644 index 0000000..6d86d71 --- /dev/null +++ b/src/main/java/TransactionArchive.java @@ -0,0 +1,40 @@ +import java.util.ArrayList; +import java.util.stream.Collectors; +import java.util.List; + +public class TransactionArchive { + private List transactions; + + public TransactionArchive() { + this.transactions = new ArrayList<>(); + } + + public boolean add(Transaction transaction) { + if (transaction == null) { + throw new IllegalArgumentException("Should not be null"); // Eller NullPointerExeption? + } + + return transactions.add(transaction); + + } + + public boolean isEmpty() { + return transactions.isEmpty(); + } + + public List getTransactions(int week) { + return transactions.stream().filter(transaction -> transaction.getWeek() == week).collect(Collectors.toList()); + } + + public List getPurchase(int week) { + return transactions.stream().filter(transaction -> transaction.getWeek() == week).filter(purchase -> transactions instanceof Purchase).map(transaction -> (Purchase) transaction).collect(Collectors.toList()); + } + + public List getSale(int week) { + return transactions.stream().filter(transaction -> transaction.getWeek() == week).filter(sale -> transactions instanceof Sale).map(transaction -> (Sale) transaction).collect(Collectors.toList()); + } + + public int countDistinctWeeks() { + return (int) transactions.stream().map(Transaction::getWeek).distinct().count(); + } +} diff --git a/src/main/java/TransactionCalculator.java b/src/main/java/TransactionCalculator.java new file mode 100644 index 0000000..0bafc6e --- /dev/null +++ b/src/main/java/TransactionCalculator.java @@ -0,0 +1,10 @@ +import java.math.BigDecimal; + +public interface TransactionCalculator { + // Methods in interface is automatically public abstract. + BigDecimal calculateGross(); + BigDecimal calculateCommission(); + BigDecimal calculateTax(); + BigDecimal calculateTotal(); +} + diff --git a/src/test/java/ExchangeTest.java b/src/test/java/ExchangeTest.java new file mode 100644 index 0000000..eb3ad47 --- /dev/null +++ b/src/test/java/ExchangeTest.java @@ -0,0 +1,49 @@ +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +public class ExchangeTest { + + private Exchange exchange; + private Stock apple; + private Stock google; + + @BeforeAll + public void setUp() { + apple = new Stock("AAPL", "Apple", new BigDecimal("100")); + google = new Stock("GOOGL", "Google", new BigDecimal("200")); + + List stocks = new ArrayList<>(); + stocks.add(apple); + stocks.add(google); + + exchange = new Exchange("ABC", stocks); + } + + @Test + public void testFindStocksBySymbol() { + List result = exchange.findStocks("AAPL"); + + assertEquals(1, result.size()); + assertEquals("AAPL", result.get(0).getSymbol()); + } + + @Test + public void testFindStocksByCompanyNames() { + List result = exchange.findStocks("e"); + + assertEquals(2, result.size()); + } + + @Test + public void testFindStocksNotInList() { + List result = exchange.findStocks("Samsung"); + + assertEquals(0, result.size()); + } + +} diff --git a/src/test/java/PortfolioTest.java b/src/test/java/PortfolioTest.java new file mode 100644 index 0000000..36f7419 --- /dev/null +++ b/src/test/java/PortfolioTest.java @@ -0,0 +1,83 @@ +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import java.math.BigDecimal; + +public class PortfolioTest { + + @Test + void testAddSharePortfolio() { + Portfolio portfolio = new Portfolio(); + + Stock stock = new Stock("AAPL", "Apple", new BigDecimal("150")); + Share share = new Share(stock, new BigDecimal("10"), new BigDecimal("140")); + + boolean result = portfolio.addShare(share); + + assertTrue(result); + assertTrue(portfolio.contains(share)); + } + + @Test + void testRemoveSharePortfolio() { + Portfolio portfolio = new Portfolio(); + + Stock stock = new Stock("AAPL", "Apple", new BigDecimal("150")); + Share share = new Share(stock, new BigDecimal("10"), new BigDecimal("140")); + + portfolio.addShare(share); + + boolean result = portfolio.removeShare(share); + + assertTrue(result); + assertFalse(portfolio.contains(share)); + } + + @Test + void testGetSharesPortfolio() { + Portfolio portfolio = new Portfolio(); + + Stock stock = new Stock("AAPL", "Apple", new BigDecimal("150")); + Share share = new Share(stock, new BigDecimal("10"), new BigDecimal("140")); + + portfolio.addShare(share); + + var shares = portfolio.getShares(); + + assertEquals(1, shares.size()); + assertTrue(shares.contains(share)); + } + + @Test + void testGetSharesBySymbolPortfolio() { + Portfolio portfolio = new Portfolio(); + + Stock stock1 = new Stock("AAPL", "Apple", new BigDecimal("150")); + Stock stock2 = new Stock("GOOGL", "Google", new BigDecimal("200")); + + Share share1 = new Share(stock1, new BigDecimal("10"), new BigDecimal("140")); + Share share2 = new Share(stock2, new BigDecimal("10"), new BigDecimal("190")); + + portfolio.addShare(share1); + portfolio.addShare(share2); + + var result = portfolio.getShares("AAPL"); + + assertEquals(1, result.size()); + assertTrue(result.contains(share1)); + } + + @Test + void testContainsPortfolio() { + Portfolio portfolio = new Portfolio(); + + Stock stock = new Stock("AAPL", "Apple", new BigDecimal("150")); + Share share = new Share(stock, new BigDecimal("10"), new BigDecimal("140")); + + portfolio.addShare(share); + + assertTrue(portfolio.contains(share)); + } + + +} diff --git a/src/test/java/ShareTest.java b/src/test/java/ShareTest.java new file mode 100644 index 0000000..ba6dc76 --- /dev/null +++ b/src/test/java/ShareTest.java @@ -0,0 +1,71 @@ +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import java.math.BigDecimal; + + +public class ShareTest { + + @Test + void testShareConstructor() { + + Stock stock = new Stock("AAPL", "Apple", new BigDecimal("150")); + BigDecimal quantity = new BigDecimal("10"); + BigDecimal purchasePrice = new BigDecimal("140"); + + Share share = new Share(stock, quantity, purchasePrice); + assertNotNull(share); + } + + @Test + void testGetStock() { + + Stock stock = new Stock("AAPL", "Apple", new BigDecimal("150")); + Share share = new Share(stock, new BigDecimal("10"), new BigDecimal("140")); + + Stock result = share.getStock(); + + assertEquals(stock, result); + } + + @Test + void testGetQuantity() { + + Stock stock = new Stock("AAPL", "Apple", new BigDecimal("150")); + Share share = new Share(stock, new BigDecimal("10"), new BigDecimal("140")); + + BigDecimal result = share.getQuantity(); + + assertEquals(new BigDecimal("10"), result); + } + + @Test + void testGetPurchasePrice() { + + Stock stock = new Stock("AAPL", "Apple", new BigDecimal("150")); + Share share = new Share(stock, new BigDecimal("10"), new BigDecimal("140")); + + BigDecimal result = share.getPurchasePrice(); + + assertEquals(new BigDecimal("140"), result); + } + + @Test + void testNullStock() { + + Share share = new Share(null, new BigDecimal("10"), new BigDecimal("100")); + + assertNull(share.getStock()); + } + + @Test + void testNegativePrice() { + + Stock stock = new Stock("AAPL", "Apple", new BigDecimal("150")); + Share share = new Share(stock, new BigDecimal("10"), new BigDecimal("-50")); + + assertEquals(new BigDecimal("-50"), share.getPurchasePrice()); + } + + +} diff --git a/src/test/java/StockTest.java b/src/test/java/StockTest.java new file mode 100644 index 0000000..1bfcc2a --- /dev/null +++ b/src/test/java/StockTest.java @@ -0,0 +1,36 @@ +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +import java.math.BigDecimal; + + +public class StockTest { + + @Test + public void testGetSalesPrice() { + Stock stock = new Stock("AAPL", "APPLE", new BigDecimal("1000")); + assertEquals(new BigDecimal("1000"), stock.getSalesPrice()); + } + + @Test + public void testAddNewSalesPrice() { + Stock stock = new Stock("AAPL", "APPLE", new BigDecimal("1000")); + stock.addNewSalesPrice(new BigDecimal("1200")); + assertEquals(new BigDecimal("1200"), stock.getSalesPrice()); + } + + @Test + public void testGetSalesPriceNone() { + Stock stock = new Stock("AAPL", "APPLE", new BigDecimal("0")); + assertEquals(new BigDecimal("0"), stock.getSalesPrice()); + } + + @Test + public void testAddNewSalesPriceNone() { + Stock stock = new Stock("AAPL", "APPLE", new BigDecimal("1000")); + stock.addNewSalesPrice(new BigDecimal("0")); + assertEquals(new BigDecimal("0"), stock.getSalesPrice()); + } + + +} diff --git a/target/classes/Exchange.class b/target/classes/Exchange.class new file mode 100644 index 0000000..dde00a7 Binary files /dev/null and b/target/classes/Exchange.class differ diff --git a/target/classes/Portfolio.class b/target/classes/Portfolio.class new file mode 100644 index 0000000..2dc1492 Binary files /dev/null and b/target/classes/Portfolio.class differ diff --git a/target/classes/PurchaseCalculator.class b/target/classes/PurchaseCalculator.class new file mode 100644 index 0000000..bab65f2 Binary files /dev/null and b/target/classes/PurchaseCalculator.class differ diff --git a/target/classes/Share.class b/target/classes/Share.class new file mode 100644 index 0000000..9e7f4f9 Binary files /dev/null and b/target/classes/Share.class differ diff --git a/target/classes/Stock.class b/target/classes/Stock.class new file mode 100644 index 0000000..af494f4 Binary files /dev/null and b/target/classes/Stock.class differ diff --git a/target/classes/TransactionCalculator.class b/target/classes/TransactionCalculator.class new file mode 100644 index 0000000..47f318a Binary files /dev/null and b/target/classes/TransactionCalculator.class differ diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 0000000..e69de29 diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..69de3f4 --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,5 @@ +C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Exchange.java +C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Portfolio.java +C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Share.java +C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Stock.java +C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\TransactionCalculator.java