/// <summary> /// Gets a Call from a Queue for a Representative of the given type /// </summary> /// <param name="repType">The SalesRepType that the call is being retrieved for</param> /// <returns>A Call from a queue, or null if there are no calls in the queue</returns> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the given ProductType cannot handle any of the ProductTypes that have Queues</exception> /// <exception cref="System.ArgumentNullException">Thrown when the given SalesRepType is null</exception> public Call GetCallForRepType(SalesRepType repType) { //If the given repType is null if (repType != null) { //Get a list of queues that have types that match the SalesRepTypes Handleable ProductTypes var matchedQueues = from q in queues where repType.Handles.Contains(q.TypeInQueue) select q; //If at least one queue matched one of the reptypes Handleable ProductTypes if (matchedQueues.Count() > 0) { //Get the list from the matchedQueues that is the longest Queue longest = matchedQueues.Aggregate((q1, q2) => (q1.Calls.Count > q2.Calls.Count) ? q1 : q2); //Return the popped call from the longest queue return(longest.Dequeue()); } else // No Queues matched { throw new ArgumentOutOfRangeException("repType", "Attempted to pass a repType couldn't handle any of the Queues productTypes"); } } else // The repType was null { throw new ArgumentNullException("repType", "Attempted to pass null SalesRepType to GetCallForRepType"); } }
/// <summary> /// Gets a SalesRepresentative that can handle the given type of product /// </summary> /// <param name="productType">The type of product</param> /// <returns>A SalesRepresentative that can handle the given ProductType. Null if no SalesRep was found</returns> /// <exception cref="System.ArgumentNullException">Thrown when the given product type is null</exception> public SalesRepresentative GetRepresentativeForProductType(ProductType productType) { // If the given product type is not null if (productType != null) { //Get the list of SalesRepTypes that can handle this product type var matching = from srt in salesForce.Keys where srt.Handles.Contains(productType) select srt; //If the number of matching SalesRepTypes is at least one if (matching.Count() > 0) { //Get the SalesRepType that has the least number of busy sales reps SalesRepType leastUtilised = matching.Aggregate((srt1, srt2) => (RepresentativesOfType(srt1) - RepresentativesBusy(srt1)) > (RepresentativesOfType(srt2) - RepresentativesBusy(srt2)) ? srt1 : srt2); return(GetFreeSalesRep(leastUtilised)); } else // No such SalesRepType exists that can handle this product type { return(null); } } else // The given productType is null { throw new ArgumentNullException("productType", "Attempted to pass null ProductType to SalesForceManager.GetRepresentativeForProductType"); } }
/// <summary> /// Updates the ListBoxes for ProductTypes on the Representatives TabPage /// </summary> /// <param name="sender">The object that triggered this event</param> /// <param name="e">The events EventArgs</param> private void UpdateRepTypeProductLists(object sender, EventArgs e) { //Clear both listBoxes listHandles.Items.Clear(); listProductTypes.Items.Clear(); //Get the currently selected SalesRepType in the salesRep listbox SalesRepType srt = (SalesRepType)listRepTypes.SelectedItem; //If there is a selected SalesRepType if (srt != null) { //Set the Handles listboxes display member listHandles.DisplayMember = "TypeName"; //Loop foreach ProductType in the SalesRepTypes handles list foreach (ProductType pt in srt.Handles) { //Add the ProductType to the handles listbox listHandles.Items.Add(pt); } //Set the productType listboxes display member listProductTypes.DisplayMember = "TypeName"; //Foreach ProductType in the list of ProductTypes that is not in the SalesRepTypes handles list foreach (ProductType pt in gov.ProductTypes.Where(pt => srt.Handles.Contains(pt) == false).ToList()) { //Add the ProductType to the ProductType Listbox listProductTypes.Items.Add(pt); } //Set the NumericUpDowns value nudRepNumber.Value = gov.RepNums[srt]; } }
/// <summary> /// Adds the given ProductType to the SalesRepTypes Handles list /// </summary> /// <param name="repType">The SalesRepType that the ProductType is being added to</param> /// <param name="toHandle">The ProductType to add to the handles list</param> public void AddRepTypeHandle(SalesRepType repType, ProductType toHandle) { //Check that the given repType is not null if (repType != null) { //Check that the given ProductType is not null if (toHandle != null) { // Check that the given reptype is actually in the Dictionary if (repNums.Keys.Contains(repType)) { // Add the ProductType to the Handles list of the matching Dictionary key repNums.Keys.FirstOrDefault(srt => srt == repType).Handles.Add(toHandle); // trigger the RepTypesChanged Event OnRepTypesChanged(); } else // The given SalesRepType is not in the Dictionary { throw new ArgumentOutOfRangeException("repType", "Attmepted to add a ProductType to a SalesRepType that was not in the Dictionary"); } } else // The given product type is null { throw new ArgumentNullException("toHandle", "Attempted to pass null ProductType to Core.AddRepTypeHandle"); } } else // The given sales rep type is null { throw new ArgumentNullException("repType", "Attempted to pass null SalesRepType to Core.AddRepTypeHandle"); } }
//------------------------------------------------------------------- //- METHODS - //------------------------------------------------------------------- /// <summary> /// Creates an new instance of the SalesRepresentative class /// </summary> /// <param name="repType">The SalesRepType of this SalesRepresentative</param> public SalesRepresentative(SalesRepType repType) { // Check that the given SalesRepType is not null if (repType != null) { this.repType = repType; } else // The given SalesRepType is null { throw new ArgumentNullException("repType", "Attempted to pass null SalesRepType to SalesRepresentative constructor"); } }
/// <summary> /// Called when a Key is pressed down while the RepTypes list is in focus /// </summary> /// <param name="sender">The ListBox that triggered this event</param> /// <param name="e">The events KeyEventArgss</param> private void listRepTypes_KeyDown(object sender, KeyEventArgs e) { //Check if the pressed key was Delete or Backspace if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete) { //If it was then get the RepresentativeType that was selected in the list SalesRepType repType = (SalesRepType)listRepTypes.SelectedItem; //Remove this RepType from the Core gov.RemoveRepType(repType); } //Else do nothing }
/// <summary> /// Called when the Representative number numericupdown's value changes /// </summary> /// <param name="sender">The NumericUpDown that triggered this event</param> /// <param name="e">The events EventArgs</param> private void nudRepNumber_ValueChanged(object sender, EventArgs e) { //Get the currently selected SalesRepType SalesRepType selected = listRepTypes.SelectedItem as SalesRepType; //If there was a selected repType if (selected != null) { //If the repNums dictionary contains this reptype as a key if (gov.RepNums.ContainsKey(selected)) { //Set the new number of representatives gov.RepNums[selected] = (int)nudRepNumber.Value; } } }
/// <summary> /// Removes the given SalesRepType from the dictionary /// </summary> /// <param name="type">The SalesRepType to remove</param> public void RemoveRepType(SalesRepType type) { // Check that the SalesRepType is actually in the Dictionary if (repNums.Keys.Contains(type)) { // Remove the repType repNums.Remove(type); // Trigger the RepTypesChanged event OnRepTypesChanged(); } else // The given SalesRepType was not in the list { throw new ArgumentOutOfRangeException("type", "Attempted to remove a SalesRepType from the repNums dictionary that was not present"); } }
/// <summary> /// Called when a key is pressed while the Handles list box is in focus /// </summary> /// <param name="sender">The ListBox that triggered this event</param> /// <param name="e">The events KeyEventArgs</param> private void listHandles_KeyDown(object sender, KeyEventArgs e) { //If the key that was pressed was either the Delete key or the Backspace key if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete) { //Get the RepType that is currently selected in the RepTypes listbox SalesRepType repType = (SalesRepType)listRepTypes.SelectedItem; //Get the ProductType that is currently selected in the Hangles ListBox ProductType toRemove = (ProductType)listHandles.SelectedItem; //Remove the ProductType from the RepTypes handle List gov.RemoveRepTypeHandle(repType, toRemove); //Set the reptypes listbox selected item to be the previously selected item listRepTypes.SelectedItem = repType; } }
/// <summary> /// Removes the given ProductType from the SalesRepTypes Handles list /// </summary> /// <param name="repType">The SalesRepTypes that the ProductType is being removed from</param> /// <param name="toRemove">The ProductType to Remove</param> public void RemoveRepTypeHandle(SalesRepType repType, ProductType toRemove) { //Check that the given repType is not null if (repType != null) { //Check that the given ProductType is not null if (toRemove != null) { // Check that the given SalesRepType is actually in the dictionary if (repNums.Keys.Contains(repType)) { //Remove the ProductType from the handles list of the matching dictionary key SalesRepType st = repNums.Keys.FirstOrDefault(srt => srt == repType); //If the handles list actually contains this ProductType if (st.Handles.Contains(toRemove)) { st.Handles.Remove(toRemove); //Trigger the RepTypesChanged event OnRepTypesChanged(); } else { throw new ArgumentOutOfRangeException("toRemove", "Attempted to remove a ProductType from a SalesRepType Handles list that was not in that list"); } } else // The given SalesRepType was not in the Dictionary { throw new ArgumentOutOfRangeException("repType", "Attmepted to remove a ProductType from a SalesRepType that was not in the Dictionary"); } } else // The given product type is null { throw new ArgumentNullException("toRemove", "Attempted to pass null ProductType to Core.RemoveRepTypeHandle"); } } else // The given sales rep type is null { throw new ArgumentNullException("repType", "Attempted to pass null SalesRepType to Core.RemoveRepTypeHandle"); } }
/// <summary> /// Gets the number of sales representatives of a given type that are currently processing calls /// </summary> /// <param name="repType">The SalesRepType to get the count of</param> /// <returns>The count of that type of SalesRepresentative that are busy</returns> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the given repType is not in the SalesForce</exception> /// <exception cref="System.ArgumentNullException">Thrown when the given repType is null</exception> public int RepresentativesBusy(SalesRepType repType) { //If repType is not null if (repType != null) { //If the SalesForce contains this type if (salesForce.ContainsKey(repType)) { //Return the number of SalesRepresentatives of this type that do not currently have assigned calls return(salesForce[repType].Where(sr => sr.CurrentlyProcessing != null).Count()); } else //This type was not contained in the dictionary { throw new ArgumentOutOfRangeException("repType", "Attempted to pass a SalesRepType that was not already in the SalesForce to SalesForceManager.RepresentativesBusy"); } } else //repType was null throw an exception { throw new ArgumentNullException("repType", "Attempted to pass null SalesRepType to SalesForceManager.RepresentativesBusy"); } }
/// <summary> /// Gets the number of sales representatives of a given type /// </summary> /// <param name="repType">The SalesRepType to get the count of</param> /// <returns>The count of that type of SalesRepresentative</returns> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the given repType is not in the SalesForce</exception> /// <exception cref="System.ArgumentNullException">Thrown when the given repType is null</exception> public int RepresentativesOfType(SalesRepType repType) { //If repType is not null if (repType != null) { //If the SalesForce contains this type if (salesForce.ContainsKey(repType)) { //Return the number of SalesRepresentatives of this type return(salesForce[repType].Count); } else //This type was not contained in the dictionary { throw new ArgumentOutOfRangeException("repType", "Attempted to pass a SalesRepType that was not already in the SalesForce to SalesForceManager.RepresentativesOfType"); } } else //repType was null throw an exception { throw new ArgumentNullException("repType", "Attempted to pass null SalesRepType to SalesForceManager.RepresentativesOfType"); } }
/// <summary> /// Called when the AddHandle button is clicked /// </summary> /// <param name="sender">The Button that triggered this event</param> /// <param name="e">The events EventArgs</param> private void btnAddHandle_Click(object sender, EventArgs e) { //Try and Get the currently selected RepType SalesRepType repType = listRepTypes.SelectedItem as SalesRepType; //If a SalesRepType was returned from above if (repType != null) { //Try and Get the currently selected ProductType ProductType toHandle = listProductTypes.SelectedItem as ProductType; //If a ProductType was returned from above if (toHandle != null) { //Add the productType to this reptypes handles list gov.AddRepTypeHandle(repType, toHandle); //Set the reptypes listbox selected item to be the previously selected item listProductTypes.SelectedItem = repType; } } }
/// <summary> /// Gets the first free SalesRep of the given type, null if no SalesRep is available /// </summary> /// <param name="repType">The type of the sales rep to retrieve</param> /// <returns>A SalesRepresentative, null if no SalesRepresentative is available</returns> private SalesRepresentative GetFreeSalesRep(SalesRepType repType) { //Check if the given rep type is not null if (repType != null) { // Check that the given repType is a key in the dictionary if (salesForce.ContainsKey(repType)) { //Get the first free Sales rep of the given type SalesRepresentative firstFree = salesForce[repType].FirstOrDefault(sr => sr.CurrentlyProcessing == null); return(firstFree); } else // The given salesRepType is not in the dictionary { throw new ArgumentOutOfRangeException("repType", "Attempted to pass SalesRepType that is not in the dictionary to SalesForceManager.GetFreeSalesRep"); } } else //The repType is null { throw new ArgumentNullException("repType", "Attempted to pass null SalesRepType to SalesForceManager.GetFreeSalesRep"); } }
/// <summary> /// Loads the Core's settings from a given XML file /// </summary> /// <param name="filepath">The filepath to the XML file</param> /// <exception cref="System.ArgumentNullException">Thrown when the given filepath is empty or null</exception> public void LoadSettingsFromFile(string filepath) { // Check that the given filepath is not empty or null if (filepath != null && filepath != string.Empty) { // Create the XDocument XDocument doc; // Attempt to create a stream for the document Stream docStream = File.OpenRead(filepath); // Load the document given the Stream doc = XDocument.Load(docStream); // Get the simulation settings element XElement settings = doc.Root.Element("SimulationSettings"); // Load the settings from the document callArrivalMultiplier = 1; // Convert.ToDouble(settings.Element("CallArrivalMultiplier").Value.ToString()); switchDelayMultiplier = 1; // Convert.ToDouble(settings.Element("SwitchDelayMultiplier").Value); maxQueueLength = 14; //Convert.ToInt32(settings.Element("MaxQueueLength").Value); singleQueueLength = true; //Convert.ToBoolean(settings.Element("SingleQueueLength").Value); // Load the seperate parts of the beginTime XElement begin = settings.Element("BeginTime"); int hour = Convert.ToInt32(begin.Element("Hours").Value); int minute = Convert.ToInt32(begin.Element("Minutes").Value); int seconds = Convert.ToInt32(begin.Element("Seconds").Value); // Create the datatime using the individual pieces beginTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, hour, minute, seconds); // Load the seperate parts of the Duration XElement dur = settings.Element("Duration"); int days = Convert.ToInt32(dur.Element("Days").Value); int hours = Convert.ToInt32(dur.Element("Hours").Value); int minutes = Convert.ToInt32(dur.Element("Minutes").Value); int durSeconds = Convert.ToInt32(dur.Element("Seconds").Value); // Create the TimeSpan with the individual pieces duration = new TimeSpan(days, hours, minutes, seconds); // Load the seperate parts of the excessive wait XElement exWait = settings.Element("ExcessiveWait"); int ewHours = Convert.ToInt32(exWait.Element("Hours").Value); int ewMinutes = Convert.ToInt32(exWait.Element("Minutes").Value); int ewSeconds = Convert.ToInt32(exWait.Element("Seconds").Value); // Create the TimeSpan with the individual pieces excessiveWait = new TimeSpan(ewHours, ewMinutes, ewSeconds); // Get the ProductType list element XElement pType = doc.Root.Element("ProductTypesList"); // Loop foreach ProductType element in the product types list foreach (XElement productType in pType.Elements("ProductType").OrderBy(pt => pt.Attribute("id").Value)) { // Get the id of the value int id = Convert.ToInt32(productType.Attribute("id").Value); // load the values string typeName = productType.Element("TypeName").Value; double probability = 0.5; //Convert.ToDouble(productType.Element("ProductTypeProbability").Value); double multiplier = 2; //Convert.ToDouble(productType.Element("ProcessingDelayMultiplier").Value); // Create the product type ProductType pt = new ProductType(typeName, multiplier, probability); // If the id is greater than the count of items if (id > productTypes.Count) { // Add it to the end of the list productTypes.Add(pt); } else // The id is not greater than the count { // Insert the ProductType into the productTypes list using the id as the index productTypes.Insert(id, pt); } } // Get the SalesRepTypesList element XElement repTypeList = doc.Root.Element("SalesRepTypesList"); // Loop foreach SalesRepType element in the list foreach (XElement salesRepType in repTypeList.Elements("SalesRepType")) { // Load the typename string typeName = salesRepType.Element("RepTypeName").Value; // Load the number of reps of this type int numReps = Convert.ToInt32(salesRepType.Element("NumberOfReps").Value); // Create the SalesRepType SalesRepType srt = new SalesRepType(typeName); // Loop foreach handleableProductType element in the sales rep types HandlesList element foreach (XElement productType in salesRepType.Element("HandlesList").Elements("HandleableProductType")) { int id = Convert.ToInt32(productType.Attribute("productTypeID").Value); // Use the id to retrieve the correct product type from the product types list srt.Handles.Add(productTypes[id]); } //Add the sales RepType to the dictionary repNums.Add(srt, numReps); } //Trigger all the events OnRepTypesChanged(); OnProductTypesChanged(); OnMainSettingsChanged(); } else // The given filepath is null or empty { throw new ArgumentNullException("filepath", "Attempted to pass null or empty string to Core.LoadSettingsFromFile"); } }