Since Gaming and Easter, Heroku, Postmodernism, DataFlow, Math and Software Engineering, I got a lot done today with regards to developing my simple game (which doesn't really even have a purpose yet but it just needs to be something) and even though I coded for only a bit - some days just thinking about coding while you're not coding fuels the coding session when you do get around to it. I find that this happens a lot especially in the shower.

Anyway, most of the work was done on the train this morning to work and then back from my C programming class.

  • Left-hand rule visualized today beautifully using 3D math primer for graphics and game development (2012, Fletcher et al)
  • Great use-case for implicit casts in C# at work today
  • Used actor objects in the game based on the advice in GCC4
  • Use static member in C++ class to represent the SDL Draw functionality in its own dedicated class Drawing::DrawRectangle()
  • Used inheritance to make a Ball class from an Actor base class which was the right thing to do
  • Used virtual to allow my ball and paddle (I think I'm going for a version of Pong here) to implement their own drawing and logic code (look ma no hands!)
    • Needed to use pure virtual members and thus abstract class to do this.
  • Got a chance to use the new auto and for constructs in c++ 14 to iterate over my vector of game objects ie actors
  • Used Vector to house my game objects in my GameWorldData struct
  • Implemented draw() and doLogic() in actors so that they can draw themselves - I mentioned this already
  • Used member initialization in the constructor - this was to ensure that my Positions were initialized correctly
  • Used protected members in c++ especially in the Actor class so that my Ball class could access the PosX and PosY members.
  • Stored pointer to base class in vector thereby making inroads to the next point - polymorphism 
  • Used polymorphism to call draw() and doLogic() on actor base class instances stored in vector

So a good days work really.

At work, I put together a Post Sharp aspect that transform a methods parameters, specifically that of a specific type but I found that while it worked great, it was a bit magic and you can’t really understand easily why, if you’re reading the code for the first time, what was going on. So I decided that even though putting attributes on methods like that was cool, it was a bit too decoupled (yes that’s possible! So decoupled you can’t see why it applies!). I instead moved to simply transform incoming parameters by enforcing that they can be implicitly transformed by  a new type with an implicit cast built in, so strings coming in would be turned into these new objects automatically (I changed the type from string to this new Type) and these new objects transform the string on-demand by way of automatic implicit casting them Pretty cool. This is what it looks like:

using System;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace Common
{
    /// <summary>
    /// A string that will automatically be represented as a valid code if 
    /// it is created with and invalid string, otherwise the orignal string is used
    /// </summary>
    public class AutoCode
    {
        /// <summary>
        /// The sanitized, generated code or the original 
        /// PW code if it wasn't invalid
        /// </summary>
        public string Value { get;set; }

        /// <summary>
        /// Indication if this code had to generate a 
        /// compatible code from the provided PW code
        /// </summary>
        public bool WasCodeOriginallyInvalid { get; }

        /// <summary>
        /// We can track the original invalid code if it was 
        /// invalid, see <see cref="WasCodeOriginallyInvalid"/>
        /// </summary>
        public string OriginalInvalidValue { get; }

        /// <summary>
        /// Converts the provided code into a 
        /// compatible code if its invalid to begin with
        /// </summary>
        /// <remarks>An invalid code is a non-alphanumeric code</remarks>
        /// <param name="value"></param>
        public AutoCode(string value)
        {
            // Turn the invalid portfolio code into a valid 
            // code which is a Hash of the invalid code such that
            // we can use the invalid code again to determine the same 
            // auto generated hash code
            // This hash is only substituted for the code if the 
            // incoming PW code is non alphanumeric which is invalid as far as 
            // using that as a code too
            const string alphanumericRegex = @"^[a-zA-Z0-9-]*$"; // note we're
            // ok with '-' so added this into pattern
            if(!Regex.IsMatch(value, alphanumericRegex))
            {
                WasCodeOriginallyInvalid = true;
                OriginalInvalidValue = value;
                using (var sha256 = new SHA256Managed())
                {
                    // This might be slow but its accurate and we'll 
                    // cross that bridge when we get there ("Make it work,
                    // then make it work fast" - Dennis Richie )
                    // An alternative might be djb2 as described here: 
                    // http://www.cse.yorku.ca/~oz/hash.html
                    var raw = Encoding.Default.GetBytes(value);

                    // PWCode -> SHA235(PWCode). 
                    // Note that by default a sha256 hash is delimited
                    // by an invalid '-' character, remove it
                    Value = BitConverter.ToString(sha256.ComputeHash(raw))
                            .Replace("-", string.Empty);;
                }
                
            }
            else
            {
                Value = value;
                WasCodeOriginallyInvalid = false;
                OriginalInvalidValue = string.Empty;
            }
        }

        /// <summary>
        /// You can use a AutoCode anywhere you can use a string because it
        /// will be converted to it implicitly
        /// </summary>
        /// <param name="code"></param>
        public static implicit operator string(AutoCode code)
        {
            return code.Value;
        }

        /// <summary>
        /// You can use a string anywhere you can use a AutoCode -
        /// because it will be converted to one implicitly
        /// </summary>
        /// <param name="code"></param>
        public static implicit operator AutoCode(string code)
        {
            return new AutoCode(code);
        }

        /// <summary>
        /// You can see the sanitized value directly
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            // You can get the sanitized value of a Code
            return Value;
        }
    }
}

But then I just threw it away.

So that basically means that I changed functions from using String to this new Type called AutoCode() and when you pass any string into a function that needs a AutoCode it won't complain, it'll just suck it into that new AutoCode type. Pretty neat and its easier to reason about that using the Aspect Orientated approach I mentioned previously.

But for interest's sake this is the Aspect I created:

 /// <inheritdoc />
    /// <summary>
    /// Automatically turn Portfolio.Code to Sanitized version of Portfolio.Code
    /// </summary>
    [Serializable]
    public class SanitizePWPortfolioCodeAttribute : MethodInterceptionAspect
    {
        public override void OnInvoke(MethodInterceptionArgs args)
        {
            // Determine which parameter is the PW Portfolio object
            var param = args.Method.GetParameters()
                         .SingleOrDefault(p => p.ParameterType == 
                         typeof(Services.PortfolioServices.Portfolio));
            if(param != null)
            {
                // Get it
                var portfolioArg = (Portfolio)args.Arguments[param.Position];
                
                if(portfolioArg == null)
                {
                    args.Proceed();
                    return;
                }
                // Modify it if needed
                // Note that a AutoCode will turn into a valid 
                // code automatically (implicit conversion to string)
                portfolioArg.Code =  new AutoCode(portfolioArg.Code);

                // Pass it back in to the pipeline
                args.Arguments.SetArgument(param.Position, portfolioArg);
                
            }
            args.Proceed();
        }
    }

Oh and checkout my new Balls that draw themselves are here ...

Out.

 


Comments powered by CComment

Twitter