Jul 122012
 

Oh how I wish there was a out of the box solution to do this where you could just enter the source and destination urls and voila! the entire blog was migrated. Unfortunately there isnt 🙁 (or atleast I am not aware of one).

So when I set out to migrate around a 1000 posts from 16 different Sharepoint blogs to WordPress, there were quite a few challenges on the way. The first step is to read the Sharepoint data.This would have been far easier with the proper database access to sharepoint db but unfortunately there was way too much red tape wrapped around it to get the access quick enough to start immediately, hence I took the dirty way out – to scrape the HTML pages and retrieving the data out of it. Scraping HTML is the usually the worst possible way to extract data from any source since the code is rarely ever reusable, bloated to handle nested tags and often filled with branching statements to handle special cases. Only go for the scraping approach if you don’t have any other way to access the data. What makes scraping bearable is the wonderful HTML Agility pack which I had blogged about earlier. Its XMLish approach to traverse HTML makes this activity quite easy.

This is the object that I used to represent each blog to be imported. It contains the source URL, destination blog, author Id. Each object represents the source site as well as the destination information needed to write to WordPress.

   class BlogsToBeMigrated
    {
        public string Url { get; set; }
        public int SiteID { get; set; }
        public int AuthorId { get; set; }
        public string DestinationBlogName { get; set; }
        public BlogsToBeMigrated(string url, int siteId, int authorID,string destination)
        {
            Url = url;
            SiteID = siteId;
            AuthorId = authorID;
            DestinationBlogName = destination;
        }
    }

This is the code to read each blog entry. Note that it takes in each blog object and extracts information out of it. The concatenation step would depend on how your sharepoint site is structured. Just make sure it points to the list view of the blog where all posts are listed in a tabular form. This helps us to take out each link and get the content to add in WordPress. To get the various xpath to navigate to the nodes, I used the chrome extension Xpath helper. This could be different for every sharepoint site. Just play around with the xpath till you get the required information

private static void MigrateSingleBlog(BlogsToBeMigrated blog)
{
    var siteUrl = String.Concat("YOUR SITE URL HERE", blog.Url, "/Lists/Posts/AllPosts.aspx");
    string siteList = ReadWebPage(siteUrl);
    DeletedBlogData(blog.SiteID);
    var listDoc = new HtmlDocument();
    listDoc.LoadHtml(siteList);
    var siteListNodes = listDoc.DocumentNode.SelectNodes("//td[@class='ms-vb-title']/table/tr/td/a");

    foreach (var site in siteListNodes)
    {
        var postUrl = String.Concat("YOUR SITE URL HERE", site.GetAttributeValue("href", "href"));
        var PageDump = ReadWebPage(postUrl);
        var postDoc = new HtmlDocument();
        postDoc.LoadHtml(PageDump);
        var siteContent = postDoc.DocumentNode.SelectSingleNode("//div[@class='ms-PostWrapper']");

        string postDate = siteContent.ChildNodes[0].InnerText;
        string postTitle = siteContent.ChildNodes[1].ChildNodes[0].ChildNodes[0].InnerText.Trim();
        var postContent = postDoc.DocumentNode.SelectSingleNode("//div[@class='ms-PostWrapper']/div[@class='ms-PostBody']/div");

        var postHtml = postContent.InnerHtml;

        MoveToWordPress(postDate, postTitle, postHtml, blog.Url,blog.SiteID,blog.AuthorId,blog.DestinationBlogName);
        Console.WriteLine(postDate + postTitle);
    }

}

Also remember to put this line in the constructor of your class before any of the HTML agility pack code is executed. This is needed because forms can be tricky elements in HTML due to their overlapping between tags which makes it difficult to parse the markup. This makes HTML Agility pack parse form tags as empty elements and the below line allows you to look inside them.

HtmlNode.ElementsFlags.Remove("form");

Now that I had access to all the sharepoint data the challenge was to enter this is in the right WordPress blogs. I took a look at CSV importer which allows bulk import of posts from CSV files. This step didnt work properly at all since the post content was way too large for a CSV file to be parsed properly. After numerous attempts to sanitize the CSV and escape each linebreak and comma, this step still ignored many valid posts and also filled gibberish in others. Then I thought of directly inserting the data in the WordPress database. Initially I was skeptical since wordpress might fill some related tables when a post was published, but found that there were no such problems. Directly inserting the data worked like a charm. It also allowed me to migrate the data multiple times each time I noticed an issue with improperly rendered markup

This is the method that enters in the WordPress blog table directly. Note that the multisite installation means different post tables which have a number in the table name. e.g. WP_2_posts, WP_3_posts etc. The index for the table name was in the BlogToBeMigrated object as I had manually created each wordpress blog which corresponded to a sharepoint blog. This step is fairly simple. It just creates a connection to the MySql database using the connector dlls, gets the maximum ID, increments it and uses that to insert a new post. The code isnt production standard but this isnt really something that I am looking to maintain for a long time. Till the migration is done right, we can just keep repeating with the required fixes and once its finished – you have a functioning site with no need to migrate anymore. Pragmatism wins.

private static void MoveToWordPress(string postDate,string postTitle,string postContent,string postUrl, int blogID, int authorID,string destinationBlogName)
{
   //Remember to include ConvertZeroDateTime=true in the connection string
    MySqlConnection wordpressConn = new MySqlConnection("DATABASE_CONNECTION STRING; ConvertZeroDateTime=true");

    using (wordpressConn)
    {
        wordpressConn.Open();
        int maxID = 0;
        var id = new MySqlCommand(String.Format("Select Max(ID) from WP_{0}_Posts", blogID), wordpressConn).ExecuteScalar();
        if (id.GetType() == typeof(System.DBNull))
            maxID = 1;
        else
            maxID = Convert.ToInt32(id);

        string SQLCommandText = "Insert into wp_{0}_posts (id,post_author,post_date,post_content,post_title,post_excerpt,post_status,comment_status,ping_status,post_name,to_ping,pinged,post_modified,post_modified_gmt,post_content_filtered,post_parent,guid,menu_order,post_type,comment_count)";
        SQLCommandText += " values (?ID,{1},?postDate,?postBody,?postTitle,'','publish','open','open',?postName,'','',?postDate,?postDate,'',0,?postGuid,0,'post',0)";
        HtmlDocument span = new HtmlDocument();

        MySqlCommand insertPost = new MySqlCommand(String.Format(SQLCommandText, blogID, authorID), wordpressConn);
        span.LoadHtml(postContent);

        var siteName = "YOUR_BLOG_URL_HERE/{0}/files/{1}";
        var imagenodes = span.DocumentNode.SelectNodes("//a/img");
        if (imagenodes != null)
        {
            foreach (var image in imagenodes)
            {
                var imageUrl = image.ParentNode.GetAttributeValue("href", "href");
                var imageThumbUrl = image.GetAttributeValue("src", "src");
                if (imageUrl.Contains("/sites"))
                {
                    var migratedFileName = imageUrl.Replace(String.Concat(postUrl, "/Lists/Posts/Attachments/"), string.Empty);
                    postContent = postContent.Replace(string.Format("href=\"{0}", imageUrl), String.Format("href=\"{0}", String.Format(siteName, destinationBlogName, migratedFileName)));
                           
                    postContent = postContent.Replace(string.Format("src=\"{0}", imageThumbUrl), String.Format("src=\"{0}", String.Format(siteName, destinationBlogName, migratedFileName)));
                }
                else
                    postContent = postContent.Replace(string.Format("src=\"{0}", imageThumbUrl), String.Format("src=\"{0}", imageUrl));
            }
        }
            span = new HtmlDocument();
            span.LoadHtml(postContent);
            var htmlNode = span.DocumentNode.SelectSingleNode("//span[@class='erte_embed']");
            if (htmlNode != null)
            {
                string urlValue = htmlNode.GetAttributeValue("id", "id");
                urlValue = HttpUtility.UrlDecode(urlValue);
                //   urlValue = urlValue;
                postContent = postContent.Replace(htmlNode.OuterHtml, urlValue);
            }

            maxID++;
            insertPost.Parameters.AddWithValue("?ID", maxID);
            insertPost.Parameters.AddWithValue("?postDate", DateTime.Parse(postDate));
            insertPost.Parameters.AddWithValue("?postBody", postContent);
            insertPost.Parameters.AddWithValue("?postTitle", postTitle);
            insertPost.Parameters.AddWithValue("?postName", postTitle.Replace('#', '-').Replace(' ', '-'));
            insertPost.Parameters.AddWithValue("?postGuid", "YOUR_BLOG_URL_HERE/?p=" + maxID);
            insertPost.ExecuteNonQuery();

        }
            
}

Note the additional processing around the image tags. This was because I had migrated the image files separately and wanted to update the image tag’s src attributes to reflect to the new path. If you plan on keeping your previous sharepoint installations up, then this step is optional since the attachments will be loaded from the sharepoint site anyway. But I would recommend migrating the images as well just for easier maintenance of the content.

