Contract Work

Monday, December 30, 2013

Learning: More Tools To Keep You Moving Forward

So, you’ve been working really hard. You are able to check everything below off the list…


  • Involved in the community
  • Setting goals
  • Doing something every day
  • Try ruby
  • Ruby in 100 minutes
  • Read Why’s poignant guide to Ruby
  • Learn Ruby the Hard Way
  • Ruby monk
  • Ruby Rogues (listened to at least a few)
  • Learn to program by Chris Pines


First off, if you were able to cross all those things off the list then seriously, great job!! You’re doing a lot, you’re working your booty off, and hopefully you’re feeling good about it. At this point, you should take a few minutes to take a look back at what you’ve accomplished. Think of everything you’ve learned and everything you didn’t know a few weeks ago. Smile about it, do a mini celebration, and get excited for the rest of your journey.

Here’s the next step… read Practical Object Oriented Programming in Ruby (POODR) by Sandi Metz. It’s amazing and you’ll want to reread it and keep it to refer to in the future. And start watching talks for past conferences. Confreaks is a great site that has talks from all sort of past Ruby conferences. It’s a great way to learn about new things that you might want to look into in the future (or now!). That’s all for now. Read that book carefully to really absorb everything, watch the talks to get inspired, and the next post on learning will be moving on to incorporating Rails!!!

Friday, December 27, 2013

Interesting Reads from the Week

I'm trying something new. I'm going to try to post interesting articles I've read (or meant to read) during the week every Friday. These articles/talks/blog posts/etc. may not have been published this past week, but it means I read or watched them this week. I'll try to also post who I heard about them from, but I didn't note that this week, so it'll be just the things I read for now.

Enjoy!

The Taxonomy of Terrible Programmers

Pairing vs. Code Review

Sublime Text Tips and Shortcuts

The Unreasonable Effectiveness of TDD

How Developers Stop Learning: Rise of the Expert Beginner

Thursday, December 26, 2013

More Bot Bits

The final component of bot functionality was setting up the database. This was really the thing that I wanted to gain some experience with and by setting up a database not in a rails application, I was able to understand some of the components a bit better. For my purposes, this database would be used to keep track of points. Often times, people will award other people points based on funny or interesting things they post. They’ll also subtract points for things but in the past, we’ve had no way to keep track of this. This bot added the following functionality: adding and subtracting points, telling a user what their score is when they ask, and printing out the leaderboard when asked.

First, Chris and I chose a database. We decided to go with Sequel because it looked pretty interesting and simple to set up. I set up the connection first that created the database but then moved that into a separate file. This way I have the option to run the create table script only when I want to create a new database table. Then I set the database connection as a global constant like this DB = Sequel.connect('sqlite://bot.rb') to get things going and set out to write the related methods.

The first method looks to see if a nickname is already in the database or if we need to add it and acts on that.

def nick_id(nick) 
  set = score.where(:nick => nick) 
  if set.empty?
    nil 
  else
    set.first[:id] 
  end
end

So, we set the variable set which find the list of every score that has the nickname nick (nick being whatever the person’s nickname is). Then, if it doesn’t find anything, then it will return nil. Otherwise, the methods grabs the id of the first matching nick it finds with that name and returns it.

The second method inserts or updates the score.

def insert_or_update_score(nick, points)
  nick.downcase!
  if nick_id(nick)
    row = score.where(:id => nick_id(nick)).first
    updated_points = row[:points] + points      
    score.where(:id => nick_id(nick)).update(:points => updated_points)
  else
    score.insert(:nick => nick, :points => points) 
  end
end

So, first I need to make sure all the nicks are being evaluated in the same way. I discovered this when testing and found that two different nicks would be saved in the database based on if they were capitalized or not. Then, this method needs to fetch a record, then increment the number and then save it back. If there is no nick, then it creates the new nick in the database and gives it points.

Finally, I wanted to be able to lookup the score and if someone has no points then the method throws an exception.

def lookup_score(nick)
  score.filter(:nick => nick).first[:points] 
rescue 
  nil
end

I added a rescue so if there are any exceptions, the rescue catches the exception and returns nil. Chris warned me that when looking at future projects, the rescue option can be dangerous because it can hide serious errors but for our purposes, using rescue is perfectly acceptable.

