Friday, April 26, 2013

Using the Blogger API to search within a post's HTML content

A couple of months ago I wanted to switch the syntax highlighter I used to have on this blog to SunlightJS. Thing is though, I didn't want to go through every individual post I had written before and check whether they are using the (old) syntax highlighter to update their HTML markup.

Another problem was that the only way I would be able to truly know if a particular post is using the old syntax highlighter was by going through it's HTML content and determine whether the post currently has a tag like the following: <pre class="

The issue here is that the normal Google driven searchbox packaged with Blogger (the one you see on the right hand side) does not search through a posts' HTML content but rather through its textual content only which means it was useless for my task.

Because of this, I decided to write a script to semi-automate this task for me. The reason I say that the script semi-automates the job is because although I wanted it to show me all the posts in which I had used the old highlighter before, I could not risk making it to update the blog post automatically to use the new syntax highlighter because that would have involved HTML parsing and it was not worth the hassle. Besides, I didn't want to risk ruining my old posts because of a script fuckup.

So what the script does is it uses the Blogger API to batch-fetch all my previous blog posts, go through each posts' individual HTML content and notify me whether that particular post is using the old syntax highlighter. Searching is done using the regular expression engine and for my case, the function was pretty trivial:

getOccurences = function(haystack, needle) {
    var matches = haystack.match(new RegExp(needle, "g"));
    return matches ? matches.length: 0;
}

The Blogger API url I used to fetch my posts' details is as follows:

https://www.googleapis.com/blogger/v3/blogs/<blogid>/posts?key=<API key>

For the script to work I needed to provide it with three things:

Here's a demo of the script in action: http://jsfiddle.net/ydtuc/77/.

And this is how it looks like:


From the live demo (or the screenshot), you can see the output of the script in the bottom right pane. The script nicely formats each of the returned matches in a way that if I click on the #number of the post, it would take me to the actual blog post and clicking on the name of the post takes me to the Blogger editor for that current post so that I can easily update it. The number in parentheses next to the title of the post is the total number of occurrences the needle appears in the haystack.

This is the full script:

var key = 'AIzaSyCEsBaStg4bOHA2Yp75OqfbjBkk_kq0cMw',
    blogId = '7117612757607239790',
    baseMatcher = 'JavaScript', // the needle.
    allPosts = [],
    isProcessing,
    updateButton = $("#update"),
    update = (function (button) {
        var updateText = function (message, color) {
            button.attr("value", message);
            if (color) {
                button.css("color", color);
            }

        },
            revertButtonMessage = function () {
                changeButtonMessage("Update", "black");
            },
            changeButtonMessage = function (message, color) {
                var didIt;
                updateText(message, color);
                setTimeout(revertButtonMessage, 1000);
            },
            switchButtonMessage = function (message, color) {
                updateText(message, color);
            };

        return {
            changeButtonMessage: changeButtonMessage,
            switchButtonMessage: switchButtonMessage,
            revertButtonMessage: revertButtonMessage
        };
    }(updateButton)),
    formatLink = function (text, href) {
        return '<a href="' + href + '" target="_blank">' + text + '</a>';
    },
    getOccurences = function (haystack, needle) {
        var matches = haystack.match(new RegExp(needle, "g"));
        return matches ? matches.length : 0;
    },
    logger = (function () {
        var logs = $("#logs"),
            appendLine = function (line) {
                logs.append((line ? line : "") + "<br/>");
            };

        return {
            log: function (items) {
                appendLine('<span class="logHeader">Logs #' + new Date().getTime() + '</span>');
                appendLine();
                $.each(items, function (i, item) {
                    appendLine(formatLink('#' + i, item.url) + ': ' + formatLink(item.title, "http://www.blogger.com/blogger.g?blogID=" + blogId + "#editor/target=post;postID=" + item.id) + ' (' + getOccurences(item.content, baseMatcher) + ')');
                });
                appendLine();
            },
            clear: function () {
                logs.html('');
            }
        };
    }()),
    filter = function (items, predicateForPass) {
        var i = 0,
            j = items.length,
            item, passed = [],
            inc = 0;

        for (; i < j; ++i) {
            item = items[i];
            if (!predicateForPass(item)) {
                continue;
            }

            passed.push(item);
        }

        return passed;
    },
    getPosts = function (pageToken) {
        var url = 'https://www.googleapis.com/blogger/v3/blogs/' + blogId + '/posts?key=' + key,
            get = function (token) {
                var pagedUrl = url + (token ? ("&pageToken=" + token) : "");
                $.get(pagedUrl, function (response) {
                    var token = response.nextPageToken;
                    allPosts = allPosts.concat(response.items);

                    if (token) {
                        return get(token);
                    }

                    isProcessing = false;
                    update.changeButtonMessage("Finished", "green");
                    var filtered = filter(allPosts, function (item) {
                        var preTotal = getOccurences(item.content, baseMatcher),
                            preNewSyntaxHighlighter = getOccurences(item.content, baseMatcher + "sunlight");
                        return (preTotal - preNewSyntaxHighlighter) > 0;
                    });

                    console.log(filtered);
                    logger.clear();
                    logger.log(filtered);
                    allPosts.length = 0;
                });
            };

        update.switchButtonMessage("Getting posts...", "green");
        isProcessing = true;

        get(pageToken);
    };