The code to migrate a single image is below. The way to get all the image tags is very similar to how each blog content was retrieved. The only difference is that instead of entering in the database, we just use Agility pack to extract all image tags in the post contennt and call the below method to download it. The files are then saved in the wp-content directory and the path is updated in the migration logic.

  private static void DownloadImage(string url,string postUrl,string destination)
        {
            string saveDir = String.Format("C:\\Wordpress_Images\\{0}\\", destination);
            string filename = string.Concat(saveDir, url.Replace(string.Concat("YOUR_SHAREPOINT_URL", postUrl, "/Lists/Posts/Attachments/"), string.Empty)).Replace("/","\\");
            FileInfo fi = new FileInfo(filename);
            if (!fi.Directory.Exists)
                Directory.CreateDirectory(fi.Directory.FullName);
            //DirectoryInfo info = new DirectoryInfo(
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.UseDefaultCredentials = true;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            if ((response.StatusCode == HttpStatusCode.OK ||
                response.StatusCode == HttpStatusCode.Moved ||
                response.StatusCode == HttpStatusCode.Redirect) &&
                response.ContentType.StartsWith("image", StringComparison.OrdinalIgnoreCase))
            {

                using (Stream inputStream = response.GetResponseStream())
                using (Stream outputStream = File.OpenWrite(filename))
                {
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    do
                    {
                        bytesRead = inputStream.Read(buffer, 0, buffer.Length);
                        outputStream.Write(buffer, 0, bytesRead);
                    } while (bytesRead != 0);
                }
            }
        }
Jan 242012
 

Reusability is one of the most underrated aspects of software development. The focus on meeting functional requirements in a product as quickly as possible often overshadows the reusability and maintainability part. Code duplication, poor adherence to design are often symptoms of such development which increase costs in the long term in favour of short term benefits.

WPF encourages creation of reusable controls, primarily by its support for creation of “lookless controls” where the client of the control is not only able to reuse the control, but also completely alter its appearance. The control in essence is just a bundle of logic with a default template. Its upto the client whether to accept this default skin or override it with one of his own. Though this concept looks similar to themes and skins in other technologies, its extremely powerful that you can alter the visual appearance of the control at a granular level. If the default template defines a button and a textbox, that can easily be changed to an filled rectangle with a Linear Gradient and a TextBlock to display the data.

Difference between User Controls and Custom Controls.

Custom controls arent the only type of control library that WPF offers. There is also the User Control library. The difference between the two lies in our end purpose. If we are simply looking to bundle a few controls together and provide basic customization to the end user, then User Controls are the way to go. They are also much more easier to use than Custom Controls. However, if your aim is to provide full customization capability to the developer who consumes your control, then Custom Controls are much better.

Dependency Properties

Dependency Properties are quite different from the conventional properties which we use in C#, and are exclusive to WPF. They do not belong to any particular class and their value can be set sources other than just the class itself. The values could come from their default values, styles, themes, callbacks etc. They also support Data binding so your UI elements can directly bind to them and update whenever the value changes, like how properties in classes implementing INotifyPropertyChanged events behave.

Custom Control Example

The custom control example I build is a filled rectangle with a slider. As you increase the slider the fill percentage of the rectangle increases as well. Here is an illustration

The control is quite simple. There are two main properties here which are exposed to the outer world – The FillColor and the EmptyColor denoting the colors of the rectangle. The third property is the Value of slider which is used within the control, but that too could be exposed out of the control. Lets see the code for the control. ( Notice the absence of any UI stuff)

public class FilledBarControl : Control
    {
        public FilledBarControl()
        {
            DataContext = this;
        }
        
        static FilledBarControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(FilledBarControl), new FrameworkPropertyMetadata(typeof(FilledBarControl)));
          
        }

        public static readonly DependencyProperty EmptyColorProperty = DependencyProperty.Register("EmptyColor", typeof(Color), typeof(FilledBarControl), new UIPropertyMetadata((Color)Colors.Transparent));

        public Color EmptyColor
        {
            // IMPORTANT: To maintain parity between setting a property in XAML and procedural code, do not touch the getter and setter inside this dependency property!
            get
            {
                return (Color)GetValue(EmptyColorProperty);
            }
            set
            {
                SetValue(EmptyColorProperty, value);
            }
        }
        

        public static readonly DependencyProperty FillColorProperty = DependencyProperty.Register("FillColor", typeof(Color), typeof(FilledBarControl), new UIPropertyMetadata((Color)Colors.Red));

        public Color FillColor
        {
            // IMPORTANT: To maintain parity between setting a property in XAML and procedural code, do not touch the getter and setter inside this dependency property!
            get
            {
                return (Color)GetValue(FillColorProperty);
            }
            set
            {
                SetValue(FillColorProperty, value);
            }
        }
    }

As you can see, there are two steps to declaring a dependency property – First is the registering of the property using the DependencyProperty.Register method and the second is the definition of the getter and setter methods. The naming convention for the DependencyObject is to append “Property” after the name of the Dependecy Property. Hence here the object becomes FillColorProperty. You can also define the default values for the Property in the Register method. It needs to be passed inside the constructor of the PropertyMetadata object. I used Red Color here, so if the developer doesnt pass any value for the FillColor, the control automatically chooses Red.

Like written before, a custom control is simply defined in code, it doesn’t necessarily need a UI to exist – the UI can be supplied by the developer using the control. The default look and feel for the control is defined in a separate file – Generic.xaml inside the themes folder. Here is the xaml for the filled Bar control.

<Style TargetType="{x:Type local:FilledBarControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:FilledBarControl}">
                    <UniformGrid Columns="1">
                        <Border BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" >                           
                            <Rectangle Height="{TemplateBinding Height}"
                            Width="{TemplateBinding Width}">
                            <Rectangle.Fill>
                                <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
                                    <GradientStop Color="{Binding Path=FillColor}"
                        Offset="0"/>
                                    <GradientStop Color="{Binding Path=FillColor}"
                        Offset="{Binding ElementName=slider, Path=Value}"/>
                                    <GradientStop Color="{Binding Path=EmptyColor}" 
                        Offset="{Binding ElementName=slider, Path=Value}"/>
                                </LinearGradientBrush>
                            </Rectangle.Fill>
                        </Rectangle>
                        </Border>

                        <Slider x:Name="slider" Width="200" Height="50" 
            Minimum="0" Maximum="1" Value="0.2"/>
                    </UniformGrid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

The XAML is just a control template containing a Uniform Grid. One of the rows is the Rectangle and the other a Slider for the value. The rectangle’s fill tag is a LinearGradientBrush with two phases. One from the Start Point (0,0) to the Value (bound to the Slider’s value) and another which starts from the Value to the end point. This gradient gives the impression of a filled rectangle whose fill percentage changes as the slider is dragged.

Now, how can a host application change the appearance of the control? There are two ways – one using the Dependency Properties and other completely overriding the Control Template itself. As you can recall, there were two dependency Properties defined in the FilledBar.cs – The FillColor and the EmptyColor. Both these properties appear in the Intellisense while defining the control in the XAML. An example of such customization would be

         <FilledBar:FilledBarControl HorizontalAlignment="Center" 
                                    VerticalAlignment="Center"  
                                    Height="100" Width="200" 
                                    BorderThickness="2" BorderBrush="#003300" 
                                    FillColor="Maroon" EmptyColor="LightGreen" />

This is how the control now looks. Note that both colours have changed as per our definition

The second form of customization is what makes Custom Controls so much more powerful than ordinary User Controls. Lets assume that a rectangular fill bar doesnt suit my requirement and my application would look better with a FilledCircle rather than a FilledBar. Rather than writing the entire control again just for one change, I could just swap out the Rectangle and substitute it with an Ellipse whose Fill is done by a RadialGradientBrush. These changes do not require any changes to the original control itself – a style can be created in the Resource Dictionary and referred to by the code.

            <Style TargetType="{x:Type FilledBar:FilledBarControl}" x:Key="FilledCircle">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type FilledBar:FilledBarControl}">
                            <UniformGrid Columns="1" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" >

                                <Ellipse Height="100" Width="100" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}"
                            >
                                        <Ellipse.Fill>
                                            <RadialGradientBrush >
                                                <GradientStop Color="{Binding Path=FillColor}"
                        Offset="0"/>
                                                <GradientStop Color="{Binding Path=FillColor}"
                        Offset="{Binding ElementName=slider, Path=Value}"/>
                                                <GradientStop Color="{Binding Path=EmptyColor}" 
                        Offset="{Binding ElementName=slider, Path=Value}"/>
                                            </RadialGradientBrush>
                                        </Ellipse.Fill>
                                    </Ellipse>
                              

                            <Slider x:Name="slider" Width="200" Height="50" 
            Minimum="0" Maximum="1" Value="0.2"/>
                        </UniformGrid>
                        </ControlTemplate>

                    </Setter.Value>
                </Setter>
                
            </Style>

