public static bool IstFarbGruppe(this GruppenTyp gruppe) { return((gruppe & GruppenTyp.Gelb) == GruppenTyp.Gelb || (gruppe & GruppenTyp.Gruen) == GruppenTyp.Gruen || (gruppe & GruppenTyp.Rot) == GruppenTyp.Rot || (gruppe & GruppenTyp.Nest) == GruppenTyp.Nest); }
private void ChangePlanGruppeCommandExecute(GruppenTyp gt) { if (!CanChangePlanGruppeCommandExecute(gt)) { return; } Planzeit.Gruppe = gt; OnPropertyChanged(nameof(EingeteiltSollTyp)); OnPropertyChanged(nameof(Planzeit)); }
/// <summary> /// <SolidColorBrush x:Key="ColorGruppeGelb" Color="DarkGoldenrod"/> /// <SolidColorBrush x:Key="ColorGruppeGruen" Color="LightGreen"/> /// <SolidColorBrush x:Key="ColorGruppeRot" Color="LightCoral"/> /// <SolidColorBrush x:Key="ColorGruppeNest" Color="LightBlue"/> /// </summary> /// <param name="gruppe"></param> /// <returns></returns> public static SolidColorBrush GetFarbeFromResources(this GruppenTyp gruppe) { var farbe = new SolidColorBrush(); if (!gruppe.IstFarbGruppe()) { return(farbe); } var key = ""; switch (gruppe) { case GruppenTyp.Gelb: key = "ColorGruppeGelb"; break; case GruppenTyp.Gruen: key = "ColorGruppeGruen"; break; case GruppenTyp.Rot: key = "ColorGruppeRot"; break; case GruppenTyp.Nest: key = "ColorGruppeNest"; break; } try { var color = Application.Current.TryFindResource(key) as SolidColorBrush; if (color == null) { return(farbe); } farbe = color; return(farbe); } catch { return(farbe); } }
public static bool CheckKernzeitAbgedeckt(this Arbeitstag arbeitstag, GruppenTyp gruppe) { if (!gruppe.IstFarbGruppe()) { return(true); } var gruppenzeiten = arbeitstag.GetMitarbeiterArbeitszeiten(gruppe); if (gruppenzeiten.Count == 0) { return(false); } var tp = new TimePeriodCollection(gruppenzeiten); var obKernzeit = tp.HasInside(arbeitstag.KernzeitBasisRange); return(obKernzeit); }
/// <summary> /// Per Definition gilt das wenn mindestens eine Planzeit existiert das diese die KernzeitStart erfüllt /// Per Definition in der Planung können keine Lücken in der Kernzeit entstehen /// </summary> /// <param name="arbeitstag"></param> /// <param name="gruppe"></param> /// <param name="startzeitNichtAbgedeckt"></param> /// <param name="ticksNichtAbgedeckt"></param> /// <returns></returns> private static bool CheckKernzeitAbgedeckt(Arbeitstag arbeitstag, GruppenTyp gruppe, out DateTime startzeitNichtAbgedeckt, out short ticksNichtAbgedeckt) { startzeitNichtAbgedeckt = arbeitstag.KernzeitGruppeStart; ticksNichtAbgedeckt = (short)((arbeitstag.KernzeitGruppeEnde - arbeitstag.KernzeitGruppeStart).TotalMinutes / 15); if (!arbeitstag.CheckKernzeitAbgedeckt(gruppe)) { var planzeiten = new TimePeriodCollection(arbeitstag.GetMitarbeiterArbeitszeiten(gruppe)); var gapCalculator = new TimeGapCalculator <TimeRange>(new TimeCalendar()); var gap = gapCalculator.GetGaps(planzeiten, arbeitstag.KernzeitBasisRange).FirstOrDefault(); if (gap == null) { return(false); } startzeitNichtAbgedeckt = gap.Start; ticksNichtAbgedeckt = (short)(gap.Duration.TotalMinutes / 15); return(false); } return(true); }
private static void FillGruppenDiensteMitKernzeitPrio(List <Mitarbeiter> maList, Arbeitstag arbeitstag, GruppenTyp gruppe, List <Mitarbeiter> schonEingeteilt) { if (!arbeitstag.Planzeiten.Any(x => ((x.Dienst & DienstTyp.Frühdienst) == DienstTyp.Frühdienst || (x.Dienst & DienstTyp.AchtUhrDienst) == DienstTyp.AchtUhrDienst || (x.Dienst & DienstTyp.KernzeitStartDienst) == DienstTyp.KernzeitStartDienst) && (x.Gruppe & gruppe) == gruppe && !x.ErledigtDurch.IsHelfer)) { var ma = NextMitarbeiter(maList, schonEingeteilt, arbeitstag, ma4Diensttyp: DienstTyp.KernzeitStartDienst); if (ma == null) { return; } schonEingeteilt.Add(ma); var plan = CreatePlanItem(arbeitstag, ma, ma.DefaultGruppe, DienstTyp.KernzeitStartDienst); arbeitstag.Planzeiten.Add(plan); } //ab hier gibt es einen Frühen vogel :) DateTime startzeit; short ticks; while (!CheckKernzeitAbgedeckt(arbeitstag, gruppe, out startzeit, out ticks)) { var maKernzeitende = NextMitarbeiter(maList, schonEingeteilt, arbeitstag); if (maKernzeitende == null) { return; } var kernzeitEndeStart = arbeitstag.KernzeitGruppeEnde.AddMinutes(-1 * 15 * maKernzeitende.TagesQuarterTicks); if (kernzeitEndeStart < startzeit) { startzeit = kernzeitEndeStart; } schonEingeteilt.Add(maKernzeitende); var trMa = new TimeRange(startzeit, startzeit.AddMinutes(15 * maKernzeitende.TagesQuarterTicks)); var planKernzeitende = CreatePlanItem(arbeitstag, maKernzeitende, maKernzeitende.DefaultGruppe, DienstTyp.KernzeitEndeDienst, trMa); arbeitstag.Planzeiten.Add(planKernzeitende); } //ab hier gibts ein "Frühen Dienst" und wenn möglich ein Dienst bis Kernzeitende oder drüber var ma9 = NextMitarbeiter(maList, schonEingeteilt, arbeitstag, ma4Diensttyp: DienstTyp.NeunUhrDienst); if (ma9 == null) { return; } schonEingeteilt.Add(ma9); var plan9 = CreatePlanItem(arbeitstag, ma9, ma9.DefaultGruppe, DienstTyp.NeunUhrDienst); arbeitstag.Planzeiten.Add(plan9); var ma10 = NextMitarbeiter(maList, schonEingeteilt, arbeitstag, ma4Diensttyp: DienstTyp.ZehnUhrDienst); if (ma10 == null) { return; } schonEingeteilt.Add(ma10); var plan10 = CreatePlanItem(arbeitstag, ma10, ma10.DefaultGruppe, DienstTyp.ZehnUhrDienst); arbeitstag.Planzeiten.Add(plan10); //hmm wenn immernoch welche übrig sind dann, halt um 9Uhr kommen while (true) { var ma = NextMitarbeiter(maList, schonEingeteilt, arbeitstag, ma4Diensttyp: DienstTyp.NeunUhrDienst); if (ma == null) { return; } schonEingeteilt.Add(ma); var plan = CreatePlanItem(arbeitstag, ma, ma.DefaultGruppe, DienstTyp.NeunUhrDienst); arbeitstag.Planzeiten.Add(plan); } }
private static PlanItem CreatePlanItem(Arbeitstag arbeitstag, Mitarbeiter ma, GruppenTyp gruppe, DienstTyp dienst, TimeRange vorgabe = null) { #region Planzeit ausrechnen var duration = ma.TagesQuarterTicks * 15; var start = arbeitstag.KernzeitGruppeStart; var ende = arbeitstag.KernzeitGruppeEnde; switch (dienst) { case DienstTyp.Frühdienst: start = arbeitstag.Frühdienst; ende = arbeitstag.Frühdienst.AddMinutes(duration); break; case DienstTyp.AchtUhrDienst: start = arbeitstag.AchtUhrDienst; ende = arbeitstag.AchtUhrDienst.AddMinutes(duration); break; case DienstTyp.KernzeitStartDienst: start = arbeitstag.KernzeitGruppeStart; ende = arbeitstag.KernzeitGruppeStart.AddMinutes(duration); break; case DienstTyp.NeunUhrDienst: start = arbeitstag.NeunUhrDienst; ende = arbeitstag.NeunUhrDienst.AddMinutes(duration); break; case DienstTyp.ZehnUhrDienst: start = arbeitstag.ZehnUhrDienst; ende = arbeitstag.ZehnUhrDienst.AddMinutes(duration); break; case DienstTyp.FsjFrühdienst: start = arbeitstag.FrühdienstFsj; ende = arbeitstag.FrühdienstFsj.AddMinutes(duration); break; case DienstTyp.FsjKernzeitdienst: start = arbeitstag.NormaldienstFsj; ende = arbeitstag.NormaldienstFsj.AddMinutes(duration); break; case DienstTyp.FsjSpätdienst: start = arbeitstag.SpätdienstEndeFsj.AddMinutes(-1 * duration); ende = arbeitstag.SpätdienstEndeFsj; break; case DienstTyp.KernzeitEndeDienst: start = arbeitstag.KernzeitGruppeEnde.AddMinutes(-1 * duration); ende = arbeitstag.KernzeitGruppeEnde; break; case DienstTyp.SechszehnUhrDienst: start = arbeitstag.SechzehnUhrDienst.AddMinutes(-1 * duration); ende = arbeitstag.SechzehnUhrDienst; break; case DienstTyp.SpätdienstEnde: start = arbeitstag.SpätdienstEnde.AddMinutes(-1 * duration); ende = arbeitstag.SpätdienstEnde; break; case DienstTyp.Frei: duration = ma.TagesSollMinuten; start = arbeitstag.KernzeitGruppeStart; ende = arbeitstag.KernzeitGruppeStart.AddMinutes(duration); break; default: break; } var zeitraum = new TimeRange(start, ende); #endregion var result = new PlanItem(); result.Arbeitstag = arbeitstag; result.ErledigtDurch = ma; result.Thema = ma?.DefaultThema ?? Themen.None; result.Zeitraum = vorgabe ?? zeitraum; result.Gruppe = gruppe; result.Dienst = dienst; result.SetHatGrossteam(); //Pausen mit Planen if (result.Zeitraum.Duration.TotalMinutes > 360) { if ((dienst & DienstTyp.KernzeitEndeDienst) == DienstTyp.KernzeitEndeDienst || (dienst & DienstTyp.SechszehnUhrDienst) == DienstTyp.SechszehnUhrDienst || (dienst & DienstTyp.SpätdienstEnde) == DienstTyp.SpätdienstEnde || (dienst & DienstTyp.FsjSpätdienst) == DienstTyp.FsjSpätdienst) { result.Zeitraum.Start = result.Zeitraum.Start.AddMinutes(-1 * 30); } else { result.Zeitraum.End = result.Zeitraum.End.AddMinutes(30); } } //Endzeiten einhalten AdjustEndzeitEnde(result); return(result); }
private static Mitarbeiter NextMitarbeiter(IList <Mitarbeiter> alleDieDaSind, IList <Mitarbeiter> schonEingeteilt, Arbeitstag arbeitstag, Arbeitswoche woche = null, DienstTyp ma4Diensttyp = DienstTyp.None, GruppenTyp etage = GruppenTyp.Gelb | GruppenTyp.Gruen | GruppenTyp.Nest | GruppenTyp.Rot) { var arbeitstagPlanzeiten = arbeitstag.Planzeiten.ToList(); var topf = alleDieDaSind.Except(schonEingeteilt).Where(x => x.DefaultGruppe.IstFarbGruppe()).ToList(); if (topf.Count == 0) { return(null); } //alle die nicht allein sind in der gruppe var sonderTopf = topf.ToList(); var mitarbeiter = new List <Mitarbeiter>(); //Wenn RandDienst dann gilt erstmal die Wunschdienst REgel zwingend if (ma4Diensttyp.IstRandDienst()) { mitarbeiter = sonderTopf = topf.Where(x => (x.Wunschdienste & ma4Diensttyp) == ma4Diensttyp).ToList(); } //erstma gucken für die ganz RandRand Dienste //alle verfügbaren wo mehr als einer noch in der Gruppe ist //und in der Gruppe darf noch keiner einen RandRandDienst haben if (sonderTopf.Count == 0 && ma4Diensttyp.IstRandRandDienst()) { sonderTopf = topf.GroupBy(x => x.DefaultGruppe).Where(x => x.Count() > 1) .SelectMany(x => x.Where(ma => !arbeitstagPlanzeiten.Any(y => y.Gruppe == ma.DefaultGruppe && y.Dienst.IstRandRandDienst()))).ToList(); } //dann gucken für die ganz Rand Dienste if (sonderTopf.Count == 0 && ma4Diensttyp.IstRandDienst()) { sonderTopf = topf.GroupBy(x => x.DefaultGruppe).Where(x => x.Count() > 1) .SelectMany(x => x.Where(ma => !arbeitstagPlanzeiten.Any(y => y.Gruppe == ma.DefaultGruppe && y.Dienst.IstRandDienst()))).ToList(); } //Probieren einen zu Finden aus einer Gruppen die noch keinen Randdienst hat if (sonderTopf.Count == 0 && ma4Diensttyp.IstRandDienst()) { sonderTopf = topf.GroupBy(x => x.DefaultGruppe) .SelectMany(x => x.Where(ma => !arbeitstagPlanzeiten.Any(y => y.Gruppe == ma.DefaultGruppe && y.Dienst.IstRandDienst()))).ToList(); } //die mit Wunschdienst aus Etage if (mitarbeiter.Count == 0) { mitarbeiter = sonderTopf.Where(x => (x.Wunschdienste & ma4Diensttyp) == ma4Diensttyp && (etage & x.DefaultGruppe) == x.DefaultGruppe).ToList(); } //die von Etage if (mitarbeiter.Count == 0) { mitarbeiter = sonderTopf.Where(x => (etage & x.DefaultGruppe) == x.DefaultGruppe).ToList(); } //Wunschdienst if (mitarbeiter.Count == 0) { mitarbeiter = sonderTopf.Where(x => (x.Wunschdienste & ma4Diensttyp) == ma4Diensttyp).ToList(); } //Wenn mit der RandDienstlogik niemand gefunden wurde, dann vllt vorher nochmal schauen ob ein Wunschdienstler Lust hat if (mitarbeiter.Count == 0 && ma4Diensttyp.IstRandDienst()) { sonderTopf = topf.Where(x => (x.Wunschdienste & ma4Diensttyp) == ma4Diensttyp).ToList(); } if (mitarbeiter.Count == 0) { mitarbeiter = sonderTopf; } if (mitarbeiter.Count == 0)//bei allen gucken wenn keiner will { mitarbeiter = topf; } //RandDienste Gleichverteilen über die Woche if (woche != null && ma4Diensttyp.IstRandDienst()) { var geplanteRanddienste = woche.Arbeitstage.SelectMany(x => x.Planzeiten.Where(p => p.Dienst == ma4Diensttyp)).ToList(); var mitarbeiterMitRanddiensten = geplanteRanddienste.Select(x => x.ErledigtDurch).Distinct().ToList(); //irgendein Mitarbeiter da, der noch gar nix hat if (mitarbeiter.Except(mitarbeiterMitRanddiensten).Any()) { mitarbeiter = mitarbeiter.Except(mitarbeiterMitRanddiensten).ToList(); } else { var mitarbeiterMitAnzahlRanddienstInderWoche = geplanteRanddienste.GroupBy(g => g.ErledigtDurch).ToDictionary(x => x.Key, c => c.Count()); var minCount = mitarbeiterMitAnzahlRanddienstInderWoche.Min(x => x.Value); var mitarbeiterMitWenigstenCounts = mitarbeiterMitAnzahlRanddienstInderWoche.Where(x => x.Value == minCount).Select(x => x.Key).ToList(); var mitarbeiterMitMehrcounts = mitarbeiterMitAnzahlRanddienstInderWoche.Where(x => x.Value != minCount).Select(x => x.Key).ToList(); if (mitarbeiter.Intersect(mitarbeiterMitWenigstenCounts).Any()) { mitarbeiter = mitarbeiter.Intersect(mitarbeiterMitWenigstenCounts).ToList(); } else if (mitarbeiter.Except(mitarbeiterMitRanddiensten.Except(mitarbeiterMitMehrcounts)).Any()) { mitarbeiter = mitarbeiter.Except(mitarbeiterMitRanddiensten.Except(mitarbeiterMitMehrcounts)).ToList(); } //sofern noch einer übrig bleibt soll derjenige der am Vortag das gemacht, nicht nochmal dran sein var vortag = woche.Arbeitstage.Single(x => x.Datum == arbeitstag.Datum.AddDays(-1)); var letzte = vortag?.Planzeiten?.Where(x => x.Dienst == ma4Diensttyp).Select(x => x.ErledigtDurch).ToList() ?? new List <Mitarbeiter>(); if (mitarbeiter.Except(letzte).Any()) { mitarbeiter = mitarbeiter.Except(letzte).ToList(); } } //am gleichen Tag vllt nicht unbedingt auch noch aus der gleichen gruppe var ma4Gruppencheck = arbeitstag.Planzeiten.Where(x => x.Dienst == ma4Diensttyp).Select(x => x.ErledigtDurch).ToList(); var maGleicherGruppe = mitarbeiter.Where(x => ma4Gruppencheck.Any(m => m.DefaultGruppe == x.DefaultGruppe)).ToList(); if (mitarbeiter.Except(maGleicherGruppe).Any()) { mitarbeiter = mitarbeiter.Except(maGleicherGruppe).ToList(); } } int ichBinDran = Zufall.Next(0, mitarbeiter.Count); #if DEBUG Console.WriteLine($"{ma4Diensttyp}: {ichBinDran} von {mitarbeiter.Count}"); #endif return(mitarbeiter[ichBinDran]); }
/// <summary> /// Gibt die Mitarbeiter Arbeitszeiten für eine Arbeitstag und eine Gruppe zurück /// </summary> /// <param name="arbeitstag"></param> /// <param name="gruppe"></param> /// <returns></returns> public static IList <TimeRange> GetMitarbeiterArbeitszeiten(this Arbeitstag arbeitstag, GruppenTyp gruppe) { return (arbeitstag.Planzeiten .Where(x => x.Gruppe == gruppe && x.Dienst != DienstTyp.Frei && (!x.ErledigtDurch?.IsHelfer ?? false)) .Select(x => x.Zeitraum) .ToList()); }
/// <summary> /// Gibt die Mitarbeiter Planitems für eine Arbeitstag und eine Gruppe zurück /// </summary> /// <param name="arbeitstag"></param> /// <param name="gruppe"></param> /// <returns></returns> public static IList <PlanItem> GetMitarbeiterArbeitsplanzeiten(this Arbeitstag arbeitstag, GruppenTyp gruppe) { return (arbeitstag.Planzeiten.Where(x => x.Gruppe == gruppe && !x.ErledigtDurch.IsHelfer) .Select(x => x) .ToList()); }
public static bool CheckKernzeitDoppelBesetzungAbgedeckt(this Arbeitstag arbeitstag, GruppenTyp gruppe) { if (!gruppe.IstFarbGruppe()) { return(true); } var gruppenzeiten = arbeitstag.GetMitarbeiterArbeitszeiten(gruppe); if (gruppenzeiten.Count < 2) { return(false); } if (gruppenzeiten.Count == 2) { var anzDoppelBesetzung = 0; foreach (var range in gruppenzeiten) { var tp = new TimePeriodCollection(new List <ITimePeriod>() { range }); if (tp.HasInside(arbeitstag.KernzeitDoppelBesetzungRange)) { anzDoppelBesetzung++; } } return(anzDoppelBesetzung >= 2); } //07:00-11:00 //09:00-13:00 //11:00-16:00 var zeitzeiger = arbeitstag.KernzeitDoppelBesetzungRange.Start; while (zeitzeiger <= arbeitstag.KernzeitDoppelBesetzungRange.End) { var count = gruppenzeiten.Count(x => x.HasInside(zeitzeiger)); if (count < 2) { return(false); } zeitzeiger = zeitzeiger.AddMinutes(1); } return(true); }
private bool CanChangePlanGruppeCommandExecute(GruppenTyp gt) { return(Planzeit.Gruppe != gt); }