Untitled
unknown
plain_text
5 years ago
5.2 kB
11
Indexable
#include <algorithm>
#include <cassert>
#include <map>
#include <string>
#include <tuple>
#include <vector>
using namespace std;
// Перечислимый тип для статуса задачи
enum class TaskStatus {
NEW, // новая
IN_PROGRESS, // в разработке
TESTING, // на тестировании
DONE // завершена
};
// Объявляем тип-синоним для map<TaskStatus, int>,
// позволяющего хранить количество задач каждого статуса
using TasksInfo = map<TaskStatus, int>;
// Выделим в отдельную функцию получение следующего по приоритету типа задачи
// Функция налагает требование на входной параметр: он не должен быть равен DONE
// При этом task_status явно не сравнивается с DONE, что позволяет
// сделать эту функцию максимально эффективной
TaskStatus Next(TaskStatus task_status) {
return static_cast<TaskStatus>(static_cast<int>(task_status) + 1);
}
// Объявляем тип-синоним для map<TaskStatus, int>,
// позволяющего хранить количество задач каждого статуса
using TasksInfo = map<TaskStatus, int>;
class TeamTasks {
public:
// Получить статистику по статусам задач конкретного разработчика
const TasksInfo& GetPersonTasksInfo(const string& person) const;
// Добавить новую задачу (в статусе NEW) для конкретного разработчика
void AddNewTask(const string& person);
// Обновить статусы по данному количеству задач конкретного разработчика
tuple<TasksInfo, TasksInfo> PerformPersonTasks(
const string& person, int task_count);
private:
map<string, TasksInfo> person_tasks_;
};
const TasksInfo& TeamTasks::GetPersonTasksInfo(const string& person) const {
return person_tasks_.at(person);
}
void TeamTasks::AddNewTask(const string& person) {
++person_tasks_[person][TaskStatus::NEW];
}
// Функция для удаления нулей из словаря
void RemoveZeros(TasksInfo& tasks_info) {
// Соберём те статусы, которые нужно убрать из словаря
vector<TaskStatus> statuses_to_remove;
for (const auto& task_item : tasks_info) {
if (task_item.second == 0) {
statuses_to_remove.push_back(task_item.first);
}
}
for (const TaskStatus status : statuses_to_remove) {
tasks_info.erase(status);
}
}
tuple<TasksInfo, TasksInfo> TeamTasks::PerformPersonTasks(
const string& person, int task_count) {
TasksInfo updated_tasks, untouched_tasks;
const bool has_person = person_tasks_.count(person);
// Здесь и далее мы будем пользоваться тем фактом, что в std::map оператор []
// в случае отсутствия ключа инициализирует значение по умолчанию,
// если это возможно.
// std::map::operator[] ->
// http://ru.cppreference.com/w/cpp/container/map/operator_at
TasksInfo& tasks = person_tasks_[person];
// Посчитаем, сколько задач каждого из статусов нужно обновить,
// пользуясь тем фактом, что по умолчанию enum class инциализирует значения
// от нуля по возрастанию.
// enum class -> http://ru.cppreference.com/w/cpp/language/enum
for (TaskStatus status = TaskStatus::NEW;
status != TaskStatus::DONE;
status = Next(status)) {
// Считаем обновлённые
updated_tasks[Next(status)] = min(task_count, tasks[status]);
// Считаем, сколько осталось обновить
task_count -= updated_tasks[Next(status)];
}
// Обновляем статус текущих задач в соответствии с информацией об обновлённых
// и находим количество нетронутых
for (TaskStatus status = TaskStatus::NEW;
status != TaskStatus::DONE;
status = Next(status)) {
untouched_tasks[status] = tasks[status] - updated_tasks[Next(status)];
tasks[status] += updated_tasks[status] - updated_tasks[Next(status)];
}
// По условию, DONE задачи не нужно возвращать в не обновлённых задачах
tasks[TaskStatus::DONE] += updated_tasks[TaskStatus::DONE];
// По условию в словарях не должно быть нулей
RemoveZeros(updated_tasks);
RemoveZeros(untouched_tasks);
RemoveZeros(person_tasks_.at(person));
if (!has_person) {
person_tasks_.erase(person);
}
return {updated_tasks, untouched_tasks};
}Editor is loading...