The only changes in the above style tag are the changing to ellipse and RadialGradientbrush. Note that instead of using the Border, we just bind the BorderBrush and BorderThickness properties to the Stroke and StrokeThickness properties of the Ellipse. This allows setting of the properties just as we did with the unchanged controls and is much more easier to read. The control is declared in xaml with the style tag referring to our user dictionary which overrides the default style written in the Generic.xaml

        <FilledBar:FilledBarControl HorizontalAlignment="Center" VerticalAlignment="Center" 
                                    Grid.Row="3" Grid.Column="1"  
                                    Style="{StaticResource ResourceKey=FilledCircle}"  
                                    Height="200" Width="200" 
                                    BorderThickness="2" BorderBrush="Brown" 
                                    FillColor="Blue" EmptyColor="Transparent">

Here is how the control looks now.

We can have multiple instance of the same control using different styles and values for Dependency Property. An example of the Host Application

Jan 202012
 

I wrote a small application to extract post and user data for groups in the popular enterprise microblogging portal, Socialcast. It lets users access data instantly about the activity going on in their groups and the number of likes/comments being posted by group members.

The details about the API can be found here and their side demo.socialcast.com can be used for testing. There are three main calls in the application

  • Message Data for the group (Using the parameters Group_Id and since to filter by the data)
  • To find the group Id using the group name using the Groups.xml API call.
  • Then finding the group members using groupname/members.xml.

The method to retrieve group_id from the groupname needed improvement. Most organizations contain upwards of a 1000 groups. Making two heavy API calls for finding out the group id from the name is a bit of a drag on the performance of the application. To avoid this, I just cached all the group Ids and names in a Dictionary<string, int> object and used that to lookup the id. For groups that were created after the tool was distributed, the API call was a fallback.

The UI of the tool is fairly simple. Just a textbox to enter the group URL and two datagridviews to display the data along with two listboxes to display the stats. Since data retrieval is a very slow process, a backgroundworker with a progress bar make sure the application doesnt freeze and the user is shown some progress.  There is also a dropdown to select the time for which the user wants to retrieve messages and whether the member information is required or not. The quickest options are selected by default.


The API access code is in a library which hides the webservice calls from the client application. Each method contains the standard page and number of records per page argument. Apart from them, there are other parameter which are needed to make the call e.g GroupName, member id etc. To simply the URL construction for the web service call a class contains the skeleton urls for each call like given below

public static class ObjectType
 {
 static string defaultFormat = ".xml";
 public static string Users = "users" + defaultFormat;
 public static string Streams = "streams" + defaultFormat;
 public static string Messages = "messages" + defaultFormat;
 public static string StreamMessages = "streams/{0}/messages" + defaultFormat;
 public static string MessagesById = "messages/{0}" + defaultFormat;
 public static string SearchUsers = "users/search" + defaultFormat;
 public static string Groups = "groups" + defaultFormat;
 public static string GroupMembers = "groups/{0}/members" + defaultFormat;
 }

public class SocialCastData
 {
 ///
<summary> /// These are the private variables which are configured
 /// as per your socialcast site
 /// </summary>
 string skeletonURL = "https://{0}.socialcast.com/api/{1}";
//Rest of code here
}

The method to construct the service url takes in the Object Type member, and appends it to the skeleton url along with filling in the domain of the socialcast site and any additional parameter (e.g. group id). This approach allows me to add new service calls easily with just one more variable in the ObjectType class. Any additional query string parameters are supplied using the serviceParams which is a list of keyvaluepairs. The list is iterated through and appended after the url. The SocialcastAuthDetails object is a must in every calls since it contains the domain, the username and password all of which are required to be supplied for getting the response.

Here is the method to get the Group ID from the groupName. The GroupQuery.QueryForGroupId accesses the cache and returns immediately if found. If not then another API call is made to get all the groups, iterate through them and identify the id. If the group id is still not found, an exception is thrown.

        private int GetGroupIdByGroupName(string groupName,SocialCastAuthDetails auth)
        {

            int _groupId = 0;
            int _pageNumber =1;
            bool moreItems = true;

            _groupId = GroupsQuery.QueryForGroupID(groupName);
            if (_groupId != 0)
                return _groupId;
            else
            {

                while (moreItems)
                {
                    XmlDocument group = new XmlDocument();
                    var serviceParams = new List>();
                    serviceParams.Add(new KeyValuePair("page", _pageNumber.ToString()));
                    serviceParams.Add(new KeyValuePair("per_page", "500"));
                    group.LoadXml(base.MakeServiceCalls(helper.GetSocialcastURL(ObjectType.Groups, auth.DomainName, null, serviceParams),GetCredentials(auth.Username,auth.Password)));
                    if (group.SelectNodes("//groups/group") == null || group.SelectNodes("//groups/group").Count == 0)
                        moreItems = false;
                    else
                    {
                        foreach (XmlNode groupNode in group.SelectNodes("//groups/group"))
                        {
                            if (String.Compare(GetNodeInnerText(groupNode, "groupname"), groupName, true) == 0)
                            {
                                string id = GetNodeInnerText(groupNode, "id");
                                _groupId = Convert.ToInt32(id);
                                GroupsQuery.AddToDictionary(groupName, _groupId);
                                moreItems = false;
                                break;
                            }
                        }
                    }
                    _pageNumber++;
                }
                return _groupId;
            }
        }

In the front end, a background worker is used to perform the time consuming operation asynchronously. Here is the code (Rough, not refactored)

    class GetStatistics
    {
        APIAccessor _api = new APIAccessor();

        public AppData GetData(string urlEnteredbyUser, string sinceWhatPeriod, bool loadUserData)
        {
            var serviceUrl = UrlReplace(urlEnteredbyUser.Trim());
            List<SocialcastMessage> messages = null;
            List<UserProfile> users = null;
            if (serviceUrl == string.Empty)
            {
                throw new GroupNotFoundException(null, "The group Url you have entered is not valid");
            }
            else
            {
                messages = GetMessageStats(serviceUrl, sinceWhatPeriod);
                if(loadUserData)
                        users = GetAllGroupUsers(serviceUrl);
                return new AppData(messages, users);
            }
        }

        private List<UserProfile> GetAllGroupUsers(string groupName)
        {
            List<UserProfile> Users = new List<UserProfile>();
            int userCount = 500;
            int pageNumber = 1;
            bool moreItems = true;
            while (moreItems)
            {
                var xdoc = _api.GetGroupMembers(groupName, pageNumber.ToString(), userCount.ToString(), GetCredentials());
                if (xdoc.SelectNodes("//users/user") == null || xdoc.SelectNodes("//users/user").Count == 0)
                    moreItems = false;
                else
                {
                    foreach (XmlNode userNode in xdoc.SelectNodes("//users/user"))
                    {
                        string name = GetNodeInnerText(userNode, "name");
                        string userName = GetNodeInnerText(userNode, "username");
                        string email = GetNodeInnerText(userNode, "contact-info/email");
                        int followingCount = Convert.ToInt32(GetNodeInnerText(userNode, "following-count"));
                        int followersCount = Convert.ToInt32(GetNodeInnerText(userNode, "followers-count"));

                        Users.Add(new UserProfile()
                        {
                            Name = name,
                            userName = userName,
                            Email = email,
                            FollowerCount = followersCount,
                            FollowingCount = followingCount
                        });
                       
                    }
                    pageNumber++;
                }
            }

            return Users;
        }

        private List<SocialcastMessage> GetMessageStats(string serviceUrl, string sinceWhatPeriod)
        {
            List<SocialcastMessage> Messages = new List<SocialcastMessage>();
            int messageCount = 500;
            int pageNumber = 1;
            bool moreItems = true;
            long sinceWhen = GetSinceWhenValue(sinceWhatPeriod);
            while (moreItems)
            {
                var xdoc = GetMessagesForTheGroup(serviceUrl, messageCount, pageNumber, sinceWhen);
                if (xdoc.SelectNodes("//messages/message") == null || xdoc.SelectNodes("//messages/message").Count == 0)
                    moreItems = false;
                else
                {
                    foreach (XmlNode node in xdoc.SelectNodes("//messages/message"))
                    {
                        DateTime createdDate;
                        DateTime.TryParse(GetNodeInnerText(node, "created-at"), out createdDate);
                        string ticksLastUpdatedDate = GetNodeInnerText(node, "last-interacted-at");
                        var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
                        epoch = epoch.AddSeconds(Int64.Parse(ticksLastUpdatedDate));
                        string permaUrl = GetNodeInnerText(node, "permalink-url");
                        string commentsCount = GetNodeInnerText(node, "comments-count");
                        string likesCount = GetNodeInnerText(node, "likes-count");
                        string title = GetNodeInnerText(node, "title");
                        string user = GetNodeInnerText(node, "user/name");

                        Messages.Add(new SocialcastMessage()
                        {
                            Title = title,
                            Url = permaUrl,
                            CreatedDate = createdDate,
                            UpdatedDate = epoch,
                            Comments = int.Parse(commentsCount),
                            Likes = int.Parse(likesCount),
                            UserName = user
                        });

                    }
                    pageNumber++;
                }
            }


            return Messages;

        }


        private long GetSinceWhenValue(string sinceWhatPeriod)
        {
            switch (sinceWhatPeriod)
            {
                case "All Messages":
                    return 0;
                case "Since Last week":
                    return GetTicksSince1970(7);
                case "Since Last Month":
                    return GetTicksSince1970(30);
                default:
                    return 0;
            }
        }

        private static long GetTicksSince1970(int days)
        {
            DateTime sinceLastWeek = DateTime.Now.Subtract(new TimeSpan(days, 0, 0, 0, 0));
            DateTime epoch = new DateTime(1970, 1, 1);
            return Convert.ToInt64(sinceLastWeek.Subtract(epoch).TotalSeconds);
        }


        private XmlDocument GetMessagesForTheGroup(string streamName, int numberOfPosts, int page, long sinceWhen)
        {
            string sinceWhenString = null;
            if (sinceWhen != 0)
                sinceWhenString = sinceWhen.ToString();
            var xdoc = _api.GetStreamMessages(streamName, numberOfPosts.ToString(), page.ToString(), sinceWhenString, GetCredentials());
           return xdoc;
        }


        private string UrlReplace(string enteredByUser)
        {
        
            string regexPattern = @"https://demo.socialcast.com/groups/([A-Za-z0-9\-]+)";
            Match match = Regex.Match(enteredByUser, regexPattern,
                RegexOptions.IgnoreCase);

            // Here we check the Match instance.
            if (match.Success)
            {
                // Finally, we get the Group value and return it
                string key = match.Groups[1].Value;
                return key;
            }
            return string.Empty;
        }

        private SocialCastAuthDetails GetCredentials()
        {
            return new SocialCastAuthDetails()
            {
                Password = "demo",
                Username = "emily@socialcast.com",
                DomainName = "demo"
            };

        }

        private string GetNodeInnerText(XmlNode node, string xpath)
        {
            try
            {
                if (node.SelectSingleNode(xpath) != null)
                {
                    return node.SelectSingleNode(xpath).InnerText.Trim();
                }
                return String.Empty;
            }
            catch
            {
                return string.Empty;
            }
        }
    }
