private async Task <MissionCompletionResult> ProcessTemporaryCommonPlace( MissionRequest request, string commonPlaceAlias, GeoCoordinate passedCoordinate) { var result = await _commonPlacesRepository.AddCommonPlace(request.UserId, commonPlaceAlias, passedCoordinate); if (result.Status != OperationResultStatus.Success) { return(new MissionCompletionResult( OperationResultStatus.Error, "Невозможно добавить временное общее место")); } request.StarsCount = 3; var recievedPoints = await RewardsCalculator.UpdateUserAfterMissionCompletion(request, _missionRepository, _appCountersService); var requestResult = await _missionRequestRepository.AddMissionRequest(request); if (requestResult.Status != OperationResultStatus.Success) { return(MissionCompletionResult.FromOperationResult(requestResult)); } return(new MissionCompletionResult { Points = recievedPoints, StarsCount = request.StarsCount, MissionCompletionStatus = MissionCompletionStatus.Success }); }
private async Task <MissionCompletionResult> ProcessCommonPlace(MissionRequest request) { var commonPlaceAlias = request.Mission.CommonPlaceAlias; var passedCoordinate = request.Proof.Coordinates.First(); if (request.User.HomeCoordinate.GetDistanceTo(passedCoordinate) < Core.Constants.GameConstants.Mission.CommonPlaceMinDistanceFromHome) { var incorrectResult = await ProcessIncorrectTry(request, _missionRepository, _missionRequestRepository); if (incorrectResult.MissionCompletionStatus == MissionCompletionStatus.IntermediateFail) { incorrectResult.Description = "StillHome"; } return(incorrectResult); } var realCommonPlace = await _commonPlacesRepository.GetCommonPlaceByAlias(request.UserId, commonPlaceAlias); if (realCommonPlace == null) { return(await ProcessTemporaryCommonPlace(request, commonPlaceAlias, passedCoordinate)); } var distance = passedCoordinate.GetDistanceTo(realCommonPlace.Coordinate); if (distance > request.Mission.AccuracyRadius) { var incorrectResult = await ProcessIncorrectTry(request, _missionRepository, _missionRequestRepository); if (incorrectResult.MissionCompletionStatus == MissionCompletionStatus.IntermediateFail) { incorrectResult.Description = distance > request.Mission.AccuracyRadius * 2 ? "Incorrect" : "IsNear"; } return(incorrectResult); } await SetStarsAccordingToTries(request, _missionRequestRepository); var completePoints = await RewardsCalculator.UpdateUserAfterMissionCompletion(request, _missionRepository, _appCountersService); var finalResult = new MissionCompletionResult { Points = completePoints, StarsCount = request.StarsCount, MissionCompletionStatus = MissionCompletionStatus.Success }; var requestResult = await _missionRequestRepository.AddMissionRequest(request); return(requestResult.Status != OperationResultStatus.Success ? MissionCompletionResult.FromOperationResult(requestResult) : finalResult); }
private async Task <MissionCompletionResult> ProcessAutoApprovedMissions(MissionRequest missionRequest) { var oldUserPoints = missionRequest.User.Points; MissionCompletionResult result; switch (missionRequest.Mission.ExecutionType) { case ExecutionType.RightAnswer: { result = await ProcessRightAnswer(missionRequest); break; } case ExecutionType.Path: { result = await ProcessGeoCoordinate(missionRequest); break; } case ExecutionType.CommonPlace: { result = await ProcessCommonPlace(missionRequest); break; } default: { throw new ArgumentOutOfRangeException(nameof(missionRequest), "Incorrect execution type"); } } if (result.Status != OperationResultStatus.Success || result.MissionCompletionStatus == MissionCompletionStatus.IntermediateFail) { return(result); } //after any mission completion user should be updated var userUpdateResult = await _userRepository.UpdateUser(missionRequest.User); if (userUpdateResult.Status != OperationResultStatus.Error) { // new points should always have value // ReSharper disable once PossibleInvalidOperationException await _ratingService.UpdateUserRating(missionRequest.User, oldUserPoints, missionRequest.User.Points.Value); } return(userUpdateResult.Status == OperationResultStatus.Success ? result : MissionCompletionResult.FromOperationResult(userUpdateResult)); }
private async Task <RightAnswerMissionCompletionResult> ProcessRightAnswer(MissionRequest request) { var userAnswers = request.Proof.CreatedText.Trim().SplitStringByDelimiter(); if (!userAnswers.AnyValues()) { return(new RightAnswerMissionCompletionResult(OperationResultStatus.Error, "Ответ не может быть пустым")); } var rightAnswers = AnswerModelHelper.SplitAnswer(request.Mission.CorrectAnswers); List <string> userAnswerStatuses; var invalidAnswersCount = ParseUserAnswers(rightAnswers, userAnswers, request.Mission.ExactAnswer ?? false, out userAnswerStatuses); var rightAnswersCount = userAnswers.Count - invalidAnswersCount; if (rightAnswersCount == 0 || rightAnswersCount < request.Mission.AnswersCount) { var result = await ProcessIncorrectTry(request, _missionRepository, _missionRequestRepository); var rightAnswerResult = RightAnswerMissionCompletionResult.FromMissionCompletionResult(result); request.DeclineReason = userAnswerStatuses.JoinToString(); rightAnswerResult.AnswerStatuses = userAnswerStatuses; return(rightAnswerResult); } await SetStarsAccordingToTries(request, _missionRequestRepository); var recievedPoints = await RewardsCalculator.UpdateUserAfterMissionCompletion(request, _missionRepository, _appCountersService); var requestResult = await _missionRequestRepository.AddMissionRequest(request); if (requestResult.Status != OperationResultStatus.Success) { return (RightAnswerMissionCompletionResult.FromMissionCompletionResult( MissionCompletionResult.FromOperationResult(requestResult))); } return(new RightAnswerMissionCompletionResult { Points = recievedPoints, StarsCount = request.StarsCount, MissionCompletionStatus = MissionCompletionStatus.Success }); }
public static async Task <MissionCompletionResult> ProcessIncorrectTry( MissionRequest request, IMissionRepository missionRepository, IMissionRequestRepository missionRequestRepository) { Expression <Func <MissionRequest, bool> > filter = a => a.MissionId == request.MissionId && a.UserId == request.UserId; var previousRequiests = await missionRequestRepository.GetMissionRequests(new QueryOptions <MissionRequest> { Filter = filter }); var tryCount = previousRequiests.Count + 1; if (tryCount >= request.Mission.TriesFor1Star) { request.DeclineReason = "Увы, достигнуто максимальное количество попыток."; await RewardsCalculator.UpdateUserAfterMissionDecline(request, missionRepository); await missionRequestRepository.AddMissionRequest(request); return(new MissionCompletionResult { MissionCompletionStatus = MissionCompletionStatus.Fail, Description = request.DeclineReason }); } var rejectResult = new MissionCompletionResult { MissionCompletionStatus = MissionCompletionStatus.IntermediateFail, TryCount = tryCount }; var failedRequesResult = await missionRequestRepository.AddMissionRequest(request); return(failedRequesResult.Status != OperationResultStatus.Success ? MissionCompletionResult.FromOperationResult(failedRequesResult) : rejectResult); }
internal static async Task <MissionCompletionResult> Process( Type uniqueMissionType, MissionRequest missionRequest, IMissionRequestRepository missionRequestRepository, IUserRepository userRepository, RatingService ratingService) { var oldUserPoints = missionRequest.User.Points; var uniqueMission = GetUniqueMission(uniqueMissionType); var result = await uniqueMission.ProcessRequest(missionRequest); if (result.Status != OperationResultStatus.Success) { return(result); } var requestResult = await missionRequestRepository.AddMissionRequest(missionRequest); if (requestResult.Status != OperationResultStatus.Success) { return(MissionCompletionResult.FromOperationResult(requestResult)); } var userUpdateResult = await userRepository.UpdateUser(missionRequest.User); //after any mission completion user should be updated if (userUpdateResult.Status != OperationResultStatus.Error) { if (!missionRequest.User.Points.HasValue) { throw new Exception($"Points are null for userId {missionRequest.UserId}, mission {missionRequest.MissionId}, status {userUpdateResult.Status}"); } await ratingService.UpdateUserRating(missionRequest.User, oldUserPoints, missionRequest.User.Points.Value); } return(userUpdateResult.Status == OperationResultStatus.Success ? result : MissionCompletionResult.FromOperationResult(userUpdateResult)); }
private async Task <MissionCompletionResult> ProcessGeoCoordinate(MissionRequest request) { SetStarsAccordingToTime(request); var missionFailed = request.StarsCount == 0; int?recievedPoints = null; if (missionFailed) { await RewardsCalculator.UpdateUserAfterMissionDecline(request, _missionRepository, _appCountersService); } else { recievedPoints = await RewardsCalculator.UpdateUserAfterMissionCompletion( request, _missionRepository, _appCountersService); } var requestResult = await _missionRequestRepository.AddMissionRequest(request); if (requestResult.Status == OperationResultStatus.Success) { return(new MissionCompletionResult { Points = recievedPoints, StarsCount = request.StarsCount, MissionCompletionStatus = missionFailed ? MissionCompletionStatus.Fail : MissionCompletionStatus.Success }); } return(MissionCompletionResult.FromOperationResult(requestResult)); }
/// <summary> /// Declines the mission. /// </summary> /// <param name="userId">The user identifier.</param> /// <param name="missionId">The mission identifier.</param> /// <returns> /// Task{OperationResult}. /// </returns> public async Task <MissionCompletionResult> DeclineMission(string userId, string missionId) { var user = await _userRepository.GetUser(userId); if (user == null) { return(new MissionCompletionResult(OperationResultStatus.Error, "User was not found")); } var currentMission = user.ActiveMissionIds.FirstOrDefault(m => m.MissionId == missionId); if (currentMission == null) { return(new MissionCompletionResult(OperationResultStatus.Error, "Mission was not found")); } var mission = await _missionRepository.GetMission(missionId); //Check if mission is unique and sensored var possibleUniqueMissionType = UniqueMissionsDictionary.GetMissionType(missionId); if (possibleUniqueMissionType == typeof(Censored)) { return (await UniqueMissionProcessor.Process( possibleUniqueMissionType, new MissionRequest { Mission = mission, MissionId = mission.Id, User = user, UserId = user.Id, Status = MissionRequestStatus.AutoApproval, LastUpdateDate = DateTime.UtcNow, Proof = new MissionProof() }, _missionRequestRepository, _userRepository, _ratingService)); } var oldPoints = user.Points; await RewardsCalculator.UpdateUserAfterMissionDecline( new MissionRequest { User = user, Mission = mission }, _missionRepository); var userUpdateResult = await _userRepository.UpdateUser(user); if (userUpdateResult.Status != OperationResultStatus.Error) { // new points should always have value // ReSharper disable once PossibleInvalidOperationException await _ratingService.UpdateUserRating(user, oldPoints, user.Points.Value); } return(userUpdateResult.Status == OperationResultStatus.Success ? new MissionCompletionResult { MissionCompletionStatus = MissionCompletionStatus.Fail } : MissionCompletionResult.FromOperationResult(userUpdateResult)); }
/// <summary> /// Completes the mission. /// </summary> /// <param name="userId">The user id.</param> /// <param name="missionId">The mission id.</param> /// <param name="missionProof">The mission proof.</param> /// <returns>Task{MissionCompletionResult}.</returns> public async Task <MissionCompletionResult> CompleteMission( string userId, string missionId, MissionProof missionProof) { var user = await _userRepository.GetUser(userId); if (user == null) { return(new MissionCompletionResult(OperationResultStatus.Error, "User was not found")); } var currentMission = user.ActiveMissionIds.FirstOrDefault(m => m.MissionId == missionId); if (currentMission == null) { return(new MissionCompletionResult(OperationResultStatus.Error, "Mission was not found")); } var mission = await _missionRepository.GetMission(missionId); var missionRequest = new MissionRequest { Mission = mission, User = user, MissionId = missionId, UserId = userId, Proof = missionProof, LastUpdateDate = DateTime.UtcNow, Status = MissionRequestStatus.AutoApproval }; var possibleUniqueMissionType = UniqueMissionsDictionary.GetMissionType(missionRequest.MissionId); if (possibleUniqueMissionType != null) { return (await UniqueMissionProcessor.Process( possibleUniqueMissionType, missionRequest, _missionRequestRepository, _userRepository, _ratingService)); } if (mission.ExecutionType == ExecutionType.PhotoCreation || mission.ExecutionType == ExecutionType.TextCreation || mission.ExecutionType == ExecutionType.Video) { missionRequest.Status = MissionRequestStatus.NotChecked; var addResult = await _missionRequestRepository.AddMissionRequest(missionRequest); if (addResult.Status != OperationResultStatus.Success) { return(MissionCompletionResult.FromOperationResult(addResult)); } return(new MissionCompletionResult { MissionCompletionStatus = MissionCompletionStatus.Waiting }); } return(await ProcessAutoApprovedMissions(missionRequest)); }