THEN WE REFACTORED!
Setting the database connection as a global constant is not a good idea and having all of these methods in the main file just make it messy and unorganized. First, I changed the database connection to an instance variable by putting it into a singleton class and initializing it.

require 'singleton'

class DB
  include Singleton
  
  def initialize(file = 'sqlite://bot.db')
    @db = Sequel.connect(file)  #setup the DB connection
  end

This meant that I also had to change all of the DB[:score] instances in the code because it was now @db. Then, instead of just putting @db in each place, I extracted it into a method that does it for us.

def score
  @db[:score]
end

And that is how I set up the bot’s database.

Thursday, December 19, 2013

IRC 101

IRC, internet relay chat, is one of the ways developers communicate… and something that can seem a little confusing when you first start, so here’s some IRC 101 so the next time everyone's talking about it, you'll know what's going on.

First, what is IRC? It’s basically internet chat rooms. A lot of people probably want to yell at me for that simplified explanation, but that's pretty much what it is. There are lots of different rooms based on lots of different topics. You pick a nickname when you join and then you can join different rooms and chat with people. You can also run your IRC configuration on a server which enables you to stay connected when you close your computer and read back when you are back at your computer with some time.

I personally don’t hang out in too many rooms. I’ve found that it’s also helpful to ask someone “in the know” about these channels. Some channels are super friendly. Others are really good about answering questions on specific topics or functionality (like the Pry channel). More are based around open-source projects (like the Spree channel). Finally, some channels are really unfriendly and people are kinda mean. I avoid those channels for obvious reasons.

Next, there are a few different ways to access the IRC servers. Some are more complicated and some are less. I, personally, use irssi, which accesses IRC via the terminal but can be a little complex to set up. I enjoy using irssi, however when people post gifs, they don’t show up inline, which means you have to click on them to see them, which can be a little annoying sometimes. Other options include Textual, Limechat, and Colloquy. There are various free trials and free versions, but a few are paid for. Here are some set up options from Chris and Sean . For irssi in particular, in addition to Sean's set up there are lots of additional scripts you can run to make lots of stuff happen including styling of the window, colors, replies, links, and much much more. Here's a pretty good guide to using irssi and here's an additional article abut IRC in general written by Spree Commerce. The Spree article gives even more options for accessing IRC.

Now for some basic functionality tips and tricks. When you want to join a channel, you just type /join followed by a space and the channel name. To direct a message to a specific person, just start the message with their nick name. You can even start by typing the beginning of the nickname and pressing tab to complete the name. To put yourself into a reply (like *allie_p goes to make coffee) just type /me in front of what you want to post in the chat. Finally, to send a message to someone just type /msg followed by a space and the nickname of the person you to message followed by the message you want to send. The message to that person will show up in a new window. With IRSSI, you can have multiple windows open (which means be in multiple rooms or conversations) and you can switch back and forth between them by pressing CTRL P or /win 3 (or whatever window you are trying to get to). To scroll up or down in a conversation, you use FN and then up or down arrows.

Final tips and tricks… check out http://textfac.es to learn about the weird faces you may see in the channels (I still don’t really understand half of them) and reacting gifs for great gifs to post in response to things.

If you’ve got more tips and tricks, feel free to add them in the comments!

Monday, December 16, 2013

Look what my Bot can do!

It’s amazing what a little chatbot can accomplish. It can make your day much brighter and more fun!! So, let’s talk about what Rosie can do, because it’s a lot.

So, first, Rosie can do some of the standard things like reply with gifs about coffee, District Taco, and lol’s. She also responds when you say good morning so that everyone every morning gets a fun response. She reacts to you when you say you love or hate coding, and she’s all about refactoring.

Those commands are accomplished via regular expressions. Regular expressions are a concise, flexible way to pick out specific words, phrases, characters, etc. Regular expressions look really terrifying when you first encounter then, but are actually really handy and not so scary once you get a handle on them. Based on Nell’s talk/suggestion at RubyConf, I made a permalink for each regex and put it as a comment in my code so I can always go back to it later. I used rubular when crafting the regex’s which made them a breeze. (Okay, not a breeze at first, but made it much easier to learn and figure out what each character did and how it altered what I was trying to do).