Dec 272010
 

Since the last post, I changed the library/API wrapper a bit. I removed all the ugly reflection stuff to retrieve the specific API urls and substituted them with static variables in a separate class. However this does have the added disadvantage that the urls are exposed to the client, but at least it wont break any client code if Socialcast decides to change the API in the future. Also in the previous example, the username, password and subdomain are variables in the wrapper itself. In the absence of oAuth, every call needs to be authenticated with the user credentials. To avoid having to handle the responsibility of storing user information, I created a class to encapsulate this information (SocialcastAuthDetails) which is passed to the API Accessor for every call. I also added the data objects to return strongly typed responses from the API accessor instead of an XmlDocument, but havent gotten around to incorporate them yet.

Here is the code to Post a message and Get the company stream. Accessing the Company Stream requires two calls – first to get the Stream ID and the next to get the messages for the particular stream.

        public XmlDocument GetCompanyStream(SocialCastAuthDetails auth)
        {
            XmlDocument streams = new XmlDocument();
            if (companyStreamID == 0)
            {
                streams.LoadXml(base.MakeServiceCalls(helper.GetSocialcastURL(ObjectType.Streams,auth.DomainName,null), GetCredentials(auth.Username,auth.Password)));

                foreach (XmlNode node in streams.GetElementsByTagName("stream"))
                {
                    if (node.SelectSingleNode("name").InnerText.ToLower() == "company stream")
                    {
                        companyStreamID = int.Parse(node.SelectSingleNode("id").InnerText);
                        break;
                    }
                }
            }
            streams = new XmlDocument();
            streams.LoadXml(base.MakeServiceCalls(
                                 helper.GetSocialcastURL(ObjectType.StreamMessages,auth.DomainName,companyStreamID.ToString()),
                                 GetCredentials(auth.Username,auth.Password)));
            return streams;
        }

        public XmlDocument PostMessage(string title,string body,SocialCastAuthDetails auth)
        {
            string data = String.Format("message[title]={0}&message[body]={1}", HttpUtility.UrlEncode(title), HttpUtility.UrlEncode(body));
            XmlDocument update = new XmlDocument();
            update.LoadXml(base.MakeServiceCallsPOST(
                                helper.GetSocialcastURL(ObjectType.Messages, auth.DomainName, null),
                                GetCredentials(auth.Username, auth.Password), data));
            return update;
        }

Since any messages which manipulates data requires a POST call instead of a GET, the WebServiceHelper class needs a new method to make the service call using POST. Also the data which is to be posted is URL encoded before being sent to this method.

  protected string MakeServiceCallsPOST(string _requestURL, NetworkCredential credentials, string data)
        {
            // Create the web request
            HttpWebRequest request = WebRequest.Create(_requestURL) as HttpWebRequest;

            request.Credentials = credentials;
            request.ContentType = "application/x-www-form-urlencoded";
            request.Method = "POST";

            byte[] bytes = Encoding.UTF8.GetBytes(data);

            request.ContentLength = bytes.Length;
            using (Stream requestStream = request.GetRequestStream())
            {
                requestStream.Write(bytes, 0, bytes.Length);

                using (WebResponse response = request.GetResponse())
                {
                    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                    {
                        return reader.ReadToEnd();
                    }
                }
            }
        }

This is the client code to post the message. The socialcast auth details class is initialized by the client and sent, so its their headache to maintain passwords and other sensitive information.

    class Program
    {
        static SocialCastAuthDetails auth = new SocialCastAuthDetails()
        {
            DomainName = "demo",
            Username = "emily@socialcast.com",
            Password = "demo"
        };
        static void Main(string[] args)
        {
            int _messageCounter=1;
            APIAccessor api = new APIAccessor();
            api.PostMessage("Posting from API", "this is a test message posted through C#", auth);
            var xdoc = api.GetCompanyStream(auth);
            Console.WriteLine("Company Steam of demo.socialcast.com");
            Console.WriteLine("******************************************************");
            foreach(XmlNode node in xdoc.GetElementsByTagName("message"))
            {
                Console.WriteLine("Message {0} posted by {1}", _messageCounter++, node.SelectSingleNode("user/name").InnerText);
                Console.WriteLine("Message: {0} {1}", node.SelectSingleNode("title").InnerText, node.SelectSingleNode("body").InnerText);
                Console.WriteLine("====================================================");
            }
        }
    }

It works!!

Oct 202010
 

For the last few months, I am almost exclusively using Ubuntu as my primary operating system. Due to this my .NET development suffered quite a bit and was limited just to work. To find a way around I installed Mono and played around with it.

Though a lot of people believe that .NET is completely tied with the Windows API, that is not exactly true. If we look at the source code of the .NET runtime (released by Microsoft under the name Rotor/SSCLI), there is a seperate layer called the Platform Adaption Layer (PAL) written which acts as an abstraction between the OS and runtime. This layer allows people to write their own implementations of the CLR to translate CIL into native code.

The mono project is one such effort which has ported .NET to both Mac and Linux environment. Even though Mono can work on Linux, I wouldnt really recommend using it for a production application because you might end up with bugs and small irritants while running it on linux which you can ill afford for a commercial application. So if you want to write once, run anywhere, Java is still your best bet.

To install Mono, first the repository needs to be added to the package manager. The mono packages are available here and a guide to add them is given here. After the source is added, click reload to update the list. The use the familiar apt-get command to install Mono. If that doesnt work enable the multiverse repositories or you can use the GUI Synaptic package manager.

Now mono is the application which can execute a .NET exe file. It however cannot compile the code. For that there is another application called mcs. To install it use the following command.

Now for the obligatory hello word program. Just write a simple program and save it as a text file.

Now lets compile it using mcs. The -v switch gives more detailed information in case a parsing error occurs.

If you observe the folder, you will see an exe file created with the same name as the source code file. Now, Linux has no idea how to run an exe without a compatibility layer (cough: emulator cough:) like WINE. So we can compare mono to be an very specific emulator only for .net applications. Even inside Windows, .NET assemblies are loaded differently than other windows dlls. The PE header contains an additional entry about the CLR version and the execution is transferred to the runtime rather than the operating system handling it. I think a similar process happens when we run the exe using mono. Here is the command.

The output of the program is displayed in the console.

Jan 312010
 

