February 25, 2013

Konami Code Problem

I don't remember exactly why, but today my friends and I were talking about the old web, where all sites were made using a notepad or at most microsoft's frontpage, and google wasn't the most used search engine yet.

Back then we used an older version of HTML, with some cool features to play with. One of them was the <marquee> tag, that made all of it's content roll over the page. We tested it in Chrome, and surprise, it still works! Take a look:

They see me rolling...

So the first question that went through our computer scientist's minds was: "What if we made all website's content with a marquee tag?"

Then we figured out an easy way to do it using javascript:
var marqueefy = function () {
     var me = $(this).clone();
     var marquee = $('').html(me);
     $(this).replaceWith(marquee);
};

var marqueeAll = function () {
     var tagsToMarquee = ['li', 'a', 'span', 'h1', 'img', 'iframe', 'p', 'hr'];
     for (tag in tagsToMarquee) {
          $('body').find(tagsToMarquee[tag]).each(marqueefy);
};
And we just need to bind it to the document ready event:
$(document).ready(function () {
     marqueeAll();
});
It works! But suddenly one of us said: "Wait! What if it did more? Call this function only when the Konami Code is typed?". And so we did.
If you are not familiar with the Konami Code, you can see it's wikipedia's page. It's a well known code created by Konami that trigged a lot of secret stuff in their games. So we thought about doing it as a jQuery plugin, to be as easy as that to use:
$(document).KonamiCode(aFunction);
We used a stack data structure to build it, where every char typed is pushed to it, and when the enter key is typed, it runs a verification code to see if the sequence typed backwards is equal to the Konami Code. The javascript code is:
(function ($) {
     $.fn.KonamiCode = function (konamiFunction) {
          var codeSequence = new Array();
          var easterEggSequence = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65, 13];
                
          return this.each(function () {
               $(this).keyup(function (e) {
               var typedSequence = new Array();

               codeSequence.push(e.keyCode);

               if (e.keyCode == 13) {
                    var i = 0;
                    while (i++ < easterEggSequence.length) {
                         typedSequence.push(codeSequence.pop());
                    }

                    if (typedSequence.reverse().toString() == easterEggSequence.toString())
                         konamiFunction();
                    else
                         codeSequence = new Array();
               }
          });
     });
};
})(jQuery);
And now it is perfectly possible to do:
$(document).KonamiCode(marqueeAll);
Cool, isn't it? That was a really fun codeventure to be in. Why don't you test it in our page? :) See ya!

May 16, 2012

The Game of Thrones problem

And there I was, excited to see the new GOT's (Game of Thrones) episode, preparing the pop corn and all the stuff. As my native language is Portuguese, I managed to download a subtitles file.

But the file came wrong, all the subtitles were late! The actor said "You can't revenge him!", and only after some seconds the subtitle appeared.
I thought: "I could search for another subtitle file on the web, but why if I can just solve it with a small program?"

So there was my challenge: Make the subtitles fit, because I really wanted to watch that episode.

As the blog's spirit is to dive ourselves in programming adventures, I decided to use a language that I'm not that familiar with: Python.

The first thing I did was understand my problem. I needed to process a .srt file, and then modify it to fit my needs (in other words, make the subtitles a little earlier, or, more easily, N seconds earlier).

The "anatomy" of a .srt file is:

id
HH:MM:ss,mmmm --> HH:MM:ss,mmmm
Subtitle goes here. In our case, an exemple could be:
Você nunca se vingará!


where id = Integer value to identify the subtitle; HH = Hours; MM = Minutes; ss = Seconds and mmmm = Milliseconds.

Basically, it shows, for each subtitle, its identification, starting time, ending time and content.

What I needed to do? Create an algorithm that catches all the time lines and modify them to be N seconds earlier.

There's two things to discover: How to make I/O operations using Python and how to handle datetime objects. That wasn't so difficult, I found all the answers at Python's doc page: http://docs.python.org/tutorial/inputoutput.html.

The pseudo-code:
       
void Shift_Subtitles (file, seconds):
     timedelta shift <-- timedelta(seconds)
     content <-- file.read()
     Foreach line in content:
           If line is timeline:
                 get start_time and end_time
                 transform to datetime object
                 new_start <-- start_time - shit
                 new_end <-- end_time - shift
                 replace line with new_start and new_end


     file.write(content)

And that's it! A solution for the subtitle problem using a simple algorithm. If you want to see the Python implementation, here it is:

 import sys  
 import datetime  
 from datetime import timedelta  
 def shiftSubtitles(str_file, sec):  
   file = open(str_file, 'r')  
   lines = file.readlines()  
   file.close()  
   file = open(str_file, 'r')  
   content = file.read()  
   file.close()  
   shift = timedelta(seconds = int(sec))  
   for line in lines:  
     if '-->' in line:  
       # Here we get HH:MM:SS:ss  
       _start = (line.split('-->')[0].rstrip().lstrip()).replace(',', ':').split(':')  
       _end = (line.split('-->')[1].rstrip().lstrip()).replace(',', ':').split(':')  
       start = datetime(1999, 01, 01, int(_start[0]), int(_start[1]), int(_start[2]), 0)  
       end = datetime(1999, 01, 01, int(_end[0]), int(_end[1]), int(_end[2]), 0)  
       new_start = (start - shift).isoformat(' ').split(' ')[1].replace('.', ',')  
       new_end = (end - shift).isoformat(' ').split(' ')[1].replace('.', ',')  
       new_line = new_start + ',000 --> ' + new_end + ',000\n'  
       content = content.replace(line, new_line)  
   file = open(str_file, 'w')  
   file.write(content)  
   file.close()  
 def main(args):  
   shiftSubtitles(args[0], args[1])  
 if __name__ == '__main__':  
   main(sys.argv[1:])  

The way to use it is very simple too:

$ > python shift_sub.py [filename].srt [seconds]

Well, I'm not a Python programmer, so I don't know if this is the best way to do it. If you know how to make this code better, please comment for us!

January 22, 2012

Starting

Several times you see yourself in a situation where you think "There could be a program to assist me on that". So why we don't just try it, in different ways? Develop solutions for our problems in different languages, just to learn, practice and use it!

This blog's goal is to show how the programming world can become an adventure, and a good one!

Subscribe because every thursday there'll be a new post :)

Bye!