diff --git a/kont2020/src/main/java/food/Customer.java b/kont2020/src/main/java/food/Customer.java
index 084ce320e2ba6654ff3a7626470a7ac6d8a6f0d3..4b16c92f6a00a4348f19826deb3961b6e4d187f4 100644
--- a/kont2020/src/main/java/food/Customer.java
+++ b/kont2020/src/main/java/food/Customer.java
@@ -1,6 +1,8 @@
 package food;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 
 import food.def.ICustomer;
 
@@ -8,6 +10,8 @@ public class Customer implements ICustomer {
 
 
 	// Add internal variables here:
+	private String name;
+	private List<MealOrder> orders; 
 	
 	
 	/**
@@ -16,6 +20,8 @@ public class Customer implements ICustomer {
 	 * @param name The name of the customer
 	 */
 	public Customer(String name) {
+		orders = new ArrayList<>();
+		this.name = name;
 	}
 	
 	
@@ -24,7 +30,7 @@ public class Customer implements ICustomer {
 	 * @return A list containing all meals bought by this customer
 	 */
 	public Collection<MealOrder> getMealsOrdered() {
-		return null; // Dummy return value
+		return new ArrayList<>(orders); 
 	}
 
 	/**
@@ -35,6 +41,7 @@ public class Customer implements ICustomer {
 	 */
 	@Override
 	public void buyMeal(String meal, double price) {
+		orders.add(new MealOrder(meal, price));
 	}
 	
 	
@@ -43,7 +50,7 @@ public class Customer implements ICustomer {
 	 */
 	@Override
 	public int getNumberOfOrderedMeals() {
-		return 0; // Dummy return value
+		return orders.size();
 	}
 	
 	/**
@@ -51,7 +58,7 @@ public class Customer implements ICustomer {
 	 */
 	@Override
 	public String getName() {
-		return null; // Dummy return value
+		return name;
 	}
 
 	/**
@@ -59,7 +66,7 @@ public class Customer implements ICustomer {
 	 */
 	@Override
 	public String toString() {
-		return null; // dummy return value
+		return name + ": " + Integer.toString(getNumberOfOrderedMeals());
 	}
 
 	/**
@@ -68,7 +75,10 @@ public class Customer implements ICustomer {
 	 */
 	@Override
 	public MealOrder getLastOrderedMeal() {
-		return null; // Dummy return value
+		if (getNumberOfOrderedMeals() == 0) {
+			return null;
+		}
+		return orders.get(orders.size() - 1);
 	}
 	
 	/**
@@ -80,7 +90,7 @@ public class Customer implements ICustomer {
 	 */
 	@Override
 	public int timesEaten(String meal) {
-		return 0; // Dummy return value
+		return (int)(orders.stream().filter(m -> m.getMeal().equals(meal)).count()); // Can easily be done by a for-loop as well
 	}
 	
 	public static void main(String[] args) {
@@ -88,6 +98,6 @@ public class Customer implements ICustomer {
 		customer.buyMeal("pancakes", 100);
 		customer.buyMeal("pancakes", 75);
 		System.out.println("Skal være 2 kjøp: " + customer.getMealsOrdered().size());
-//		System.out.println("Skal være pris 75: " + customer.getLastOrderedMeal().getPrice()); // Som definert i README.
+		System.out.println("Skal være pris 75: " + customer.getLastOrderedMeal().getPrice()); // Som definert i README.
 	}
 }
diff --git a/kont2020/src/main/java/food/Kitchen.java b/kont2020/src/main/java/food/Kitchen.java
index dfd14d53bc7f7b97e828fe178e825e2ff229984e..89f865813a39733985ce4c806624846fc682198e 100644
--- a/kont2020/src/main/java/food/Kitchen.java
+++ b/kont2020/src/main/java/food/Kitchen.java
@@ -1,5 +1,6 @@
 package food;
 
+import java.util.ArrayList;
 import java.util.Collection;
 
 import food.def.IKitchen;
@@ -10,9 +11,21 @@ import food.def.PriceProvider;
 public class Kitchen implements IKitchen {
 
 	// Add internal variables here:
+	private Collection<String> recipes;
+	private Collection<Customer> customers;
+	
+	private Collection<PriceProvider> priceProviders;
+	private Collection<KitchenObserver> observers;
+
+	private double turnover;
 	
 	public Kitchen() {
 		super();
+		recipes = new ArrayList<>();
+		customers = new ArrayList<>();
+		priceProviders = new ArrayList<>();
+		observers = new ArrayList<>();
+		turnover = 0;
 	}
 	
 	
@@ -24,6 +37,8 @@ public class Kitchen implements IKitchen {
 	 */
 	@Override
 	public void addCustomer(Customer customer) {
+		if (customers.contains(customer)) throw new IllegalArgumentException("Customer already registered");
+		customers.add(customer);
 	}
 
 	/**
@@ -32,6 +47,7 @@ public class Kitchen implements IKitchen {
 	 */
 	@Override
 	public void addRecipe(String recipe) {
+		recipes.add(recipe);
 	}
 	
 	/**
@@ -41,7 +57,7 @@ public class Kitchen implements IKitchen {
 	 */
 	@Override
 	public double getTurnover() {
-		return 0; // Dummy return value
+		return turnover;
 	}
 
 	
@@ -50,7 +66,7 @@ public class Kitchen implements IKitchen {
 	 */
 	@Override
 	public Collection<String> getRecipes() {
-		return null; // Dummy return value
+		return new ArrayList<>(recipes);
 	}
 	
 	/**
@@ -59,8 +75,11 @@ public class Kitchen implements IKitchen {
 	 * @return The customer with the given name, or null if no such customer is registered
 	 */
 	public Customer getCustomer(String name) {
-		return null; // dummy return value
-	}
+		return customers.stream()
+				.filter(c -> c.getName().equals(name))
+				.findAny()
+				.orElse(null);
+	} // A nice exercise would be to make this with a for loop instead.
 
 	/**
 	 * Make a meal, with a given (standard)price and to a given customer.
@@ -78,11 +97,22 @@ public class Kitchen implements IKitchen {
 	 */
 	@Override
 	public void provideMeal(String meal, double price, String customerName) {
-	}
+		Customer customer = getCustomer(customerName);
+		if (customer == null || !recipes.contains(meal)) throw new IllegalStateException("Couldn't make meal!");
+		
+		price = computeActualPrice(meal, price, customer); // Added for task 2.3
+		turnover += price; // updating the turnover, ya'know.
+		customer.buyMeal(meal, price);
+		
+		for (var obs : observers) {
+			obs.mealOrder(meal, price); // For task 2.4: inform all observers!
+		}
+}
 		
 	/**
 	 * Exercise 2.3 - Delegation
-	 * Calculate the total rebate of the given meal, using the priceDelegates of this Kitchen
+	 * Calculate the total rebate of the given meal, using the PriceProviders (said 
+	 * priceDelegates in the exam, fixed afterwards) of this Kitchen
 	 * If more than one rebate exist, each of them applies. See README for example.
 	 * 
 	 * @param meal The name of the meal
@@ -91,19 +121,27 @@ public class Kitchen implements IKitchen {
 	 * @return The resulting price after all rebates have been considered.
 	 */
 	double computeActualPrice(String meal, double price, Customer customer) {
-		return 0; // Dummy return value
+		double rebate = 1;
+		for (PriceProvider priceProvider : this.priceProviders) {
+			rebate = rebate * priceProvider.providePrice(meal, price, customer);
+		}
+		return rebate * price;
 	}
 	
 	// Exercise 2.3 - Delegation - these may not be all methods you need to create!
 	@Override
 	public void addPriceProvider(PriceProvider pp) {
-		
+		priceProviders.add(pp);
 	}
 
-	// Exercise 2.4 - Observerer - these may not be all methods you need to create!
+	public void removePriceProvider(PriceProvider pp) {
+		priceProviders.remove(pp);
+	}
+
+	// Oppgave 4 - observatør-observert
 	@Override
 	public void addObserver(KitchenObserver ko) {
-		
+		observers.add(ko);
 	}
 
 	
diff --git a/kont2020/src/main/java/food/MealOrder.java b/kont2020/src/main/java/food/MealOrder.java
index 964b60a7bac0522169fd111410056dd1d9e28d73..3e60965eaaf1cd8def456b11d81dc3858f7b8f67 100644
--- a/kont2020/src/main/java/food/MealOrder.java
+++ b/kont2020/src/main/java/food/MealOrder.java
@@ -11,4 +11,20 @@ public class MealOrder {
 	
 	// Consult the README for a description of requirements.
 	
+	private String meal;
+	private double price;
+	
+	public MealOrder(String meal, double price) {
+		this.meal = meal;
+		this.price = price;
+	}
+	
+	public String getMeal() {
+		return meal;
+	}
+	
+	public double getPrice() {
+		return price;
+	}
+	
 }
diff --git a/kont2020/src/main/java/food/ObserveToPrintTopRevenue.java b/kont2020/src/main/java/food/ObserveToPrintTopRevenue.java
index 8f7e49b14d1d776330634d279430403e5f4ec798..fe83eeb38b52a49db5b3aa07d2e3e836fe3a7915 100644
--- a/kont2020/src/main/java/food/ObserveToPrintTopRevenue.java
+++ b/kont2020/src/main/java/food/ObserveToPrintTopRevenue.java
@@ -21,7 +21,8 @@ import food.def.KitchenObserver;
 public class ObserveToPrintTopRevenue implements KitchenObserver {
 
 	// Internal variables go here:
-	
+	Map<String, Double> meals = new HashMap<>();
+
 	
 	/**
 	 * 
@@ -30,7 +31,29 @@ public class ObserveToPrintTopRevenue implements KitchenObserver {
 	 * If no meal has been sold: returns an empty string.
 	 */
 	public String getTopSellers() {
-		return null; // dummy return value
+		if (meals.size() == 0) return "";
+		List<String> highestMeals = new ArrayList<>();
+		double highestPrice = 0.0;
+		
+		for (var entry : meals.entrySet()) {
+			if (entry.getValue() > highestPrice) {
+				highestMeals.clear();
+				highestMeals.add(entry.getKey());
+				highestPrice = entry.getValue();
+			} else if (entry.getValue() == highestPrice) {
+				highestMeals.add(entry.getKey());
+			}
+		}
+		Collections.sort(highestMeals);
+		
+		StringBuilder sb = new StringBuilder();
+		for (String meal : highestMeals) {
+			sb.append(meal);
+			sb.append(": ");
+			sb.append(highestPrice);
+			sb.append("\n");
+		}
+		return sb.substring(0, sb.length() - 1).toString();
 	}
 	
 
@@ -42,6 +65,8 @@ public class ObserveToPrintTopRevenue implements KitchenObserver {
 	 */
 	@Override
 	public void mealOrder(String meal, double price) {
+		meals.put(meal, meals.getOrDefault(meal, 0.0) + price);
+		System.out.println(getTopSellers());
 	}
 	
 
diff --git a/kont2020/src/main/java/food/RebateEveryFifthBuyFromSameCustomer.java b/kont2020/src/main/java/food/RebateEveryFifthBuyFromSameCustomer.java
index d76c4b6487544e9575d79a8a21fe7f74666a39d0..cfd8b06e466156df7002d44070c7becd63dbacd1 100644
--- a/kont2020/src/main/java/food/RebateEveryFifthBuyFromSameCustomer.java
+++ b/kont2020/src/main/java/food/RebateEveryFifthBuyFromSameCustomer.java
@@ -16,7 +16,7 @@ public class RebateEveryFifthBuyFromSameCustomer implements PriceProvider {
 	 */
 	@Override
 	public double providePrice(String meal, double price, Customer customer) {
-		return 0; // dummy return value
+		return customer.timesEaten(meal) % 5 == 0 ? 0.5 : 1.0;
 	}
 
 }
diff --git a/kont2020/src/main/java/food/RebateFreeEveryThousandSale.java b/kont2020/src/main/java/food/RebateFreeEveryThousandSale.java
index 074fae0edfb91b62f6fe6dd6baad792ad6a4ee1d..c7fbc9dbcc0935aebd22e1e3270645282b6e5bfa 100644
--- a/kont2020/src/main/java/food/RebateFreeEveryThousandSale.java
+++ b/kont2020/src/main/java/food/RebateFreeEveryThousandSale.java
@@ -7,10 +7,22 @@ import food.def.PriceProvider;
  * is given away for free. Not the first buy!
  */
 public class RebateFreeEveryThousandSale implements PriceProvider {
-
+	
+	// Need an internal counter. We don't need Kithchen to keep track of number
+	// sales, since providePrice is called once every sale!
+	int counter;
+	
 	@Override
 	public double providePrice(String meal, double price, Customer customer) {
-		return 0; // dummy return value
+
+		
+		if (counter++ != 0 && counter % 1000 == 0) {
+			return 0;
+		}
+		return 1;
+
+		
+		//		return counter++ > 0 && (counter % 1000 == 0) ? 0.0 : 1.0; // This is rather ugly, should perhaps be done on several lines for legibility...
 	}
 
 
diff --git a/kont2020/src/main/java/stuff/AverageComputerTest.java b/kont2020/src/main/java/stuff/AverageComputerTest.java
index bb82e5d8738760ca249e4c37d24969523aa78772..8749c3af3b9aeb439ee9dfe4838f58a19a382572 100644
--- a/kont2020/src/main/java/stuff/AverageComputerTest.java
+++ b/kont2020/src/main/java/stuff/AverageComputerTest.java
@@ -1,14 +1,43 @@
 package stuff;
 
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
+
 import org.junit.Assert;
 import org.junit.Test;
 
 public class AverageComputerTest {
 
-  @Test
-  public void testComputeAverage() {
-    final AverageComputer ac = new AverageComputer(Arrays.asList(3, 4, 5));
-    Assert.assertEquals(4.0, ac.computeAverage(), 0.0000001);
-  }
+	private static final double epsilon = 1e-8;
+
+	@Test
+	public void testComputeAverage() {
+		final AverageComputer ac = new AverageComputer(Arrays.asList(3, 4, 5));
+		Assert.assertEquals(4.0, ac.computeAverage(), epsilon);
+	}
+
+	// We can manipulate the list by adding to it from outside after 
+	// it has been added to the method.
+	@Test
+	public void testNewComputerNotModifiedByChangingList() {
+		List<Integer> intVals = new ArrayList<>();
+		intVals.addAll(Arrays.asList(2, 3, 1, 4));
+		AverageComputer avg = new AverageComputer(intVals);
+
+		assertEquals(2.5, avg.computeAverage(), epsilon);
+		intVals.add(5);
+		assertEquals(2.5, avg.computeAverage(), epsilon);
+	}
+
+	// No cast from integer, thereby messing up those numbers...
+	@Test
+	public void testRetValIsCastBeforeDivide() {
+		AverageComputer ac = new AverageComputer(Arrays.asList(3, 4));
+
+		assertEquals(3.5, ac.computeAverage(), epsilon);
+	}
+
 }
diff --git a/kont2020/src/main/java/stuff/MathController.java b/kont2020/src/main/java/stuff/MathController.java
index 47c33887194f2f60eb8e8df3c42636d05e67f01e..de7ad1e8a499b4231c4fef7b02d754b777fd4d41 100644
--- a/kont2020/src/main/java/stuff/MathController.java
+++ b/kont2020/src/main/java/stuff/MathController.java
@@ -45,8 +45,34 @@ public class MathController {
 	 */
 	@FXML
 	private void onCalculate() {
+		double res;
+		double val1 = Double.parseDouble(firstField.getText());
+		double val2 = Double.parseDouble(secondField.getText());
+		switch (typeSelector.getValue()) { // Could use chained if-elseif-else instead of switch
+			case '+':
+				res = val1 + val2;
+				break;
+			case '-':
+				res = val1 - val2;
+				break;
+			case '*':
+				res = val1 * val2;
+				break;
+			case '/':
+				res = val1 / val2;
+				break;
+			default:
+				throw new IllegalArgumentException("Unexpected value: " + typeSelector.getValue());
+		}
+		
+		resultArea.setText(Double.toString(res));
 	}
 
 	
 	// Is there a method missing here? Where could it be?
+	@FXML
+	private void randomizeNumbers() {
+		firstField.setText(Integer.toString(rand.nextInt(100) + 1));
+		secondField.setText(Integer.toString(rand.nextInt(100) + 1));
+	}
 }
diff --git a/kont2020/src/main/java/stuff/Movie.java b/kont2020/src/main/java/stuff/Movie.java
index 4b0d88f6b09224ce2b5e5a63e1d08265552c7541..93f5fbe3137c013408a3e7a3d16f07c435ec88a2 100644
--- a/kont2020/src/main/java/stuff/Movie.java
+++ b/kont2020/src/main/java/stuff/Movie.java
@@ -5,6 +5,36 @@ import static org.junit.Assert.assertEquals;
 public class Movie {
 
 	// See the README file for a description of what is required for this file.
+	private String title;
+	private int timesWatched;
+	private Integer rating;
+	
+	public Movie(String title) {
+		if (title == null) throw new IllegalArgumentException("Title must not be null");
+		this.title = title;
+		this.timesWatched = 0;
+		this.rating = null;
+	}
+	
+	public String getTitle() {
+		return title;
+	}
+	
+	public int getTimesWatched() {
+		return timesWatched;
+	}
+	
+	public Integer getRating() {
+		return rating;
+	}
+	
+	public void setRating(Integer rating) {
+		this.rating = rating;
+	}
+	
+	public void watch() {
+		timesWatched += 1;
+	}
 
 	public static void main(String[] args) {
 
diff --git a/kont2020/src/main/java/stuff/MovieRegister.java b/kont2020/src/main/java/stuff/MovieRegister.java
index e901cca813c730550ac31fb70032f7ae29237199..ceec6549b89182d3a4397e02ccddeb160dc81d37 100644
--- a/kont2020/src/main/java/stuff/MovieRegister.java
+++ b/kont2020/src/main/java/stuff/MovieRegister.java
@@ -1,57 +1,67 @@
 package stuff;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.function.Predicate;
+import java.util.stream.Collectors;
 
 public class MovieRegister {
 
 
 	// Add internal variables
-	
+	private Collection<Movie> movies = new ArrayList<>();
+
+
 	/**
 	 * Add movie to register
 	 * @param movie
 	 */
 	public void addMovie(Movie movie) {
+		movies.add(movie);
 	}
-		
+
 	/**
 	 * 
 	 * @param title
 	 * @return the movie with matching title, or null if no such movie exists.
 	 */
 	Movie findMovie(String title) {
-		return null; // dummy return value
+		return movies.stream().filter(m -> m.getTitle().equals(title)).findAny().orElse(null);
 	}
-	
+
 	/**
 	 * Filter all registered movies based on a Predicate, and return them as a Collection.
 	 * @param pred is the filter for which movies to watch
 	 * @return A collection of movies testing true to pred.
 	 */
 	Collection<Movie> filterMovies(Predicate<Movie> pred) {
-		return null; // dummy return value
+		return movies.stream().filter(pred).collect(Collectors.toList());
 	}
-	
+
 	/**
 	 * Watch movie 'title'.
 	 * @param title
 	 * @throws IllegalStateException if the title does not exist.
 	 */
 	public void watch(String title) {
+		try {
+			findMovie(title).watch();
+		} catch (NullPointerException e) {
+			throw new IllegalStateException("Movie does not exsits!");
+		}
 	}
-	
+
 	/**
 	 * Small example of use of the class. Does NOT necessarily cover all uses of methods specified in assignment. 
 	 * @param args
 	 */
 	public static void main(String[] args) {
-		
-//		MovieRegister cb = new MovieRegister();
-//		cb.addMovie(new Movie("Das Boot"));
-//		cb.watch("Das Boot");
-//		System.out.println("Should be 1: " + cb.findMovie("Das Boot").getTimesWatched());
-		
+
+				MovieRegister cb = new MovieRegister();
+				cb.addMovie(new Movie("Das Boot"));
+				cb.watch("Das Boot");
+				System.out.println("Should be 1: " + cb.findMovie("Das Boot").getTimesWatched());
+
 	}
 
 }
diff --git a/kont2020/src/test/java/food/CustomerTest.java b/kont2020/src/test/java/food/CustomerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..945234adb84394c29323467ccb12bb1d35453650
--- /dev/null
+++ b/kont2020/src/test/java/food/CustomerTest.java
@@ -0,0 +1,75 @@
+package food;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.junit.Test;
+
+import food.def.ICustomer;
+
+public class CustomerTest {
+
+	@Test
+	public void testAddOrdered() {
+		ICustomer c = new Customer("Per");
+		c.buyMeal("pancakes", 99.50);
+	}
+
+	@Test
+	public void testGetMealsOrdered() {
+		ICustomer c = new Customer("Per");
+		c.buyMeal("pancakes", 99.50);
+		Collection<String> tmp = new ArrayList<>();
+		MealOrder mealOrder = c.getMealsOrdered().iterator().next();
+		assertEquals("pancakes", mealOrder.getMeal());
+	}
+
+	@Test
+	public void testGetNumberOfOrderedRecipes() {
+		ICustomer c = new Customer("Per");
+		assertEquals(0, c.getNumberOfOrderedMeals());
+		c.buyMeal("pancakes", 99.50);
+		assertEquals(1, c.getNumberOfOrderedMeals());
+	}
+
+	@Test
+	public void testGetName() {
+		ICustomer c = new Customer("Per");
+		assertEquals("Per", c.getName());
+	}
+
+	@Test
+	public void testToString() {
+		ICustomer c = new Customer("Per");
+		assertEquals("Per: 0", c.toString());
+	}
+
+	@Test
+	public void testCustomerCanBeConstructedWithName() {
+		ICustomer c = new Customer("Per");
+	}
+
+	@Test
+	public void testHowManyTimesHaveIEaten() {
+		ICustomer c = new Customer("Per");
+		assertEquals(0, c.timesEaten("pancakes"));
+		c.buyMeal("pancakes", 99.50);
+		assertEquals(1, c.timesEaten("pancakes"));
+		c.buyMeal("pancakes", 99.50);
+		assertEquals(2, c.timesEaten("pancakes"));
+	}
+	
+
+	@Test
+	public void testLastBoughtMeal() {
+		ICustomer c = new Customer("Per");
+		c.buyMeal("pancakes", 99.50);
+		assertEquals("pancakes", c.getLastOrderedMeal().getMeal());
+		c.buyMeal("waffles", 49.50);
+		assertEquals("waffles", c.getLastOrderedMeal().getMeal());
+	}
+	
+	
+}
diff --git a/kont2020/src/test/java/food/GatherStatisticsTest.java b/kont2020/src/test/java/food/GatherStatisticsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c7a8d6068c192cef17d4249d16d680971dcd3280
--- /dev/null
+++ b/kont2020/src/test/java/food/GatherStatisticsTest.java
@@ -0,0 +1,35 @@
+package food;
+
+import static org.junit.Assert.*;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.Test;
+
+public class GatherStatisticsTest {
+
+	@Test
+	public void GatherMostSoldIsCalculated() {
+		Kitchen k = new Kitchen();
+		k.addCustomer(new Customer("Per"));
+		k.addCustomer(new Customer("Ida"));
+		k.addRecipe("pancakes");
+		k.addRecipe("waffles");
+		ObserveToPrintTopRevenue gs = new ObserveToPrintTopRevenue();
+		k.addObserver(gs);
+		k.provideMeal("pancakes", 50, "Per");
+		assertEquals("pancakes: 50.0", gs.getTopSellers());
+		k.provideMeal("pancakes", 50, "Per");
+		assertEquals("pancakes: 100.0", gs.getTopSellers());
+		k.provideMeal("waffles", 50, "Ida");
+		assertEquals("pancakes: 100.0", gs.getTopSellers());
+		k.provideMeal("waffles", 50, "Ida");
+		Collection<String> top = Arrays.asList(gs.getTopSellers().split("\n"));
+		System.out.println(top);
+		assertTrue(top.contains("pancakes: 100.0"));
+		assertTrue(top.contains("waffles: 100.0"));
+		
+	}
+
+}
diff --git a/kont2020/src/test/java/food/KitchenObserverTest.java b/kont2020/src/test/java/food/KitchenObserverTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..65028a280a21061af2ec52a7bdf3bd2ff8317fee
--- /dev/null
+++ b/kont2020/src/test/java/food/KitchenObserverTest.java
@@ -0,0 +1,98 @@
+package food;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import food.def.KitchenObserver;
+
+
+public class KitchenObserverTest {
+
+	
+	double delta = 0.000001;
+	
+	
+	private boolean matchAll(String source, String...strings) {
+		for (String string : strings) {
+			if (!source.contains(string)) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	@Test
+	public void testMakeMealsCallsObservers() {
+		Kitchen k = new Kitchen();
+		k.addRecipe("Pancakes");
+		k.addCustomer(new Customer("Per"));
+		KitchenObserver mock = Mockito.mock(KitchenObserver.class) ;
+		k.addObserver(mock);
+		k.provideMeal("Pancakes", 60.0, "Per");
+		Mockito.verify(mock, Mockito.times(1)).mealOrder(Mockito.any(String.class), Mockito.any(double.class));
+	}
+	
+
+	@Test
+	public void testGatherStatisticsFreshHasZeroValue() {
+		ObserveToPrintTopRevenue statistics = new ObserveToPrintTopRevenue();
+		assertEquals("", statistics.getTopSellers());
+	}
+
+	@Test
+	public void testGatherStatisticsOneAddedHasValue() {
+		ObserveToPrintTopRevenue statistics = new ObserveToPrintTopRevenue();
+		statistics.mealOrder("pancakes", 50.0);
+		assertTrue(statistics.getTopSellers().contains("pancakes"));
+		assertTrue(statistics.getTopSellers().contains("50"));
+	}
+	
+	@Test
+	public void testGatherStatisticsTwoAddedHasCorrectValue() {
+		ObserveToPrintTopRevenue statistics = new ObserveToPrintTopRevenue();
+		statistics.mealOrder("pancakes", 50);
+		statistics.mealOrder("pancakes", 40);
+		assertTrue(matchAll(statistics.getTopSellers(), "pancakes", "90"));
+	}
+	
+	@Test
+	public void testGatherStatisticsTwoDifferentAddedHasCorrectValue() {
+		
+		ObserveToPrintTopRevenue statistics = new ObserveToPrintTopRevenue();
+		statistics.mealOrder("pancakes", 50);
+		statistics.mealOrder("waffles", 40);
+		assertTrue(matchAll(statistics.getTopSellers(), "pancakes", "50"));
+	}
+	
+	@Test
+	public void testGatherStatisticsTwoDifferentEqualAmountShowsBoth() {
+		
+		ObserveToPrintTopRevenue statistics = new ObserveToPrintTopRevenue();
+		statistics.mealOrder("waffles", 100);
+		statistics.mealOrder("pancakes", 50);
+		statistics.mealOrder("pancakes", 50);
+		List<String> tmp = Arrays.asList(statistics.getTopSellers().split("\n"));
+		assertEquals(2, tmp.size());
+		assertTrue(matchAll(tmp.get(0), "pancakes", "100"));
+		assertTrue(matchAll(tmp.get(1), "waffles", "100"));
+	}
+	
+	@Test
+	public void testGatherStatisticsTwoDifferentDifferentAmountShowsOne() {
+		
+		ObserveToPrintTopRevenue statistics = new ObserveToPrintTopRevenue();
+		statistics.mealOrder("pancakes", 50);
+		statistics.mealOrder("pancakes", 50);
+		statistics.mealOrder("waffles", 100);
+		statistics.mealOrder("pancakes", 50);
+		assertTrue(matchAll(statistics.getTopSellers(), "pancakes", "150"));
+	}
+}
diff --git a/kont2020/src/test/java/food/KitchenTest.java b/kont2020/src/test/java/food/KitchenTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..3c5b5244cab48a8a4acd4b90fb18506311a7e349
--- /dev/null
+++ b/kont2020/src/test/java/food/KitchenTest.java
@@ -0,0 +1,122 @@
+package food;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import food.Customer;
+import food.Kitchen;
+import food.RebateEveryFifthBuyFromSameCustomer;
+import food.RebateFreeEveryThousandSale;
+import food.def.IKitchen;
+import food.def.KitchenObserver;
+import food.def.PriceProvider;
+
+public class KitchenTest {
+
+	double delta = 0.000001;
+	
+	@Test
+	public void testEmptyConstructor() {
+		IKitchen k = new Kitchen();
+	}
+
+	@Test
+	public void testAddRecipe() {
+		IKitchen k = new Kitchen();
+		k.addRecipe("Pannekaker");
+		assertEquals(1, k.getRecipes().size());
+	}
+	
+	@Test
+	public void testGetRecipes() {
+		IKitchen k = new Kitchen();
+		k.addRecipe("Waffles");
+		k.addRecipe("Pancakes");
+		Collection<String> tmp = new HashSet<>();
+		tmp.add("Waffles");
+		tmp.add("Pancakes");
+		assertEquals(tmp, new HashSet<>(k.getRecipes()));
+	}
+		
+	@Test
+	public void testAddCustomer() {
+		IKitchen k = new Kitchen();
+		k.addCustomer(new Customer("Per"));
+	}
+	
+	@Test
+	public void testFindCustomer() {
+		IKitchen k = new Kitchen();
+		k.addCustomer(new Customer("Per"));
+		assertEquals("Per", k.getCustomer("Per").getName());
+	}
+	
+	@Test
+	public void testCustomerOrdersRecipeWorksWhenInitiated() {
+		IKitchen k = new Kitchen();
+		k.addRecipe("Pancakes");
+		k.addCustomer(new Customer("Per"));
+		k.provideMeal("Pancakes", 99.50, "Per");
+		assertEquals(1, k.getCustomer("Per").getNumberOfOrderedMeals());
+	}
+	
+	@Test
+	public void testCustomerOrdersRecipeWorksFailsOnNonexistentRecipe() {
+		IKitchen k = new Kitchen();
+		k.addRecipe("Pancakes");
+		Customer customer = new Customer("Per");
+		k.addCustomer(customer);
+		try {
+			k.provideMeal("PanKakes", 99.50, "Per");
+			fail("Meal should not be successfully made with unknown recipe 'PanKakes'.");
+		} catch (IllegalStateException e) {
+			assertEquals("Unsuccessful meal should not be registered to customer.", 0, customer.getNumberOfOrderedMeals());
+		}
+	}
+	
+	@Test
+	public void testCustomerOrdersRecipeWorksFailsOnNonexistentCustomer() {
+		IKitchen k = new Kitchen();
+		k.addRecipe("Pancakes");
+		Customer c = new Customer("Per");
+		k.addCustomer(c);
+		try {
+			k.provideMeal("Pancakes", 99.50, "Finns_inte");
+			fail("Meal should not be successfully made with unknown customer 'Finns_inte'.");
+		} catch (IllegalStateException e) {
+			assertEquals("Unsuccessful meal should not be registered to customer.", 0, c.getNumberOfOrderedMeals());
+		}
+	}
+	
+	@Test
+	public void testEmptyKitchenHasZeroTurnover() {
+		IKitchen k = new Kitchen();
+		assertEquals(0.0, k.getTurnover(), delta);
+	}
+	
+	@Test
+	public void testMakingDishIncreasesTurnover() {
+		IKitchen k = new Kitchen();
+		k.addRecipe("Pancakes");
+		k.addCustomer(new Customer("Per"));
+		k.provideMeal("Pancakes", 99.50, "Per");
+		assertEquals(99.50, k.getTurnover(), delta);
+	}
+	
+	@Test
+	public void testMakingDishWithSpecialPriceHasCorrectTurnover() {
+		IKitchen k = new Kitchen();
+		k.addRecipe("Pancakes");
+		k.addCustomer(new Customer("Per"));
+		k.provideMeal("Pancakes", 60.0, "Per");
+		assertEquals(60.0, k.getTurnover(), delta);
+	}
+	
+	
+}
diff --git a/kont2020/src/test/java/food/PriceProviderTest.java b/kont2020/src/test/java/food/PriceProviderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca55e10e4854f1cc3585fc9e2443f7c2bc9463f2
--- /dev/null
+++ b/kont2020/src/test/java/food/PriceProviderTest.java
@@ -0,0 +1,125 @@
+package food;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import food.Customer;
+import food.Kitchen;
+import food.RebateEveryFifthBuyFromSameCustomer;
+import food.def.KitchenObserver;
+import food.def.PriceProvider;
+
+public class PriceProviderTest {
+
+	double delta = 0.000001;
+	
+	@Test
+	public void testCanAddDelegates() {
+		Kitchen k = new Kitchen();
+		k.addRecipe("pancakes");
+		k.addCustomer(new Customer("per"));
+		PriceProvider delegate = Mockito.mock(PriceProvider.class);
+		k.addPriceProvider(delegate );
+		k.provideMeal("pancakes", 100, "per");
+		Mockito.verify(delegate, Mockito.times(1)).providePrice(Mockito.any(String.class), Mockito.anyDouble(), Mockito.any(Customer.class));
+	}
+	
+
+	@Test
+	public void testCanAddTwoDelegates() {
+		Kitchen k = new Kitchen();
+		k.addRecipe("pancakes");
+		k.addCustomer(new Customer("per"));
+		
+		PriceProvider delegate1 = Mockito.mock(PriceProvider.class) ;
+		k.addPriceProvider(delegate1);
+		
+		PriceProvider delegate2 = Mockito.mock(PriceProvider.class) ;
+		k.addPriceProvider(delegate2);
+		
+		k.provideMeal("pancakes", 100, "per");
+
+		Mockito.verify(delegate1, Mockito.times(1)).providePrice(Mockito.any(String.class), Mockito.anyDouble(), Mockito.any(Customer.class));
+		Mockito.verify(delegate2, Mockito.times(1)).providePrice(Mockito.any(String.class), Mockito.anyDouble(), Mockito.any(Customer.class));
+	}
+	
+	
+	@Test
+	public void testDelegateWorksViaKitchen() {
+		Kitchen k = new Kitchen();
+		k.addPriceProvider(new RebateEveryFifthBuyFromSameCustomer());
+		k.addRecipe("Pancakes");
+		k.addCustomer(new Customer("Per"));
+		k.provideMeal("Pancakes", 100, "Per");
+		assertEquals(50, k.getTurnover(), delta);
+	}
+	
+	
+	@Test
+	public void testEveryFifthBuysRebateFirstBuyGivesRebate() {
+		Customer customer = new Customer("Per");
+		RebateEveryFifthBuyFromSameCustomer rebate = new RebateEveryFifthBuyFromSameCustomer();
+		assertEquals(0.5, rebate.providePrice("pancakes", 100, customer), delta);
+	}
+	@Test
+	public void testEveryFifthBuysRebateSecondBuyNoRebate() {
+		Customer customer = new Customer("Per");
+		RebateEveryFifthBuyFromSameCustomer rebate = new RebateEveryFifthBuyFromSameCustomer();
+		assertEquals(0.5, rebate.providePrice("pancakes", 100, customer), delta);
+		customer.buyMeal("pancakes", 50);
+		assertEquals(1, rebate.providePrice("pancakes", 100, customer), delta);
+		customer.buyMeal("pancakes", 100);
+	}
+	
+	@Test
+	public void testEveryFifthBuysRebateSixthBuyGivesRebate() {
+		Customer customer = new Customer("Per");
+		RebateEveryFifthBuyFromSameCustomer rebate = new RebateEveryFifthBuyFromSameCustomer();
+		
+		double fac = rebate.providePrice("pancakes", 100, customer);
+		assertEquals(.5, fac, delta);
+		customer.buyMeal("pancakes", 100);
+		
+		for (int i = 0; i < 4; i++) {
+			fac = rebate.providePrice("pancakes", 100, customer);
+			assertEquals(1.0, fac, delta);
+			customer.buyMeal("pancakes", 100);
+		}
+		assertEquals(0.5, rebate.providePrice("pancakes", 100, customer), delta);
+	}
+	
+	@Test
+	public void testFreeEveryThousandNoRebateOnFirst() {
+		Customer customer = new Customer("Per");
+		RebateFreeEveryThousandSale rebate = new RebateFreeEveryThousandSale();
+		assertEquals(1, rebate.providePrice("pancakes", 100, customer), delta);
+	}
+	
+	@Test
+	public void testFreeEveryThousandRebateOnThousand() {
+		RebateFreeEveryThousandSale rebate = new RebateFreeEveryThousandSale();
+		Customer customer = new Customer("Per");
+		assertEquals(1, rebate.providePrice("pancakes", 100, customer), delta);
+		customer.buyMeal("pancakes", 100);
+		for (int i = 0; i < 999; i++) {
+			rebate.providePrice("Pancakes", 100, customer);
+			assertEquals(1, rebate.providePrice("pancakes", 100, customer), delta);
+			customer.buyMeal("pancakes", 100);
+		}
+		assertEquals(0, rebate.providePrice("pancakes", 100, customer), delta);
+	}
+	
+	@Test
+	public void testTwoRebatesWorkOneTriggersOneDoesnt() {
+		Kitchen k = new Kitchen();
+		k.addPriceProvider(new RebateEveryFifthBuyFromSameCustomer());
+		k.addPriceProvider(new RebateFreeEveryThousandSale());
+		k.addRecipe("Pancakes");
+		k.addCustomer(new Customer("Per"));
+		k.provideMeal("Pancakes", 100, "Per");
+		assertEquals(50, k.getTurnover(), delta);
+	}
+	
+}
diff --git a/kont2020/src/test/java/stuff/MovieRegisterTest.java b/kont2020/src/test/java/stuff/MovieRegisterTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f33a7c4e339735c511da548e2b1d2504ebaab2e
--- /dev/null
+++ b/kont2020/src/test/java/stuff/MovieRegisterTest.java
@@ -0,0 +1,60 @@
+package stuff;
+
+import static org.junit.Assert.*;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class MovieRegisterTest extends MovieRegister {
+
+
+	@Test
+	public void NewRegisterNoMovies() {
+		MovieRegister mr = new MovieRegister();
+		assertEquals(null, mr.findMovie("Das Boot"));
+	}
+
+	@Test
+	public void RegisterCanAddMovies() {
+		MovieRegister mr = new MovieRegister();
+		Movie movie = new Movie("Das Boot");
+		mr.addMovie(movie);
+		assertEquals(movie, mr.findMovie("Das Boot"));
+	}
+	
+	@Test
+	public void RegisterWatchOnce() {
+		MovieRegister cb = new MovieRegister();
+		cb.addMovie(new Movie("Das Boot"));
+		cb.watch("Das Boot");
+		assertEquals(1, cb.findMovie("Das Boot").getTimesWatched());
+	}
+	
+	@Test(expected=IllegalStateException.class)
+	public void RegisterWatchNonExistingMovie() {
+		MovieRegister cb = new MovieRegister();
+		cb.addMovie(new Movie("Das Boot"));
+		cb.watch("The cars that ate Paris");
+	}
+	
+	@Test
+	public void RegisterWatchTwice() {
+		MovieRegister cb = new MovieRegister();
+		cb.addMovie(new Movie("Das Boot"));
+		cb.watch("Das Boot");
+		cb.watch("Das Boot");
+		assertEquals(2, cb.findMovie("Das Boot").getTimesWatched());
+	}
+	
+	
+	@Test
+	public void RegisterAddTwoMovies() {
+		MovieRegister cb = new MovieRegister();
+		cb.addMovie(new Movie("Das Boot"));
+		cb.addMovie(new Movie("The cars that ate Paris"));
+		cb.watch("Das Boot");
+		cb.watch("Das Boot");
+		assertEquals(2, cb.findMovie("Das Boot").getTimesWatched());
+	}
+		
+}
diff --git a/kont2020/src/test/java/stuff/MovieTest.java b/kont2020/src/test/java/stuff/MovieTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..614f1852569664ce7444ed079cacf5c847ce0689
--- /dev/null
+++ b/kont2020/src/test/java/stuff/MovieTest.java
@@ -0,0 +1,53 @@
+package stuff;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class MovieTest extends Movie {
+
+	public MovieTest() {
+		super("test");
+	}
+
+	@Test
+	public void nameIsStored() {
+		Movie movie = new Movie("Das Boot");
+		assertEquals("Das Boot", movie.getTitle());
+	}
+
+	@Test
+	public void newRecipeZeroEaten() {
+		Movie movie = new Movie("cheese");
+		assertEquals(0, movie.getTimesWatched());
+	}
+	
+	@Test
+	public void newRecipeOnceEaten() {
+		Movie movie = new Movie("cheese");
+		movie.watch();
+		assertEquals(1, movie.getTimesWatched());
+	}
+	
+	@Test
+	public void newRecipeTwiceEaten() {
+		Movie recipe = new Movie("cheese");
+		recipe.watch();
+		recipe.watch();
+		assertEquals(2, recipe.getTimesWatched());
+	}
+	
+	@Test
+	public void newRecipeNullRating() {
+		Movie recipe = new Movie("cheese");
+		assertEquals(null, recipe.getRating());
+	}
+	
+	@Test
+	public void newRecipeRatedWorks() {
+		Movie recipe = new Movie("cheese");
+		recipe.setRating(3);
+		assertEquals(3, (int)recipe.getRating());
+	}
+		
+}