Recently someone asked me to write a TicTacToe game. So I worked out a rough logic for it. Heres the code. The idea is that the computer first scans through the tic-tac-toe board for any winning positions available. If none are available, then it looks for the manual user’s winning positions. If its able to find them, it blocks it. If not the next available position is filled. The game can be played by clicking any of the squares below.

Here is the code for the game as a silverlight application. The complete project can be downloaded here.

The XAML is quite simple. Just a grid with three rows and three columns

    <grid x:Name="gridGame" Background="White" Width="300" Height="300" HorizontalAlignment="Center" VerticalAlignment="Center">
        </grid><grid .RowDefinitions>
            <rowdefinition Height="100" />
            <rowdefinition Height="100" />
            <rowdefinition Height="100" />
        </grid>
        <grid .ColumnDefinitions>
            <columndefinition Width="100" />
            <columndefinition Width="100" />
            <columndefinition Width="100" />
        </grid>

It is then filled with the buttons in the Code Behind. I have hardcoded the grid size of three but this will work with any size.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 public MainPage()
        {
            InitializeComponent();
            InitializeGameLogic(true);
        }
 
        private void InitializeGameLogic(bool _fromConstructor)
        {
            if (!_fromConstructor)
            {
                gridGame.Children.Clear();
            }
            _logic = new TicTacLogic();
            for (int i = 0; i < 3; i++)
                for (int j = 0; j < 3; j++)
                {
                    Button _btnGrid = new Button();
                    _btnGrid.Name = "btn" + i.ToString() + j.ToString();
                    gridGame.Children.Add(_btnGrid);
                    Grid.SetRow(_btnGrid, j);
                    Grid.SetColumn(_btnGrid, i);
                    _btnGrid.Height = 80;
                    _btnGrid.Width = 80;
                    _btnGrid.Click += new RoutedEventHandler(_btnGrid_Click);
                }
            _logic.StartGame();
        }

All the dynamically generated buttons have a single event handler. The idea is to identify the button which sent the event from the name. Once we have the position of the button, the content has to be changed with an X. After the user marks, the computer does its stuff and makes its move. After every marking, a check is done if someone has won or the board is full.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
void _btnGrid_Click(object sender, RoutedEventArgs e)
        {
            Button _userClicked = sender as Button;
            int _xPos = Convert.ToInt32(_userClicked.Name.Substring(3,1));
            int _yPos = Convert.ToInt32(_userClicked.Name.Substring(4,1));
            _userClicked.Content = GetMarking("X");
            _logic.ClickUser(_xPos, _yPos);
            if (!(_logic.CheckIfSomeoneWon() || _logic.CheckIfBoardFull()))
            {
                int _xCom = 0;
                int _yCom = 0;
                _logic.MoveComputer(ref _xCom, ref _yCom);
                foreach (UIElement _tempElem in gridGame.Children)
                {
                    Button _comBtn = _tempElem as Button;
                    if (_comBtn != null && _comBtn.Name == "btn" + _xCom + _yCom)
                    {
                        _comBtn.Content = GetMarking("O");
                        break;
                    }
                }
                if (_logic.CheckIfSomeoneWon() || _logic.CheckIfBoardFull())
                    InitializeGameLogic(false);
            }
            else
                InitializeGameLogic(false);
 
        }
 
        private TextBlock GetMarking(string _mark)
        {
            TextBlock _t = new TextBlock();
            _t.Text = _mark;
            _t.FontSize = 25;
            _t.FontWeight = FontWeights.Bold;
            return _t;
        }

The Board class maintains two important things. The position of all the squares and which player has it marked. The Board doesnt depend on the Player objects. It has an object of the WinningPositions object which calculates the winning positions which can be compared with later. This object makes it possible to play with larger grids.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
public class Board
{
    readonly int MAXSIZE;
    List<positionmarking> _boardState = new List</positionmarking><positionmarking>();
    List<position []> _allWinningPositions;
 
    public List<positionmarking> BoardState { get { return _boardState; } }
    public List<position []> AllWinningPositions { get { return _allWinningPositions; } }
    public int MaxSize { get { return MAXSIZE; } }
 
    public Board()
    {
        this.MAXSIZE = 3;
        Initialize();
    }
 
    public Board(int _maxSize)
    {
        MAXSIZE = _maxSize;
        Initialize();
    }
 
    private void Initialize()
    {
        _allWinningPositions = (new WinningPositions(MAXSIZE)).AllWinningPositions;
        for(int _xPos=0;_xPos<maxsize ;_xPos++)
            for (int _yPos = 0; _yPos < MAXSIZE; _yPos++)
            {
                _boardState.Add(new PositionMarking(_xPos,_yPos));
            }
    }
 
    internal void MarkPosition(int _xUser, int _yUser, bool _userMarked)
    {
        foreach (PositionMarking _tempPos in _boardState)
        {
            if (_tempPos.BoardPosition.X == _xUser && _tempPos.BoardPosition.Y == _yUser)
            {
                _tempPos.MarkPosition(_userMarked);
                break;
            }
        }
#if DEBUG
        PrintBoardState();
#endif
    }
 
    internal bool? MarkedByUser(Position _tempPos)
    {
        foreach (PositionMarking _tempMark in _boardState)
        {
            if (_tempPos.X == _tempMark.BoardPosition.X && _tempPos.Y == _tempMark.BoardPosition.Y)
                return _tempMark.IsUserMarked;
 
        }
        throw new Exception("Position Not found on Board");
    }
 
    #if DEBUG
    internal void PrintBoardState()
    {
        string _userMarked = "";
        string _compMarked = "";
        foreach (PositionMarking _tempMark in _boardState)
        {
 
            if (_tempMark.IsUserMarked == true)
                _userMarked += "("+ _tempMark.BoardPosition.X + "," + _tempMark.BoardPosition.Y + ") ";
            else if (_tempMark.IsUserMarked == false)
                _compMarked += "(" + _tempMark.BoardPosition.X + "," + _tempMark.BoardPosition.Y + ") ";
        }
        Debug.WriteLine("USER: " + _userMarked);
        Debug.WriteLine("COMP: " + _compMarked);
        Debug.WriteLine("________________________________________");
    }
#endif
    internal bool IsBoardFull()
    {
        foreach (PositionMarking _tempMark in _boardState)
        {
            if (_tempMark.IsUserMarked == null)
                return false;
 
        }
        MessageBox.Show("Board Full");
        return true;
    }
}

The Winning Position class is given below and all positions are calculated at initialization. First the horizontal ones are considered and then the vertical ones. The remaining diagonal positons are taken care later. Each winning position is stored in an array of the position object which just holds the value of the Squares. These arrays are stored in a generic List.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public class WinningPositions
{
    List<position []> _allWinningPositions = new List</position><position []>();
    Position[] _winPos1;
    Position[] _winPos2;
 
    public List</position><position []> AllWinningPositions
    {
        get { return _allWinningPositions; }
    }
 
    public WinningPositions(int _maxSize)
    {
        _winPos1 = new Position[_maxSize];
        _winPos2 = new Position[_maxSize];
        PopulateWinningPositions();
    }
 
    private void PopulateWinningPositions()
    {
        int _iCounter=0;
        int _xPos = 0;
        int _yPos = 0;
        for (_xPos = 0; _xPos < _winPos2.Length; _xPos++)
        {
            for (_yPos = 0; _yPos < _winPos2.Length; _yPos++)
            {
                _winPos1[_iCounter] = new Position(_xPos, _yPos);
                _winPos2[_iCounter] = new Position(_yPos, _xPos);
                _iCounter++;
            }
            _allWinningPositions.Add(_winPos1);
            _allWinningPositions.Add(_winPos2);
            _winPos1 = new Position[_winPos1.Length];
            _winPos2 = new Position[_winPos2.Length];
            _iCounter = 0;
        }
        _iCounter = 0;
        for (_xPos = 0, _yPos = 0;_xPos < _winPos1.Length; _xPos++, _yPos++)
        {
            _winPos1[_iCounter] = new Position(_xPos, _yPos);
 
            _iCounter++;
        }
        _allWinningPositions.Add(_winPos1);
        _iCounter = 0;
        for (_xPos = 0, _yPos = _winPos1.Length - 1; _xPos < _winPos1.Length; _xPos++, _yPos--)
        {
            _winPos2[_iCounter] = new Position(_xPos, _yPos);
            _iCounter++;
        }
        _allWinningPositions.Add(_winPos2);
    }
}

Then there is the Player class of which we create two objects. The user takes care of his own moving logic, all we need to do is to change the state of the square for him. But the computer has its method called the SmartMove. Here we first move through the winning positions to identify any open squares that can be marked. If there are no squares, then we look to block the opponent’s winning. If even this opportunity is not found, we mark an available open square.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
public class Player
{
    Board _currentBoardPosition;
    bool _isComputer;
    List<position> _allMarkedPositions;
 
