private void PutIdleUsersAtCashiers() { var availableUsers = users.Where(u => u.Cashier == null).ToList(); if (availableUsers.Count == 0) { return; } // Any idle users, and any free cashier stations, and any non-served tickets? var availableCashiers = cashiers.Where(c => c.CurrentUser == null).ToList(); var servableSeviceTypes = serviceTypes.Where(st => st.Queue.HasTickets).ToList(); bool validOperation = (availableUsers.Count > 0) && (availableCashiers.Count > 0) && (servableSeviceTypes.Count > 0); if (!validOperation) { // This office is working at max capacity, or there are no waiting customers return; } float cashierOpenProbability = this.UserCashierOpeningsPerTick; TestRandom(cashierOpenProbability, () => { DummyUser idleUser = GetRandom(availableUsers); DummyCashier freeCashier = GetRandom(availableCashiers); DummyServiceType serviceType = GetRandom(servableSeviceTypes); Log("{0} manning {1}, dealing with {2}", idleUser, freeCashier, serviceType); freeCashier.Open(idleUser, serviceType); }); }
public void Open(DummyUser user, DummyServiceType serviceType) { if (CurrentUser != null) throw new InvalidOperationException("Cashier already occupied"); CurrentUser = user; ServiceType = serviceType; user.Cashier = this; }
public void Close() { if (CurrentTicket != null) throw new InvalidOperationException("Cannot close while in service"); CurrentUser.Cashier = null; CurrentUser = null; ServiceType = null; }
public void Open(DummyUser user, DummyServiceType serviceType) { if (CurrentUser != null) { throw new InvalidOperationException("Cashier already occupied"); } CurrentUser = user; ServiceType = serviceType; user.Cashier = this; }
private void CreateDummies() { logFallback = this.LogString; #region Service types and queues serviceTypes.Clear(); for (int i = 0; i < ServiceTypeCount; i++) { byte letterCharCode = (byte)(65 + i); char letter = Encoding.Default.GetChars(new[] { letterCharCode })[0]; var st = new DummyServiceType { Number = i + 1, TicketPrefix = letter.ToString() }; serviceTypes.Add(st); } #endregion #region Users users.Clear(); for (int i = 0; i < UserCount; i++) { users.Add(new DummyUser { Number = i + 1, Cashier = null }); } #endregion #region Cashiers cashiers.Clear(); for (int i = 0; i < CashierCount; i++) { cashiers.Add(new DummyCashier { Number = i + 1 }); } #endregion }
private void DoArrivingCustomers() { // Select a service type for the customer to request DummyServiceType st = GetRandom(serviceTypes); // Reduce willingness to enqueue where there are lots of ppl ahead in line float reconsideredProb = 1f; if (st.Queue.Count > 5) { reconsideredProb /= (st.Queue.Count - 5); } TestRandom(TicketsDispensedPerTick * reconsideredProb, () => { // Take a ticket in that ST, enqueue it var ticket = st.GetTicket(true); ticket.TaskDuration = GetRandomTaskDuration(); string durationDesc = ticket.TaskDuration.TotalSeconds > 5d ? string.Format(" (case dur.: {0}s)", (int)(ticket.TaskDuration.TotalSeconds)) : string.Empty; Log("New customer got ticket {0}{1}", ticket, durationDesc); }); }