public void CreatePostVoteShouldAddVoteOnPostAndIncreaseOrDecreaseVoteCount() { var options = new DbContextOptionsBuilder <ApplicationDbContext>() .UseInMemoryDatabase(databaseName: "CreatePostVoteShouldAddVoteOnPostAndIncreaseOrDecreaseVoteCountDB") .Options; var dbContext = new ApplicationDbContext(options); var commentService = new Mock <ICommentService>(); var postId = "asdasdasd"; var post = new Post { Id = postId, VoteCount = 5, }; var postService = new Mock <IPostService>(); postService.Setup(x => x.GetPostById(postId)).Returns(post); var vote = new VotePost { PostId = post.Id, UpOrDown = false, }; var voteService = new VoteService(dbContext, postService.Object, commentService.Object); voteService.CreatePostVote(vote); Assert.Equal(4, post.VoteCount); }
public async Task <IActionResult> Post([FromBody] VotePost v) { try { await _repo.SubmitVoteAsync(v, Request.HttpContext.Connection.RemoteIpAddress.ToString()); return(StatusCode(201)); } catch (TooManyVotesException) { return(StatusCode(403)); } catch (LowIntegrityVotingException) { return(StatusCode(403)); } catch (InvalidVoteException) { return(StatusCode(400)); } catch (RepeatVoteException) { return(StatusCode(403)); } }
public void ChangePostVote(VotePost vote, bool up) { if (vote == null) { return; } var post = this.postService.GetPostById(vote.PostId); if (up == true) { vote.UpOrDown = true; } else { vote.UpOrDown = false; } if (vote.UpOrDown == true) { post.VoteCount += 2; } else { post.VoteCount -= 2; } this.context.SaveChanges(); }
/// <summary> /// /// </summary> /// <param name="topicId"></param> /// <param name="votes"></param> public List <Vote> Vote(string topicId, VotePost votes) { // 获取这个人所有的投票 // 清除原来的票 // 投新票 if (string.IsNullOrEmpty(votes.uid)) { throw new ArgumentNullException("wechat id"); } var userVotes = GetUserVotes(topicId, votes.uid); if (Connection.State == System.Data.ConnectionState.Closed) { Connection.Open(); } var trans = Connection.BeginTransaction(); try { #region - 清除voteUser在主题topicId下的所有投票结果 foreach (var vote in userVotes) { Connection.Execute(SQL_VOTE_DECREASE_OPTION_VOTE, new { topicId = vote.Topic.Id, subjectId = vote.Subject.Id, optionId = vote.Option.Id }, trans); } Connection.Execute(SQL_TOPIC_REMOVE_VOTES, new { topicId, voteUser = votes.uid }, trans); userVotes.Clear(); #endregion for (var i = 0; i < votes.subs.Count(); i++) { var subject = votes.subs[i]; for (var j = 0; j < subject.ops.Count(); j++) { var option = subject.ops[j]; if (option.order <= 0) { option.order = Option.DefaultOrder; } Connection.Execute(SQL_TOPIC_VOTE, new { TopicId = topicId, SubjectId = subject.id, OptionId = option.id, VoteUser = votes.uid, VoteOrder = option.order }, trans); Connection.Execute(SQL_VOTE_INCREASE_OPTION_VOTE, new { topicId, subjectId = subject.id, optionId = option.id }, trans); } } trans.Commit(); return(userVotes); } catch (Exception ex) { trans.Rollback(); throw ex; } finally { trans.Dispose(); Connection.Close(); } }
private VotePost CreateVotePost(User user, Post post) { var dbVotePost = new VotePost() { User = user, Post = post }; return(dbVotePost); }
private VotePost CreatePost(string userId, string postId) { var dbVotePost = new VotePost() { UserId = userId, PostId = postId }; return(dbVotePost); }
public IHttpActionResult Vote(string id, [FromBody] VotePost voteBody) { try { voteService = new VoteService(); return(Ok(voteService.Vote(id, voteBody))); } catch (Exception ex) { log.Error(ex); return(InternalServerError(ex)); } }
internal IUserVotePostService GetService(User user, Post post, VotePost votePost) { var unitOfWork = this.GetRedditCloneUnitOfWork(); unitOfWork.Users.Add(user); unitOfWork.Posts.Add(post); unitOfWork.VotePostRepository.Add(votePost); unitOfWork.Complete(); var service = this.GetService(unitOfWork, user.Id); return(service); }
private bool IsDownVoteValid(VotePost votePost) { if (votePost == null) { return(false); } if (votePost.Value >= 0) { return(false); } else { return(true); } }
public void CreatePostVote(VotePost vote) { this.context.VotePosts.Add(vote); var post = this.postService.GetPostById(vote.PostId); if (vote.UpOrDown == true) { post.VoteCount++; } else { post.VoteCount--; } this.context.SaveChanges(); }
public void DeletePostVote(VotePost vote) { if (vote == null) { return; } var post = this.postService.GetPostById(vote.PostId); if (vote.UpOrDown == true) { post.VoteCount--; } else { post.VoteCount++; } this.context.VotePosts.Remove(vote); this.context.SaveChanges(); }
public async Task VoteAsync(int postId, string userId, bool isUpVote) { var postVote = this.postRepository.All() .FirstOrDefault(x => x.PostId == postId && x.UserId == userId); if (postVote != null) { postVote.Type = isUpVote ? VoteType.UpVote : VoteType.DownVote; } else { postVote = new VotePost { PostId = postId, UserId = userId, Type = isUpVote ? VoteType.UpVote : VoteType.DownVote }; await this.postRepository.AddAsync(postVote); } await this.postRepository.SaveChangesAsync(); }
public IActionResult VotePost([FromBody] VoteInputModel model) { var currentUser = this.userService.GetUserByName(this.User.Identity.Name); var post = this.postService.GetPostById(model.Id); var userVote = this.voteService.GetVotePostById(post.Id, currentUser.Id); if (model.VoteDown != model.VoteUp && userVote == null) { var vote = new VotePost { PostId = model.Id, UserId = currentUser.Id, }; if (model.VoteUp == true) { vote.UpOrDown = true; } else if (model.VoteDown == true) { vote.UpOrDown = false; } this.voteService.CreatePostVote(vote); } else if (model.VoteDown != model.VoteUp && userVote != null) { this.voteService.ChangePostVote(userVote, model.VoteUp); } else if (model.VoteDown == model.VoteUp && userVote != null) { this.voteService.DeletePostVote(userVote); } return(new JsonResult(post.VoteCount.ToString())); }
// POST: api/Vote public StatusCodeResult Post([FromBody] VotePost v) { int ipId = GetIpId(); // Make sure the call isn't malformed if (!ModelState.IsValid || v.WinId == v.LoseId) { //return BadRequest(); return(StatusCode(400)); } // Check if the player names are valid if (!_context.Players.Where(x => x.Id == v.WinId).Any() || !_context.Players.Where(x => x.Id == v.LoseId).Any()) { //return BadRequest(); return(StatusCode(400)); } // Check if the user has made this vote combination before bool hasUserMadeThisVote = (from votes in _context.Votes where votes.IpId == ipId && votes.WinId == v.WinId && votes.LoseId == v.LoseId select votes).Any(); bool hasUserMadeOppositeVote = (from votes in _context.Votes where votes.IpId == ipId && votes.WinId == v.LoseId && votes.LoseId == v.WinId select votes).Any(); if (hasUserMadeThisVote || hasUserMadeOppositeVote) { //return Forbid(); return(StatusCode(403)); } // Prepare data Player playerWin = _context.Players.Where(x => x.Id == v.WinId).SingleOrDefault(); Player playerLose = _context.Players.Where(x => x.Id == v.LoseId).SingleOrDefault(); _context.Update(playerWin); _context.Update(playerLose); // Update vote counts playerWin.Wins++; playerLose.Losses++; // Calculate change in player rating int oldWinRating = playerWin.Shitlo; int oldLoseRating = playerLose.Shitlo; int ratingDiff = Math.Abs(oldWinRating - oldLoseRating); const int MIN_CHANGE = 1; // Minimum rating change for a comparison const int MAX_CHANGE = 50; // Maximum rating change for a comparison const int EVEN_CHANGE = 15; // Rating change for an even comparison const double EULERS_NUMBER = 2.71828; // | 1000 beats 1000 -> +/- 15 const double EXPECTED_SCALING = -0.00264; // k value of 15 e^(-k 500) = 4 | 1500 beats 1000 -> +/- 4 const double UNEXPECTED_SCALING = 0.00240; // k value of 15 e^( k 500) = 50 | 1000 beats 1500 -> +/- 50 double CalcRatingChange(double scaling) { return(EVEN_CHANGE * Math.Pow(EULERS_NUMBER, scaling * ratingDiff)); } // Ae^(kx), HUGE thanks to Itheory and Eight Bit for the formula & helping me implement it. int change = Convert.ToInt32((oldWinRating >= oldLoseRating) ? Math.Max(CalcRatingChange(EXPECTED_SCALING), MIN_CHANGE) // Expected result : Math.Min(CalcRatingChange(UNEXPECTED_SCALING), MAX_CHANGE)); // Unexpected result playerWin.Shitlo = oldWinRating + change; playerLose.Shitlo = oldLoseRating - change; // Save vote to database Vote vote = new Vote { Date = DateTime.Now, IpId = ipId, WinId = v.WinId, LoseId = v.LoseId }; _context.Votes.Add(vote); // Send this vote to subscribed clients _hub.Clients.All.SendAsync("recentvote", new string[] { playerWin.Name, playerLose.Name }); // Commit changes & return success _context.SaveChanges(); // TODO: return different status code if this fails //return Ok(); return(StatusCode(201)); }
internal void AddEnitytiesToUnitOfWork(IRedditCloneUnitOfWork unitOfWork, User user, Post post, VotePost votePost) { this.AddEnitytiesToUnitOfWork(unitOfWork, user, post); unitOfWork.VotePostRepository.Add(votePost); unitOfWork.Complete(); }
public async Task SubmitVoteAsync(VotePost v, string ip) { User user = await IdentifyUserAsync(ip); // Make sure they're allowed to vote if (user.VoteLimit >= _ALLOWED_VOTES_PER_MINUTE) // Haven't voted more than X times per minute { throw new TooManyVotesException(); } if (user.AntiTamper >= _ANTI_TAMPERING_THRESHOLD) // Haven't made too many "troll" votes { throw new LowIntegrityVotingException(); } // Make sure the call isn't malformed if (v.WinId == v.LoseId) { throw new InvalidVoteException(); } // Check if the player names are valid if (!_context.Players.Where(x => x.Id == v.WinId).Any() || !_context.Players.Where(x => x.Id == v.LoseId).Any()) { throw new InvalidVoteException(); } // Disable vote flooding Vote latestVote = await _context.Votes.LastAsync(); if (v.WinId == latestVote.WinId || _ANTI_FLOOD) { throw new TooManyVotesException(); } // Make player instances Player playerWin = _context.Players.Where(x => x.Id == v.WinId).SingleOrDefault(); Player playerLose = _context.Players.Where(x => x.Id == v.LoseId).SingleOrDefault(); // Check if the player roles are valid if (playerWin.Role != playerLose.Role) { throw new InvalidVoteException(); } // Check if the user has made this vote combination before bool hasUserMadeThisVote = (from votes in _context.Votes where votes.UserId == user.Id && votes.WinId == v.WinId && votes.LoseId == v.LoseId select votes) .Any(); bool hasUserMadeOppositeVote = (from votes in _context.Votes where votes.UserId == user.Id && votes.WinId == v.LoseId && votes.LoseId == v.WinId select votes) .Any(); if (hasUserMadeThisVote || hasUserMadeOppositeVote) { throw new RepeatVoteException(); } // Prepare data _context.Update(playerWin); _context.Update(playerLose); _context.Update(user); // Update stats playerWin.Wins++; playerLose.Losses++; // Calculate change in player rating int ratingDiff = Math.Max(Math.Abs(playerWin.Rating - playerLose.Rating), 100); int maxRatingDiff = Math.Max((int)await this.GetMaxRatingDiffAsync(playerWin.Role), 100); double quotient = ratingDiff / maxRatingDiff; const double EULERS_NUMBER = 2.71828; const double MIN_CHANGE_PERCENT = 0.01; // Minimum rating change for a comparison const double EVEN_CHANGE_PERCENT = 0.025; // Rating change for an even comparison const double MAX_CHANGE_PERCENT = 0.05; // Maximum rating change for a comparison int ratingChange = 0; if (/* Unexpected result */ playerWin.Rating < playerLose.Rating) { ratingChange = Convert.ToInt32(ratingDiff * Math.Max(EVEN_CHANGE_PERCENT * Math.Pow(EULERS_NUMBER, 2 * Math.Log(MIN_CHANGE_PERCENT / EVEN_CHANGE_PERCENT) * quotient), MIN_CHANGE_PERCENT)); } else // Expected result { ratingChange = Convert.ToInt32(ratingDiff * Math.Min(EVEN_CHANGE_PERCENT * Math.Pow(EULERS_NUMBER, 2 * Math.Log(MAX_CHANGE_PERCENT / EVEN_CHANGE_PERCENT) * quotient), MAX_CHANGE_PERCENT)); } playerWin.Rating += ratingChange; playerLose.Rating -= ratingChange; // Add vote to database _context.Votes.Add(new Vote { Date = DateTime.Now, UserId = user.Id, WinId = v.WinId, LoseId = v.LoseId }); // Make this vote show up in everyone's browser if (_REAL_TIME_VOTES) { await _hub.Clients.All.SendAsync("recentvote", new string[] { playerWin.Name, playerLose.Name }); } // Increment user limits user.VoteLimit++; if (_ANTI_TROLL) { user.AntiTamper = Convert.ToInt32(user.AntiTamper * Math.Pow(4.64158883361, quotient)); } // Done await _context.SaveChangesAsync(); }