updateButton.click(function () {
    if (isProcessing) {
        return update.changeButtonMessage("Busy; try again later", "red");
    }

    getPosts();
});

getPosts();

Friday, April 19, 2013

Fading a UITexture's opacity within a panel in NGUI

Here is a common scenario I'm commonly finding myself into: changing a UITexture's opacity using its parent UIPanel's alpha field.

The first time I tried this out, I couldn't get it to work. I was changing the opacity of the UIPanel using the alpha field but the UITexture inside the panel wasn't fading.


Long story short, you need to change the Shader of your UITexture to something like Unlit/Transparent Colored:


And this will give you the result you desired:


This is how it can be done programatically in C#:

var uiTexture = powerupTexture.AddComponent<UITexture>();
uiTexture.shader = Shader.Find("Unlit/Transparent Colored");

Friday, April 12, 2013

Clearing the browser cache of the Unity Web Player

For my current Unity web project, I am downloading scenes as AssetBundles hosted on my server, and now I have found myself constantly uploading the updated scenes whenever I make these (constant) changes.

Problem is, when I try the game online to see how the downloaded scene looks, my main game file which is downloading these scenes keeps on using the cached scenes from before.

That's because I am downloading the AssetBundles using WWW.LoadFromCacheOrDownload

To clear the cache, just head on over to http://unity3d.com/webplayer_setup/setup-3.x/ where you will see something like this:


And from there, you can simply delete the cache, or even make sure that while you're still working on the game, don't keep a cache at all.

Thursday, April 11, 2013

Showing a Kongregate user's avatar image in a Unity 3D game

I decided that the game I'm currently working on is going to be tied to Kongregate, and since I'm doing that, might as well try to use as many features of the API as I can.

One of the features I'm trying to integrate in my game is the ability to render a Kongregate user's avatar in the game itself. For this tutorial, I will be using Kongregate's JSON REST API to fetch user data.

After skimming through the Kongregate API documentation, I found the page about the user-info REST call.

The url for a user-info call is formatted as follows: http://www.kongregate.com/api/user_info.json?username=<username> where username is obviously the username for the user account you're searching for.

This provides you with a response such as the following:

{
   "friends":[],
   "muted_users":[],
   "friend_ids":[],
   "muted_user_ids":[],
   "user_id":3590097,
   "username":"agnt666",
   "private":false,
   "page_num":1,
   "num_pages":1,
   "success":true,
   "user_vars":{
      "username":"agnt666",
      "level":3,
      "points":165,
      "avatar_url":"http://cdn4.kongcdn.com/assets/resize-image/50x50/assets/avatars/defaults/ant.png",
      "chat_avatar_url":"http://cdn4.kongcdn.com/assets/resize-image/16x16/assets/avatars/defaults/ant.png",
      "developer":false,
      "moderator":false,
      "admin":false,
      "gender":"Male",
      "age":25,
      "game_title":"Typocalypse 3D",
      "game_url":"http://www.kongregate.com/games/agnt666/typocalypse-3d"
   }
}

And the above response provides me with what I needed; the avatar url:

