Christer’s blog o’ fun

September 29, 2007

Bioshock for the win!

Filed under: Games — christer @ 11:50 pm

Just completed Bioshock on the hardest level! I was supposed to be watching a movie tonight but could not find anyone I wanted to see so I fired up Bioshock on my Xbox 360 and managed to finish the game.

Bioshock is probably one of the best game I have ever played. The story is amazing and the gameplay is incredible. I don’t want to say anything about how the ending was or how the last fight was because it might spoil the game for others. I did not manage to get all tape recorders and some other stuff, so I might play it again sometime on the easiest level just to get 100% (achievement junkie).

If you haven’t picked up this game yet then it sucks to be you.

I also picked up Halo 3 earlier today so I might try that out tomorrow. :)

Voting using YUI sliders and AJAX

Filed under: Work related — christer @ 7:16 pm

Some weeks back at work we had a political debate featuring the leaders of the 8 biggest political parties in Norway. The event was streamed live on the net via VGTV (our internet “TV channel”).

We wanted to involve the viewers so we made it possible for them to vote for their favourite politicians while the debate lasted. We wanted to see if some of the things the politicians said would alter the viewers’ votes. To be able to do this without interrupting the video stream we had to do some AJAX trickery. I was in charge of the technical solution and since I haven’t been blogging too much about technical stuff lately I thought I could write a post about some of the stuff I used for the voting.

First I’ll include a screenshot of how the web page showing the video looked like.

Debate snapshot

The stream was shown where the nice black box is and the voting was done using the two thumbs to the right (over and below the images of the politicians). The thumbs are actually the “handle” on two horizontal sliders that were implemented using the Slider widget of the YAHOO! User Interface library (YUI). The sliders are made using some simple HTML markup and a little bit of JavaScript code. The images between the two sliders are just a simple list with some background images for the elements. The HTML markup that was used to make the voting box looks something like this:

<div id="booth">
  <div id="positive">
    <div id="positiveSlider">
      <div id="positiveSliderThumb"><img src="images/positiveThumb.gif" /></div>
    </div>
  </div>
  <ul id="parties">
    <li id="noParty"> </li>
    <li id="party1"> </li>
    <li id="party2"> </li>
    <li id="party3"> </li>
    <li id="party4"> </li>
    <li id="party5"> </li>
    <li id="party6"> </li>
    <li id="party7"> </li>
    <li id="party8"> </li>
  </ul>
  <div id="negative">
    <div id="negativeSlider">
      <div id="negativeSliderThumb"><img src="images/negativeThumb.gif" /></div>
    </div>
  </div>
</div>

As you can see the sliders are just a div container that contains another container that represents the “handle” of the slider. In this case the handles are images of thumbs. These elements are styled using CSS and the following code is used in a style sheet:

#booth {float: left; background: #f2f2f2 url(images/boothBg.gif) 0 0 no-repeat; width: 435px; height: 453px;}
#positive,
#negative {clear: left; position: relative;}
#positive {background: transparent url(graphs/positiveGraph.png) bottom right no-repeat; height: 180px;}
#negative {background: transparent url(graphs/negativeGraph.png) top right no-repeat; height: 125px;}
#positiveSlider,
#negativeSlider {position: absolute; width: 430px; height: 45px; left: 5px;}
#positiveSlider {bottom: 0px;}
#negativeSlider {top: 0px;}
#positiveSlider:hover,
#negativeSlider:hover {cursor: pointer;}
#positiveSliderThumb,
#negativeSliderThumb {position: absolute;}

#parties {list-style-type: none; padding: 0; margin: 0;}
#parties li {float: left; padding: 0; margin: 0;}

#noParty {width: 51px; height: 57px; background: transparent url(images/noParty.jpg) 0 0 no-repeat;}
#party1 {width: 49px; height: 57px; background: transparent url(images/party1.jpg) 0 0 no-repeat;}
#party2 {width: 47px; height: 57px; background: transparent url(images/party2.jpg) 0 0 no-repeat;}
#party3 {width: 51px; height: 57px; background: transparent url(images/party3.jpg) 0 0 no-repeat;}
#party4 {width: 43px; height: 57px; background: transparent url(images/party4.jpg) 0 0 no-repeat;}
#party5 {width: 52px; height: 57px; background: transparent url(images/party5.jpg) 0 0 no-repeat;}
#party6 {width: 47px; height: 57px; background: transparent url(images/party6.jpg) 0 0 no-repeat;}
#party7 {width: 47px; height: 57px; background: transparent url(images/party7.jpg) 0 0 no-repeat;}
#party8 {width: 48px; height: 57px; background: transparent url(images/party8.jpg) 0 0 no-repeat;}

The reason that I used empty list elements with background images instead of just placing image tags in the list elements was because of a margin below the list that appeared when I used image tags. I could not seem to remove it using CSS, so I used background images instead.

The rest of the CSS code should be pretty self explanatory. The slider containers should have a relative position, and the slider thumbs should be absolute. This is specified in the YUI docs for the slider widget.

The JS code that was used to create the sliders are pretty simple as well:

/* Create the slider object for the positive vote */
var positiveSlider = YAHOO.widget.Slider.getHorizSlider("positiveSlider", "positiveSliderThumb", 0, 390, 48);

/* Run the validatePositiveVote function when the slideEnd event is fired, which happens when a slide is finished */
positiveSlider.subscribe("slideEnd", validatePositiveVote);

To create the slider object you need to specify the slider container as the first argument and the slider thumb container as the second argument. The three last arguments are the left and right boundaries and the width of each “tick” in the slider respectively. If the last argument is skipped the slider will move in a more smooth manner, but in this case I wanted to “attach” the slider thumbs to the images of the politicians.

The sliders also let you run different code when certain events occur. The different events are: “slideStart”, “slideEnd” and “change”.

Since we don’t want the users to place both their votes on the same politician we run some validation functions. The validatePositiveVote function looks something like:

function validatePositiveVote() {
  var currentPositiveVote = positiveSlider.getValue();
  var currentNegativeVote = negativeSlider.getValue();

  if (currentPositiveVote == currentNegativeVote) {
    negativeSlider.setValue(0);
  }
}

As we can see we simply fetch both the sliders’ values and if they are the same we will move the slider that was already placed on the politician back to start. positiveSlider and negativeSlider are in this case global variables.

To be able to register the votes I made a function that would see if the user had changed his votes and if so, post the votes to a PHP script that would register the votes in a database. To make a function run periodically I used the windows.setInterval() JS function. The function takes two parameters. The first parameter is the function we want to run and the second is the interval in microseconds.

/* Update the votes every 10 seconds */
window.setInterval(updateVotes, 10000);

The updateVotes function uses the Connection Manager utility of YUI to send a POST request to the PHP script. The function looks something like this:

function updateVotes() {
  var positiveVote = positiveSlider.getValue();
  var callback = {
    success: function(o) {},
    failure: function(o) {},
    argument: null
  };

  if (positiveVote != lastPositiveVote) {
    lastPositiveVote = positiveVote;

    YAHOO.util.Connect.asyncRequest('POST', 'registerVote.php', callback, "vote=" + positiveVote + "&positive=1&clientKey=" + clientKey);
  }
}

First we just fetch the x coordinate of the positive slider and post it to the registerVote.php script if the vote is different from the last vote. The clientKey that is sent in the POST is just a unique key that each client (browser) gets when first visiting the site.

If you look at the screenshot above you can also see some graphs. These graphs are generated in a php script that runs as a cronjob every minute using the data from the database gathered by the registerVote.php script. The graphs are refreshed using javascript so the user does not have to refresh the page. I used the setInterval function for this as well. The function that refreshes the graphs looks something like:

function updateStats () {
  /* Send the date as a GET argument to make sure we get a new image every time */
  var date = escape(Date());

  YAHOO.util.Dom.setStyle('positive', 'background-image', 'url(graphs/positiveGraph.png?' + date + ')');
  YAHOO.util.Dom.setStyle('negative', 'background-image', 'url(graphs/negativeGraph.png?' + date + ')');
}

The date argument is sent along with the url so we won’t get a cached version of the image resulting in a never changing graph. The background image is positioned using CSS but we won’t need to change that since the graph shall be placed on the same position every time.

And that was about it I guess. If something is not clear, don’t hesitate to ask. And if you think something should have been done differently, please let me know. :)

September 27, 2007

Back from Thassos

Filed under: Trips — christer @ 10:30 am

Yesterday Tone and I came back from one week on Thassos. It was good to be back home but I guess it would be nice to have had a couple more days in the sun.

We had a very nice time eating lots of good food and drinking lots of good wine. The first couple of days the weather was not so fine though but the rest of the time the weather was hot and sunny.

I managed to outdo her in the art of sunbathing which I’m quite proud of. Since I had brought a couple of books I could stay on the beach reading all day long while Tone was getting more and more impatient. We both thought it would be the other way around.

Two days after we arrived we rented a scooter and drove around the island looking at some of the other places one could visit. There are some small beaches around the island but it was a bit too cold the day we had the scooter to check them all out.

It was a nice trip but we’re probably not going back there. There are too many other places to visit. :)

September 17, 2007

Project Euler

Filed under: Technology — christer @ 9:25 am

I have kinda forgotten about Project Euler the last couple of months so I logged in earlier today and solved 3 problems (12, 15 and 19). Now I’m apparently 21% genius!

I’ll probably forget about it for some months again and come back with an update later on.

September 6, 2007

Thassos, here we come

Filed under: Trips — christer @ 7:56 pm

A couple of days ago I ordered a couple of tickets to Thassos (Greece) for my girlfriend and me. We are leaving on Wednesday the 19th and are staying for a week. :)

She is leaving for her last year of med. school in Poland in October so we thought we should have a vacation together before she left.  Hopefully we will have lots of sun and nice weather.

September 3, 2007

Back in business

Filed under: Games — christer @ 2:34 pm

So last week I made a phone call to Xbox 360 support to see how far my 360 had come. The support guy told me that the last update he could see in his system was that they had received my 360. He told me that I would have to wait some more weeks for it to return.

2 minutes after I hung up this guy from DHL calls me and wants to know if I’m home, because he had a package for me… Guess what was in that package. :)  Xbox 360 support should probably get their systems up to date.

Blog at WordPress.com.