package com.javarush.task.task27.task2712.kitchen;
import com.javarush.task.task27.task2712.ConsoleHelper;
import com.javarush.task.task27.task2712.Tablet;
import com.javarush.task.task27.task2712.statistic.StatisticManager;
import com.javarush.task.task27.task2712.statistic.event.CookedOrderEventDataRow;
import java.util.Observable;
import java.util.Observer;
public class Cook extends Observable implements Observer {
private String name;
public Cook(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
@Override
public void update(Observable o, Object arg) {
Tablet tablet = (Tablet)o;
Order order = (Order) arg;
ConsoleHelper.writeMessage(String.format("Start cooking — %s, cooking time %dmin", order, order.getTotalCookingTime()));
StatisticManager.getInstance().register(new CookedOrderEventDataRow(tablet.toString(), this.name, order.getTotalCookingTime()*60, order.getDishes()));
setChanged();
notifyObservers(order);
}
}
package com.javarush.task.task27.task2712;
import com.javarush.task.task27.task2712.kitchen.Dish;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class ConsoleHelper {
private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public static void writeMessage(String message) {
System.out.println(message);
}
public static String readString() throws IOException {
return br.readLine();
}
public static List<Dish> getAllDishesForOrder() throws IOException {
List<Dish> list = new ArrayList<Dish>();
writeMessage(Dish.allDishesToString());
writeMessage("Выберите блюда. Для завершения наберите 'exit'.");
String str = null;
str = readString().trim();
while (!str.equalsIgnoreCase("exit")) {
if (Dish.allDishesToString().toLowerCase().contains(str.toLowerCase()))
list.add(Dish.valueOf(str));
else
writeMessage("Такого блюда нет!");
writeMessage("Введите строку — название блюда:");
str = readString().trim();
}
return list;
}
}
package com.javarush.task.task27.task2712.kitchen;
public enum Dish {
Fish (25),
Steak (30),
Soup (15),
Juice (5),
Water (3);
private int duration;
public int getDuration() {
return duration;
}
Dish(int duration) {
this.duration = duration;
}
public static String allDishesToString(){
StringBuilder sb = new StringBuilder("");
for (Dish dish : Dish.values())
sb.append(", " + dish);
return sb.toString().substring(2);
}
}
package com.javarush.task.task27.task2712.kitchen;
import com.javarush.task.task27.task2712.ConsoleHelper;
import com.javarush.task.task27.task2712.Tablet;
import java.io.IOException;
import java.util.List;
public class Order {
private final Tablet tablet;
protected List<Dish> dishes;
public Order(Tablet tablet) throws IOException {
this.tablet = tablet;
this.dishes = ConsoleHelper.getAllDishesForOrder();
}
public List<Dish> getDishes() {
return dishes;
}
public boolean isEmpty() {
return dishes.isEmpty();
}
@Override
public String toString(){
if (dishes.isEmpty())
return "";
else
return "Your order: " + dishes + " of " + tablet;
}
public int getTotalCookingTime() {
int i = 0;
for (Dish dish : dishes) {
i += dish.getDuration();
}
return i;
}
}
package com.javarush.task.task27.task2712;
import com.javarush.task.task27.task2712.ad.AdvertisementManager;
import com.javarush.task.task27.task2712.ad.NoVideoAvailableException;
import com.javarush.task.task27.task2712.kitchen.Order;
import java.io.IOException;
import java.util.Observable;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.javarush.task.task27.task2712.ConsoleHelper.writeMessage;
public class Tablet extends Observable {
final int number;
static Logger logger = Logger.getLogger(Tablet.class.getName());
public Tablet(int number) {
this.number = number;
}
@Override
public String toString() {
return "Tablet{number=" + number + "}";
}
public int getNumber() {
return number;
}
public Order createOrder(){
Order order = null;
AdvertisementManager advertisementManager = null;
try {
order = new Order(this);
if (!order.isEmpty()) {
writeMessage(order.toString());
advertisementManager = new AdvertisementManager(order.getTotalCookingTime()*60);
advertisementManager.processVideos();
setChanged();
notifyObservers(order);
}
} catch (NoVideoAvailableException e) {
logger.log(Level.INFO,"No video is available for the order " + order);
} catch (IOException e) {
logger.log(Level.SEVERE,"Console is unavailable.");
}
return order;
}
}
package com.javarush.task.task27.task2712.ad;
import java.util.ArrayList;
import java.util.List;
public class AdvertisementStorage {
private static AdvertisementStorage ourInstance = new AdvertisementStorage();
private final List<Advertisement> videos = new ArrayList<>();
public static AdvertisementStorage getInstance() {
return ourInstance;
}
private AdvertisementStorage() {
Object someContent = new Object();
add(new Advertisement(someContent, "First Video", 5000, 100, 3 * 60));
add(new Advertisement(someContent, "Second Video", 100, 10, 15 * 60));
add(new Advertisement(someContent, "Third Video", 400, 2, 10 * 60));
}
public List<Advertisement> list() {
return videos;
}
public void add(Advertisement advertisement) {
videos.add(advertisement);
}
}
package com.javarush.task.task27.task2712.ad;
public class Advertisement {
private Object content;
private String name;
public Object getContent() {
return content;
}
public long getInitialAmount() {
return initialAmount;
}
private long initialAmount;
private int hits;
private int duration;
private long amountPerOneDisplaying;
public Advertisement(Object content, String name, long initialAmount, int hits, int duration) {
this.content = content;
this.name = name;
this.initialAmount = initialAmount;
this.hits = hits;
this.duration = duration;
this.amountPerOneDisplaying = initialAmount / hits;
}
public String getName() {
return name;
}
public int getDuration() {
return duration;
}
public long getAmountPerOneDisplaying() {
return amountPerOneDisplaying;
}
public int getHits() {
return hits;
}
public void revalidate() throws NoVideoAvailableException {
if (hits < 1) {
throw new NoVideoAvailableException();
}
hits--;
}
}
package com.javarush.task.task27.task2712.ad;
import com.javarush.task.task27.task2712.ConsoleHelper;
import com.javarush.task.task27.task2712.statistic.StatisticManager;
import com.javarush.task.task27.task2712.statistic.event.VideoSelectedEventDataRow;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class AdvertisementManager {
private final AdvertisementStorage storage = AdvertisementStorage.getInstance();
private int timeSeconds;
private List<Advertisement> videosToShow = new ArrayList<>();
public AdvertisementManager(int timeSeconds) {
this.timeSeconds = timeSeconds;
}
public void processVideos() throws NoVideoAvailableException {
videosToShow = findVideosToShow();
if (videosToShow == null) {
throw new NoVideoAvailableException();
} else {
Collections.sort(videosToShow, (Advertisement ad1, Advertisement ad2) -> {
if (ad1.getAmountPerOneDisplaying() > ad2.getAmountPerOneDisplaying()) return -1;
else if (ad1.getAmountPerOneDisplaying() < ad2.getAmountPerOneDisplaying()) return 1;
long oneSecAmount1 = ad1.getAmountPerOneDisplaying() * 1000 / ad1.getDuration();
long oneSecAmount2 = ad2.getAmountPerOneDisplaying() * 1000 / ad2.getDuration();
if (oneSecAmount1 < oneSecAmount2) return -1;
else if(oneSecAmount1 > oneSecAmount2) return 1;
return 0;
});
long totalAmount = 0;
int totalDuration = 0;
for (Advertisement ad : videosToShow) {
totalAmount += ad.getAmountPerOneDisplaying();
totalDuration += ad.getDuration();
}
StatisticManager.getInstance().register(new VideoSelectedEventDataRow(videosToShow, totalAmount, totalDuration));
for (Advertisement ad : videosToShow) {
long oneSecAmount = ad.getAmountPerOneDisplaying() * 1000 / ad.getDuration();
ConsoleHelper.writeMessage(String.format("%s is displaying... %d, %d",
ad.getName(),
ad.getAmountPerOneDisplaying(),
oneSecAmount));
ad.revalidate();
}
}
}
private List<Advertisement> findVideosToShow() {
List<List<Advertisement>> listOfLists = new ArrayList<>();
List<Advertisement> storageVideos = storage.list();
int blockTime;
for (Advertisement ad : storageVideos) {
blockTime = ad.getDuration();
if (blockTime <= timeSeconds) {
List<Advertisement> tempList = new ArrayList<>();
tempList.add(ad);
listOfLists.add(tempList);
}
}
boolean flag = true;
while (flag) {
flag = false;
for (int j = 0; j < listOfLists.size(); j++) {
List<Advertisement> currentList = listOfLists.get(j);
for (Advertisement ad : storageVideos) {
blockTime = ad.getDuration();
List<Advertisement> tempList = new ArrayList<>();
for (Advertisement a : currentList) {
tempList.add(a);
blockTime += a.getDuration();
}
tempList.add(ad);
if (!currentList.contains(ad) && !isListContains(listOfLists, tempList)
&& blockTime <= timeSeconds && ad.getHits() > 0) {
listOfLists.add(tempList);
flag = true;
}
}
}
}
Collections.sort(listOfLists, (List<Advertisement> list1, List<Advertisement> list2) -> {
long list1Amount = 0, list2Amount = 0;
int list1Duration = 0, list2Duration = 0;
int list1Count = list1.size();
int list2Count = list2.size();
for (Advertisement ad : list1) {
list1Amount += ad.getAmountPerOneDisplaying();
list1Duration += ad.getDuration();
}
for (Advertisement ad : list2) {
list2Amount += ad.getAmountPerOneDisplaying();
list2Duration += ad.getDuration();
}
if (list1Amount > list2Amount) return -1;
else if (list1Amount < list2Amount) return 1;
if (list1Duration > list2Duration) return -1;
else if (list1Duration < list2Duration) return 1;
if (list1Count < list2Count) return -1;
else if (list1Count > list2Count) return 1;
return 0;
});
if (!listOfLists.isEmpty()) {
return listOfLists.get(0);
} else {
return null;
}
}
private static boolean isListContains(List<List<Advertisement>> listOfLists, List<Advertisement> list) {
for (List<Advertisement> l : listOfLists) {
int x = list.size();
for (Advertisement ad : list) {
if (l.contains(ad)) {
x--;
}
if (x == 0) return true;
}
}
return false;
}
}
package com.javarush.task.task27.task2712.kitchen;
import com.javarush.task.task27.task2712.ConsoleHelper;
import java.io.IOException;
import java.util.Observable;
import java.util.Observer;
public class Waiter implements Observer {
@Override
public void update(Observable o, Object arg) {
ConsoleHelper.writeMessage(arg + " was cooked by " + o);
}
}
package com.javarush.task.task27.task2712.statistic.event;
import com.javarush.task.task27.task2712.kitchen.Dish;
import java.util.Date;
import java.util.List;
public class CookedOrderEventDataRow implements EventDataRow {
private String tabletName;
private String cookName;
private int cookingTimeSeconds;
private List<Dish> cookingDishs;
private Date currentDate;
public String getTabletName() {
return tabletName;
}
public String getCookName() {
return cookName;
}
public int getCookingTimeSeconds() {
return cookingTimeSeconds;
}
public List<Dish> getCookingDishs() {
return cookingDishs;
}
public Date getCurrentDate() {
return currentDate;
}
public CookedOrderEventDataRow(String tabletName, String cookName, int cookingTimeSeconds, List<Dish> cookingDishs){
this.tabletName = tabletName;
this.cookName = cookName;
this.cookingTimeSeconds = cookingTimeSeconds;
this.cookingDishs = cookingDishs;
currentDate = new Date();
}
@Override
public EventType getType() {
return EventType.COOKED_ORDER;
}
}
package com.javarush.task.task27.task2712.statistic.event;
import com.javarush.task.task27.task2712.statistic.event.EventDataRow;
import java.util.Date;
public class NoAvailableVideoEventDataRow implements EventDataRow {
private int totalDuration;
private Date currentDate;
public int getTotalDuration() {
return totalDuration;
}
public Date getCurrentDate() {
return currentDate;
}
public NoAvailableVideoEventDataRow(int totalDuration){
this.totalDuration = totalDuration;
currentDate = new Date();
}
@Override
public EventType getType() {
return EventType.NO_AVAILABLE_VIDEO;
}
}
package com.javarush.task.task27.task2712.statistic.event;
import com.javarush.task.task27.task2712.ad.Advertisement;
import com.javarush.task.task27.task2712.statistic.event.EventDataRow;
import java.util.Date;
import java.util.List;
public class VideoSelectedEventDataRow implements EventDataRow {
private List<Advertisement> optimalVideoSet;
private long amount;
private int totalDuration;
private Date currentDate;
public List<Advertisement> getOptimalVideoSet() {
return optimalVideoSet;
}
public long getAmount() {
return amount;
}
public int getTotalDuration() {
return totalDuration;
}
public Date getCurrentDate() {
return currentDate;
}
public VideoSelectedEventDataRow(List<Advertisement> optimalVideoSet, long amount, int totalDuration){
this.optimalVideoSet = optimalVideoSet;
this.amount = amount;
this.totalDuration = totalDuration;
currentDate = new Date();
}
@Override
public EventType getType() {
return EventType.SELECTED_VIDEOS;
}
}
ge com.javarush.task.task27.task2712.statistic;
import com.javarush.task.task27.task2712.ConsoleHelper;
import com.javarush.task.task27.task2712.statistic.event.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class StatisticManager {
private static StatisticManager ourInstance = new StatisticManager();
private StatisticStorage statisticStorage = new StatisticStorage();
public static StatisticManager getInstance() {
return ourInstance;
}
private StatisticManager() {
}
public void register(EventDataRow data){
if (data == null) return;
statisticStorage.put(data);
}
private class StatisticStorage {
private Map<EventType, List<EventDataRow>> storage = new HashMap<EventType, List<EventDataRow>>();
private StatisticStorage(){
for (EventType et : EventType.values())
storage.put(et, new ArrayList<EventDataRow>());
}
private void put(EventDataRow data){
storage.get(data.getType()).add(data);
}
}
}
package com.javarush.task.task27.task2712;
import com.javarush.task.task27.task2712.ad.AdvertisementManager;
import com.javarush.task.task27.task2712.ad.NoVideoAvailableException;
import com.javarush.task.task27.task2712.kitchen.Order;
import java.io.IOException;
import java.util.Observable;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.javarush.task.task27.task2712.ConsoleHelper.writeMessage;
public class Tablet extends Observable {
final int number;
static Logger logger = Logger.getLogger(Tablet.class.getName());
public Tablet(int number) {
this.number = number;
}
@Override
public String toString() {
return "Tablet{number=" + number + "}";
}
public int getNumber() {
return number;
}
public Order createOrder(){
Order order = null;
AdvertisementManager advertisementManager = null;
try {
order = new Order(this);
if (!order.isEmpty()) {
writeMessage(order.toString());
advertisementManager = new AdvertisementManager(order.getTotalCookingTime()*60);
advertisementManager.processVideos();
setChanged();
notifyObservers(order);
}
} catch (NoVideoAvailableException e) {
logger.log(Level.INFO,"No video is available for the order " + order);
} catch (IOException e) {
logger.log(Level.SEVERE,"Console is unavailable.");
}
return order;
}
}