"avatar_url" : "http://cdn4.kongcdn.com/assets/resize-image/50x50/assets/avatars/defaults/ant.png"


Getting the avatar url in C#
Getting the username of the current Kongregate logged-in user is beyond the scope of this post (TODO: maybe in another one), so for this code I'm assuming you already have it.

public UITexture kongregateTexture;

IEnumerator FetchUserDetails(string username) {
    // Build the url for the REST call
    var detailsUrl = String.Format("/api/user_info.json?username={0}", username);

    // Do the call 
    var www = new WWW(detailsUrl);

    // ...and wait until we get back a response
    yield return www;

    // Get the JSON response text
    var responseText = www.text;

    // Deserialize it into a statically typed object to read to be able to read it's contents
    // For this demo, I'm using this JSON deserializer script: https://raw.github.com/gist/1411710/MiniJSON.cs
    var deserialized = MiniJSON.Json.Deserialize(responseText) as Dictionary<string,object>;

    //// TODO: a null check would be nice here

    // Get the user_vars object
    var userVars = deserialized["user_vars"] as Dictionary<string,object>;

    // Read the avatar url
    var avatar_url = user_vars["avatar_url"].ToString(); // http://cdn4.kongcdn.com/assets/resize-image/50x50/assets/avatars/defaults/ant.png

    //// Do the same routine to fetch the image
    var wwwAvatar = new WWW(avatar_url);
    yield return wwwAvatar;

    // And now we have the texture!
    Texture2D avatarTexture = wwwAvatar.texture;

    // Render the texture (I'm using an NGUI SimpleTexture widget)
    kongregateTexture.mainTexture = avatarTexture;
}

And this is the result with a shitty border I made around it:


Possible exception: Security Exception: No valid crossdomain policy available to allow access
Notice that in the above code, to build the url of the REST call, I used Kongregate's relative url: "/api/user-info.json...".

If I had used this instead String.Format("http://www.kongregate.com/api/user_info.json?username={0}", username);, I would have received this exception when running the game and looking at the debug log (console):


This error is thrown when reading the text field of the WWW instance (get_text).

So be very careful about that when doing the REST calls; always use relative urls! ...and this of course works because the game is hosted on http://www.kongregate.com.

Monday, April 8, 2013

Auto-Generating generic Tuple classes with T4 in C#

And yet again, here's another perfect example for using the T4 code generation toolkit in Visual Studio.

For a recent project, I wanted to use the Tuple class provided in the .NET Framework...problem was, I was stuck with .NET 3.5 and the Tuple class was introduced in version 4 of the framework. So, instead of writing a single Tuple class by hand (which would have been very trivial to do), I decided to write a T4 template which would generate all the Tuple classes I needed automatically.

The template itself is very trivial and the number of Tuple classes it generates is dependent on the value that I specify in the max variable at the top of the template.

For each of the Tuple classes the template generates, it creates a contructor which accepts all of the properties that the tuple will contain and also the actual properties that will be accessed from the outside.

Here's an example of what the template autogenerates for me when using max = 3 (granted, the first class it generates is a bit pointless but that can be easily omitted from within the template if it bothers you):
namespace FunWithTuples
{
    /// <summary>
    /// Represents a 1-tuple
    /// </summary>
    public class Tuple<T1>
    {
        public T1 Item1 { get; set; }

        public Tuple(T1 item1) 
        {
            Item1 = item1;
        }
    }

    /// <summary>
    /// Represents a 2-tuple
    /// </summary>
    public class Tuple<T1, T2>
    {
        public T1 Item1 { get; set; }
        public T2 Item2 { get; set; }

        public Tuple(T1 item1, T2 item2) 
        {
            Item1 = item1;
            Item2 = item2;
        }
    }

    /// <summary>
    /// Represents a 3-tuple
    /// </summary>
    public class Tuple<T1, T2, T3>
    {
        public T1 Item1 { get; set; }
        public T2 Item2 { get; set; }
        public T3 Item3 { get; set; }

        public Tuple(T1 item1, T2 item2, T3 item3) 
        {
            Item1 = item1;
            Item2 = item2;
            Item3 = item3;
        }
    }
}



And this is the full T4 Template:

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>

