Showing posts with label ruby. Show all posts
Showing posts with label ruby. Show all posts

Sunday, June 8, 2014

Old friends: Iterative Development & Comunidad Prode

The FIFA World Cup has brought a lot of attention to the internet: social, games, portals and so on... (pause) duh, we are in 2014, aren't we?
Alright, Comunidad Prode was not an exception. During the last couple of weeks, I saw a lot (I mean a lot) of new people signing up, creating user groups to have their own private tournaments.

In numbers, we had 2000 users in the system, but only 600 were active (by active I mean actually playing predictions for the last AFA season). During the last weeks, number of signups raised to 5000 users, and around 2800 active.
Also, while we used to have between 300 and 400 visits per day, we are now going over 1000:

Images from Quicklytics, awesome app from my bud Eduardo Scoz 

Something that also caught my attention while looking at these analytic info was the referral pages. People was coming the to site, as expected, from Facebook, Google searchs, etc, but surprisingly, a lot was coming from an online newspaper. The reason was because of this article that I share with you.

At the same time, Fernando Carolei, a journalist who covers technology and new tendencies in public television channels in Argentina, was promoting the site as well in some of his "live" sections. After that, we had exchanged a few twitter direct messages, and he was telling me that he was using Comunidad Prode for a while, and found it actually pretty good :).

Anyway, as most of my blog posts, tech/programming stuff are present, and here is what I have today before wrapping up.
As iterative software development promotes, you might have heard to not overdesing; for a given problem and context, solve it in the "smartly-cheapest" way. In eXtremme Programming, this means DTSTTCPW: do the simplest thing that could possibly work.

That said, in the first version of Comunidad Prode, the way to handle user rankings was to calculate, on the fly, the points for a given user coming into the site. When the number of people started to grow, I started to see some heavy processing time. Long story short, rather than calculate points "dynamicaly", I moved it as part of the publishing results process (this is when the results of real games are set).

In a few words, the way to do this was getting all the users playing on a given tournament, do the calculation, and then save it for future requests.
Considering that active users is now going from 600 to now 3000, I am anticipating a bottleneck here; processing time will definitely go up, so, it is time to *refactor*. What's the simplest solution here? Maybe multithreading processing. Let's try that, and see... I leave you with these lines of code!


  page_size = ENV['PUBLISH_PAGE_SIZE'] || 500
  users = week.tournament.users
  pages = (users.count / page_size) + 1  
  
  threads = (1..pages).map do |i|
    Thread.new(i) do |i|
      update_ranking_for week, users.shift(page_size)
    end
  end
  threads.each {|t| t.join}  


Before, the method update_ranking_for was just taking the week as a param, and the users to update was getting figured out in the inside. Now, a group of users is passed into, and processing will happen in parallel. Technically speaking, if 600 users were taking a minute long to get processed, if we do it now in three groups of 200, time will go down to 20 seconds (1/3 of a minute).

Enjoy!

Saturday, May 3, 2014

Comunidad Prode keep on growing

Exactly 2 years ago, first commit to the git repo was made


Today, I am releasing code base 3.0, which in terms of end users, means support for not only "league-style" tournaments, but also "cup-style". The reason is quite straightforward: the ability to play predictions for the FIFA World Cup 2014, given the large group of users who asked for this feature.

Since this is a programming blog, lets go to the point. From the domain perspective, even though this is arguably, there were differences on how to represent a match as it was, versus a world cup match (knockout match from now on). Even though the match has a date and time to be played, we never wanted to tie that to the match just because AFA schedule is a real mess, with kickoff times changing from one day to another. That said, the decision was for the week to have a date (one week has many matches), and past that date, the related match results can no longer be predicted.

The situation for the knockout matches was different, we did want to predict on a match by match basis, and we needed to group them by an identifier (group A, group B, semi-final, etc).   

Now, when a user predicts a match, that gets persisted as a user_match. The relation between both is that each user match belongs to match, but now, it can also belong to a knockout match. How to achieve this, at least decently? I had the opportunity to use active record polymorphic associations a year ago or so, and I saw a perfect fit here for that as well. Here is the outcome.

 class Match < ActiveRecord::Base  
   has_many :user_matches, as: :related_match  
   ...  
 end  

 class KnockoutMatch < ActiveRecord::Base
   has_many :user_matches, as: :related_match
   ...
 end

 class UserMatch < ActiveRecord::Base
   belongs_to :related_match, polymorphic: true # match or knockout_match
   ...
 end

