private long TransverseSalaries(EmployeeNode managerNode, long sum) { sum += managerNode.Salary; if (managerNode.Reportees.Any()) { foreach (var node in managerNode.Reportees) { sum += TransverseSalaries(node, 0); } } return(sum); }
/// <summary> /// Recursively creates a hierachial tree map with the CEO as the root node /// </summary> /// <param name="node"></param> private void BuildEmployeeTree(EmployeeNode node) { ValidateManagerIsEmployee(node.ManagerId); //define node descendants i.e. subordinates to the current employee node.Reportees = GetDirectReportees(node.Id); if (node.Reportees.Count() == 0) { return; } else { foreach (EmployeeNode temp in node.Reportees) { //further build the tree recursively by defining the reportees to each employee at this tree level BuildEmployeeTree(temp); } } }
/// <summary> /// Reads a CSV file and generates a list of employees, any parsing error will result in an exception being thrown /// and program will be halted /// </summary> /// <param name="input">Represents data from the CSV file with three expected columns of type integer</param> private void ParseEmployeeCSV(string input) { this.UnorderedEmployeeList = new List <EmployeeNode>(); foreach (var line in input.Split(Environment.NewLine)) { string[] columns = line.Split(','); if (columns.Length != 3) { throw new Exception(ErrorMessages.INVALID_CSV_COLUMN_COUNT); } EmployeeNode node = new EmployeeNode(ParseEmployeeId(columns[0]), ParseManagerId(columns[1]), ParseSalary(columns[2])); if (this.UnorderedEmployeeList.Contains(node)) { throw new Exception(ErrorMessages.DUPLICATE_EMPLOYEE_DEFINED); } this.UnorderedEmployeeList.Add(node); } //validate that all managers are valid employees var managers = this.UnorderedEmployeeList.Where(x => x.ManagerId != null) .Select(x => x.ManagerId.Value) .Distinct() .ToList(); if (managers.Where(x => !(this.UnorderedEmployeeList.Select(e => e.Id).Contains(x))).Any()) { throw new Exception(ErrorMessages.EMPLOYEE_NOT_FOUND); } //check for Circular References ValidateCircularReference(); }