<#
var max = 3; // The total number of classes to generate
#>
namespace FunWithTuples
{
<#
max += 1;
for (var i = 1; i < max; ++i) {
#>
    /// 
    /// Represents a <#=i#>-tuple
    /// 
    public class Tuple<#=GetGenericTypesSignature(i)#>
    {
<#
for (var j = 1; j < i + 1; ++j) {
#>
        public T<#=j#> Item<#=j#> { get; set; }
<#
}
#>

        public Tuple(<#=GetConstructorArguments(i)#>) 
        {
<#
for (var j = 1; j < i + 1; ++j) {
#>
            Item<#=j#> = item<#=j#>;
<#
}
#>
        }
    }

<#
}
#>
}
<#+
    public string GetGenericTypesSignature(int total) {
        return String.Format("<{0}>", String.Join(", ", Enumerable.Range(1, total).Select(n => "T" + n).ToArray()));
    }

    public string GetConstructorArguments(int total) {
        return String.Join(", ", Enumerable.Range(1, total).Select(n => String.Format("T{0} item{0}", n)).ToArray());
    }
#>


Friday, April 5, 2013

Absolute value bars for fractions in LaTeX

The simplest way on how to include |absolute value| bars in LaTeX is to use the this notation: \left| and \right|.

Here's an example:

y = \left|\frac{1}{x}\right|

And that would be rendered as:



Common CIL incantations

Since I recently decided to try my hand at CIL by writing assemblies by hand, I'm now writing this post where I will list down a couple of basic CIL routines.

I am of course primarily writing this post for myself so that future me will have a reference if he (I?) decides to do something with it again.

Hello World
.assembly helloworld {}
.assembly extern mscorlib {}

.method public static void Main () {
    .entrypoint
    ldstr "Hello World!"
    call void [mscorlib]System.Console::WriteLine(string)
    ret
}
Including external assemblies
.assembly extern mscorlib {}
Pushing a 32 bit integer constant to the stack
ldc.i4 42
Pushing a 64 bit integer constant to the stack
ldc.i8 829190
Pushing a string constant to the stack
ldstr "Andreas"
Declaring and loading unnamed variables (popping elements off the stack)
.locals init (int32, string) // init specifies that the variables must be initialized to the default types
ldc.i4 42
stloc.0 // storing the 32 bit integer at position 0 by popping it off the stack
ldstr "CIL"
stloc.1
Defining a class
.class MathHelpers extends [mscorlib]System.Object {
    .method void .ctor() { // Constructor
        ldarg.0
        call instance void [mscorlib]System.Object::.ctor()
    }

    .method public instance int32 Inc(int32) { // Instance method; the instance keyword can be omitted
        ldarg.0
        ldc.i4.1
        add
        ret
    }
    
    .method public static int32 Add(int32 n, int32 m) {  // Static method
        ldarg n
        ldarg m
        add
        ret
    }
}
Invoking methods from external assemblies
.assembly extern mscorlib {}

// ...

ldstr "Writelining"
call void [mscorlib]System.Console::WriteLine(string)
Invoking an instance method
.locals init (class MathHelpers mh)

newobj instance void MathHelpers::.ctor()
stloc mh

call instance void MathHelpers::Show()
Invoking a static method
call void MyNamespace.MyClass::StaticMethod()
Using an array
.locals init (string[] names);

.ldc.i4.4 // the int32 constant that's used for the size of the array: new string[4]
newarr string
stloc names

// Add element 0
ldloc names
ldc.i4.0 // array index
ldstr "Dreas"
stelem.ref

// Add element 1
ldloc names
ldc.i4.1 // array index
ldstr "John"
stelem.ref

Adding a line break for IntelliSense in XML documentation comments

This is a quick post on how to insert a line break for XML documentation comments in C#.

The easiest way I've found is to use a non breaking space (ASCII code 255) in combination with the paragraph tags: <para>

To insert the non breaking space, press ALT + 255 (from the numeric keypad).

Here's an example:

/// <summary>
/// <para>This method does everything.</para>
/// <para> </para>
/// <para>...and I mean everything.</para>
/// </summary>
private void DoEverything() {

And this is how it looks in IntelliSense: