February 2008 - Posts
Today it's been just launched our first public WLA! Although really is the second one the first is in it's final touches with the customer, but we expect to have it ready quite soon too.
The agent's name is iZ@psoe.es and it has been made near one month and a half for the current spanish government by PedroA and me, targeted to the general elections that are taking place right now and will finish the 9th of march.
It has lots of functionalities related to the elections, like consulting the census, near 1300 government proposals, where do you have to vote, multimedia videos and MP3, a pack of custom emoticons, customized funny responses...
The Activity window is used a lot, for example to play the videos and flash animations:
It has a Windows Live Maps mashup to show for example where do you have to vote after asking you some basic address parameters:
We've developed a big search engine to filter, query and ask for political proposals, being able to show key ones, refine your searches with more keywords, show related videos for some proposals... along with a tag cloud that contains the general keywords (there are 156 general keywords and hundreds of synonims to ease the searchs).

The agent has lists of political parties, candidate lists, related blogs, websites, information, volunteer pages...
We didn't wanted to force the user into searching by default, so the agent shows some information in a menu when saluted, and lets the user do something, or just chit-chat with the agent for a while (after some chatting it will remind the user it's main function, speaking about the political proposals).
Once you start either using the search engine or the other options, you are "driven" through the steps until either you cancel or finish. In the search, you start entering keywords and synonims to refine your search "query"; if key proposals are found, they are automatically loaded in the Activity Window while you keep searching; When you've finally found just one proposal, or you want to see your current search results, it is loaded too at the AW.
Initial feedback from some users says that some people do not read the help and they think they can search from the very beginning (it is triggered with patterns like "search" or "proposals"), so maybe we should have either forced an initial search, or made a smaller initial help command so that more users noticed how the search is activated.
It's been a quite intensive development because we had a great release date deadline limitation, and we had to deal with challenges like XML file cachings and quite complex data transformations and manipulations (we used SQL Server 2005 DTS and two custom .NET Applications to import data, transform and manipulate it and export it to our desired destinations).
Official info about the agent can be found here (in spanish).
It is the first WORKING Agent in Spain. Another one was made before, but was removed due to both technical and content problems.
It is a titanic work for two people and while it might not be perfect, we're really proud of the amount of work done in so few time... We've had also a lot of fun during the development, and customer feedback and agent testing has been very useful to improve the recognized patterns.
Enjoy it and if you want, leave a comment telling what you think of the agent :)
Update: Added more info explaining how the search works and how it is triggered.