The next set up functions are random things that Rosie will say periodically.
on :message do |m|
  if rand(500) == 0
    m.reply "SQUIRREL!"
  end
end
This basically say that for each message sent, the script will see if that number matches 0 and if it does, then the bot will reply with “SQUIRREL!”. There’s another one of these built in there as well, but people will have to wait to see what that is.

Finally, there are some responses where rosie can choose to respond as a reply or as an action.
These options look like this:
on :message, /#{config.nick}\?/i do |m| 
  response = [
    [:reply, "Did someone ask for me?"],
    [:reply,    "http://31.media.tumblr.com/fe021d747a605a8a7cba5767011251e1/tumblr_mjpo4q44aj1rjatglo1_500.gif"],
    [:reply, "what do you want now?"],
    [:reply, "#{m.user.nick}, why are you bothering me?"],
    [:reply, "it wasn't me."],
    [:reply, "yyyyeessss?"],
    [:action, "hides"],
  ]
  msg = response.sample    
  if msg.first == :action   
    m.channel.action msg.last 
  else
    m.reply msg.last  
  end
end
So, each line…
The first line says that on the message whatever the configured nickname of the bot is (meaning that I can change Rosie’s name and the regex will still work) followed by the “?” then (next line) Rosie will reply with one of the options in the array. The next few lines show the options that Rosie can reply with and whether they are a reply or an action. A reply would look like this:
Rosie: It wasn’t me
While an action would look like this:
*Rosie hides
Then, msg = response.sample says picks a random value from the message array. (Next line) if the first element in that array is an action (:action), then (next line) add /me to it when it replies in the channel. Otherwise, reply like normal.

The next post will talk about functionality that incorporates some more complicated methods and a database!

Friday, December 13, 2013

Because it's been a little while... Here's another Euler!

Project Eulers 7 and 8

Just a few more Euler’s left and I realized the other day how long it had been since I’d posted some answers! I’m also posting both 7 and 8 because really, problem 7 uses the prime library again, so the answer is really short and sweet.

So, first, here is the problem:
By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.

What is the 10 001st prime number?


First, here are the tests:

require 'problem7/problem7'

describe 'Prime number positions' do 
  
  it "is the 6th prime number" do 
    expect(Problem7.prime_place(6)).to eq 13
  end

  it "is the 10001st prime number" do
    expect(Problem7.prime_place(10001)).to eq 104743
  end

end

The tests and the code are pretty simple. You’re just using the resources in the prime library and then use the library to list (take) the numbers up until a certain position (ie- the 10,001st position) and then put the last number which is the answer to the question. So, here’s the code:
require 'prime'

module Problem7

        def self.prime_place(position)
          prime_place = Prime.take(position).last
        end

  puts Prime.take(10001).last

end


And now for Euler 8. This problem was actually really tough for me for two reasons… first, it seemed different than most of the others I had done up until now and second, how the heck do you test this thing?!

Here’s the problem:
 Find the greatest product of five consecutive digits in the 1000-digit number.

 73167176531330624919225119674426574742355349194934
 96983520312774506326239578318016984801869478851843
 85861560789112949495459501737958331952853208805511
 12540698747158523863050715693290963295227443043557
 66896648950445244523161731856403098711121722383113
 62229893423380308135336276614282806444486645238749
 30358907296290491560440772390713810515859307960866
 70172427121883998797908792274921901699720888093776
 65727333001053367881220235421809751254540594752243
 52584907711670556013604839586446706324415722155397
 53697817977846174064955149290862569321978468622482
 83972241375657056057490261407972968652414535100474
 82166370484403199890008895243450658541227588666881
 16427171479924442928230863465674813919123162824586
 17866458359124566529476545682848912883142607690042
 24219022671055626321111109370544217506941658960408
 07198403850962455444362981230987879927244284909188
 84580156166097919133875499200524063689912560717606
 05886116467109405077541002256983155200055935729725 
 71636269561882670428252483600823257530420752963450

So, first for the test. After asking around a bit, the best suggestion I got for testing was to break down the string and take 10 or 15 characters and figure out the largest product from that string and then do the same with the larger number.

Here are the tests:
require 'problem8/problem8'