    public Player(bool _isComputer,Board _currentBoardPos)
    {
        this._isComputer = _isComputer;
        _allMarkedPositions = new List</position><position>();
        _currentBoardPosition = _currentBoardPos;
    }
 
    internal void SmartMove(ref int _xCom, ref int _yCom)
    {
        bool _markingDone = false;
        bool _blockUser = false;
        Position _userBlock = new Position();
        foreach (Position[] _winPos in _currentBoardPosition.AllWinningPositions)
        {
            int _userMarked = 0;
            int _computerMarked = 0;
            int _nullMarked=0;
 
            Position _openPos= new Position();
            foreach (Position _tempPos in _winPos)
            {
                bool? isUserMarked = _currentBoardPosition.MarkedByUser(_tempPos);
                if (isUserMarked==true)
                    _userMarked++;
                else if (isUserMarked == false)
                    _computerMarked++;
                else
                {
                    _openPos = _tempPos;
                    _nullMarked++;
                }
 
            }
            if (_computerMarked == 2 && _nullMarked == 1)
            {
                Debug.WriteLine("Wining block: " + _openPos.X + "," + _openPos.Y);
                _currentBoardPosition.MarkPosition(_openPos.X, _openPos.Y, false);
                _xCom = _openPos.X;
                _yCom = _openPos.Y;
                _markingDone = true;
                break;
            }
            else if (_userMarked == 2 && _nullMarked == 1)
            {
                _userBlock = _openPos;
                _blockUser = true;
            }
 
        }
        if (_blockUser && !_markingDone)
        {
            _currentBoardPosition.MarkPosition(_userBlock.X, _userBlock.Y, false);
            _xCom = _userBlock.X;
            _yCom = _userBlock.Y;
            _markingDone = true;
        }
 
        if (!_markingDone)
        {
 
            //No Winning Position Found or not able to block;
            foreach (PositionMarking _posMark in _currentBoardPosition.BoardState)
            {
                if (_posMark.IsUserMarked == null)
                {
                    _markingDone = true;
                    _currentBoardPosition.MarkPosition(_posMark.BoardPosition.X, _posMark.BoardPosition.Y,false);
                    _xCom = _posMark.BoardPosition.X;
                    _yCom = _posMark.BoardPosition.Y;
                    break;
                }
            }
 
        }
    }
}
</position>

Since the Board needs to maintain the state of each and every position on itself, we have another object for it, which maintains a position object and a nullable boolean. If the boolean is true, then the square is marked by the user, if false – then by the computer. If its still null – its open and can be marked. The marking is done by the object’s method which makes a check to make sure no players marking is overwritten by another.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class PositionMarking
{
    Position _boardPos;
    bool? _isUserMarked;
 
    public Position BoardPosition { get { return _boardPos; } }
    public bool? IsUserMarked { get { return _isUserMarked; } }
 
    public PositionMarking(int _xPos,int _yPos)
    {
        _isUserMarked = null;
        _boardPos = new Position(_xPos, _yPos);
    }
 
    public void MarkPosition(bool _markedByUser)
    {
        if(_isUserMarked == null)
        _isUserMarked = _markedByUser;
        else
        throw new Exception("Position already taken");
    }
}

Then there is the rest of the code including our business logic layer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
public class TicTacLogic
{
    bool _userToMove;
    bool _resultHasCome;
    Player _user;
    Player _computer;
    Board _gameBoard;
 
    public TicTacLogic()
    {
        _userToMove = true;
        _resultHasCome = false;
    }
 
    internal void StartGame()
    {
        Initialize();
    }
 
    internal bool ClickUser(int _xUser, int _yUser)
    {
        return _gameBoard.MarkPosition(_xUser, _yUser, true);
    }
 
    internal void MoveComputer(ref int _xCom, ref int _yCom)
    {
        _computer.SmartMove(ref _xCom, ref _yCom);
    }
 
    internal void Initialize()
    {
        _gameBoard = new Board(3);
        _user = new Player(false,_gameBoard);
        _computer = new Player(true,_gameBoard);
 
    }
 
    public bool CheckIfSomeoneWon()
    {
        foreach (Position[] _tempWin in _gameBoard.AllWinningPositions)
        {
            int _userWon=0;
            int _compWon=0;
            foreach (Position _p in _tempWin)
            {
                bool? isUserMarked = _gameBoard.MarkedByUser(_p);
                if (isUserMarked == null)
                    break;
                else if (isUserMarked == true)
                    _userWon++;
                else
                    _compWon++;
 
            }
            if (_userWon == _gameBoard.MaxSize)
            {
                MessageBox.Show("User Won");
                return true;
            }
            else if (_compWon == _gameBoard.MaxSize)
            {
                MessageBox.Show("Computer Won");
                return true;
            }
 
        }
        return false;
    }
 
    internal bool CheckIfBoardFull()
    {
        return _gameBoard.IsBoardFull();
    }
}
 
public class Position
{
    int _xPos;
    int _yPos;
 
    public Position()
    {
    }
 
    public int X { get { return _xPos; } }
    public int Y { get { return _yPos; } }
 
    public Position(int xPos, int yPos)
    {
        this._xPos = xPos;
        this._yPos = yPos;
    }
}

Jan 032010
 

In continuation to my earlier post about multithreading in .NET, I am writing about the ReaderWriterLock class which is one more method of thread synchronization.

