1
0
Fork 0
SVEN/StorageSim/src/storagesim/Simulation.java

392 lines
14 KiB
Java

package storagesim;
import java.time.LocalDate;
import java.time.temporal.IsoFields;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import java.util.stream.Collectors;
import lib.OpenSimplexNoise;
import lib.SQLConnection;
/**
* Runs a loop with a strict interval to simulate time passing
*
* @author Manuel
*/
public class Simulation {
boolean running;
public LocalDate currentTime;
OpenSimplexNoise noise;
final float STEPS_PER_SECOND = 1 / 30f;
final int MAX_STEPS = 1;
final int TOLERANCE = 200;
public Simulation() {
this.running = false;
this.currentTime = LocalDate.now();
//this.currentTime = LocalDate.parse("2020-02-06");
this.noise = new OpenSimplexNoise();
}
/**
* Starts and contains the loop
*
* @author Manuel
*/
public void run(LocalDate time) {
// initialise timing values
double interval = 1000f / (STEPS_PER_SECOND);
double previousMillis = System.currentTimeMillis() - interval;
this.currentTime = time;
do {
// update current time
double currentMillis = System.currentTimeMillis();
double deltaMillis = currentMillis - previousMillis;
// run code if enough time has passed
int steps = 0;
while (deltaMillis >= interval && steps < MAX_STEPS) {
// --------------------
// this is the code that is executed in the specified interval
SQLConnection db = new SQLConnection();
System.out.println("Date: " + this.currentTime.toString());
simulateSales(db);
sellItems(db);
disposeItems(db);
receiveOrders(db);
sortStorage(db);
checkStorage(db);
sortStatistics(db);
db.close();
this.currentTime.plusDays(1);
// this.running = false;
// --------------------
steps++;
deltaMillis -= interval;
}
if (steps > 0) {
// only change time if any code was executed
previousMillis = currentMillis;
}
} while (this.running);
}
/**
* Removes all Items sold in the last time frame
*
* @author Johann
*/
public void sellItems(SQLConnection db) {
// Liste der verkauften waren wird erstellt
ArrayList<HashMap<String, String>> Verkauft = db.queryToMap(
"SELECT * FROM t_statistik WHERE `Woche` = " + this.currentTime.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR));
int MengePalette; // Zwischenspeicher für die Menge der Items auf einer Palette
for (HashMap<String, String> Artikel : Verkauft) {
int VerkaufteID = Integer.parseInt(Artikel.get("f_Artikel_ID")); // ID des momentan Bearbeiteten Produktes
// Alle Paletten werden zwischengespeichert
ArrayList<HashMap<String, String>> Paletten = db.queryToMap("SELECT * FROM t_mindesthaltbarkeit WHERE `f_ProduktID` = " + VerkaufteID + " ORDER BY Menge");
int Zähler = 0; // in einer späteren for() schleife wird ein weiterer Zähler benötigt
for (int VerkaufteMenge = Integer.parseInt(Artikel.get("Menge")); VerkaufteMenge > 0; Zähler++) {
if (Paletten.size() > Zähler) {
// Der Rest auf einer Palette an Items
MengePalette = Integer.parseInt(Paletten.get(Zähler).get("Menge"));
if (VerkaufteMenge <= MengePalette) // Wenn mehr auf der einen Palette ist als verkauft wurde
{
MengePalette -= VerkaufteMenge;
VerkaufteMenge = 0; // Alles wurde entfernt und die Palette wurde neu beschrieben
} else // Wenn mehr verkauft wurde als auf der einen Palette war
{
VerkaufteMenge -= MengePalette;
// Die Palette wird gelert, und die Variable neu beschrieben, es wird die
// nächste Palette zu rate gezogen
MengePalette = 0;
}
db.execute("UPDATE t_mindesthaltbarkeit SET `Menge` = " + MengePalette
+ " WHERE t_mindesthaltbarkeit.`ID` = " + Paletten.get(Zähler).get("ID"));
db.execute("UPDATE t_lager SET `Menge` = " + MengePalette
+ " WHERE t_lager.`Paletten_ID` = " + Paletten.get(Zähler).get("ID"));
} else {
break;
}
}
}
}
/**
* Disposes of all items that have expired
*
* @author Johann
*/
public void disposeItems(SQLConnection db) {
ArrayList<HashMap<String, String>> Waren = db.queryToMap("SELECT t_mindesthaltbarkeit.ID, t_mindesthaltbarkeit.Haltbarkeit, t_mindesthaltbarkeit.Menge, t_artikel.Name FROM t_mindesthaltbarkeit INNER JOIN t_artikel ON t_mindesthaltbarkeit.f_ProduktID = t_artikel.ID");
// Waren liste wird erstellt
// Nach Produkten die verworfen werden müssen suchen
for (HashMap<String, String> Ware : Waren) {
LocalDate Datum2 = LocalDate.parse(Ware.get("Haltbarkeit")); // Das DAtum des wahrscheinlich nichtmehr
// Haltbaren abfragen
// Compare
if (this.currentTime.isAfter(Datum2)) // Abfagen ob das Item abgelaufen ist
{
int ID = Integer.parseInt(Ware.get("ID")); // Speichern welches Produkt abgelaufen ist
System.out.printf("Eine Pallette mit %s %s ist abgelaufen.\n", Ware.get("Menge"), Ware.get("Name"));
db.execute("UPDATE t_mindesthaltbarkeit SET `Menge` = '0' WHERE t_mindesthaltbarkeit.`ID` = "
+ ID); // produkt verwerfen
db.execute("UPDATE t_lager SET `Menge` = '0' WHERE t_lager.`Paletten_ID` = "
+ ID);
}
}
// Leere Paletten wegwerfen
Waren = db.queryToMap("SELECT * FROM t_mindesthaltbarkeit"); // Liste mit allen Palette wird aufgerufen
for (HashMap<String, String> Ware : Waren) {
if (Integer.parseInt(Ware.get("Menge")) == 0) // Wenn eine Palette leer ist
{
db.execute("DELETE FROM t_mindesthaltbarkeit WHERE t_mindesthaltbarkeit.`ID` = " + Ware.get("ID")); // Palette
// wir
// geleert
}
}
// Leere Paletten in der Haupttabelle werden verworfen
Waren = db.queryToMap("SELECT * FROM t_lager"); // Liste der Waren in der Haupttabelle wird erstellt
for (HashMap<String, String> Ware : Waren) {
if (Integer.parseInt(Ware.get("Menge")) == 0) // Leere Paletten werden gesucht
{
// leere Palette wird gelöscht
db.execute("DELETE FROM t_lager WHERE t_lager.`Lagerplatz` = " + Ware.get("Lagerplatz"));
}
}
}
/**
* Receive orders and puts them into storage
*
* @author Johann, Manuel
*/
public void receiveOrders(SQLConnection db) {
ArrayList<HashMap<String, String>> Angekommen = db.queryToMap(
"SELECT t_bestellungen.ID, f_Artikel_ID, Einkaufspreis, Ankunftsdatum, Menge, Marke, Name FROM t_bestellungen " +
"INNER JOIN t_artikel ON t_bestellungen.f_Artikel_ID = t_artikel.ID " +
"WHERE Ankunftsdatum <= ('" + this.currentTime.toString() + "')");
ArrayList<HashMap<String, String>> Artikel = db
.queryToMap("SELECT ID, `MHK in Tagen`, Anzahl_pro_Palette FROM t_artikel");
ArrayList<HashMap<String, String>> Haltbarkeit;
LocalDate HaltbarBis;
int MHKinTagen;
for (HashMap<String, String> row : Angekommen) {
int Artikel_ID = Integer.parseInt(row.get("f_Artikel_ID"));
MHKinTagen = Integer.parseInt(Artikel.get(Artikel_ID - 1).get("MHK in Tagen"));
if (MHKinTagen >= 0) {
HaltbarBis = this.currentTime.plusDays(MHKinTagen);
} else {
HaltbarBis = LocalDate.parse("9999-12-31");
}
int PalettenMenge = Integer.parseInt(Artikel.get(Artikel_ID - 1).get("Anzahl_pro_Palette"));
int BestellMenge = Integer.parseInt(row.get("Menge"));
while (BestellMenge > 0) {
int Menge = BestellMenge > PalettenMenge ? PalettenMenge : BestellMenge;
BestellMenge -= Menge;
db.execute("INSERT INTO t_mindesthaltbarkeit SET f_ProduktID = " + row.get("f_Artikel_ID")
+ ", Haltbarkeit = ('" + HaltbarBis.toString() + "')" + ", Menge = " + Menge);
Haltbarkeit = db.queryToMap("SELECT ID, f_ProduktID, Haltbarkeit, Menge FROM t_mindesthaltbarkeit");
String palettenID = Haltbarkeit.get(Haltbarkeit.size()-1).get("ID") ;
int lagerplatz = findStorageSpace(db);
db.execute("INSERT INTO t_lager SET Lagerplatz = " + lagerplatz + ", Paletten_ID = " + palettenID + ", f_Artikel_ID = "
+ row.get("f_Artikel_ID") + ", Ankunft = ('" + row.get("Ankunftsdatum") + "')" + ", Menge = "
+ Menge);
}
db.execute("DELETE FROM t_bestellungen WHERE ID = " + row.get("ID"));
}
while (Angekommen.size() > 0) {
BWLHelper.Bestellungen(db, this.currentTime, Angekommen, "Pascal");
}
}
/**
* Goes through all available storage locations and finds the first empty in
* line
*
* @author Manuel
*/
public int findStorageSpace(SQLConnection db) {
ArrayList<HashMap<String, String>> Lagerplätze = db.queryToMap("SELECT Lagerplatz FROM t_lager");
ArrayList<Integer> BelegteLagerplätze = new ArrayList<>(
Lagerplätze.stream().filter((map) -> map.containsKey("Lagerplatz"))
.map(map -> Integer.parseInt(map.get("Lagerplatz"))).collect(Collectors.toList()));
BelegteLagerplätze.sort((a, b) -> Integer.compare(a, b));
int val = 1;
for (int i = 0; i < BelegteLagerplätze.size(); i++) {
if (val < BelegteLagerplätze.get(i)) {
break;
} else {
val = BelegteLagerplätze.get(i) + 1;
}
}
return val;
}
/**
* Sorts storage to group products by type and removes gaps
*
* @author Johann
*/
public void sortStorage(SQLConnection db) {
ArrayList<HashMap<String, String>> products = db.queryToMap("SELECT ID FROM t_artikel");
int Lagerplatz = 1;
ArrayList<HashMap<String, String>> Waren = db.queryToMap("SELECT * FROM t_lager");
ArrayList<HashMap<String, String>> Waren_unverändert = db.queryToMap("SELECT * FROM t_lager");
String[][] Waren_sortiert = new String[Waren.size()][5];
for (HashMap<String, String> product : products) {
int productID = Integer.parseInt(product.get("ID"));
Waren = db.queryToMap("SELECT * FROM t_lager WHERE f_Artikel_ID = " + productID);
if (Waren.size() != 0) {
for (HashMap<String, String> Ware : Waren) {
Waren_sortiert[Lagerplatz - 1][0] = Integer.toString(Lagerplatz);
Waren_sortiert[Lagerplatz - 1][1] = Ware.get("Paletten_ID");
Waren_sortiert[Lagerplatz - 1][2] = Ware.get("f_Artikel_ID");
Waren_sortiert[Lagerplatz - 1][3] = Ware.get("Ankunft");
Waren_sortiert[Lagerplatz - 1][4] = Ware.get("Menge");
Lagerplatz++;
}
}
}
for (int u = 0; u <= Waren_sortiert.length - 1; u++) {
db.execute("UPDATE `t_lager` SET `Lagerplatz` = " + Waren_sortiert[u][0] + ", Paletten_ID = " + Waren_sortiert[u][1] + ", `f_Artikel_ID` = "
+ Waren_sortiert[u][2] + ", `Ankunft` = ('" + Waren_sortiert[u][3] + "')" + ", `Menge` = "
+ Waren_sortiert[u][4] + " WHERE `t_lager`.`Lagerplatz` = "
+ Waren_unverändert.get(u).get("Lagerplatz"));
}
System.out.println("Lager wurde sortiert.");
}
/**
* Check if items have to be restocked and order them accordingly
*
* @author Pascal
*/
public void checkStorage(SQLConnection db) {
ArrayList<HashMap<String, String>> produkte = db.queryToMap("SELECT * FROM t_artikel");
for (HashMap<String, String> produkt : produkte) {
int produktID = Integer.parseInt(produkt.get("ID"));
int sollbestand = Integer.parseInt(produkt.get("Sollbestand"));
int ZinsenProzent = 8;
if (sollbestand > 0) {
boolean sicherheitsbestand = produkt.get("Sicherheitsbestand") == "1";
BWLHelper.sys2(db, this.currentTime, produktID, 7, sollbestand, ZinsenProzent, sicherheitsbestand);
} else {
BWLHelper.sys1(db, this.currentTime, produktID, ZinsenProzent);
}
}
BWLHelper.lagerStatistik(db, this.currentTime.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR));
}
/**
* Summarises sales statistics in extra table
*
* @author Johann
*/
public void sortStatistics(SQLConnection db) {
ArrayList<HashMap<String, String>> products = db.queryToMap("SELECT ID FROM t_artikel");
ArrayList<HashMap<String, String>> Verkaufszahlen;
int KWoche = currentTime.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
int Verkauft;
db.execute("TRUNCATE t_verkaufszahlen");
for(int n = 1; n < KWoche; n++)
{
Verkaufszahlen = db.queryToMap("SELECT * FROM `t_statistik` WHERE `Woche` = " + n);
if(Verkaufszahlen.size() > 0)
{
for (HashMap<String, String> product : products) {
int productID = Integer.parseInt(product.get("ID"));
Verkauft = 0;
Verkaufszahlen = db.queryToMap("SELECT * FROM `t_statistik` WHERE `f_Artikel_ID` = " + productID + " AND `Woche` = " + n);
if(Verkaufszahlen.size() > 0)
{
for(int u = 0; u < Verkaufszahlen.size(); u++)
{
Verkauft += Integer.parseInt(Verkaufszahlen.get(u).get("Menge"));
}
db.execute("INSERT INTO `t_verkaufszahlen` (`ID`, `f_Artikel_ID`, `Woche`, `Menge`, `Verkaufspreis`) VALUES (NULL, '" + productID + "', '" + n + "', '" + Verkauft + "', '" + Verkaufszahlen.get(0).get("Verkaufspreis") + "')");
}
}
}
}
}
/**
* Simulate sales through random noise
*
* @author Manuel
*/
public void simulateSales(SQLConnection db) {
ArrayList<HashMap<String, String>> products = db.queryToMap("SELECT ID, Verkaufspreis, Anzahl_pro_Palette FROM t_artikel");
Random r = new Random();
for (HashMap<String, String> product : products) {
int productID = Integer.parseInt(product.get("ID"));
int variance = Integer.parseInt(product.get("Anzahl_pro_Palette"));
double stepSize = 52f * (r.nextDouble() + 0.00001) * 4;
double val = (1 + this.noise.eval(productID * 100, this.currentTime.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR) / stepSize)) / 20.0;
int sales = (int)(val * variance) + 1;
//TODO somewhere we should check if we have enough of a product in storage
db.execute("INSERT INTO t_statistik SET f_Artikel_ID = " + productID +
", Woche = " + this.currentTime.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR) +
", Menge = " + sales +
", Verkaufspreis = " + product.get("Verkaufspreis"));
}
}
}