Click here to Skip to main content
15,885,365 members
Articles / Programming Languages / C# 5.0

Beginning the Rule of Ready Project

Rate me:
Please Sign up or sign in to vote.
4.33/5 (3 votes)
26 Sep 2013CPOL5 min read 23.3K   207   13  
The beginning of Rule of Ready
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RuleOfReady.Core.DomainModels
{
    /// <summary>
    /// Object for storing a Partial Sequence (e.g. 2 3, as part of 2 3 4)
    /// </summary>
    public class MahjongPartialSequence : IEnumerable<MahjongTile>
    {

        /// <summary>
        /// The partial sequence this object represents
        /// </summary>
        public IEnumerable<MahjongTile> PartialSequence { get; private set; }

        /// <summary>
        /// The completed sequence this partial sequence is part of
        /// </summary>
        public IEnumerable<MahjongSequence> PossibleCompletions { get; private set; }

        /// <summary>
        /// This tile needed to complete this partial sequence
        /// </summary>
        public IEnumerable<MahjongTile> WaitingTiles { get; private set; }

        /// <summary>
        /// Create a new partial sequence given a sequence, at a partial sequence in it
        /// </summary>
        /// <param name="sequence">sequence that this partial sequence is part of</param>
        /// <param name="partialSequence">the partial sequence of tiles</param>
        public MahjongPartialSequence(MahjongSequence sequence, IEnumerable<MahjongTile> partialSequence)
        {
            if (!(sequence.Count() - 1 == partialSequence.Count()))
                throw new ArgumentException("Partial Sequence has the wrong number of tiles", "partialSequence");

            ;
            if (partialSequence.Except(sequence).Any())
                throw new ArgumentException("Partial sequence not (completely) part of sequence", "partialSequence");

            this.PartialSequence = partialSequence;
            this.PossibleCompletions = this.DeterminePossibleCompletions(sequence, partialSequence);
            this.WaitingTiles = this.PossibleCompletions.SelectMany(seq => seq.Except(partialSequence));
            
        }

        #region IEnumerable<MahjongTile> Implementation

        /// <summary>
        /// Gets the enumerator for the partial sequence list
        /// </summary>
        /// <returns>enumerator for the partial sequence list</returns>
        public IEnumerator<MahjongTile> GetEnumerator()
        {
            return this.PartialSequence.GetEnumerator();
        }
        /// <summary>
        /// Gets the enumerator for the partial sequence list
        /// </summary>
        /// <returns>enumerator for the partial sequence list</returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.PartialSequence.GetEnumerator();
        }

        private IEnumerable<MahjongSequence> DeterminePossibleCompletions(MahjongSequence sequence,
                                                                          IEnumerable<MahjongTile> partialSequence)
        {
            yield return sequence;
            // if the partial doesn't contain a terminal...

            IEnumerable<MahjongSuitTile> partialSeq = partialSequence.Cast<MahjongSuitTile>();

            Func<MahjongSuitTile, bool> NotATerminal =
                tile => (tile.SuitNumber != MahjongSuitNumber.One && tile.SuitNumber != MahjongSuitNumber.Nine);
                    
            if (partialSeq.All(tile => NotATerminal(tile)))
            {
                MahjongSuitTile firstCompletedTile = sequence.Except(partialSequence).Cast<MahjongSuitTile>().Single();
                IEnumerable<MahjongSuitTile> otherCompletedSequence = new List<MahjongSuitTile>();
                if (partialSequence.All(tile => tile < firstCompletedTile))
                    otherCompletedSequence = Enumerable.Repeat(new MahjongSuitTile(firstCompletedTile.SuitType, firstCompletedTile.SuitNumberInt - 3), 1)
                                                       .Concat(partialSeq);
                else if (partialSequence.All(tile => tile > firstCompletedTile))
                    otherCompletedSequence = partialSeq.Concat(
                        Enumerable.Repeat(new MahjongSuitTile(firstCompletedTile.SuitType, firstCompletedTile.SuitNumberInt + 3), 1));
                if (otherCompletedSequence.Any())
                    yield return new MahjongSequence(otherCompletedSequence);
            }
        }
        
        #endregion


    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United States United States
I'm a software developer that works with a small team on websites in .Net. Software development is a career of constant learning, and here I'm learning by sharing.

Comments and Discussions