public SimulationManager(string marker, int run, WorkshiftsCM workshiftsCM, TicketGenerationPlan plan, int daysToSimulate) { this.marker = marker; this.run = run; this.workshiftsCM = workshiftsCM; this.plan = plan; this.daysToSimulate = daysToSimulate; // Init Basic Tickers var shiftManager = new ShiftManagerTicker(this, workshiftsCM, inputQueue, doneQueue, Accounting); shiftManager.LogEvent += ShiftManager_LogEvent; Add(shiftManager); Add(new NewTicketTicker(plan, inputQueue)); // Needed for Grafana unixTimestamp = (Int32)((DateTimeOffset)DateTime.Today.ToUniversalTime()).ToUnixTimeSeconds(); }
public NewTicketTicker(TicketGenerationPlan plan, MultiLevelTicketQueue inputQueue) { tickets = plan.Tickets.OrderBy(t => t.createAtTicks).ToList(); this.inputQueue = inputQueue; }
public int Run() { init(); if (UseDatabase) { ConnectDb(); } else if (TruncateFirst || DropAndCreateFirst || ClearTablesForMarker) { Print("You cannot do any data operations without --usedb"); return(1); } EmployeeTypesCM employeeTypesCM = new EmployeeTypesCM(); employeeTypesCM.Load(EmployeeTypesFilename); WorkshiftsCM workshifts = new WorkshiftsCM(employeeTypesCM); workshifts.Load(WorkshiftsFilename); TicketGenerationPlan ticketGenerationPlan = new TicketGenerationPlan(); ticketGenerationPlan.Load(TicketGenerationPlan); Print("All files loaded"); Print(string.Format("Total tickets: {0}", ticketGenerationPlan.TotalTickets)); if (Days == null) { Days = ticketGenerationPlan.NumberOfDays; Print("Found {0} days in ticket plan", Days); } int run = 0; if (UseDatabase) { if (DropAndCreateFirst) { DropTables(true); CreateTables(); } if (TruncateFirst) { TruncateTables(); } if (ClearTablesForMarker) { Print("Deleted old datapoints (if exists) ({0})", DeleteDatapointsForMarker(Name)); Print("Deleted old summary (if exists) ({0})", DeleteSummariesForMarker(Name)); } var getRunNumberCmd = new MySqlCommand(string.Format("select ifnull(max(run),0) as max from datapoints where marker=@Marker", Statics.TableSummaries), conn); getRunNumberCmd.Parameters.Add("@Marker", MySqlDbType.VarChar).Value = Name; using (var getRunNumberCmdReader = getRunNumberCmd.ExecuteReader()) { getRunNumberCmdReader.Read(); run = getRunNumberCmdReader.GetInt32("max") + 1; } Print("Run number {0}", run); } SimulationManager sm = new SimulationManager(Name, run, workshifts, ticketGenerationPlan, Days.Value); if (UseDatabase) { sm.NewDatapoint += Sm_NewDatapoint; } if (Debug) { sm.LogEvent += Print; } sm.Run(); if (UseDatabase) { Print("Inserting {0} datapoints into db if connected", datapoints.Count); int inserts = 0; if (datapoints.Count > 0) { inserts += InternalMySqlHelper.GetBulkInsert(conn, "datapoints", datapoints.ToArray()).ExecuteNonQuery(); } Print("Inserts: {0}", inserts); } List <TicketEntity> tickets = ticketGenerationPlan.Tickets; SimulationSummary ss = new SimulationSummary( Name, run, tickets.Where(t => t.Solved).Count(), tickets.Where(t => t.Deployed).Count(), tickets.Where(t => t.Started).Count(), tickets.Count(), tickets.Where(t => !t.Solved && t.Difficulty == Models.SupportLevel.Level1st).Count(), tickets.Where(t => !t.Solved && t.Difficulty == Models.SupportLevel.Level2nd).Count(), tickets.Where(t => t.Solved).Any() ? tickets.Where(t => t.Solved).Average(i => i.Duration) : 0, sm.Accounting.TotalExpenses, sm.Accounting.TotalWorkingHours, sm.Accounting.TotalWorkingHours != 0? sm.Accounting.TotalExpenses / sm.Accounting.TotalWorkingHours : 0, tickets.Where(t => !t.Solved).Count() ); if (UseDatabase) { var summaryInsert = InternalMySqlHelper.GetInsert(conn, TablePrefix + Statics.TableSummaries, ss); Print("Insert summary ({0})", summaryInsert.ExecuteNonQuery()); } Print("Solved tickets: {0}/{1}", ss.SolvedTickets, ss.TotalTickets); Print("Deployed tickets: {0} ", ss.DeployedTickets); Print("Started tickets: {0} ", ss.StartedTickets); Print("Open 1st level tickets: {0} ", ss.Open1stLevelTickets); Print("Open 2nd level tickets: {0} ", ss.Open2ndLevelTickets); Print("Average Duration: {0} ", ss.AverageTicketSolveDuration); Print("Total Costs: {0:C} ", ss.TotalCosts); Print("Total Costs: {0:#,##0} h ", ss.TotalCosts); Print("Average hourly wage: {0:C}", ss.AverageHourlyWage); return(0); }
public int Run() { init(); var distributioGenerator = new TicketsPerDayDistributionGenerator(); distributioGenerator.Load(TicketsPerDayDistributionFileName); var g = new Normal(NumOfTickets, NumOfTickets / 100); var ticketsPerNDay = new TicketsPerNDays(); for (int day = 0; day < DaysToGenerate; day++) { int ticketsForThatDay = (int)g.Sample(); for (int h = 0; h < TicketsPerDayDistributionGenerator.HOURS_PER_DAY; h++) { var hourDist = Decimal.ToDouble(distributioGenerator.Get(h)) / 100; var gHourDist = new Normal(hourDist, hourDist >= 1 ? 0.1 : hourDist / 100); var ticketsForHour = gHourDist.Sample() * ticketsForThatDay; ticketsPerNDay.Set(day, h, (int)ticketsForHour); } } ticketsPerNDay.Save(FilenameTicketDistribution); Print("Generated Tickets per n day file"); int ticketNumber = 0; int ticks = 0; var gSupportLevel = new Normal(BoundaryConditions.LevelDistributionFactor, 1); TicketGenerationPlan tge = new TicketGenerationPlan(); for (int day = 0; day < DaysToGenerate; day++) { for (int h = 0; h < TicketsPerDayDistributionGenerator.HOURS_PER_DAY; h++) { var ticketsToSolve = ticketsPerNDay.Get(day, h); for (int t = 0; t < ticketsToSolve; t++) { var time = ticks + ((double)t / (double)ticketsToSolve) * (double)60; var supportLevel = SupportLevel.Level1st; if (gSupportLevel.Sample() >= 2) { supportLevel = SupportLevel.Level2nd; } var ticket = new TicketEntity(ticketNumber, supportLevel, GetLevelDifficulties(), (int)time); tge.Tickets.Add(ticket); ticketNumber++; } ticks += 60; } } var avg1StLevel = tge.Tickets.Average(i => i.DifficultyToSolveDurationMin[SupportLevel.Level1st]); var avg2ndLevel = tge.Tickets.Average(i => i.DifficultyToSolveDurationMin[SupportLevel.Level2nd]); var numOf1stLevel = tge.Tickets.Count(i => i.Difficulty == SupportLevel.Level1st); var numOf2ndLevel = tge.Tickets.Count(i => i.Difficulty == SupportLevel.Level2nd); var percentageOf1stLevel = (double)numOf1stLevel / (double)(numOf1stLevel + numOf2ndLevel) * 100; Console.WriteLine("Avg 1st: {0:0.00} ticks 2nd: {1:0.00} ticks Tickets: 1st: {2:0.00} ({3:0.00}%) 2nd: {4:0.00}", avg1StLevel, avg2ndLevel, numOf1stLevel, percentageOf1stLevel, numOf2ndLevel); tge.Save(FilenameTicketGeneration); return(0); }