so now, by calling user_match.related_match you will get the associated "real" match, no matter if it is a match or a knockout match, for instance, to get the real score and calculate the user prediction points.

The rest of the changes are just around that, and those who don't, are the usual gem version upgrades to stay up to date, for instance, bump rails from 4.0.4 to 4.1.0, as well as ruby from 2.0.0 to 2.1.1.

Saturday, July 27, 2013

Kicking off second year of Comunidad Prode

We are just a few days away of a new season of the Argentina professional soccer league, which in terms of Comunidad Prode, means the site second year of life!

During the off-season (and a little before too), I have tried to focus on upgrading the site, in order to bring end users always a better experience. That means, keep up with the latest and greatest versions of frameworks, gems, etc, as well as improving performance by running different set of profiling tools. Major list of upgrades are as follows...






As of now, we have around 1100 people playing on the site, and we look forward to, not only have more players, but to enrich experience of current ones!!

Sunday, July 21, 2013

Screencasting the RomanNumerals kata

In every aspect of life, it is known that practice something will make you better at it. Sportsman practice long hours before a given competition, musicians practice as well before performing on stage, but us, software people (developers, architects, etc), not always do the same thing.

Quoting Robert Martin (aka Uncle Bob) in his book The Clean Coder, "you should plan on working 60 hours per week. The first 40 are for your employer. The remaining 20 are for you [...] you should be reading, practicing, learning, and otherwise enhancing your career. [...]  During that 20 hours you should be doing those things that reinforce that passion [towards software]. Those 20 hours should be fun!"

That said, I have decided to record and share this following kata, hoping that someone picks it up and get contagious, in a good way :).
Audio is in Spanish thou, bummer, I know.

Closing... If you haven't read The Clean Coder, and now you feel like doing it, I humbly suggest reading Clean Code first.


Wednesday, March 6, 2013

20th anniversary of Ruby, version 2.0 is out!

Ten days ago or so, the first stable release of ruby 2.0 was shipped, so I decided to give it a try. Since I had to do a few things to get it working, I list them all below as a cheat sheet for myself, or others as well...

First of all, I should mention that I run OSX 10.8 Mountain Lion.That said, let's see.

Get the latest version of RVM and check if I am missing any required package:

 $ rvm get stable  
 $ rvm requirements  

In my case, openssl is what I needed to install, but other scenarios might be different.

 $ rvm pkg install openssl  

Then, when I tried to install a gem, i got an error like the following:

 ERROR: Loading command: install (LoadError) 
 cannot load such file -- openssl

That might be because there is an incorrect reference to the openssl config file, so, let's see where it did install, and then provide the correct path

 $ find . -type f -name "openssl.cnf"  
 $ rvm install 2.0.0 --with-openssl-dir=[path_found_above] --verify-downloads 1

After that, everything went fine.
In order to check all ruby installations your system has, you can run:

 $ rvm list  

Version 2.0.0-p0 should be there, and if you want to make your default, do:

 $ rvm --default use 2.0.0  

Even though you make any given ruby version the system's default, I humbly suggest creating gemsets per directory, with its own version of ruby and gems. For further reading about gemsets, check this out.



Wednesday, August 1, 2012

Launching ComunidadProde

Hi!

Time is up, break is over, and the new season of the different Argentina soccer leagues are kicking off!
If you are from Argentina, I am sure you have heard about the Prode game before. If not, let's say it is a prediction game, where you guess if a soccer match will end up with a home victory, guest victory, or even tied.

Comunidad Prode is a site we are launching these days with Matías Rodriguez, so you can play it online, with some slight differences from the original Prode game, in order to make it more exciting. Our major goal is to give room to true fans whose teams are not playing in first division, so we are including all 5 AFA leagues (Nacional B, Primera A, B, C, and D).

The other intention we look forward is for people to socialize, so, we are not only including Facebook and Twitter support (so you can post how good you are :)), but also the ability to create your own custom groups and play your own little tournament with co-workers, friends, etc.

The site was built with Ruby on Rails, not only the front end, but also a RESTful api, that us, as admins, can leverage in order to publish matches results. We are now working on extending this api, so to provide mobile support for end users as well... coming soon!

Habemus Prode!