describe 'largest products of consecutive numbers' do 
  it "is the largest product of 5 consective numbers" do 
    expect(Problem8.product(7316717653)).to eq 1764
  end

  it "is the largest product of 5 consecutive numbers" do 
    expect(Problem8.product(7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450)).to eq 40824
  end
end

And so, here’s the solution. First, I created an empty array. Then I wanted to use .each_cons which takes every set of consecutive numbers based on the number of characters you ask for (in this case, it would be 5 because I’m looking for the largest product of 5 consecutive numbers) but .each_cons wouldn’t work because you can’t call .each_cons on a string. So, first, I had to separate the string into individual characters by using each_char. Once the string was separated into each_char (each character) I used the map method to make each of the string characters into an array of integers. Then, I used each_cons(5) which separated the array of integers into arrays of every five characters. The I took the product of each of those integers and pushed it into an array. Finally, the max is called on that array which gives the largest number needed for the answer.
module Problem8
  
  def self.product
    arr = []

    "731671765313306249192251196744265747423553491949349698352"\
    "0312774506326239578318016984801869478851843858615607891129"\
    "4949545950173795833195285320880551112540698747158523863050"\
    "7156932909632952274430435576689664895044524452316173185640"\
    "3098711121722383113622298934233803081353362766142828064444"\
    "8664523874930358907296290491560440772390713810515859307960"\
    "8667017242712188399879790879227492190169972088809377665727"\
    "3330010533678812202354218097512545405947522435258490771167"\
    "0556013604839586446706324415722155397536978179778461740649"\
    "5514929086256932197846862248283972241375657056057490261407"\
    "9729686524145351004748216637048440319989000889524345065854"\
    "1227588666881164271714799244429282308634656748139191231628"\
    "2458617866458359124566529476545682848912883142607690042242"\
    "1902267105562632111110937054421750694165896040807198403850"\
    "9624554443629812309878799272442849091888458015616609791913"\
    "3875499200524063689912560717606058861164671094050775410022"\
    "5698315520005593572972571636269561882670428252483600823257"\
    "530420752963450".each_char.map(&:to_i).each_cons(5) { |a| p arr << a.reduce(:*) }     
    puts arr.max 
  end
end

Phew! Look forward to the last two Eulers, 9 and 10, which I’ll hopefully get to post soon.

Monday, December 9, 2013

Building a Bot

I recently mentioned in my mentorship goals that one of the things I wanted to quickly dive into were databases. There are a variety of database types and ways to work with them. I was able to get an introductory handle by looking over Learn SQL the Hard Way and doing some additional research but databases are difficult to understand until you really start doing work with them.

At the same time, the bot in an IRC channel I often use was acting up. Basically, the bot was/is pretty much broken and needs to be restarted but no one knows who is actually able to restart the bot. Chris and I decided that a great first project for us to work on via the mentorship program would be to build a bot and to add a database component to it.

So first, what is a bot? A bot is a program that you can connect into a chat room (in this case an IRC channel) which will then respond to different conversations or things happening in the chat room. Most workplaces I’ve spoke to that utilize hipchat, campfire, or other internal chat communication tools have some sort of bot that hangs out in the room as well and makes it more entertaining. It’ll pop up funny gifs or respond to things people say. It can also be useful by providing information about testing or alert the room when someone deploys code.

My bot’s name is Rosie. She’s awesome. I’ll write up a few posts in the future that describe more about what she does but for now, I just want to go over the setup. First, I used cinch. Cinch is a great, easy way to set up a bot and gives pretty straightforward instructions that get you moving quickly.

This is what the setup code looks like.

bot = Cinch::Bot.new do 
  configure do |c| 
    c.server = 'irc.freenode.net' 
    c.realname = 'Rosie' 
    
      c.channels = ['#rosie'] 
      c.user = 'rosie_' 
      c.nick = c.user 
  end

