Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
<source>10</source>
<target>10</target>
</configuration>
</plugin>
</plugins>
</build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package ru.hilariousstartups.javaskills.psplayer;

import lombok.extern.slf4j.Slf4j;
import ru.hilariousstartups.javaskills.psplayer.swagger_codegen.model.CheckoutLine;
import ru.hilariousstartups.javaskills.psplayer.swagger_codegen.model.Employee;

import java.util.ArrayList;
import java.util.List;

/**
* Управляет кассирами на кассах: следит, кто когда ушел отдыхать,
* когда может работать снова, кого именно сажать на кассу.
* Используется в стратегии "не увольнять сразу"
*/
@Slf4j
public class CheckoutAdmin {

private List<Employee> employees;
private List<EmployeeWorkTable> timesheet;
private boolean notFailed = false;

public CheckoutAdmin(List<Employee> employees) {
this.employees = new ArrayList<>(employees);
init();
}

private void init() {
if (employees == null || employees.isEmpty()) {
timesheet = new ArrayList<>();
return;
}
timesheet = new ArrayList<>(employees.size());
employees.forEach(it -> timesheet.add(new EmployeeWorkTable(it)));
}

public Employee sendToWorkAny(int currentTime) {
var candidate = timesheet.stream()
.filter(it -> it.isReadyToWork(currentTime))
.findAny().orElse(null);
if (candidate == null) {
if (notFailed || currentTime % 120 == 0) {
log.warn("Not enough employees to work at=" + currentTime + ", " + timesheet);
}
notFailed = false;
return null;
}
notFailed = true;
candidate.startWork(currentTime);
return candidate.getEmployee();
}

// TODO add tests
// FIXME учесть уволенных
public void considerNew(List<Employee> employeeList,
List<CheckoutLine> checkoutLines,
Integer tickCount) {
var newWorkers = new ArrayList<>(employeeList);
newWorkers.removeAll(employees);
employees.addAll(newWorkers);
for (Employee newbie : newWorkers) {
var alreadyAssigned = checkoutLines.stream()
.anyMatch(line -> newbie.getId().equals(line.getEmployeeId()));
final EmployeeWorkTable newbieWorkTable = new EmployeeWorkTable(newbie);
if (alreadyAssigned) {
newbieWorkTable.startWork(tickCount);
}
timesheet.add(newbieWorkTable);
log.info(newbieWorkTable.toString());
}
}

public List<Employee> getEmployees() {
return employees;
}

public List<EmployeeWorkTable> getTimesheet() {
return timesheet;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package ru.hilariousstartups.javaskills.psplayer;

import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import ru.hilariousstartups.javaskills.psplayer.swagger_codegen.model.Employee;

class EmployeeWorkTable {
private final static int HOUR_IN_TICKS = 60;
private final static int WORK_SHIFT_IN_TICKS = 8 * HOUR_IN_TICKS;
private final static int REST_TIME_IN_TICKS = 16 * HOUR_IN_TICKS;

@NonNull
private Employee employee;
private Integer startedWork = null;

public EmployeeWorkTable(Employee employee) {
this.employee = employee;
}

// probably change return type
public boolean startWork(int currentTime) {
if (isReadyToWork(currentTime)) {
startedWork = currentTime;
return true;
}
return false;
}

/**
* @return time (in ticks) when this employee started his last work shift.
* Null if it never works.
*/
@Nullable
public Integer getStartedWork() {
return startedWork;
}

@NonNull
public Employee getEmployee() {
return employee;
}

/**
* @return time (in ticks) when this employee will finish his work shift.
* Null if it never works
*/
@Nullable
public Integer getFinishedWork() {
if (startedWork == null) {
return null;
}
return startedWork + WORK_SHIFT_IN_TICKS;
}

/**
* @return time (in ticks) when this employee could start to work.
* Null if it never works and could start immediately
*/
@Nullable
public Integer getReadyToWork() {
if (startedWork == null) {
return null;
}
return getFinishedWork() + REST_TIME_IN_TICKS;
}

public boolean isReadyToWork(int currentTime) {
if (startedWork == null) {
return true;
}
return getReadyToWork() <= currentTime;
}

public static int getWorkShiftInTicks() {
return WORK_SHIFT_IN_TICKS;
}

public static int getRestTimeInTicks() {
return REST_TIME_IN_TICKS;
}

public static int getHourInTicks() {
return HOUR_IN_TICKS;
}

@Override
public String toString() {
final StringBuffer sb = new StringBuffer("EmployeeWorkTable{");
sb.append("employee(").append(employee.getId()).append(")");
sb.append(" ").append(employee.getFirstName());
sb.append(", exp=").append(employee.getExperience());
sb.append(", $").append(employee.getSalary());
sb.append(", started=").append(startedWork);
sb.append('}');
return sb.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package ru.hilariousstartups.javaskills.psplayer;

import lombok.extern.slf4j.Slf4j;
import ru.hilariousstartups.javaskills.psplayer.swagger_codegen.model.Employee;
import ru.hilariousstartups.javaskills.psplayer.swagger_codegen.model.EmployeeRecruitmentOffer;
import ru.hilariousstartups.javaskills.psplayer.swagger_codegen.model.HireEmployeeCommand;

import java.util.ArrayList;
import java.util.List;

/**
* Отвечает за найим и увольнение
*/
@Slf4j
public class HRDepartment {

private List<EmployeeRecruitmentOffer> recruitmentAgency;
private List<Employee> employees;
private int checkoutCount; // сколько всего касс

public HRDepartment(List<EmployeeRecruitmentOffer> recruitmentAgency, List<Employee> employees, int checkoutCount) {
this.recruitmentAgency = recruitmentAgency;
this.employees = employees;
this.checkoutCount = checkoutCount;
}


public List<EmployeeRecruitmentOffer> getRecruitmentAgency() {
return recruitmentAgency;
}

public List<HireEmployeeCommand> firstHire() {
List<HireEmployeeCommand> result = new ArrayList<>(recruitmentAgency.size());
for (int i = 0; i < 3 && i < recruitmentAgency.size(); i++) {
var offer = recruitmentAgency.get(i);
result.add(new HireEmployeeCommand()
.experience(HireEmployeeCommand.ExperienceEnum.fromValue(offer.getEmployeeType()))

);

}
// TODO получать реальный id
result.get(0).checkoutLineId(1);
log.debug("Всего предложений:" + recruitmentAgency.size());
log.debug(recruitmentAgency.toString());
log.debug(result.toString());
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package ru.hilariousstartups.javaskills.psplayer;

import lombok.extern.slf4j.Slf4j;
import ru.hilariousstartups.javaskills.psplayer.swagger_codegen.model.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
* Выкладывает товар на полки, определяет наценки.
* Будет ли заниматься заказом товара - пока не знаю
*/
@Slf4j
public class Merchandaizer {

public enum Margin {
DOLLAR_ONE, PERCENT_10, PERCENT_20, PERCENT_50, PERCENT_100;

public Margin next() {
switch (this) {
case DOLLAR_ONE:
return PERCENT_10;
case PERCENT_10:
return PERCENT_20;
case PERCENT_20:
return PERCENT_50;
case PERCENT_50:
return PERCENT_100;
case PERCENT_100:
return PERCENT_100;
default:
return DOLLAR_ONE; // never happens
}
}
}

private static final Integer DEFAULT_QUANTITY = 100;
private List<RackCell> racks;
private List<Product> stock;
private List<Integer> productsOnRack;
private List<Integer> racksToPutOff;

public Merchandaizer(List<RackCell> racks, List<Product> stock) {
this.racks = new ArrayList<>(racks);
this.stock = new ArrayList<>(stock);
this.stock.sort(Comparator.comparing(Product::getStockPrice));
}

public List<PutOffRackCellCommand> removeSold() {
var result = racksToPutOff.stream().map(id ->
new PutOffRackCellCommand().rackCellId(id)
).collect(Collectors.toList());
return result;
}

public List<PutOnRackCellCommand> inspectRacks(CurrentWorldResponse world) {
racksToPutOff = new ArrayList<>();
racks = world.getRackCells();
stock = world.getStock();
stock.sort(Comparator.comparing(Product::getStockPrice).reversed());
productsOnRack = racks.stream()
.filter(r -> r.getProductId() != null)
.map(RackCell::getProductId)
.collect(Collectors.toList());

List<PutOnRackCellCommand> result = new ArrayList<>();

racks.stream()
.filter(rack -> rack.getProductId() == null || rack.getProductQuantity().equals(0))
.forEach(rack -> {
PutOnRackCellCommand command;
if (rack.getProductId() == null) {
command = putNextFromStock(rack);
} else {
command = addSame(rack);
}
result.add(command);
});
return result;
}

private PutOnRackCellCommand addSame(RackCell rack) {
Product productToPutOnRack = stock.stream()
.filter(it -> it.getId().equals(rack.getProductId()))
.findAny()
.orElseThrow(() -> new IllegalStateException("Product is lost on stock:" + rack.getProductId()));

final Integer inStock = productToPutOnRack.getInStock();
int rackCapacity = rack.getCapacity();
double sellPrice = definePrice(productToPutOnRack);
return new PutOnRackCellCommand().productId(productToPutOnRack.getId())
.rackCellId(rack.getId())
.productQuantity(Math.min(inStock, rackCapacity))
.sellPrice(sellPrice);
}


private PutOnRackCellCommand putNextFromStock(RackCell rack) {
Product productToPutOnRack;
productToPutOnRack = stock.stream()
.filter(product -> !productsOnRack.contains(product.getId())
&& product.getInStock() > 0)
.findFirst()
.orElseThrow(() -> new IllegalStateException("Store is empty"));
productsOnRack.add(productToPutOnRack.getId());
racksToPutOff.add(rack.getId());
final Integer inStock = productToPutOnRack.getInStock();
int rackCapacity = rack.getCapacity();
double sellPrice = definePrice(productToPutOnRack);
return new PutOnRackCellCommand().productId(productToPutOnRack.getId())
.rackCellId(rack.getId())
.productQuantity(Math.min(inStock, rackCapacity))
.sellPrice(sellPrice);
}

private double definePrice(Product product) {
if (product.getSellPrice() == null) {
return product.getStockPrice() + 1;
}
return product.getSellPrice() * 1.1; // add 10%
}

public List<BuyStockCommand> inspectStore() {
List<BuyStockCommand> result = new ArrayList<>();
stock.stream().filter(it -> it.getInStock().equals(0))
.forEach(product -> result.add(new BuyStockCommand()
.productId(product.getId())
.quantity(DEFAULT_QUANTITY)
));
if (result.size() > 5) {
return result;
} else {
return Collections.emptyList();// избегаем мелких закупок
}
}

public List<BuyStockCommand> initialBuyIn() {
List<BuyStockCommand> buyStockCommands = new ArrayList<>(50);
stock.forEach(it -> buyStockCommands.add(
new BuyStockCommand().productId(it.getId()).quantity(DEFAULT_QUANTITY)
));
return buyStockCommands;
}
}
Loading