Show the Local Weather – Part 2

Read Part 1 here. Part 1 covers how to get a user’s geolocation to dynamically generate the weather according to the user’s location.

Part 2 is about using the user’s location to get the local weather forecast.

I used OpenWeatherMap‘s API to get the weather information. You’ll need to sign up (it’s free!) and get an API key: http://openweathermap.org/appid

  1. Sign up and get an API key from OpenWeatherMap.
  2. This is an example of the URL (API call) you will use to get weather info:
    http://api.openweathermap.org/data/2.5/weather?lat=33.7708&lon=-84.2931&units=imperial&APPID={APIKEY}

    This is the URL to OpenWeatherMap API:

    http://api.openweathermap.org/data/2.5/weather?

    You can use a city name, city ID, or longitude & latitude coordinates. I decided to use the longitude and latitude for more accurate weather.

    This is where you put the latitude and longitude coordinates.

    lat=11.111&lon=-11.111

    The longitude and latitude coordinates were derived from Part 1:

    {"ip":"8.8.8.8",
    "country_code":"US",
    "country_name":"United States",
    "region_code":"NY",
    "region_name":"New York",
    "city":"New York City",
    "zip_code":"10128",
    "time_zone":"America/New_York",
    "latitude":40.7142700,
    "longitude":-74.0059700,}

    You can also toggle Celsius and Fahrenheit with

    &units=

    Celsius: units=metric
    Fahrenheit: units=imperial

    Read more here.

    In place of {APIKEY} paste your OpenWeatherApp API key. You can find your key when you log into your account and go to the API Keys tab.

  3. Test your API call with Postman by placing the full URL ( http://…APPID=…..) in as a GET request. You should get a response similar to something like this:
    {"coord":{"lon":139,"lat":35},
    "sys":{"country":"JP","sunrise":1369769524,"sunset":1369821049},
    "weather":[{"id":804,"main":"clouds","description":"overcast clouds","icon":"04n"}],
    "main":{"temp":289.5,"humidity":89,"pressure":1013,"temp_min":287.04,"temp_max":292.04},
    "wind":{"speed":7.31,"deg":187.002},
    "rain":{"3h":0},
    "clouds":{"all":92},
    "dt":1369824698,
    "id":1851632,
    "name":"Shuzenji",
    "cod":200}

    Play around with different locations and when it is successful, you can go to the next step!

  4. Start writing your JavaScript function! We need to create an AJAX call to get the data returned from the API and store it in our own variables so we can use the information. I used the jQuery .ajax function.
    function getWeather(url) {
    	$.ajax({
    		url : url,
    		dataType : "json",
    		success : function(data) {		
    			var temp = data['main']['temp'];
    			var image = data['weather'][0]['icon'];
    			var desc = data['weather'][0]['description'];
    			var humidity = data['main']['humidity'];
    			var rain = data['weather'][0]['main'];
                            var sunset = new Date((data['sys']['sunset'])*1000);
                            sunset = sunset.toString().slice(16,21);
                            document.getElementById('image').src="http://openweathermap.org/img/w/" + image + ".png";
    			$('#temp').html(temp);
    			$('#desc').html(desc);
    			$('#wind').html(rain);
                            $('#sunset').html(sunset);
                            $('#humidity').html(humidity + "%");
    		}
    	});
    }

    The sunset variable is storing the sunset UNIX number and converting it to a readable format according to the user’s timezone.

    I am passing in the parameter to getWeather the URL saved as Weather in Part 1. It’s the URL you use to make the weather API call.

To load OpenWeatherMap’s weather icons, use this img source format:

http://openweathermap.org/img/w/" + image + ".png";

Where:

var image = data['weather'][0]['icon'];

Final Product: http://sunsplat.github.io/fcc_weather/index.html

Source for how to get the weather icons here: https://openweathermap.desk.com/customer/portal/questions/13287488-weather-icon-id

Another weather API you can use: forecast.io

Ruby Algorithm Interview Challenge

I recently had a Junior Ruby Developer interview where I had to complete a coding challenge live. I didn’t finish in time and didn’t get the position, but I wanted to complete it anyway.

The Challenge:

Convert numbers into their word equivalent.

ie. 1 = “one”, 23 = “twenty three”, 1234 = “one thousand two hundred thirty four”


My Solution:

def convert_num(num)
	ones = {
		'1' => "one",
		'2' => "two",
		'3' => "three",
		'4' => "four", 
		'5' => "five",
		'6' => "six",
		'7' => "seven",
		'8' => "eight",
		'9' => "nine"
	}

	teens = {
		'11' => "eleven",
		'12' => "twelve",
		'13' => "thirteen",
		'14' => "fourteen",
		'15' => "fifteen",
		'16' => "sixteen",
		'17' => "seventeen",
		'18' => "eighteen",
		'19' => "nineteen"
	}

	tens = {
		'10' => "ten",
		'20' => "twenty",
		'30' => "thirty",
		'40' => "forty",
		'50' => "fifty",
		'60' => "sixty",
		'70' => "seventy",
		'80' => "eighty",
		'90' => 'ninety'
	}

	hundreds = {
		'100' => "one hundred",
		'1000' => "one thousand"
	}

big_num = []
#first check ones place
	string_num = num.to_s
	if ones.include?(string_num)
		ones[string_num]
#check teens
	elsif teens.include?(string_num)
		teens[string_num]
#check tens
	elsif tens.include?(string_num)
		tens[string_num]
#check hundreds
	elsif hundreds.include?(string_num)
		hundreds[string_num]
#split the number up 
	else
		num_array = string_num.split('')
		if num_array.length == 4
			big_num << ones[num_array[0]] + " thousand"
			big_num << ones[num_array[1]] + " hundred"
			big_num << tens[num_array[2] + '0']
			big_num << ones[num_array[3]]
		elsif num_array.length == 3
			big_num << ones[num_array[0]] + " hundred"
			big_num << tens[num_array[1] + '0']
			big_num << ones[num_array[2]]
		else
			big_num << tens[num_array[0] + '0']
			big_num << ones[num_array[1]]
		end
		big_num.join(" ")
	end
	
end

How I approached this challenge (my thinking process):
I was told that the highest number passed into this algorithm would be 9,999

  1. First I knew I needed to create a list of all the numbers and their written equivalent. Since the keys would not match an array index sequence, I decided to store the information in a hash.
  2. The ones place is its own hash because I knew I would need to use this hash again when dealing with hundreds and thousands.
  3. I placed the teens in their own hash because there’s no pattern to the written form and would only be used if one if the numbers in the teens hash appeared.
  4. Same goes for the tens. Twenty is different from two and thirty is different from three. So they get their own hash as well.
  5. If the number being passed matches exactly with any of the keys in these hashes, then I just need to use that key to grab the value and output it.
  6. If the number being passed does NOT match with any of the keys in my hashes, then I want to split the number up and search through the array created.
  7. If the length of the array is 4 (has 4 digits), then I know I need to add the word “thousand” after the first index (0), and “hundred” after the second index (1). I push these in order into a new array called big_num.
  8. The tens place is tricky as the numbers are all single digits. I add a ‘0’ to the end of the digit and search my tens hash for the matching key.
  9. I follow this same pattern for numbers that have a length of 3 and numbers with a length of 2.
  10. Then I join the elements in big_num together so that they form one string.

The following tests and outputs:

p convert_num(3)
  => "three"
p convert_num(15)
  => "fifteen"
p convert_num(90)
  => "ninety"
p convert_num(45)
  => "forty five"
p convert_num(202)
  => "two hundred two"
p convert_num(100)
  => "one hundred"
p convert_num(1200)
  => "one thousand two hundred"
p convert_num(9999)
  => "nine thousand nine hundred ninety nine"

Pretty sure that there can be some more refactoring, but will have to keep working through the logic to find a way to simplify it.

Deploy Sinatra app on Heroku

This is for everyone who has finished their Sinatra application and wants to deploy it on Heroku.

FYI::You will need to have all your files uploaded on your Github repo to be able to deploy on Heroku. The following steps are assuming you have deployed to Heroku before. If you haven’t, follow this excellent tutorial.

Example app name: Hangman
app file: game/hangman.rb

Steps:

1. Create a Gemfile in your app directory that has the following:
The file path should look something like this: game/Gemfile where ‘game’ is the name of your app directory

source 'https://rubygems.org'
gem 'sinatra'
gem 'sinatra-contrib'

Be sure it list ALL gems you use in this Gemfile otherwise Heroku will give you an H10 – App Crashed error.

2. Create a config.ru file in your app directory:
The file path should look something like this: game/config.ru

require './hangman'
run Sinatra::Application

3. In your app file (ie. hangman.rb), require Sinatra:

require 'sinatra'

If you don’t have any content in the file, create a simple Hello World by adding the following below your require statement:

get '/' do
  "Hello World!"
end

4. Run Bundle Update
In your terminal (or Command Prompt):

$ bundle update

This will create and update your Gemfile.lock.
You can also manually create a Gemfile.lock and run bundle update after.

5. Commit your new files to Github and push to Heroku!

$ git add config.ru Gemfile Gemfile.lock
$ git commit -m "adding Heroku deployment files"
$ git push origin master
$ git push heroku master

Bonfire: Falsy Bouncer

Challenge:

Remove all falsy values from an array.

Falsy values in JavaScript are false, null, 0, “”, undefined, and NaN.

Use the following:
Array.filter()
Boolean objects


My Solution:

function bouncer(arr) {
  // Don't show a false ID to this bouncer.

  var newArray = [];
  for (var i = 0; i < arr.length; i++) {
    var arrBool = Boolean(arr[i]);
    if (arrBool === true) {
      newArray.push(arr[i]);
      //return newArray;
    }
  }
  return newArray;
}


bouncer([7, "ate", "", false, 9]);

To approach this challenge, I broke it down like this (my thinking process):
1. I need to pass each element of the given array (arr) through a loop to check if each item value is 'false' or 'true'.
2. I can use the Boolean object to check if an item is false or true. I’ll do that within my loop.
3. I don’t know how to use Array.filter(), even after reading the Mozilla page. I’ll ignore that for now.
4. What kind of loop will allow me to iterate through each item in the array? I can use a ‘for loop‘.
5. Do I need to use split()? No, .split() only works for strings.
6. Oh, if you have an array, you can check each individually by using their index number, which starts with 0. So, [0=>7, 1=>”ate”, 2=>””, 3=>false, 4=>9]. Then I’ll start my ‘for loop’ variable ‘i’ at 0 (var i = 0), iterate the length of the array (i< arr.length), and increment by 1 because I want to go through every index in the array (i++).
7. I’ll use an if statement within my loop to check if the values are true or false.
8. After I check if the value is true or false, I want to take all the true values and put them somewhere. Maybe I’ll create a new array called newArray and store all the true values (var newArray = []). I want to be able to return the newArray so I’ll declare this newArray outside of my loop.
8. To add items to an array, you can use .push(), with what you want to push included inside the parentheses.
9. I tried to do newArray = newArray.push(arr[i]); but was getting an error. I removed newArray = and now it works! Will need to look into why that is later.
10. I want to return the new array, so I’ll write return newArray outside of my for loop.
11. I also want to return my newArray in my if statement so that the for loop can access the newArray values.
12. Well, returning the newArray within my if statement causes an error, so I’ll comment that out.
13. Yay! Passed all tests!

Bonfire: Slasher Flick

Use either .splice() or .slice() to get the answer to this coding challenge from FreeCodeCamp.

The Challenge:

Return the remaining elements of an array after chopping off n elements from the head.

The head meaning the beginning of the array, or the zeroth index


My Solution:

function slasher(arr, howMany) {
  // it doesn't always pay to be first
  arr = arr.slice(howMany, arr.length);
  return arr;
}

slasher([1, 2, 3], 2);

I used the .slice() method and sliced starting at the howMany value, through the length of the array. This challenge took me about ten minutes! Are they getting easier or am I just getting better? I hope it’s the latter!

Bonfire: Factorialize a Number

Factorialize a Number – great JavaScript coding challenge from free online full-stack bootcamp FreeCodeCamp. This was a tough one that required a couple hours to figure out. Taking a break from these challenges really makes them harder when you start back up!

Challenge:

Return the factorial of the provided integer.

If the integer is represented with the letter n, a factorial is the product of all positive integers less than or equal to n.

Factorials are often represented with the shorthand notation n!

For example: 5! = 1 * 2 * 3 * 4 * 5 = 120


Solution:

function factorialize(num) {
  var total = 1;
  for (var i = 0; num > i; i++) {
    total = total * (i+1);
  }
  return total;
}

factorialize(5);

Bonfire: Chunky Monkey

The Chunky Monkey Bonfire took me about 40 minutes to solve. It was a real tough one and I had to Google to find some help.  I used the .push() method and the .slice() method. Came across Wulkan’s blog in my search and his solution to the challenge really helped me find mine. Thanks Wulkan!

The Challenge:

Bonfire: Chunky Monkey

Write a function that splits an array (first argument) into groups the length of size (second argument) and returns them as a multidimensional array.

For example:
chunk(["a", "b", "c", "d"], 2) should return [["a", "b"], ["c", "d"]]
chunk([0, 1, 2, 3, 4, 5], 3)
 should return [[0, 1, 2], [3, 4, 5]]


The Solution:

function chunk(arr, size) {

  var newArr = [];
  for (i = 0; i < arr.length;) {
    newArr.push(arr.slice(i, i += size));
  }
  return newArr;
 
}

chunk(["a", "b", "c", "d"], 2, "");

I was having trouble with controlling the incrementation in the ‘for loop’ so I just took out the ‘i++’ and it worked!

Bonfire: Truncate a string

Using .splice() to solve FreeCodeCamp‘s Bonfire: Truncate a string.

The Challenge:

Truncate a string (first argument) if it is longer than the given maximum string length (second argument). Return the truncated string with a “…” ending.

Note that the three dots at the end add to the string length.

Try it yourself before viewing my solution! If you use Google Chrome as your browser, you can right click and Inspect Element to use the console to test your code.


The Solution:

function truncate(str, num) {

  if (str.length > num) {
    return str.slice(0, (num-3)) + "...";
  } else {
    return str;
  }
}

truncate("A-tisket a-tasket A green and yellow basket", 11, "");
truncate("A-tisket a-tasket A green and yellow basket", "A-tisket a-tasket A green and yellow basket".length);

Bonfire: Repeat a String Repeat a String

Three in a row! Are these challenges easier than the first Bonfires or is all this training really starting to improve my programming brain? (I hope it’s the latter!)

This is my solution to FreeCodeCamp‘s Bonfire: Repeat a string repeat a string. This one was much easier to complete as you only need to check if the num argument is less than zero.

The Challenge:

Repeat a given string (first argument) n times (second argument). Return an empty string if n is a negative number.

The Solution:

function repeat(str, num) {

  if (num < 0) {
    return "";
  } else {
    return str.repeat(num);
  }
}

repeat("*", 3, "");
repeat("abc", 3, "");