public void CanAssignNewTaskTest() { var newTask = new Task { Name = "New task" }; newTask.Tips.Add(new Tip { Name = "Tip 0", SuspendTime = 0 }); newTask.Tips.Add(new Tip { Name = "Tip 1", SuspendTime = 30 }); newTask.Tips.Add(new Tip { Name = "Tip 2", SuspendTime = 60 }); Expect.Call(dispatcherFactory.CrearteDispatcher(game)).Return(taskDispatcher); Expect.Call(taskDispatcher.GetNextTaskForTeam(null, null, null)).Return(newTask).IgnoreArguments(); Expect.Call(teamTaskStateRepository.SaveOrUpdate(null)).IgnoreArguments(); Expect.Call(acceptedTipRepository.SaveOrUpdate(null)).IgnoreArguments(); mocks.ReplayAll(); var service = new TaskService(taskRepository, teamTaskStateRepository, acceptedCodeRepository, acceptedBadCodeRepository, acceptedTipRepository, dispatcherFactory); var teamGameState = new TeamGameState{ Game = game, Team = team }; var oldTask = new Task { Name = "Old task" }; var recalcDateTime = new DateTime(2011, 1, 1, 21, 0, 0); service.AssignNewTask(teamGameState, oldTask, recalcDateTime); mocks.VerifyAll(); Assert.AreEqual(newTask, teamGameState.ActiveTaskState.Task); Assert.AreEqual(recalcDateTime, teamGameState.ActiveTaskState.TaskStartTime); Assert.AreEqual(1, teamGameState.ActiveTaskState.AcceptedTips.Count()); Assert.AreEqual(0, teamGameState.AcceptedTasks.Count()); }
/// <summary> /// Проверка на необходимость выдачи первого задания. /// </summary> private void CheckForFirstTask(TeamGameState teamGameState, DateTime recalcDateTime) { if (teamGameState.Game.GameDate > recalcDateTime) return; if (teamGameState.AcceptedTasks.Count == 0 && teamGameState.ActiveTaskState == null) { gameService.AssignNewTask(teamGameState, null); } }
public static Team CreateTeamGameState(this Team team, Game game) { var tgs = new TeamGameState { Game = game, Team = team }; team.TeamGameState = tgs; team.Game = game; game.Teams.Add(team); return team; }
public void CanAssignFirstTaskTest() { var tgs = new TeamGameState { Game = game }; game.Teams.Add(new Team { TeamGameState = tgs }); Expect.Call(repository.Get(1)) .Return(game).Repeat.Any(); Expect.Call(() => gameService.AssignNewTask(tgs, null)); mocks.ReplayAll(); service.RecalcGameState(new DateTime(2010, 1, 1, 21, 0, 0)); mocks.VerifyAll(); }
public void TeamFinishGame(TeamGameState teamGameState, DateTime recalcTime) { teamGameState.GameDoneTime = recalcTime; teamGameState.ActiveTaskState = null; }
public void SubmitCode(string codes, TeamGameState teamGameState, User user, DateTime recalcTime) { if (teamGameState.ActiveTaskState == null || teamGameState.ActiveTaskState.AcceptedBadCodes.Count >= GameConsnt.BadCodesLimit) return; List<string> codesList = GetCodes(codes, teamGameState.Game.PrefixMainCode, teamGameState.Game.PrefixBonusCode); if (codesList.Count == 0) return; if (codesList.Count > teamGameState.ActiveTaskState.Task.Codes.Count) throw new MaxCodesCountException(String.Format("Запрещено вводить количество кодов, за один раз, большее, чем количество кодов в задании.")); foreach (Code code in teamGameState.ActiveTaskState.Task.Codes) { if (codesList.Contains(code.Name.Trim().ToUpper())) { codesList.Remove(code.Name.Trim().ToUpper()); if (!teamGameState.ActiveTaskState.AcceptedCodes.Any(x => x.Code == code)) { // Добавляем правильный принятый код AcceptedCode acceptedCode = new AcceptedCode { AcceptTime = recalcTime, Code = code, TeamTaskState = teamGameState.ActiveTaskState }; teamGameState.ActiveTaskState.AcceptedCodes.Add(acceptedCode); acceptedCodeRepository.SaveOrUpdate(acceptedCode); } } } // Добавляем некорректные принятые коды foreach (string badCode in codesList) { if (!teamGameState.ActiveTaskState.AcceptedBadCodes.Any(x => x.Name.Trim().ToUpper() == badCode)) { AcceptedBadCode acceptedBadCode = new AcceptedBadCode { AcceptTime = recalcTime, Name = badCode, TeamTaskState = teamGameState.ActiveTaskState }; teamGameState.ActiveTaskState.AcceptedBadCodes.Add(acceptedBadCode); acceptedBadCodeRepository.SaveOrUpdate(acceptedBadCode); } } // Если приняты все основные коды, то помечаем задание выполненым и назначаем новое if (teamGameState.ActiveTaskState.AcceptedCodes.Count == teamGameState.ActiveTaskState.Task.Codes.Count/*(x => x.IsBonus == 0)*/ && teamGameState.ActiveTaskState.AcceptedCodes.Count > 0) { Task oldTask = teamGameState.ActiveTaskState.Task; CloseTaskForTeam(teamGameState.ActiveTaskState, TeamTaskStateFlag.Success, recalcTime); AssignNewTask(teamGameState, oldTask, recalcTime); } CheckExceededBadCodes(teamGameState, recalcTime); }
/// <summary> /// Назначение нового задания команде. /// </summary> public void AssignNewTask(TeamGameState teamGameState, Task oldTask, DateTime dateTimeNow) { taskService.AssignNewTask(teamGameState, oldTask, dateTimeNow); }
public void ShouldNotAssignFirstTaskTest() { var team = new Team(); var tgs = new TeamGameState { Game = game, Team = team }; team.TeamGameState = tgs; game.Teams.Add(team); Expect.Call(repository.Get(1)) .Return(game).Repeat.Any(); DoNotExpect.Call(() => gameService.AssignNewTask(tgs, null)); mocks.ReplayAll(); service.RecalcGameState(new DateTime(2010, 1, 1, 20, 59, 59)); mocks.VerifyAll(); }
/// <summary> /// Назначение нового задания команде. /// </summary> public void AssignNewTask(TeamGameState teamGameState, Task oldTask) { taskService.AssignNewTask(teamGameState, oldTask); }
/// <summary> /// Проверка на превышение количества левых кодов. При превышении задание закрывается сразу перед первой подсказкой. /// </summary> /// <param name="teamGameState"></param> /// <param name="recalcDateTime"></param> private void CheckExceededBadCodes(TeamGameState teamGameState, DateTime recalcDateTime) { gameService.CheckExceededBadCodes(teamGameState, recalcDateTime); }
/// <summary> /// Проверка на перебор времени по заданию. /// </summary> /// <param name="teamGameState"></param> /// <param name="recalcDateTime"></param> private void CheckOvertime(TeamGameState teamGameState, DateTime recalcDateTime) { if (teamGameState == null || teamGameState.ActiveTaskState == null) return; // время выполнения задания TimeSpan taskTime = recalcDateTime - teamGameState.ActiveTaskState.TaskStartTime; int timePerTask = teamGameState.Game.TimePerTask; // Если задание с "ускорением" и "ускорение" произошло if (teamGameState.ActiveTaskState.Task.TaskType == TaskTypes.NeedForSpeed && teamGameState.ActiveTaskState.AccelerationTaskStartTime != null) { taskTime = recalcDateTime - (DateTime)teamGameState.ActiveTaskState.AccelerationTaskStartTime; timePerTask = teamGameState.Game.TimePerTask - teamGameState.ActiveTaskState.Task.Tips.Last(tip => tip.SuspendTime > 0).SuspendTime; } if (taskTime.TotalMinutes >= timePerTask) { // Если все основные коды приняты, то задание считаем выполненым успешно TeamTaskStateFlag closeFlag = teamGameState.ActiveTaskState.AcceptedCodes.Count(x => !x.Code.IsBonus) == teamGameState.ActiveTaskState.Task.Codes.Count(x => !x.IsBonus) ? TeamTaskStateFlag.Success : TeamTaskStateFlag.Overtime; Task oldTask = teamGameState.ActiveTaskState.Task; gameService.CloseTaskForTeam(teamGameState.ActiveTaskState, closeFlag, recalcDateTime); gameService.AssignNewTask(teamGameState, oldTask, recalcDateTime); } }
/// <summary> /// Проверка на необходимость выдачи подсказки. /// </summary> /// <param name="teamGameState"></param> /// <param name="recalcDateTime"></param> private void CheckForNextTip(TeamGameState teamGameState, DateTime recalcDateTime) { if (teamGameState == null || teamGameState.ActiveTaskState == null) return; // Для заданий с выбором подсказок ничерта не делаем if (teamGameState.ActiveTaskState.Task.TaskType == TaskTypes.RussianRoulette) return; // время выполнения задания TimeSpan taskTime = recalcDateTime - teamGameState.ActiveTaskState.TaskStartTime; foreach (Tip tip in teamGameState.ActiveTaskState.Task.Tips) { if (taskTime.TotalMinutes >= tip.SuspendTime) { // если подсказка еще не получена if (!teamGameState.ActiveTaskState.AcceptedTips.Any(t => t.Tip == tip)) { // отправляем команде подсказку gameService.AssignNewTaskTip(teamGameState.ActiveTaskState, tip, recalcDateTime); } } } }
/// <summary> /// Проверка на превышение количества левых кодов. При превышении задание закрывается сразу перед первой подсказкой. /// </summary> /// <param name="teamGameState"></param> private void CheckExceededBadCodes(TeamGameState teamGameState) { gameService.CheckExceededBadCodes(teamGameState); }
public Task GetNextTaskForTeam(IRepository<Task> taskRepository, TeamGameState teamGameState, Task oldTask) { // Получаем все незаблокированные задания для текущей игры var gameTasks = taskRepository.GetAll() .Where(t => t.Game == teamGameState.Game && !t.Locked); // Формируем список номеров групп заданий, с которыми команда уже познакомилась List<int> executedGroupTags = new List<int>(); foreach (TeamTaskState acceptedTask in teamGameState.AcceptedTasks.Where(x => x.Task.GroupTag != 0)) { if (!executedGroupTags.Contains(acceptedTask.Task.GroupTag)) executedGroupTags.Add(acceptedTask.Task.GroupTag); } // Получаем доступные (невыполненные) для команды задания List<Task> accessibleTasks = new List<Task>(); foreach (Task task in gameTasks) { // Если задание не получено // и задание не входит ни в одну "засвеченную" группу, // и не запрещена выдача задания текущей команде, // то добавляем задание в список if (!teamGameState.AcceptedTasks.Any(x => x.Task == task) && !executedGroupTags.Contains(task.GroupTag) && !task.NotForTeams.Contains(teamGameState.Team)) accessibleTasks.Add(task); } // Формируем список выполняемых заданий другими командами Dictionary<Task, int> executingTasks = new Dictionary<Task, int>(); foreach (Team team in teamGameState.Game.Teams) { if (team.TeamGameState != null && team.TeamGameState.ActiveTaskState != null) { Task task = team.TeamGameState.ActiveTaskState.Task; if (executingTasks.ContainsKey(task)) { executingTasks[task] = executingTasks[task] + 1; } else { executingTasks.Add(task, 1); } } } // Получаем задания выполненные командами, которые помечены опцией "Анти-слив" var excludeExecutedTasks = new List<Task>(); foreach (Team team in teamGameState.Team.PreventTasksAfterTeams) { if (team.TeamGameState != null) { foreach (var task in team.TeamGameState.AcceptedTasks) { if (!excludeExecutedTasks.Contains(task.Task)) excludeExecutedTasks.Add(task.Task); } } } List<Task> tasksWithMaxPoints = new List<Task>(); int maxPoints = 0; // Рассчитываем приоритет для каждого задания // и отбираем задания с максимальным приоритетом foreach (Task task in accessibleTasks) { int taskPoints = GetTaskPoints(task, oldTask, executingTasks, excludeExecutedTasks, teamGameState); // Не выдавать задание вообще if (taskPoints == MinPoints) continue; if (taskPoints > maxPoints) { maxPoints = taskPoints; tasksWithMaxPoints.Clear(); tasksWithMaxPoints.Add(task); } else if (taskPoints == maxPoints) { tasksWithMaxPoints.Add(task); } } // Если заданий с одинаковым приоритетом несколько, // то берем произвольное if (tasksWithMaxPoints.Count > 1) { // Выбираем новое задание из доступных с максимальным приоритетом Task newTask = null; Random rnd = new Random(); int indx = rnd.Next(tasksWithMaxPoints.Count); int i = 0; foreach (Task task in tasksWithMaxPoints) { if (i == indx) newTask = task; i++; } return newTask; } return tasksWithMaxPoints.Count == 0 ? null : tasksWithMaxPoints.First(); }
/// <summary> /// Вычисление приоритета для задания. /// </summary> /// <param name="task">Задание для которого нужно вычислить приоритет.</param> /// <param name="oldTask">Предыдущее задание выполненное командой.</param> /// <param name="executingTasks">Задания выполняемые в данных момент другими командами.</param> /// <param name="excludeExecutedTasks">Задания выполненные командами, которые помечены опцией "Анти-слив".</param> /// <returns>Приоритет задания.</returns> private static int GetTaskPoints(Task task, Task oldTask, Dictionary<Task, int> executingTasks, List<Task> excludeExecutedTasks, TeamGameState teamGameState) { int taskPoints = 1000; //-------------------------------------------------------------------- // Если задание связано с предыдущим выданным, то +MaxPoints ))) if (task.AfterTask != null) { if (oldTask == null) return MinPoints; // Не выдавать if (task.AfterTask == oldTask) { var oldTeamTaskState = teamGameState.AcceptedTasks.First(x => x.Task == oldTask); if (task.GiveTaskAfter == GiveTaskAfter.Strictly) { if (oldTeamTaskState.State == (int)TeamTaskStateFlag.Success) { return MaxPoints; // Выдать незамедлительно } return MinPoints; // Не выдавать } if (task.GiveTaskAfter == GiveTaskAfter.StrictlyOrFinaly) { if (oldTeamTaskState.State == (int)TeamTaskStateFlag.Success) { return MaxPoints; // Выдать незамедлительно } return -1000; // Выдать с наименьшим приоритетом } if (task.GiveTaskAfter == GiveTaskAfter.InAnyCase) { return MaxPoints; // Выдать незамедлительно } } return MinPoints; } //-------------------------------------------------------------------- // Если задание типа Челлендж, то +500 if (task.StreetChallendge) { taskPoints += 500; return taskPoints; } //-------------------------------------------------------------------- // Если задание c агентами выполняется другой командой, то -500 // Задание с агентами одновременно может выполняться только одной командой if (task.Agents && executingTasks.ContainsKey(task)) taskPoints -= 500; //-------------------------------------------------------------------- // Если задание выполнено командами, которые помечены опцией "Анти-слив", то -700 if (excludeExecutedTasks.Contains(task)) taskPoints -= 700; //-------------------------------------------------------------------- // Если задание выполняет другая команда, то -50 if (executingTasks.ContainsKey(task)) taskPoints -= 50 * executingTasks[task]; //-------------------------------------------------------------------- // Если предыдущее задание команды входит в список блокировки по предшествованию, то -400 if (task.NotAfterTasks.Contains(oldTask)) taskPoints -= 400; //-------------------------------------------------------------------- // Если хотя бы одно задание из списка блокировки по одновременности выполняется, то -200 if (task.NotOneTimeTasks.Intersect(executingTasks.Keys).Count() > 0) taskPoints -= 200; //-------------------------------------------------------------------- // Если задание содержит коды со сложностью "+500", то +30 foreach (Code code in task.Codes) { if (code.Danger == "+500") { taskPoints += 30; break; } } //-------------------------------------------------------------------- // Повышаем приоритет для заданий с бонусами // П = П + 10 * (число бонусных кодов в задании) int bonusCodes = 0; foreach (Code code in task.Codes) { bonusCodes += code.IsBonus ? 1 : 0; } taskPoints += bonusCodes * 10; //-------------------------------------------------------------------- // Применяем собственный приоритет задачи taskPoints += task.Priority; return taskPoints; }
public void AssignNewTask(TeamGameState teamGameState, Task oldTask, DateTime recalcTime) { Check.Require(teamGameState.ActiveTaskState == null, "Невозможно назначить команде новую задачу, т.к. коменде уже назначена задача."); // Пытаемся получить следующее задание для команды Task newTask = dispatcherFactory.CrearteDispatcher(teamGameState.Game) .GetNextTaskForTeam(taskRepository, teamGameState, oldTask); // Если нет нового задания, то команда завершила игру if (newTask == null) { TeamFinishGame(teamGameState, recalcTime); return; } TeamTaskState teamTaskState = new TeamTaskState { TaskStartTime = recalcTime, TaskFinishTime = null, State = (int) TeamTaskStateFlag.Execute, TeamGameState = teamGameState, Task = newTask, NextTask = null }; teamGameState.ActiveTaskState = teamTaskState; teamTaskStateRepository.SaveOrUpdate(teamTaskState); //Сразу же отправляем команде первую подсказку (т.е. текст задания) AssignNewTaskTip(teamTaskState, teamTaskState.Task.Tips.First(), recalcTime); }
/// <summary> /// Обработка принятого кода от команды. /// </summary> /// <param name="codes">Принятый код.</param> /// <param name="teamGameState">Команда отправившая код.</param> /// <param name="user">Игрок отправившый код.</param> public void SubmitCode(string codes, TeamGameState teamGameState, User user) { taskService.SubmitCode(codes, teamGameState, user); }
public void CanFinishTeamGameTest() { Expect.Call(dispatcherFactory.CrearteDispatcher(game)).Return(taskDispatcher); Expect.Call(taskDispatcher.GetNextTaskForTeam(null, null, null)).Return(null).IgnoreArguments(); mocks.ReplayAll(); var service = new TaskService(taskRepository, teamTaskStateRepository, acceptedCodeRepository, acceptedBadCodeRepository, acceptedTipRepository, dispatcherFactory); var teamGameState = new TeamGameState { Game = game, Team = team }; var oldTask = new Task { Name = "Old task" }; var recalcDateTime = new DateTime(2011, 1, 1, 21, 0, 0); service.AssignNewTask(teamGameState, oldTask, recalcDateTime); mocks.VerifyAll(); Assert.IsNull(teamGameState.ActiveTaskState); Assert.AreEqual(recalcDateTime, teamGameState.GameDoneTime); Assert.AreEqual(0, teamGameState.AcceptedTasks.Count()); }
/// <summary> /// Проверка на превышение количества левых кодов. При превышении задание закрывается сразу перед первой подсказкой. /// </summary> public void CheckExceededBadCodes(TeamGameState teamGameState) { taskService.CheckExceededBadCodes(teamGameState); }
public void CanNotAssignNewTaskTest() { var service = new TaskService(taskRepository, teamTaskStateRepository, acceptedCodeRepository, acceptedBadCodeRepository, acceptedTipRepository, dispatcherFactory); var oldTask = new Task { Name = "Old task" }; var teamGameState = new TeamGameState { Game = game, Team = team, ActiveTaskState = new TeamTaskState { Task = oldTask } }; service.AssignNewTask(teamGameState, oldTask, new DateTime(2011, 1, 1, 21, 0, 0)); }
public void ShouldNotAssignFirstTaskTest4() { var team = new Team(); var tts = new TeamTaskState { Task = task1 }; var tgs = new TeamGameState { Game = game, Team = team, ActiveTaskState = tts }; tgs.AcceptedTasks.Add(tts); team.TeamGameState = tgs; game.Teams.Add(team); Expect.Call(repository.Get(1)) .Return(game).Repeat.Any(); DoNotExpect.Call(() => gameService.AssignNewTask(tgs, null)); mocks.ReplayAll(); service.RecalcGameState(new DateTime(2010, 1, 1, 22, 0, 0)); mocks.VerifyAll(); }
public void TeamFinishGameTest() { var service = new TaskService(taskRepository, teamTaskStateRepository, acceptedCodeRepository, acceptedBadCodeRepository, acceptedTipRepository, dispatcherFactory); DateTime recalcTime = DateTime.Now; var teamGameState = new TeamGameState { Game = game, Team = team }; service.TeamFinishGame(teamGameState, recalcTime); Assert.AreEqual(recalcTime, teamGameState.GameDoneTime); Assert.IsNull(teamGameState.ActiveTaskState); }
/// <summary> /// Обработка принятого кода от команды. /// </summary> /// <param name="codes">Принятый код.</param> /// <param name="teamGameState">Команда отправившая код.</param> /// <param name="user">Игрок отправившый код.</param> /// <param name="dateTimeNow"></param> public void SubmitCode(string codes, TeamGameState teamGameState, User user, DateTime dateTimeNow) { taskService.SubmitCode(codes, teamGameState, user, dateTimeNow); }
/// <summary> /// Проверка на превышение количества левых кодов. При превышении задание закрывается сразу перед первой подсказкой. /// </summary> public void CheckExceededBadCodes(TeamGameState teamGameState, DateTime recalcTime) { if (teamGameState == null || teamGameState.ActiveTaskState == null) return; if ((teamGameState.ActiveTaskState.AcceptedBadCodes.Count >= GameConsnt.BadCodesLimit) && (((recalcTime - teamGameState.ActiveTaskState.TaskStartTime).TotalMinutes + 1) //+1 - чтобы сработало до того, как покажется первая подсказка. >= (teamGameState.ActiveTaskState.Task.Tips.First(x => x.SuspendTime > 0).SuspendTime))) { Task oldTask = teamGameState.ActiveTaskState.Task; CloseTaskForTeam(teamGameState.ActiveTaskState, TeamTaskStateFlag.Cheat, recalcTime); AssignNewTask(teamGameState, oldTask, recalcTime); } }
/// <summary> /// Проверка на превышение количества левых кодов. При превышении задание закрывается сразу перед первой подсказкой. /// </summary> public void CheckExceededBadCodes(TeamGameState teamGameState, DateTime dateTimeNow) { taskService.CheckExceededBadCodes(teamGameState, dateTimeNow); }
public void TeamFinishGame(TeamGameState teamGameState) { teamGameState.GameDoneTime = DateTime.Now; teamGameState.ActiveTaskState = null; teamGameStateRepository.SaveOrUpdate(teamGameState); //teamGameState.Team.TeamGameState = null; //teamRepository.SaveOrUpdate(teamGameState.Team); teamGameStateRepository.DbContext.CommitChanges(); }