Skip to contentMethod: lambda$findeBestesSimulationsErgebnis$7()
1: package tagesplanung;
2:
3: import auftraege.Dokumentenklasse;
4: import auftraege.ProduktionsAuftrag;
5: import auftraege.auftragsBildungsParameter.abstraction.ProduktionsauftragsParameter;
6: import com.google.common.collect.Sets;
7: import maschine.Maschine;
8: import material.MaterialMitMessung;
9: import mensch.Mitarbeiter;
10: import produktionsauftrag.ProduktionsAuftragServiceImpl;
11: import produktionsauftrag.ProduktionsAuftragsService;
12: import rollenbelegung.ErmittelteBelegungen;
13: import rollenbelegung.MaschinenRollenbelegungService;
14: import rollenbelegung.Produktionsplaner;
15: import rollenbelegung.SortierParameter.MaschinenRollenbelegungServiceParameter;
16: import rollenbelegung.SortierParameter.MaschinenSortierParameter.MaschinenSortierParameter;
17: import rollenbelegung.SortierParameter.MitarbeiterSortierParameter.MitarbeiterSortierParameter;
18: import rollenbelegung.SortierParameter.ProduktionsAuftragsSortierParameter.ProduktionsAuftragSortierParameter;
19: import rollenbelegung.SortierParameter.ZuordnungsParameter;
20: import simulation.SimulationsErgebnis;
21: import simulation.SimulationsErgebnisBuilder;
22: import simulation.SimulationsService;
23: import simulation.SimulationsServiceImpl;
24: import simulation.exceptions.SimulationsException;
25: import util.Pair;
26:
27: import java.time.LocalDateTime;
28: import java.util.ArrayList;
29: import java.util.Arrays;
30: import java.util.Collection;
31: import java.util.HashMap;
32: import java.util.LinkedHashSet;
33: import java.util.List;
34: import java.util.Map;
35: import java.util.Set;
36: import java.util.stream.Collectors;
37:
38: /**
39: * Implementierung der Schnittstelle {@link TagesplanungsService}.
40: */
41: public class TagesplanungsServiceImpl implements TagesplanungsService {
42:         
43:         private final ProduktionsAuftragsService produktionsAuftragsService;
44:         private final MaschinenRollenbelegungService maschinenRollenbelegungService;
45:         private final SimulationsService simulationsService;
46:         private final LocalDateTime startZeit;
47:         
48:         /**
49:          * Standard-Konstruktor. nutzt für Zeitbezogene Methoden ein LocalDateTime.now().
50:          */
51:         public TagesplanungsServiceImpl() {
52:                 this(LocalDateTime.now());
53:         }
54:         
55:         /**
56:          * Konstruktor, bei welchem zeitbezogene Methoden eine benutzerdefinierte Startzeit angeben können.
57:          *
58:          * @param startZeit
59:          *                 benutzerdefinierte Startzeit.
60:          */
61:         public TagesplanungsServiceImpl(final LocalDateTime startZeit) {
62:                 this.startZeit = startZeit;
63:                 this.produktionsAuftragsService = new ProduktionsAuftragServiceImpl();
64:                 this.maschinenRollenbelegungService = new Produktionsplaner();
65:                 this.simulationsService = new SimulationsServiceImpl();
66:         }
67:         
68:         @Override
69:         public Pair<Collection<Dokumentenklasse>, SimulationsErgebnis> planeUndSimuliere(
70:                         final Collection<Dokumentenklasse> dokumentenklassen,
71:                         final Set<ProduktionsauftragsParameter> produktionsauftragsParameter,
72:                         final List<Maschine> maschinen,
73:                         final List<Mitarbeiter> mitarbeiter,
74:                         final MaschinenRollenbelegungServiceParameter maschinenRollenbelegungServiceParameter,
75:                         final Collection<MaterialMitMessung<?>> verfuegbaresMaterial) throws SimulationsException {
76:                 
77:                 // Produktionsaufträge erstellen
78:                 final Pair<Collection<Dokumentenklasse>, List<ProduktionsAuftrag>> ergebnisErstelleProduktionsauftraege =
79:                                 this.produktionsAuftragsService
80:                                 .erstelleProduktionsauftraege(produktionsauftragsParameter, dokumentenklassen);
81:                 final Collection<Dokumentenklasse> nichtZugeordneteDokumentenklassen =
82:                                 ergebnisErstelleProduktionsauftraege.getFirst();
83:                 final List<ProduktionsAuftrag> erstellteProduktionsauftraege = ergebnisErstelleProduktionsauftraege.getSecond();
84:                 
85:                 // Belegungen finden
86:                 final ErmittelteBelegungen ermittelteBelegungen = this.maschinenRollenbelegungService.findeBelegungAberErzeugeKeineKalendereintraege(
87:                                 maschinen,
88:                                 mitarbeiter,
89:                                 erstellteProduktionsauftraege,
90:                                 maschinenRollenbelegungServiceParameter);
91:                 
92:                 // Prüfen und Simulieren
93:                 final SimulationsErgebnis simulationsErgebnis =
94:                                 this.simulationsService.pruefeUndSimuliereProduktionsplanung(verfuegbaresMaterial, ermittelteBelegungen);
95:                 return Pair.create(nichtZugeordneteDokumentenklassen, simulationsErgebnis);
96:         }
97:         
98:         @Override
99:         public Pair<Set<ProduktionsauftragsParameter>, MaschinenRollenbelegungServiceParameter> findeOptimaleParameterAus(
100:                         final Collection<Dokumentenklasse> dokumentenklassen,
101:                         final List<Maschine> maschinen,
102:                         final List<Mitarbeiter> mitarbeiter,
103:                         final Collection<MaterialMitMessung<?>> verfuegbaresMaterial,
104:                         final Set<ProduktionsauftragsParameter> produktionsauftragsParameter,
105:                         final MaschinenRollenbelegungServiceParameter maschinenRollenbelegungServiceParameter) {
106:                 final Map<Pair<Collection<Dokumentenklasse>, SimulationsErgebnis>, Pair<Set<ProduktionsauftragsParameter>,
107:                 MaschinenRollenbelegungServiceParameter>> ergebnisParameterMap = new HashMap<>();
108:                 
109:                 final List<Pair<Set<ProduktionsauftragsParameter>, MaschinenRollenbelegungServiceParameter>> parameterVariationen =
110:                                 this.erzeugeParameterVariationenAus(produktionsauftragsParameter, maschinenRollenbelegungServiceParameter);
111:                 
112:                 for (final Pair<Set<ProduktionsauftragsParameter>, MaschinenRollenbelegungServiceParameter> parameterVariation : parameterVariationen) {
113:                         
114:                         final Set<ProduktionsauftragsParameter> produktionsauftragsParameterVariation = parameterVariation.getFirst();
115:                         final MaschinenRollenbelegungServiceParameter maschinenRollenbelegungServiceParameterVariation = parameterVariation.getSecond();
116:                         try {
117:                                 // Produktionsaufträge erstellen, Belegungen finden, Prüfen und Simulieren
118:                                 final Pair<Collection<Dokumentenklasse>, SimulationsErgebnis> ergebnisPlaneUndSimuliere = this.planeUndSimuliere(
119:                                                 dokumentenklassen,
120:                                                 produktionsauftragsParameterVariation,
121:                                                 maschinen,
122:                                                 mitarbeiter,
123:                                                 maschinenRollenbelegungServiceParameterVariation,
124:                                                 verfuegbaresMaterial);
125:                                 // Tue das Ergebnis mit der gewählten Parameterbelegung in die ErgebnisMap
126:                                 ergebnisParameterMap.put(
127:                                                 Pair.create(ergebnisPlaneUndSimuliere.getFirst(), ergebnisPlaneUndSimuliere.getSecond()),
128:                                                 Pair.create(produktionsauftragsParameterVariation, maschinenRollenbelegungServiceParameterVariation));
129:                         } catch (final SimulationsException e) {
130:                                 // empty
131:                         }
132:                 }
133:                 // finde das beste Ergebnis
134:                 final Pair<Collection<Dokumentenklasse>, SimulationsErgebnis> bestesErgebnis = this.findeBestesErgebnis(ergebnisParameterMap.keySet());
135:                 // gib die Parameter des besten Ergebnisses zurück
136:                 return ergebnisParameterMap.get(bestesErgebnis);
137:         }
138:         
139:         
140:         @Override
141:         public Pair<Collection<Dokumentenklasse>, SimulationsErgebnis> planeUndSimuliereMitOptimalenParameternAus(
142:                         final Collection<Dokumentenklasse> dokumentenklassen,
143:                         final List<Maschine> maschinen,
144:                         final List<Mitarbeiter> mitarbeiter,
145:                         final Collection<MaterialMitMessung<?>> verfuegbaresMaterial,
146:                         final Set<ProduktionsauftragsParameter> produktionsauftragsParameter,
147:                         final MaschinenRollenbelegungServiceParameter maschinenRollenBelegungServiceParameter) {
148:                 
149:                 final Pair<Set<ProduktionsauftragsParameter>, MaschinenRollenbelegungServiceParameter> optimaleParameter =
150:                                 this.findeOptimaleParameterAus(
151:                                                 dokumentenklassen,
152:                                                 maschinen,
153:                                                 mitarbeiter,
154:                                                 verfuegbaresMaterial,
155:                                                 produktionsauftragsParameter,
156:                                                 maschinenRollenBelegungServiceParameter);
157:                 return this.planeUndSimuliere(
158:                                 dokumentenklassen,
159:                                 optimaleParameter.getFirst(),
160:                                 maschinen,
161:                                 mitarbeiter,
162:                                 optimaleParameter.getSecond(),
163:                                 verfuegbaresMaterial);
164:         }
165:         
166:         /**
167:          * Erzeugt auf Basis der übergebenen produktionsauftragsParameter und maschinenRollenbelegungServiceParameter alle möglichen auf Teilmengenbildung
168:          * basierenden Parameterkombinationen.
169:          *
170:          * @param produktionsauftragsParameter
171:          *                 deren Potenzmenge gebildet wird
172:          * @param maschinenRollenbelegungServiceParameter
173:          *                 deren Potenzmenge gebildet wird
174:          *
175:          * @return Potenzmenge aller zu variierenden Parameter
176:          */
177:         public List<Pair<Set<ProduktionsauftragsParameter>, MaschinenRollenbelegungServiceParameter>> erzeugeParameterVariationenAus(
178:                         final Set<ProduktionsauftragsParameter> produktionsauftragsParameter,
179:                         final MaschinenRollenbelegungServiceParameter maschinenRollenbelegungServiceParameter) {
180:                 return this.kombiniereProduktionsauftragsParameterUndMaschinenRollenbelegungServiceParameter(
181:                                 this.erzeugeProduktionsauftragsParameterVariationenAus(produktionsauftragsParameter),
182:                                 this.erzeugeMaschinenRollenbelegungServiceParameterVariationenAus(maschinenRollenbelegungServiceParameter));
183:         }
184:         
185:         
186:         /**
187:          * Bildet alle möglichen Kombinationen aus den Elementen der übergebenen Collections.
188:          *
189:          * @param produktionsauftragsParameterVaritionen
190:          *                 die mit {@link MaschinenRollenbelegungServiceParameter}n kombiniert werden
191:          * @param maschinenRollenbelegungServiceParameterVaritionen
192:          *                 die mit {@link ProduktionsauftragsParameter}n kombiniert werden
193:          *
194:          * @return {@link Collection} von {@link Pair} die alle möglichen Kombinationen enthält
195:          */
196:         private List<Pair<Set<ProduktionsauftragsParameter>, MaschinenRollenbelegungServiceParameter>>
197:         kombiniereProduktionsauftragsParameterUndMaschinenRollenbelegungServiceParameter(
198:                         final List<Set<ProduktionsauftragsParameter>> produktionsauftragsParameterVaritionen,
199:                         final List<MaschinenRollenbelegungServiceParameter> maschinenRollenbelegungServiceParameterVaritionen) {
200:                 
201:                 return produktionsauftragsParameterVaritionen.stream().flatMap(produktionsauftragsParameter ->
202:                 maschinenRollenbelegungServiceParameterVaritionen.stream()
203:                 .map(maschinenRollenbelegungServiceParameter -> Pair.create(produktionsauftragsParameter, maschinenRollenbelegungServiceParameter))
204:                                 ).collect(Collectors.toList());
205:         }
206:         
207:         
208:         /**
209:          * Erzeugt alle möglichen Parameterkombinationen zu den übergebenen {@link ProduktionsauftragsParameter}n.
210:          *
211:          * @param produktionsauftragsParameter
212:          *                 , die variiert werden
213:          *
214:          * @return Potenzmenge der übergenen {@link ProduktionsauftragsParameter}
215:          */
216:         private List<Set<ProduktionsauftragsParameter>> erzeugeProduktionsauftragsParameterVariationenAus(
217:                         final Set<ProduktionsauftragsParameter> produktionsauftragsParameter) {
218:                 return new ArrayList<>(Sets.powerSet(produktionsauftragsParameter));
219:         }
220:         
221:         /**
222:          * Erzeugt auf Basis der übergebenen {@link MaschinenRollenbelegungServiceParameter} alle möglichen Parameterkombinationen.
223:          *
224:          * @return Potenzmenge aller übergebenen {@link MaschinenRollenbelegungServiceParameter}.
225:          */
226:         private List<MaschinenRollenbelegungServiceParameter> erzeugeMaschinenRollenbelegungServiceParameterVariationenAus(
227:                         final MaschinenRollenbelegungServiceParameter maschinenRollenbelegungServiceParameter) {
228:                 
229:                 final List<List<ProduktionsAuftragSortierParameter>> produktionsAuftragSortierParameterVariationen =
230:                                 Sets.powerSet(new LinkedHashSet<>(maschinenRollenbelegungServiceParameter.getProduktionsAuftragsSortierungsarten())).stream()
231:                                 .map(ArrayList::new).collect(Collectors.toList());
232:                 
233:                 final List<List<MaschinenSortierParameter>> maschinenSortierParameterVariationen =
234:                                 Sets.powerSet(new LinkedHashSet<>(maschinenRollenbelegungServiceParameter.getMaschinenSortierungsarten())).stream()
235:                                 .map(ArrayList::new)
236:                                 .collect(Collectors.toList());
237:                 
238:                 final List<List<MitarbeiterSortierParameter>> mitarbeiterSortierParameterVariationen =
239:                                 Sets.powerSet(new LinkedHashSet<>(maschinenRollenbelegungServiceParameter.getMitarbeiterSortierungsarten())).stream()
240:                                 .map(ArrayList::new).collect(Collectors.toList());
241:                 final List<ZuordnungsParameter> zuordnungsParameterVariationen = Arrays.asList(ZuordnungsParameter.values());
242:                 
243:                 return produktionsAuftragSortierParameterVariationen.stream()
244:                                 .flatMap(
245:                                                 produktionsSortierVariation -> maschinenSortierParameterVariationen.stream().flatMap(
246:                                                                 maschinenSortierVariation -> mitarbeiterSortierParameterVariationen.stream()
247:                                                                 .flatMap(
248:                                                                                 mitarbeiterSortierVariation -> zuordnungsParameterVariationen.stream().map(
249:                                                                                                 zuordnungsParameterVariation -> new MaschinenRollenbelegungServiceParameter(
250:                                                                                                                 produktionsSortierVariation, maschinenSortierVariation, mitarbeiterSortierVariation,
251:                                                                                                                 zuordnungsParameterVariation,
252:                                                                                                                 maschinenRollenbelegungServiceParameter.getStartZeit())))))
253:                                 .collect(Collectors.toList());
254:         }
255:         
256:         
257:         /**
258:          * Findet das beste Ergebnis aus der Kombination von {@link Collection}s von Dokumentenklassen und {@link SimulationsErgebnis}sen. Dabei werden die übrigen
259:          * Dokumentenklassen dem {@link SimulationsErgebnis} als nichtEingehalteneSLAs dem {@link SimulationsErgebnis} hinzugefügt.
260:          *
261:          * @param uebrigeDokumentenklassenUndSimulationsErgebnisse
262:          *                 Kombination von {@link Collection}s von Dokumentenklassen und {@link SimulationsErgebnis}sen
263:          *
264:          * @return die beste Kombination von {@link Dokumentenklasse}-{@link Collection} und {@link SimulationsErgebnis}
265:          */
266:         private Pair<Collection<Dokumentenklasse>, SimulationsErgebnis> findeBestesErgebnis(
267:                         final Set<Pair<Collection<Dokumentenklasse>, SimulationsErgebnis>> uebrigeDokumentenklassenUndSimulationsErgebnisse) {
268:                 
269:                 final Map<SimulationsErgebnis, Pair<Collection<Dokumentenklasse>, SimulationsErgebnis>> bestesErgebnisMap =
270:                                 new HashMap<>();
271:                 
272:                 final SimulationsErgebnisBuilder builder = SimulationsErgebnisBuilder.create();
273:                 uebrigeDokumentenklassenUndSimulationsErgebnisse.forEach(e -> {
274:                         final Collection<Dokumentenklasse> uebrigeDokumentenklassen = e.getFirst();
275:                         final SimulationsErgebnis simulationsErgebnis = e.getSecond();
276:                         uebrigeDokumentenklassen.addAll(simulationsErgebnis.getNichtEingehalteneSlas());
277:                         builder.pruefErgebnis(simulationsErgebnis.getPruefErgebnis()).verbrauchteZeitProProduktionsAuftrag(
278:                                         simulationsErgebnis.getVerbrauchteZeitProProduktionsAuftrag())
279:                         .auslastungProMaschine(simulationsErgebnis.getAuslastungProMaschine())
280:                         .auslastungProMitarbeiter(simulationsErgebnis.getAuslastungProMitarbeiter())
281:                         .nichtEingehalteneSlas(uebrigeDokumentenklassen);
282:                         bestesErgebnisMap.put(builder.build(), e);
283:                 });
284:                 
285:                 final SimulationsErgebnis bestesSimulationsErgebnis =
286:                                 this.findeBestesSimulationsErgebnis(bestesErgebnisMap.keySet());
287:                 
288:                 return bestesErgebnisMap.get(bestesSimulationsErgebnis);
289:         }
290:         
291:         
292:         /**
293:          * Findet aus dem übergebenem {@link Set} das beste bzw. größte {@link SimulationsErgebnis}
294:          *
295:          * @param simulationsErgebnisse
296:          *                 Menge von SimulationsErgebnissen
297:          *
298:          * @return das beste {@link SimulationsErgebnis}
299:          */
300:         private SimulationsErgebnis findeBestesSimulationsErgebnis(final Set<SimulationsErgebnis> simulationsErgebnisse) {
301:                 return simulationsErgebnisse.stream().max(SimulationsErgebnis::compareTo)
302:                                 .orElseThrow(() -> new SimulationsException("Das übergebene Set ist leer!"));
303:         }
304:         
305: }