The ReaderWriterLock is based on the fact that the Monitor locking (lock keyword in C#) doesnt really make any distinction whether the thread accessing the variable is reading it or writing to it. If its only reading it, then we should not need an exclusive lock. So If we allow multiple threads to read the value, it would be much faster than having mutually exclusive locks, which means a more scalable application? On paper, yes – but not in reality.

The problem with ReaderWriterLock is with its implementation. Several experts have slammed this technique and found that outside of limited scenarios, it is actually far slower than the Monitor.Enter method used to get an exclusive lock. ReaderWriterLock gives higher priority to reader threads then writers. This makes sense if you have many readers and only a few writers. So a lot of readers are able to read the resource while the writer has to wait longer to get the lock. But what If you have equal or more writers. The process of favoring readers make writer threads queued up and take a very long time to complete.

Jeffrey Richter says that this performance loss is due to support for Recursion in the ReaderWriterLock class. Due to this, the class needs to maintain a record of the number of times each thread acquires the lock and increment and decrement the counter. When multiple reader threads acquire the same lock (remember ReaderWriterLock class allows simultaneous reads), a counter is maintained for each thread. This overhead is what causes the ReaderWriterLock to pale in comparison to the Monitor class. It is approximately 6 times slower.

Here is a code sample. The Threads 1 and 3 are reader threads while the Thread 2 is a writer one. When you take a look at the output, its clear that the readers are granted simultaneous access to the _value variable, but when the writer thread is writing to it, all the readers wait in queue patiently for it to finish executing. I have made the DoWorkRead method parametrized in order to identify the thread on which the method is being executed.

class Program
{
    int _value = 0;
    ReaderWriterLock _rwLock = new ReaderWriterLock();
 
    static void Main(string[] args)
    {
        Program _prgm = new Program();
        for (int i = 0; i &lt; 20; i++)
        {
            Thread _t1Obj = new Thread(_prgm.DoWorkRead); //Reader Thread
            //Writer Thread
            Thread _t2Obj = new Thread(new ThreadStart(_prgm.DoWorkWrite));
            //Reader Again
            Thread _t3Obj = new Thread(_prgm.DoWorkRead); 
 
            //Start all threads
            _t1Obj.Start("Thread 1");
            _t2Obj.Start();
            _t3Obj.Start("Thread 3");
 
            //Wait for them to finish execution
            _t1Obj.Join();
            _t2Obj.Join();
            _t3Obj.Join();
        }
 
    }
 
    public void DoWorkRead(object threadName)
    {
        //Accquire Reader Lock.
        _rwLock.AcquireReaderLock(Timeout.Infinite);
        Console.WriteLine("Read start: Thread: " + threadName + " " + _value);
        if (threadName.ToString() == "Thread 1")
            //Irregular sleeps makes more chances of
            //Multiple threads trying to access it
            //at same time
            Thread.Sleep(10);
        else
            Thread.Sleep(250);
        Console.WriteLine("Read end  : Thread: " + threadName + " " + _value);
        _rwLock.ReleaseReaderLock();
        //Release Lock
    }
 
    public void DoWorkWrite()
    {
        _rwLock.AcquireWriterLock(Timeout.Infinite);
        Console.WriteLine("\nWriter start: " + _value);
        _value++; //Writing
        Console.WriteLine("Writer End: " + _value);
        _rwLock.ReleaseWriterLock();
        Console.WriteLine();
    }
 
}

A look at the output shows the once the writer acquires a lock, it is mutually exclusive, but both the reader threads are able to access the variable _value.

One more problem with the ReaderWriterLock class is that it allows Reader threads to acquire writer locks. If you set an infinite timeout, it will create a deadlock situation, where the thread just waits to get the Writer lock but cant because the very same thread holds on to the Reader lock and is yet to release it. So the application just waits and waits.

        public void DoWorkRead(object threadName)
        {
            //Accquire Reader Lock.
            _rwLock.AcquireReaderLock(Timeout.Infinite);
            Console.WriteLine("Read start: Thread: " + threadName + " " + _value);
            //NEVER EVER DO THE BELOW. IT WILL CREATE A DEADLOCK
            _rwLock.AcquireWriterLock(Timeout.Infinite);
            Thread.Sleep(10);
            Console.WriteLine("Read start: Thread: " + threadName + " " + _value);
            _rwLock.ReleaseReaderLock();
            //Release Lock
        }

Keeping all these issues in mind, Microsoft introduced a new class – the ReaderWriterLockSlim class from .NET 3.0 onwards, while leaving the old one in there as well, for backwards compatibility. This class placed Lock recursion in the hands of the developers by giving an enum that could be set during object recursion. With recursion out of the way, performance is dramatically better and comparable to the Monitor class. It also took care of the deadlock situation above. As a conclusion, it is always better to avoid the ReaderWriterLock class and use the slim implementation instead. If you are on .NET 2.0, then since that option is not open to you, its better to look at some other synchronization technique.

Dec 302009
 

I got an interesting problem by email recently where someone had asked me to solve the given below problem:-

A squad of robotic rovers are to be landed by NASA on a plateau on Mars.This plateau, which is curiously rectangular, must be navigated by therovers so that their on-board cameras can get a complete view of the surrounding terrain to send back to Earth.

A rover’s position and location is represented by a combination of x and y co-ordinates and a letter representing one of the four cardinal compass points. The plateau is divided up into a grid to simplify navigation. An example position might be 0, 0, N, which means the rover is in the bottom
left corner and facing North.

In order to control a rover, NASA sends a simple string of letters. The possible letters are ‘L’, ‘R’ and ‘M’. ‘L’ and ‘R’ makes the rover spin 90 degrees left or right respectively, without moving from its current spot. ‘M’ means move forward one grid point, and maintain the same heading.

Assume that the square directly North from (x, y) is (x, y+1).

INPUT:
The first line of input is the upper-right coordinates of the plateau, the lower-left coordinates are assumed to be 0,0.

The rest of the input is information pertaining to the rovers that have been deployed. Each rover has two lines of input. The first line gives the rover’s position, and the second line is a series of instructions telling the rover how to explore the plateau.

The position is made up of two integers and a letter separated by spaces, corresponding to the x and  co-ordinates and the rover’s orientation.

Each rover will be finished sequentially, which means that the second rover won’t start to move until the first one has finished moving.

OUTPUT
The output for each rover should be its final co-ordinates and heading.

I worked out a simple solution for this problem. Of course there is a lot of room for improvement as this solution is the bare minimum one. The rover parses the instructions one at a time. Here are improvements I have planned to be implemented in later versions

  • Understand multiple instruction and process them at once to improve performance
  • Identify cyclic instructions that have no net effect on coordinates and ignore them
  • Move multiple rover objects at same time.
  • Prevent two rovers from taking at same positions at the same time.

Heres what I have for now.

The Rover class stores the state of each Rover on the grid.

 ///
    /// This class is responsible for maintaining the state of each Rover
    /// and processing the instructions given to it.
    ///
    class Rover
    {
        //private objects : Coordinates, Direction, Instruction Array
        private Coordinates _rovCor;
        private Direction _rovDir;
        private string _instructionArray;
 
        //readonly properties for above objects
        public int X { get { return _rovCor.X; } }
        public int Y { get { return _rovCor.Y; } }
        public Direction RoverDirection { get { return _rovDir; } }
 
        ///
        /// Constructor. Passes to Struct coorinates for getting coordinate object
        ///
        public Rover(int _xCor, int _yCor, char _startDir, string _instructionArray)
        {
            this._rovCor = new Coordinates(_xCor, _yCor);
            this._rovDir = GetDirection(_startDir);
            this._instructionArray = _instructionArray;
        }
 
        //Parses The Start Position into Direction Enum
        private Direction GetDirection(char _startDir)
        {
            switch (_startDir)
            {
                case 'N':
                    return Direction.North;
                case 'S':
                    return Direction.South;
                case 'E':
                    return Direction.East;
                case 'W':
                    return Direction.West;
                default:
                    throw new Exception("Unknown Direction Supplied. Accepted values are N,S,E,W");
            }
        }
 
        //Processes the Instruction Array
        public void ProcessInstructionArray()
        {
            foreach (char _instruction in _instructionArray)
            {
                ProcessInstruction(_instruction);
            }
        }
 
        //Processes individual instructions. delegates tasks to other methods
        //after checking instruction type.
        private void ProcessInstruction(char _instruction)
        {
            if ((_instruction == 'L') || (_instruction == 'R'))
            {
                ProcessDirectionInstruction(_instruction);
            }
            else if (_instruction == 'M')
                ProcessMoveInstruction();
            else
                throw new Exception("Invalid Instruction Processed. Please supply only L,R and M");
        }
 
        //Move Instruction is processed by the Coordinate Object
        private void ProcessMoveInstruction()
        {
            this._rovCor.UpdateCoordinates(_rovDir);
        }
 
        //This Processes the direction of the Rover. Instructions L and R
        //are processed by this method.
        private void ProcessDirectionInstruction(char _instruction)
        {
            int _rovDirInt = (int)this._rovDir;
 
            if (_instruction == 'L')
            {
                if (_rovDirInt == 0)
                    _rovDirInt = 4;
                this._rovDir = (Direction)(_rovDirInt - 1);
            }
            else
            {
                if (_rovDirInt == 3)
                    _rovDirInt = -1;
                this._rovDir = (Direction)(_rovDirInt + 1);
            }
 
        }
    }

The Rover class stores its coordinates and Directions as a struct and an enum. Here is the code for them.

    ///
    /// This enumeration is for the Direction the Rover is currently facing in.
    ///
    enum Direction { North, East, South, West, };
 
    ///
    /// This is Stuct which holds the current coordinates of the Rover.
    /// It is also used to hold the max coordinates of the Grid.
    ///
    struct Coordinates
    {
        private int _xCor;
        private int _yCor;
 
        public int X { get { return _xCor; } }
 
        public int Y { get { return _yCor; } }
 
        public Coordinates(int _xCor, int _yCor)
        {
            this._xCor = _xCor;
            this._yCor = _yCor;
        }
 
        public void UpdateCoordinates(Direction _dirObj)
        {
            switch (_dirObj)
            {
                case Direction.North:
                    this._yCor++;
                    break;
                case Direction.South:
                    this._yCor--;
                    break;
                case Direction.East:
                    this._xCor++;
                    break;
                case Direction.West:
                    this._xCor--;
                    break;
            }
        }
    }

The Grid class contains a generic list of all the rovers on the grid. It moves each rover in the list and makes sure the rover doesn’t cross the boundaries. If it does then an exception is thrown.

    ///
    /// This class is responsible for holding all the Rovers
    /// and also making sure no rovers cross the grid boundaries.
    /// The ToString() method is overridden to get the state of
    /// all rovers on the grid in an easy to read string format
    ///
    class Grid
    {
        //Maximum coordinates for the grid
        private Coordinates _maxCoordinates;
 
        //Collection Object to hold all rovers on grid
        private List _allRoversOnGrid;
 
        //Constructor to intialize Rover collection and max coordinates
        public Grid(Coordinates _maxCor)
        {
            this._maxCoordinates = _maxCor;
            _allRoversOnGrid = new List();
        }
 
        //Rovers can only be added to the collection. Nothing else
        //is exposed outside
        public void AddToRoverCollection(Rover _roverObj)
        {
            _allRoversOnGrid.Add(_roverObj);
        }
 
        //This method processes all the rovers on the grid and their instruction arrays
        public void MoveAllRoversOnGrid()
        {
            foreach (Rover _tempRov in _allRoversOnGrid)
            {
                _tempRov.ProcessInstructionArray();
                this.DoIntegrityCheck(_tempRov);
            }
        }
 
        //Making sure the Rover object stays within the grid.
        private void DoIntegrityCheck(Rover _tempRov)
        {
            if ((_tempRov.X &gt; _maxCoordinates.X) || (_tempRov.Y &gt; _maxCoordinates.Y))
            {
                throw new Exception("Rover Failed Grid Integrity. Moved out of Grid Boundaries");
            }
        }
 
        //Overriding the ToString method to get all rovers states
        public override string ToString()
        {
            StringBuilder _AllRoversState = new StringBuilder();
            _AllRoversState.Append("**********************************");
            _AllRoversState.Append(Environment.NewLine);
            _AllRoversState.Append("Number of Rovers currently on Grid: " + this._allRoversOnGrid.Count);
            _AllRoversState.Append(Environment.NewLine);
            _AllRoversState.Append(String.Format("Max Coordinates: X: {0},Y: {1}", _maxCoordinates.X, _maxCoordinates.Y));
            _AllRoversState.Append(Environment.NewLine);
            _AllRoversState.Append("Each Rover state as below: ");
            _AllRoversState.Append(Environment.NewLine);
            foreach (Rover _tempRov in _allRoversOnGrid)
            {
                _AllRoversState.Append(String.Format("Rover Details -- X:{0},Y:{1},Direction:{2}", _tempRov.X, _tempRov.Y, _tempRov.RoverDirection));
                _AllRoversState.Append(Environment.NewLine);
            }
            _AllRoversState.Append("**********************************");
            return _AllRoversState.ToString();
        }
 
    }

Finally, the code to call the Grid class:-

    class Program
    {
        static void Main(string[] args)
        {
 
            //Creating Grid Object
            Grid _testGrid = new Grid(new Coordinates(5,5));
            //Adding two rovers as per sample input
            _testGrid.AddToRoverCollection(new Rover(1, 2, 'N', "LMLMLMLMM"));
            _testGrid.AddToRoverCollection(new Rover(3, 3, 'E', "MMRMMRMRRM"));
            //move all rovers
            _testGrid.MoveAllRoversOnGrid();
            //Get Rover Final state using Grids ToString() method.
            Console.WriteLine(_testGrid.ToString());
        }
    }

To download the solution click here.

Dec 262009
 

Events and Delegates are quite tied together in .NET, but there are differences in terms of usage. Events are implemented through delegates, but they are not quite interchangeable. The event keyword is an access modifier on the delegate which restricts its usage outside the class which it belongs to.

First the similarities. See the below code, which declares a delegate and creates objects for it with and without the event modifier. Then uses both of them, without any difference whatsoever.

    class Test
    {
        public delegate void MyDelegate(string _someRandomMessage);
 
        //One is a delegate while other is an event.
        public MyDelegate _mydelObj;
        public event MyDelegate _myeventObj;
 
        public Test(){
            _mydelObj = s =&gt; Console.WriteLine("Delegate Invoked: " + s);
            _myeventObj = s =&gt; Console.WriteLine("Event Invoked: " + s);
        }
 
        public void TestDelegates(){
            _mydelObj.Invoke("I am a delegate");
            _myeventObj.Invoke("I am an event");
        }
    }

The main difference starts when you access events outside of the class they were declared in. I created one more class SomeOtherClass (very unimaginative!!) and invoked the public delegate objects from this. When its a plain delegate object, there is no restriction on resetting the invocation list, adding to it, removing from it and also invoking the delegate itself. But try doing that to the event object, and you the compiler will throw the The event ‘EventsAndDelegates.Test._myeventObj’ can only appear on the left hand side of += or -= (except when used from within the type ‘EventsAndDelegates.Test’)

    class SomeOtherClass{
        Test _testObj = new Test();
        public SomeOtherClass()
        {
            _testObj._mydelObj += s =&gt; Console.WriteLine("Calling from Outside class: "+s);
            _testObj._myeventObj += s =&gt; Console.WriteLine("Calling Event from Outside class " + s);
            //The below code wont work. An event's invocation list cannot be accessed
            //from outside. It can be added to or removed from.
            _testObj._myeventObj = s =&gt; Console.WriteLine("Trying to reset the invocation list");
        }
 
        public void InvokeBaseDelegate(){
            _testObj._mydelObj("Delegate Invoked");
            //This will throw an error. An event cannot be triggered from anyother type
            //other than the one which it belongs to
            _testObj._myeventObj("Event Triggered");
        }
    }

This key difference is due to the way events and delegates are exposed outside the class which they are declared in. There is an extra IL declaration for an event object which declares two accessors add and remove for the event. Only these are accessible outside the class.

.event EventsAndDelegates.Test/MyDelegate _myeventObj
{
  .addon instance void EventsAndDelegates.Test::add__myeventObj(class EventsAndDelegates.Test/MyDelegate)
  .removeon instance void EventsAndDelegates.Test::remove__myeventObj(class EventsAndDelegates.Test/MyDelegate)
} // end of event Test::_myeventObj

When this is accessed in SomeOtherClass, the Delegate.Combine method used to add to the delegate object’s invocation list is not available for the event and the only alternatives are the add and remove accessors. Similarly the Invoke method is not available outside the class because of which the events cant be triggered.

.method public hidebysig specialname rtspecialname
        instance void  .ctor() cil managed
{
//Removed for Brevity
  IL_0035:  ldsfld     class EventsAndDelegates.Test/MyDelegate EventsAndDelegates.SomeOtherClass::'CS$&lt;&gt;9__CachedAnonymousMethodDelegate2'
  IL_003a:  call       class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
                                                                                          class [mscorlib]System.Delegate)
  IL_003f:  castclass  EventsAndDelegates.Test/MyDelegate
//Removed for brevity
  IL_0067:  ldsfld     class EventsAndDelegates.Test/MyDelegate EventsAndDelegates.SomeOtherClass::'CS$&lt;&gt;9__CachedAnonymousMethodDelegate3'
//Notice the add_ accessor being called instead of the Delegate.Combine method
  IL_006c:  callvirt   instance void EventsAndDelegates.Test::add__myeventObj(class EventsAndDelegates.Test/MyDelegate)
  IL_0071:  ret
} // end of method SomeOtherClass::.ctor

