/// <summary> /// Store original plan name and contents in reference containers. /// </summary> /// <param name="plans">A list of valid plans.</param> private void StorePlanReferences(IEnumerable <List <string> > plans) { foreach (var plan in plans) { string planName = VoteString.GetPlanName(plan.First()); string cleanName = VoteString.RemoveBBCode(planName); cleanName = VoteString.DeUrlContent(cleanName); if (!VoteCounter.ReferencePlanNames.Contains(cleanName, Agnostic.StringComparer)) { VoteCounter.ReferencePlanNames.Add(cleanName); VoteCounter.ReferencePlans[cleanName] = plan; } } }
/// <summary> /// Gets a list of all full-vote plans (of which there will only be one, if found). /// </summary> /// <param name="post">The post to extract plans from.</param> /// <returns>Returns a list of plans (which are lists of vote lines).</returns> private List <List <string> > GetAllFullPostPlans(PostComponents post) { List <List <string> > results = new List <List <string> >(); if (post.VoteLines.Any()) { // Group blocks based on parent vote lines (no prefix). // Key for each block is the parent vote line. var voteBlocks = post.VoteLines.GroupAdjacentToPreviousKey( (s) => string.IsNullOrEmpty(VoteString.GetVotePrefix(s)), (s) => s, (s) => s); // If the vote has any plans with content in them, we can't make this a full-post plan. if (!voteBlocks.Any(b => b.Count() > 1 && VoteString.GetPlanName(b.Key) != null)) { // The post must have more than one line to count for a plan label. if (post.VoteLines.Count > 1) { var firstLine = post.VoteLines.First(); string planname = VoteString.GetPlanName(firstLine); if (planname != null) { // If it's named after a user, it must be the post author. Otherwise, anything is fine. if (VoteCounter.ReferenceVoters.Contains(planname, Agnostic.StringComparer)) { if (Agnostic.StringComparer.Equals(planname, post.Author)) { results.Add(post.VoteLines); } } else { results.Add(post.VoteLines); } } } } } return(results); }
/// <summary> /// Gets a list of all plans within the post that have defined content (child lines). /// </summary> /// <param name="post">The post to extract plans from.</param> /// <returns>Returns a list of plans (which are lists of vote lines).</returns> private List <List <string> > GetAllPlansWithContent(PostComponents post) { List <List <string> > results = new List <List <string> >(); results.AddRange(post.BasePlans.Select(a => a.ToList())); if (post.VoteLines.Any()) { // Group blocks based on parent vote lines (no prefix). // Key for each block is the parent vote line. var voteBlocks = post.VoteLines.GroupAdjacentToPreviousKey( (s) => string.IsNullOrEmpty(VoteString.GetVotePrefix(s)), (s) => s, (s) => s); foreach (var block in voteBlocks) { if (block.Count() > 1) { string planname = VoteString.GetPlanName(block.Key); if (planname != null) { // Add a named vote that is named after a user only if it matches the post author's name. if (VoteCounter.ReferenceVoters.Contains(planname, Agnostic.StringComparer)) { if (Agnostic.StringComparer.Equals(planname, post.Author)) { results.Add(block.ToList()); } } else { // If it's not named after a user, add it normally. results.Add(block.ToList()); } } } } } return(results); }
/// <summary> /// Gets a list of all full-vote plans (of which there will only be one, if found). /// </summary> /// <param name="post">The post to extract plans from.</param> /// <returns>Returns a list of plans (which are lists of vote lines).</returns> private List <List <string> > GetAllOneLinePlans(PostComponents post) { List <List <string> > results = new List <List <string> >(); if (post.VoteLines.Any()) { // Group blocks based on parent vote lines (no prefix). // Key for each block is the parent vote line. var voteBlocks = post.VoteLines.GroupAdjacentToPreviousKey( (s) => string.IsNullOrEmpty(VoteString.GetVotePrefix(s)), (s) => s, (s) => s); foreach (var block in voteBlocks) { if (block.Count() == 1) { string planname = VoteString.GetPlanName(block.Key); if (planname != null) { if (VoteCounter.ReferenceVoters.Contains(planname, Agnostic.StringComparer)) { if (Agnostic.StringComparer.Equals(planname, post.Author)) { results.Add(block.ToList()); } } else { results.Add(block.ToList()); } } } } } return(results); }
/// <summary> /// Get the lines of the vote that we will be processing out of the post. /// Only take the .VoteLines, and condense any instances of known plans /// to just a reference to the plan name. /// </summary> /// <param name="post">The post we're getting the vote from.</param> /// <returns>Returns the vote with plans compressed.</returns> public List <string> GetWorkingVote(PostComponents post) { List <string> vote = new List <string>(); if (post == null || !post.IsVote) { return(vote); } // First determine if any base plans are copies of an original definition, or being defined in this post. // If they're just copies, then embed them in the working vote. if (post.BasePlans.Any()) { var voters = VoteCounter.GetVotersCollection(VoteType.Plan); bool checkPlan = true; string planName; foreach (var bPlan in post.BasePlans) { planName = VoteString.GetMarkedPlanName(bPlan.Key); if (planName == null) { continue; } // As long as we keep finding base plans that are defined in this post, keep skipping. if (checkPlan) { if (VoteCounter.HasPlan(planName) && voters[planName] == post.ID) { continue; } } checkPlan = false; // If we reach here, any further plans are copy/pastes of defined plans, and should // have the key added to the working vote. vote.Add(bPlan.Key); } } // Then make sure there are actual vote lines to process. if (!post.VoteLines.Any()) { return(vote); } // Then check if the *entire post* should be treated as a complete plan. string postPlanName = VoteString.GetPlanName(post.VoteLines.First()); if (postPlanName != null && VoteCounter.ReferencePlans.ContainsKey(postPlanName) && VoteCounter.ReferencePlans[postPlanName].Skip(1).SequenceEqual(post.VoteLines.Skip(1), Agnostic.StringComparer)) { // Replace known plans with just the plan key. They'll be expanded later. vote.Add(post.VoteLines.First()); } else { // If the entire post isn't an auto-plan, break it down into blocks. // Break the remainder of the vote into blocks so that we can compare vs auto-plans. // Group blocks based on parent vote lines (no prefix). // Key for each block is the parent vote line. var voteBlocks = post.VoteLines.GroupAdjacentToPreviousKey( (s) => string.IsNullOrEmpty(VoteString.GetVotePrefix(s)), (s) => s, (s) => s); foreach (var block in voteBlocks) { // Multi-line blocks might be a plan. Check. if (block.Count() > 1) { // See if the block key marks a known plan. string planName = VoteString.GetPlanName(block.Key); if (planName != null && VoteCounter.ReferencePlans.ContainsKey(planName) && VoteCounter.ReferencePlans[planName].Skip(1).SequenceEqual(block.Skip(1), Agnostic.StringComparer)) { // Replace known plans with just the plan key. They'll be expanded later. vote.Add(block.Key); } else { // If it's not a known plan, pass everything through. vote.AddRange(block); } } else { // Single lines can be added normally vote.AddRange(block); //vote.Add(block.Key); } } } return(vote); }