Now, to walk through each line.
The first line bot = Cinch::Bot.new do creates a new bot using cinch. This new method takes a block.
In the next line configure do |c| , we are in the block configuring the method. This method also takes a block and passes in the cinch configuration for the bot which means it passes in a reference to itself that you can configure.
The third line c.server = 'irc.freenode.net' shows the server we are connecting to.
Then c.realname = 'Rosie' is the real name that will show up when someone asks who is in the IRC channel.
Next, c.channels = ['#rosie'] is the channel that the bot connects to. Right now I’m just testing her out, so I have her connecting to an independent channel that no one is using.
Coming to the end, the 2nd to last line c.user = 'rosie_' gives the nick name of the bot that will show up in the channel.
And finally, c.nick = c.user sets the nickname to the same thing as the username.

So, there’s the initial setup. I’ll do future posts on both functionality and integration of a database, as well as one on what is IRC in general for those not familiar with it.

Tuesday, December 3, 2013

Mentorship Goals

As many of you know from past posts, I was recently awarded Chris Sexton from the Arlington Ruby group as my mentor. I say awarded because it’s been going really great and I think he’s awesome. I’m so glad Chris is my mentor and we’ve been meeting regularly to make sure I’m learning what I want to. This brings me to my next point, as many of you also know, I think it is very important to set goals. In addition to setting goals for myself so that I can achieve them, goal setting is a vital part of a mentor/mentee relationship. Part of being an effective mentee (I’m going to do a full post about this in the near future) is making it easy for someone to mentor you by being proactive and knowing what you want to learn and accomplish.

One of the first things I did, before chris and I even had a chance to sit down for our first meeting, was let him know what my goals were during this time period. These goals have already changed once or twice and I can always continue to add new goals as we go along, but providing Chris with my goals sets us up for success. I know I’m going to learn a lot and he knows exactly what I want to focus on to learn.

Here are the goals I sent him:
- Pair program at least once per month
- Determine projects to work on (building off of what I have already done and building new things)
- Feel more comfortable with defining my abilities
- Feel comfortable with looking at/thinking about projects that are in progress (not just building rails apps from scratch)
- Learn more about databases and become more comfortable working with them
- Determine how to set good programming goals (there's so much to learn, how do you determine what gets you to the next level and how to get there)
- Commit to OSS

I’ve already started my first project with him of building a bot! The bot is going to be awesome and we’re going to incorporate some information that needs to go into a database in order for me to really get a better sense of working with databases, how they work, and what problems might arise when using them. I’ll definitely be doing some posts soon on the process of building a bot.

Sunday, December 1, 2013

Learning… The next few tutorials and tools

My apologies for not posting for a few weeks on this topic! I imagine that those of you who followed the last post on tools to get started with have completed those three resources and are very ready to move on.

Next on the list is learn ruby the hard way. This tutorial is great and you can get it free, online. I recommend working through it. This will take you a while and probably, at some point in the middle, you will lose steam and not want to do the rest of the lessons. BUT continue and push through it. Take notes. Do ALL the extra credit. Keep all your exercises in a folder. It gives you a really solid step by step guide to ruby that is a little more advanced than the last group of links I provided. It also provided me with a lot of good questions to ask more seasoned developers to get more information on how certain things worked or what certain things were.

If you’d like to simultaneously be reading a book while doing this, I recommend Chris Pines "Learn to program". To be honest, I didn’t read this book but have since skimmed through most of it. This will give you a good foundational background in programming. Now, this is the stuff that may get tedious and may seem boring (I know I had a really difficult time keeping motivated and focused through this part.) It is so annoying when you just want to build cool things but you just don’t know enough yet to build awesomeness. Don’t worry, the awesomeness is coming!!! But you’ve gotta make it through this first.

Next, do Ruby Monk. I did Ruby Monk way too late, but once I did it, it clarified a lot of definitions and parts of Ruby for me once I did it.

Additionally, start listening to podcasts and figuring out which resources you like. I really enjoy Ruby Rogues, especially their picks at the end but there are a lot of different podcasts, both free and for a low-cost.

Finally, I wanted to toss out two additional resources that aren’t necessarily tutorials. This is an awesome resource: http://iwanttolearnruby.com. It lists a lot of different tutorials and resources, notes the level and cost (if any). It’s a good place to find a lot of the resources I’ve mentioned and more. And last, this article came out this week and I thought it was a really great read with some good messages and thoughts to keep in mind about what she wishes people had told her when she started learning to code. https://medium.com/learning-to-code/565fc9dcb329

Keep going!!