In a previous post we talked about basic use of the Anything pattern.
One "poltergeist" issue we may face is having an Anything pattern not catching long, multiple word user inputs. In our specific case it was only taking up to 4 word street names.
Everything seems to be working perfectly, but "mysteriously" 5+ word street names are not taken, what is the problem or how do we solve it?
Well, it took me a few to understand why wasn't working, and I found the answer looking at the BasicMatching.pkg library (where the Anything patterns are stored):
subpattern Anything {minlength="1" maxlength="100" score="MACRO_WEAK_SCORE" style="raw"}
subpattern AnythingWeaker {minlength="1" maxlength="100" score="MACRO_WEAKER_SCORE" style="raw"}
[...]
As I've marked in bold in the code fragment, the default Anything gets matched with something with a weak score (45 "points"), but there is a AnythingWeaker version which can handle even worse scorings (35 "points").
This is logic, because long user inputs will probably not only be unmatched, but get lower scores than short ones (the different between existing patterns and failed one gets bigger as the input increases length).
I've been able to capture 12 word user inputs using AnythingWeaker, so it should be enough... but for a real "catch-all", there is an unused score macro called FAILED_SCORE which captures inputs with 0 score :O
In few hours I'll be going to the <MIND camp /> event organized by the people of the Madrid dotNETClubs (one of the two events I talked about last month).
The agenda for both events has been finished:
Notice that the DNCMadDay event has been posponed one week, to the 14th of march (PI day! Thanks for the tip Blanca ;)
So, expect a review of the event the next week!
Everyone has good and bad days. Today I've had one that started quite well but got worse and worse as the afternoon came. So, in order to reminder myself that I'm doing the right thing, I'm writing this post.
One of my defects is that I always tray to do things the best way I can. I'm never fully satisfied with the results of a project, there is always room for improving, optimizing or making the same in a better way.
At work this means that as soon as I finish a project I start thinking about how it could be better, faster or less resource-consuming. Sadly, sometimes I start thinking the same before ending the project (which usually means something is going the wrong way), but more on this later.
Since I started my website, initially just my spanish development portal and manual "library" www.lawebdeprogramacion.com, I've always tried to improve. From the initial, JS & HTML only website, to the ASP 3.0 + SQL Server 2k "2.0 version", and now a part of a blog community and resource portal, I've fight and spent countless hours not only learning programming languages, but redesigning, creating javascripts, fighting for better free hostings (which finally ended ;), promoting the website everywhere I could, gathering new materials...
I don't believe in perfection, but ironicaly I'm always trying to achieve it (I've still got a loooong way to go ;)
Now in Kartones.Net slowly it is being noticeable, because as I learn how Community Server works, I can make my own modules, customize blogs, disable or create new sections, create mashups (like the home twitter news)... and some surprises that I hope to show soon.
But going back to the "sadly" part, at work I've only once been able to see a project evolve, grow, get mature, improve... Almost all times is the same: I develop something and then I take another project and the last one "dissapears" from sight, many times forever.
And when it doesn't, usually is to come back as a nuisance, just knocking your door to say "hi, remember my small problem with this or that? I'm here for it". But you can't open the door and invite it inside, serve a tea and talk about the problem. You have to take your first-aid kit, cut here, patch there and kick it off your house.
The problem usually is "delivery times". Rush time comes, and we start to ponderate between "do it right and not be able to finish in time" or "do it as well as you can in the provided time frame, hoping to improve it in the future". And usually, resulting software gets degraded quality. Notice I'm not saying "bad software", just degraded, not as good as I would like to.
Sometimes it's the customer, sometimes the bosses, the tight schedule, the technology restrictions... but it's a pity that happens way too often.
I would love to create not one or two, but most (if not all) projects as "my proud sons", as masterpieces that worked flawlessly like a mechanical clock's gear system. I try to do it with "my own projects" (my portal and my experiments and internal mini-tools), but I almost always hit a wall when doing it professionally.
My current project is going very well thanks to PedroA's incredible effort and the fact that we make an almost perfect pair-programming team, delivering every requisite and change in time (when not ahead of schedule), surviving insane last-minute changes and new functionalities, but, as always, some things could have been done better. We've avoided a lot of possible constraints and have almost ready a product I'm very proud of, but mostly because of our overwork and sometimes even "law-breaking" techniques of ignoring everyone and trying to do something as we risked betting to be a more correct approach.
Until that utopic day in which we can work as we see fit/100% right, we'll have to stick to our personal projects to trully work "correctly and flawlessly".
Recently I added a new feature to Kartones.Net, a Twitter account and a auto-posting in twitter module.
The problem is that the component seems to have a a nasty bug, probably caused by the mixture of being used as a Community Server spam rule (so CS handles it's lifecycle and instantiation) plus using a singleton (which I think is not a good idea since affects CS modules and objects lifecycle management), and resulting in the twitter spam rule being unloaded from memory after near 30 minutes of having saved/updated it's spam rule configuration parameters.
This bug, among with the fact that I prefer having CS modules instead of "hacked spam rules" (also, spam rules should be called on new comments, not blog posts per se, while CS modules are "for every event") made me take the original code, change some little things and convert it to a CS module, which has been added to my KartonesNet CS2007 Addon Pack.
We've had it "under testing" in the portal for a whole week and all seems to work fine. No more undesired unloading problems ;)

As you will have noticed, having a lot of work making WLAs means lot's of incoming posts about the topic. I've planned at least another two or three more, but I'll try to talk about other topics too. Anyway, let's get to the topic.
Sometimes, we might need to create a Catch-all pattern like the default "+ CATCH=Anything" , for example to get every user input under a filter under specific conditions.
For example, we could be doing a search and want everything that the user types to be checked for available responses (instead of using multiple patterns, centralized in one).
+ PASS=Anything {score=200}
VALID = false
if (PASS == "abracadabra")
VALID = true
if (VALID)
- Congratulations, you guessed the magic word :)
else
- Invalid!
This code will only work if the user types correctly "abracadabra" in lowercase. Else it will fail. We have functions to do lowercasing and even thawed versions of a variable, but the less code the better, so go and take a look at \BuddyScriptLib\Required\BasicMatching.pkg library...
Change the first line to the following:
+ KEYWORD=AnythingThawed {score=200}
Voila! Now "AbraCaDaBrA" will work too, and if we add more ifs/checks, we only have to make sure they are typed in thawed version (lowercase and no special characters), no need to worry for formatting PASS.
Mini-post as reminder. The four special HTML tags to allow chatting with a contact or Agent from an hiperlink, add it to your contact list and other stuff:
<a href="msnim:chat?contact=sample@email.com">Chat</a>
<a href="msnim:add?contact=sample@email.com">Add to contact list</a>
<a href="msnim:voice?contact=sample@email.com">Voice chat</a>
<a href="msnim:video?contact=sample@email.com">video conversation</a>
Buddyscript has objects, but internally they are n-dimensional arrays of strings. They can have properties, like real objects, but have some limitations.
One I've come across recently was that the Buddyscript "for each" can't iterate a non-list object (a scalar), and because of code restrictions, we had to be able to handle both looping scalars and lists. Of course this can be done with a simple "if" that uses the Count() function and behaves differently if we have one or N elements.
But the Count function is a bit fragile. If the variable passed is not a list it will throw an exception. So I've made a small "safe count" function to allow counting scalars (as 1), lists and empty scalars (as 0):
function SCount(LIST)
if (!Exist(LIST))
return 0
if (LIST == "")
return 0
if (IsObject(LIST))
return Count(LIST)
else
return 1
This is a small test-pattern I made to test it:
+ _test_scount
VAR1 = ""
VAR2 = ""
VAR2.EL = ""
VAR3 = ""
VAR3.EL = 1
VAR4 = ""
VAR4[0] = 1
VAR5 = ""
VAR5.EL = ""
VAR5.EL[0] = 1
VAR6 = ""
VAR6.EL = ""
VAR6.EL[0] = 1
VAR6.EL[1] = 2
VAR6.EL[2] = 3
RES = SCount(VAR1)
- var1: RES
nop
RES = SCount(VAR2.EL)
- var2.el: RES
nop
RES = SCount(VAR3.EL)
- var3.el: RES
nop
RES = SCount(VAR4)
- var4[0]: RES
nop
RES = SCount(VAR5.EL)
- var5.el: RES
nop
RES = SCount(VAR6.EL)
- var6.el: RES
And this are the output results:
var1: 0
var2.el: 0
var3.el: 1
var4[0]: 1
var5.el: 1
var6.el: 3
Since last year's speech with Vicente (which was in may!), I've been very off from XNA. I have installed XNA GS 2.0 but still haven't played with it :/
But it is never too late, so I'm digging deep into both the new features (networking mostly) and on every interesting post I find related to XNA.
One series of posts I'm following now is about building an XNA Game Engine from scratch, step by step. I find this very useful (in blogs, not in books) as anybody can learn whatever level they have, and if you already know something you can always skip to the next chapter/post.
Right now this are the written posts and their content:
Also, I found a great post about converting XNA 1.0 projects to XNA 2.0.
Update (19-Feb-2008): Added five new tutorials.
I've added this CS TwitterModule to the community, and created an official Twitter account (http://twitter.com/KartonesNet) to auto-post the title and (tiny-URLed) link to new contents.
Here is the result of an initial test (I've decided to remove the "post:" start and just leave title + link):
So, now we've got the following systems to get notified of content updates:
Not bad... stay tuned for more news soon, having insomnia is quite productive!