It makes sense to restrict an event’s invocation list from an outside class. For example, if your application makes use of a public API which polls for the weather at a location and raises an event when there is going to be heavy snow. Someone in your team might have subsribed to the event to send out notifications to employees take caution while travelling. However, your need to subscribe to the event could be totally different. In that case if you use the = sign instead of the += while assigning a handler, the previous code for sending out notifications would not work. Needless to say, there would be a lot of pi**ed off employees baying for your blood the next day.

Apart from this, there is one more difference between delegates and events while declaring them in an interface. An interface cannot contain delegate objects, however they can contain events. If you try to do so, you would get an error Interfaces cannot contain fields.

Dec 262009
 

In the previous post we saw how anonymous methods can help reduce verbose delegate code. With C# 3.0, there was a new language feature introduced which further reduces the delegate code – Lambda expressions.

Lambda expressions use automatic type inference, which relieves you of explicitly declaring the type. Here is a simple example of lambda expressions usage. Notice how the code for the delegate object is concisely declared. What is signifies is that the value of x is to be passed to the method, which is then squared and returned. The operator => signifies sending of the parameter (LHS) to the method (RHS).

1
2
3
4
5
6
7
8
9
10
11
	private delegate int Square(int x);
 
	// Simple Lambda expression example
	public static void Test()
	{
        //Note I dont declare the type of variable x. Its automatically inferred.
		Square myVar = x => x*x;
        //Call the delegate
		int n = myVar(5);
        Console.WriteLine(n); //prints 25
	}

When we dive into the MSIL, we find an identical code to Anonymous methods. There is a delegate which is created by the compiler automatically and also the implementation of the inline code is spun off into a separate method b_0. Whats important to note is that both the return type and the arguments of the method is automatically inferred by the compiler. This is not possible with anonymous methods, where we have to explicitly declare the list of arguments to the delegate.

1
2
3
4
5
6
7
8
.method private hidebysig static int32  '<test>b__0'(int32 x) cil managed
{
  IL_0000:  ldarg.0
  IL_0001:  ldarg.0
  IL_0002:  mul
  IL_0003:  ret
} // end of method TestLambda::'</test><test>b__0'
</test>

Since lambda expression pass the parameter to the method, the syntax is slightly different for delegates which don’t take any parameters.

1
2
3
4
5
6
7
8
9
private delegate void DoSomething();
    public static void MethodsWithNoArguments()
    {
        DoSomething _methWithNoArgs = () => Console.WriteLine(
        "Lambda Expression without arguments and return types");
 
        //prints the message.
        _methWithNoArgs();
    }

Lambda expressions can also be used to send a delegate object as a parameter to any method. In the below example, I wrote a delegate which takes in a delegate as a parameter and invokes it using the other argument. Note how lambda expressions automatically inferred the type of the delegate object being passed to it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private delegate void PrintMessage(string s);
private delegate void DoSomething();
 //Takes in the Print Message Delegate as an argument.
 private delegate void LamArguments(PrintMessage _printMsg,string _message);
 
    public static void TestDelegateParams()
    {
        //This delegate takes in the PrintMEssage delgate as the 
        // parameter and invokes it. 
        LamArguments _lamARg = (mymsg, _message) =>
        {
            mymsg.Invoke(_message);
        };
 
        //Assigning a method to the PrintMessage delegate's invocation list.
        PrintMessage _printMsg = _message =>
            {
                Console.WriteLine(_message);
            };
 
        //Sending the message 
        _lamARg(_printMsg, "Hello World");
    }