На собеседование в одной из фирм мне дали вот такое тестовое задание на знание основ c#. Надеюсь, оно и для вас не окажется сложным. Для тех кто хочет проверить себя, привожу решение этого задания.
Техническое задание
Требуется написать программу CalculateBonus для рассчета премии по следующей формуле:
Bonus = Salary * SalaryProcent/100% * Koef
где:
Salary - зарплата сотрудника , целое число типа int
SalaryProcent - процент от зарплаты, предназначенный на выплату премии, типа byte
Koef - поправочный коэффиециент , типа double
Параметры передаются из командной строки в следующем формате:
обязательный параметр:
argv[0] string (разделенные запятой код сотрудника(отдел и должность) и фамилия)
опциональные параметеры:
argv[1] int, зарплата, если неуказана принимается равной 500
argv[2] byte процент от зарплаты, предназначенный на выплату премии, по умолчанию 10%.
argv[3] double поправочный коэффициент, по умолчанию 0.96.
Например:
CalculateBonus.EXE 12,Сидоров 650 10 0.90 - означает запрос на рассчет
премии для сотрудника отдела с кодом 1 (QA) занимающего должность с кодом 2(Manager) с фамилией Сидоров, зарплата которого 650, процент от зарплаты на выплату премии составляет 10%, поправочный коэффициент = 0.90.
CalculateBonus.EXE 01,Петров - означает запрос на рассчет премии для сотрудинка отдела с кодом 0, состоящего в должности 1. Значения для остальных параметров следует взять по умолчанию.
C суммы премии большей чем 10, должен быть списан налог в размере 13%. Данная функциональность реализуется отдельной функцией bool PayTax(ref decimal bonus, out int TaxRate)
уменьшающей сумму премии(параметр Bonus) на сумму налогов , возравращающей в параметре TaxRate ставку налога, возвращаемое значение типа bool показывает были ли вычтены налоги.
Программа должна генерировать отчет в следующем формате:
Сотрудник: ИВАНОВ (Фамилия сотрудника в верхнем регистре)
Должность: Manager (Должность сотрудника)
Отдел: QA (Отдел сотрудника)
Премия: 55,42 (Вычисленная премия)
Включая налог: 13 % (В случае же если премия составила < 10 и налог невзимался "Не включая налог: 13%")
Программа должна возращать cледующие значения
0 - если премия успешно была начислена
-1 - если не был передан обязательный(0й) аргумент
-2 - если указаный департамент не существует
-3 - если указанная должность не существует
Все допустимые значения возврата должны быть членами переисления ReturnCodes
Особенности реализации:
Существуют следующие отделы
RD = 0, //Отдел разработок
QA, //Отдел тестирования
Support, //Отдел технической поддержки
Sales, //Отдел продаж
Marketing, //Отдел маркетинга
Все допустимые коды отделов должны быть членами перечисления Departments.
Существвуют следующие должности
Employee = 0,
Lead,
Manager,
Director
Все допустимые коды должностей должны быть членами перечисления Ranks
Переменная для хранения итоговой премии(Bonus) должна быть обьявлена как decimal , при вычислениях потеря точности должна быть сведена к возможному миниму.
Разбор задания
Итак, приступим. Опишем сначала в перечислениях существующие в программе должности, отделы и ошибки, возвращаемые при некорректной работе программы.
/// <summary>
/// Existing departments.
/// </summary>
public enum Departments
{
/// <summary>
/// Development Department.
/// </summary>
RD = 0, //Отдел разработок
/// <summary>
/// Testing Department.
/// </summary>
QA, //Отдел тестирования
/// <summary>
/// Technical Support Department.
/// </summary>
Support, //Отдел технической поддержки
/// <summary>
/// Sales Department.
/// </summary>
Sales, //Отдел продаж
/// <summary>
/// Marketing Department.
/// </summary>
Marketing, //Отдел маркетинга
} |
/// <summary>
/// Existing ranks.
/// </summary>
public enum Ranks
{
/// <summary>
/// Employee.
/// </summary>
Employee,
/// <summary>
/// Lead.
/// </summary>
Lead,
/// <summary>
/// Manager.
/// </summary>
Manager,
/// <summary>
/// Director.
/// </summary>
Director
} |
/// <summary>
/// Codes, which can returns the program.
/// </summary>
public enum ReturnCodes
{
/// <summary>
/// Successfully.
/// </summary>
Ok = 0,
/// <summary>
/// Incorrectly arguments command line.
/// </summary>
ErrorArgs = -1,
/// <summary>
/// Id departments is not validate.
/// </summary>
ErrorDepartments = -2,
/// <summary>
/// Id ranks is not validate.
/// </summary>
ErrorRanks = -3
} |
Далее опишем самый главный класс Employee, в котором содержатся соответствующие свойства типа lastName, department и д.р., а также метод для вычисления бонуса CulcBonus()
/// <summary>
/// Class provides the employee.
/// </summary>
public class Employee
{
/// <summary>
/// The last name of employee.
/// </summary>
private string lastName;
/// <summary>
/// The reedonly properties of field lastName.
/// </summary>
public string LastName
{
get { return lastName; }
}
/// <summary>
/// The department of employee.
/// </summary>
private Departments department;
/// <summary>
/// The reedonly properties of field department.
/// </summary>
public Departments Department
{
get { return department; }
}
/// <summary>
/// The role of employee.
/// </summary>
private Ranks role;
/// <summary>
/// The reedonly properties of field role.
/// </summary>
public Ranks Role
{
get { return role; }
}
/// <summary>
/// The bonus of employee.
/// </summary>
private decimal bonus;
/// <summary>
/// The properties of field bonus.
/// </summary>
public decimal Bonus
{
get { return bonus; }
set { bonus = value; }
}
/// <summary>
/// The salary of employee.
/// </summary>
private int salary;
/// <summary>
/// Percentage of salary, which accrue bonus.
/// </summary>
private byte percentOfSalary;
/// <summary>
/// Correction factor of bonus.
/// </summary>
private double correctionFactor;
/// <summary>
/// Constructor.
/// </summary>
/// <param name="department">ID departments.</param>
/// <param name="role">ID ranks.</param>
/// <param name="lastName">Last name.</param>
/// <param name="salary">Salary.</param>
/// <param name="percentOfSalary">% of salary to bonus.</param>
/// <param name="correctionFactor">Correction factor.</param>
public Employee(Departments department, Ranks role, string lastName, int salary, byte percentOfSalary, double correctionFactor)
{
this.department = department;
this.role = role;
this.lastName = lastName;
this.salary = salary;
this.percentOfSalary = percentOfSalary;
this.correctionFactor = correctionFactor;
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="department">ID departments.</param>
/// <param name="role">ID ranks.</param>
/// <param name="lastName">Last name.</param>
/// <param name="salary">Salary.</param>
/// <param name="percentOfSalary">% of salary to bonus.</param>
public Employee(Departments department, Ranks role, string lastName, int salary, byte percentOfSalary)
{
this.department = department;
this.role = role;
this.lastName = lastName;
this.salary = salary;
this.percentOfSalary = percentOfSalary;
this.correctionFactor = 0.96;
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="department">ID departments.</param>
/// <param name="role">ID ranks.</param>
/// <param name="lastName">Last name.</param>
/// <param name="salary">Salary.</param>
public Employee(Departments department, Ranks role, string lastName, int salary)
{
this.department = department;
this.role = role;
this.lastName = lastName;
this.salary = salary;
this.percentOfSalary = 10;
this.correctionFactor = 0.96;
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="department">ID departments.</param>
/// <param name="role">ID ranks.</param>
/// <param name="lastName">Last name.</param>
public Employee(Departments department, Ranks role, string lastName)
{
this.department = department;
this.role = role;
this.lastName = lastName;
this.salary = 500;
this.percentOfSalary = 10;
this.correctionFactor = 0.96;
}
/// <summary>
/// Calculating bonus.
/// </summary>
public void CulcBonus()
{
bonus = (decimal)((salary * percentOfSalary / 100) * correctionFactor);
}
} |
Затем в теле программы, определяем константы приложения, считываем аргументы командной строки , рассчитываем бонус работника и выводим результат на экран.
/// <summary>
/// The Main class which contains the entry point.
/// </summary>
public class MainClass
{
/// <summary>
/// The minimum bonus for the tax.
/// </summary>
public const int minBonusOfTax = 10;
/// <summary>
/// Tax Rate.
/// </summary>
public const int constTaxRate = 13;
/// <summary>
/// Entry point.
/// </summary>
/// <param name="args">Arguments command line.
/// Command-line arguments to be set as follows:AB,C D E F
/// where A - ID departments
/// where В - ID ranks
/// where С - last name
/// where D - salary
/// where E - % of salary to bonus
/// where D - correction factor</param>
/// <returns></returns>
static public int Main(string[] args)
{
Employee employee = null;
int role = 0;
int department = 0;
string[] strs = null;
//Разбиваем первый аргумент на составляющие.
try
{
strs = args[0].Split(',');
if (strs.Length != 2)
{
Console.WriteLine("Входные параметры заданы неверно!");
return (int)ReturnCodes.ErrorArgs;
}
department = Int32.Parse(strs[0].Substring(0, 1));
role = Int32.Parse(strs[0].Substring(1, 1));
}
#region CatchBlock
catch (IndexOutOfRangeException exIndex)
{
Console.WriteLine("Не заданы параметры командной строки!");
return (int)ReturnCodes.ErrorArgs;
}
catch (Exception ex)
{
Console.WriteLine("Не верный формат входных параметров!");
Console.WriteLine("Формат должен быть следующим: AB,C D E F ");
Console.WriteLine("где A - ID отдела(число) ");
Console.WriteLine("где В - ID должности(число) ");
Console.WriteLine("где С - фамилия работника(строка) ");
Console.WriteLine("где D - зарплата сотрудника(число) ");
Console.WriteLine("где E - % от зарплаты на премию(число) ");
Console.WriteLine("где D - поправочный коэффициент(число) ");
return (int)ReturnCodes.ErrorArgs;
}
#endregion
int check = 0;
//Проверяем на существование введённых номера отдела и должности
check = CheckExistence(role, department);
if (check != 0)
{
return check;
}
//В зависимости от количества аргументов командной строки, создаём объект Emploee
switch (args.Length)
{
case 1:
{
employee = new Employee((Departments)department, (Ranks)role, strs[1]);
break;
}
case 2:
{
try
{
employee = new Employee((Departments)department, (Ranks)role, strs[1], Int32.Parse(args[1]));
}
#region CatchBlock
catch (FormatException e)
{
Console.WriteLine("Неверный формат данных у зарплаты!");
Console.WriteLine("Зарплата должна указываться числом!");
return (int)ReturnCodes.ErrorArgs;
}
#endregion
break;
}
case 3:
{
try
{
employee = new Employee((Departments)department, (Ranks)role, strs[1], Int32.Parse(args[1]), Byte.Parse(args[2]));
}
#region CatchBlock
catch (FormatException e)
{
Console.WriteLine("Неверный формат данных у зарплаты или у процентов бонуса!");
Console.WriteLine("Зарплата и проценты должны указываться числами!");
return (int)ReturnCodes.ErrorArgs;
}
#endregion
break;
}
case 4:
{
try
{
employee = new Employee((Departments)department, (Ranks)role, strs[1], Int32.Parse(args[1]), Byte.Parse(args[2]), Double.Parse(args[3]));
}
#region CatchBlock
catch (FormatException e)
{
Console.WriteLine("Неверный формат данных у зарплаты или у процентов или у коэффициента!");
Console.WriteLine("Зарплата, проценты и коэффициент должны указываться числами!");
return (int)ReturnCodes.ErrorArgs;
}
#endregion
break;
}
default:
{
Console.WriteLine("ERROR: Не указан обязательный аргумент командной строки!");
return (int)ReturnCodes.ErrorArgs;
}
}
try
{
//рассчитываем бонус работника
employee.CulcBonus();
}
#region CatchBlock
catch (NullReferenceException exNull)
{
Console.WriteLine("Невозможно рассчитать бонус рабочего, т.к. входящие параметры заданы не верно!");
return (int)ReturnCodes.ErrorArgs;
}
#endregion
//Создаём вспомагательные переменные, т.к. св-ва нельзя передавать с ref/out.
decimal bonus = employee.Bonus;
int TaxRate=0;
//Снимается налог с бонуса
bool payTax=PayTax(ref bonus, out TaxRate);
employee.Bonus = bonus;
//Вывод результатов на экран
Console.WriteLine("Cотрудник:"+employee.LastName.ToUpper());
Console.WriteLine("Должность:"+employee.Role.ToString());
Console.WriteLine("Отдел:" + employee.Department.ToString());
Console.WriteLine("Премия:" + employee.Bonus);
if (payTax == true)
{
Console.WriteLine("Включая налог:" + constTaxRate + "%");
}
else
{
Console.WriteLine("Не включая налог:"+ constTaxRate + "%");
}
return 0;
}
/// <summary>
/// The method for paying taxes.
/// </summary>
/// <param name="bonus">The amount of bonus.</param>
/// <param name="TaxRate">c</param>
/// <returns>True - if tax paid, false - if tax is not paid.</returns>
static bool PayTax(ref decimal bonus, out int TaxRate)
{
if (bonus > minBonusOfTax)
{
TaxRate = constTaxRate;
bonus = bonus - (bonus * TaxRate / 100);
return true;
}
else
{
TaxRate = 0;
return false;
}
}
/// <summary>
/// The function validate id deparnments and id ranks.
/// </summary>
/// <param name="checkR">The id ranks.</param>
/// <param name="checkD">The id deparnments.</param>
/// <returns>0 - if successfully
/// -2 - if id departments is not validate
/// -3 - if id ranks is not validate</returns>
static int CheckExistence( int checkR, int checkD)
{
Array arrD = Enum.GetValues(typeof(Departments));
if (checkD > (int)arrD.GetValue(0) && checkD <= (int)arrD.GetValue(arrD.Length - 1))
{
Array arrR = Enum.GetValues(typeof(Ranks));
if (checkR > (int)arrR.GetValue(0) && checkR <= (int)arrR.GetValue(arrR.Length - 1))
return (int)ReturnCodes.Ok;
else
{
Console.WriteLine("Указанной должности не существует!");
return (int)ReturnCodes.ErrorDepartments;
}
}
else
{
Console.WriteLine("Указанного отдела не существует!");
return (int)ReturnCodes.ErrorRanks;
}
}
} |
Надеюсь, вам понравилось задание, интересно будет увидеть ваши реализации.