Alexander Ramadan

Where I Sometimes Write Stuff


Headless Browsing for SEOs
2016-03-16

I was totally inspired by Mike King's talk about technical SEO.

I've always had most of my interest in SEO around the technical aspects, which have spoken to me more than the content/outreach side of the field. So this talk discussed a lot of topics that were very interesting to me, one of them being headless browsing.

Headless Browsing for SEO

I had always heard of headless browsers, but ignored them for the most part, relying on other tools to do my audits. But I decided it was time to put my fear of the unknown behind me and give using one a shot. Checkout this article for a good run down on what Headless browsing is.

I went with PhantomJS as it seems to be the de facto headless browsing implementation. The PhantomJS website walks you through installing the library, and gives you some example code to start with. Having some knowledge of JS helps getting all this working quickly.

Here are some of the most useful sections of the site or tutorials I found for using it:

Below is a small code sample that opens a webpage in a headless browser, renders it, then takes a snapshot and saves that picture to your harddrive.

A lot of this code is from the example code on the site, but I made some changes so that it was more useful to me. The main change is that I leveraged command line arguments so that you can pass the URL, device size (mobile or desktop) and a file name to save the image with as arguments rather than having to edit the source code each time you want to crawl a new page. I also included the viewportSize for a mobile device and a desktop screen so that you can choose which you want to render. It seems like the script originally wants to default to mobile, so by passing either "desktop" or "mobile" as an arugment will let you render in the different sizes.

To use the script do this:

  1. Download and install PhantomJS
  2. Copy the code from the window above
  3. Paste into a text editor (not Microsoft Word)
  4. Save the file as example.js to your desktop (or where ever you want)
  5. Go to the terminal or command line
  6. Navigate to where you saved the file via the command line
  7. Run the code like explained below

Once you have the script saved, to run it you'll need to pass 3 arguments to the script:

  • Full URL of the page you want to crawl
  • Device size (either "desktop" or "mobile")
  • A file name to save the image of the page as

To run the code, use the command line, navigate to where the script is saved and use this to execute the script,

phantomjs example.js url device filename

So, if I wanted to run it for this site's homepage, I would type

phantomjs example.js http://alexanderramadan.com mobile homepage

This will download and render http://alexanderramadan.com with the viewPort set to a mobile device size. It will also save the image of the page we rendered as "homepage.png".

It's been very interesting playing around with this and I can definitely see the benefits of pragmatically browsing a page. It's also been interesting to see what renders and what doesn't.

Definitely a nice tool to have handy if needed. Next, I'll be looking at HorsemanJS which seems to give users a simipler way to interact with PhantomJS.


SEO Bookmarklet
2016-01-15

A while ago I wrote a small Javascript bookmarklet that allowed me to do 3 get 3 page elements quickly from the current page I am on:

  • URL
  • Title tag
  • Desrctiption tag

You can read more about this small project and get the bookmarklet for your own use here


The 24 or 8 Debate
2015-12-03

I hadn't really thought of it until I saw the question posed, "Which number should the Lakers retire for Kobe, 8 or 24?"

I'm not sure if this issue has ever come up, where a player changed numbers without switching teams. The only other case I can think of this happening with a player who would get their number retired is Jordan, with 23 and 45, but in that case, there is simply no question.

My reflex is to answer, the number 8. It was the first number I saw Kobe play with, and being a big sucker for nostalgia, it seemed right. I remember meeting Kobe outside of a mall right before his rookie season, becoming an instant fan. I owned a (much to large for my height, but it was 2000) number 8 authentic jersey. It's the number that reminds me of watching the Lakers with my dad. It'll always be Kobe's number to me.

But obviouly not everyone will agree, so I tried to look at it without my own history affecting my choice.

If we try to look at Kobe's PPG each season it's a bit hard to tell where he was more productive, it's also not very telling of anything really

Obviously I will need to dig a bit deeper.

In this brief analysis I awarded 1 point for each of the following categories in which Kobe achieved during a season:

  • Championship
  • All Star Appearance
  • All Star MVP
  • Season MVP
  • Finals MVP
  • First Team All NBA
  • First Team Defense
  • Season Scoring Champ
  • Other (ie. slam dunk champ)

Here is the crude chart I used to add these up

Results:

  • Kobe #8 (96-05) - 18 points
  • Kobe #24 (06-15) - 32 pints

It's pretty easy to see which number he was more productive in, number 24.

While he won more championships in number 8, he had many more personal achievements in 24. He won his only season and finals MVPs while wearing 24, as well as being the scoring Champ twice. He also had a higher PPG while wearing 24.

If you don't like this approach (I admit it's not very scientific), another angle to approach this is, while Kobe wore #8 he largely shared the spotlight, and team, with fellow Laker legned, Shaq. What Kobe could achieve without Shaq was always in question, as was his maturity. He was embrolied in drama on and off the court, although never distracting from his ability to produce.

But when Kobe wore #24, the Laker's were his. He took them from nothing to Champions. He emerged as a legend while wearing 24. From hitting countless clutch shots, to scoring an amazing 81 points in a single game, Kobe became the Black Mamba in 24.

What Should They Do?

I kind of hope they can figure out a way to reitre both numbers, not really sure how this could be done, maybe a holographic image projected on a blank jersey that changes throughout the game, rotating between 8 and 24.

In reality, this is a small issue. Older fans will might remember Kobe as number 8 and if that has any kind of emotional attachement, then that will always be his number. Those not hung up on nostalgia will recognize 24 as his number.

When it comes down to it, it doesn't matter. Kobe is the greatest Laker of all time, regardless of the numbers. Let's just ask him which he'd rather have.


How Fast Have People Climbed The Nose in Yosemite?
2015-11-16

How Fast Have Teams of 2 Climbed The Nose in Yosemite? Fast.

I've been reading Alex Honnold's new book, Alone on the Wall, which discusses his speed ascent of 2,900 foot Nose, as well as a history of previous ascents. The first "speed ascent" of The Nose was in 1975 by Jim Bridwell, John Long and Billy Westbay, with a time of 17 hours, 45 minutes. The most recent speed ascent, done by Alex Honnold & HansFlorien was 2 hours, 23 minutes and 46 seconds in 2012.

Almost 15 hours faster. Insane.

Here's a look at the progress of the Nose speed ascents over the last years. You'll notice that once you hit 2002, the climbers were beating each other by minutes and, in some cases, seconds.

Year Team Time
2012 Hans Florine & Alex Honnold 2:23:46
2010 Dean Potter & Sean Leary 2:36:45
2008 Hans Florine & Yuji Hirayama 2:37:05
2008 Hans Florine & Yuji Hirayama 2:43:33
2008 Alexander & Thomas Huber 2:45:45
2007 Alexander & Thomas Huber 2:48:30
2007 Hans Florine & Yuji Hirayama 2:48:55
2007 Dean Potter & Timmy O'Neil 3:24:20
2002 Hans Florine & Jim Herson 3:57:27
2001 Dean Potter & Timmy O'Neil 3:59:35
2001 Hans Florine & Peter Croft 4:22:00
2001 Peter Croft & Dave Schultz 4:48:00
1992 Hans Florine & Andres Puhvel 6:01:00
1990 Peter Croft & Dave Schultz 6:40:00
1990 Hans Florine & Steve Schneider 8:06:00
1986 John Bachar & Peter Croft 10:05:00
1984 Duncan Critchley & Romain Vogler 9:30:00
1975 Jim Bridwell, John Long, Billy Westbay 17:45:00

It wasn't until the early 2000's that climbers started to account for seconds when doing speed ascents.


Trying to Deal with Hidden Content and SEO
2015-11-04

Update At the State of Search conference, @methode's presentation it was revealed that,

On indexing JS. Googlebot doesn't click or hover or focus. So do it doesn't see content that requires user action

What this means is that even if you use the method of hiding content using Javascript/jQuery Googlebot won't index the content. So, this in fact won't work as I hoped.


I recently ran into an issue with a site that had a block of text that was not being indexed because, of what we believe, is the use of display: none to toggle that content in and out of view.

The use of CSS to hide and reveal content is an issue where the SEO community seems split.Google has said that it will crawl and index content hidden in a div as long as it "isn't spammy", but that's not very definitive. They have also said that they may slightly "discount" content that is hidden from users. Because of this many SEO's recommend against hiding content using CSS OR javascript all together. So, as an SEO trying to juggle design considerations as well as SEO issues we're left not really knowing what we should do. What else is new?

In this case, I believe a possible here is to avoid using CSS and display: none to hide the content all together and rather use jQuery to animate the content in and out of view.

Here is how that would work

In this scenario we're not using display: none, but we're still hiding the content, just using jQuery. I don't know if this would fix the issue to be honest. It will require further testing, and it might be different from site to site, but it is an alternative to using display: none, if that is what is really causing this issue.

Ideally, any content that is core to the page should be visible to the user as soon as the page loads, with nothing hidden.

As with most things regarding your site and SEO, always test your implementation to see if it is achieving your goals. In this case, indexing the content you're hiding with javascript.


What Makes the Warriors Special
2015-06-17

What makes the 2014-15 Warriors so special? Their record was fantastic, but teams have had better records. They have one of the best offenses and defenses in the league, but that has happened before.

Why are they so special?

It boils down to Steph Curry, and his role on the team. No one will doubt that Curry is the team's best player, hell he was the best player in the league for the entire season. Why is that special? They're the first team in 20 years to win a championship when their best player for the entire season was a point guard.

This observation isn't new. Max Kellermen of Sports Nation and 710 ESPN is constantly preaching the idea that teams don't win rings when they are lead by a point guard, and he's right.

In in the past 20 years, a teams hasn't won a championship when their best player was a point guard. It just doesn't happen. To illustrate my point, let's look back at the champions of the past 20 years to see what I mean.

Disclaimer: The term "best player" is mostly a matter of opinion, but these were the teams best player in my mind.

Year Champs Best Player IMO Pos.
2014 Spurs Kawhi SF
2013 Heat James SF
2012 Heat James SF
2011 Mavericks Dirk PF
2010 Lakers Kobe SG
2009 Lakers Kobe SG
2008 Celtics Pierce/Garnet SF/PF
2007 Spurs Duncan PF
2006 Heat Wade/Shaq SG/C
2005 Spurs Duncan PF
2004 Pistons Hamilton SG
2003 Spurs Duncan PF
2002 Lakers Shaq C
2001 Lakers Shaq C
2000 Lakers Shaq C
1999 Spurs Duncan/Robinson PF/C
1998 Bulls Jordan SG
1997 Bulls Jordan SG
1996 Bulls Jordan SG
1995 Rockets Hakeem C

Notice anything? Teams that win rings aren't led by point guards. Nearly every other position is represented here, but not PGs.

Let's look at the other best team in each of these seasons

Year Opp Best Player IMO Pos.
2014 Heat James SF
2013 Spurs Duncan PF
2012 Thunder Durant SF
2011 Heat James SF
2010 Celtics Pierce/Garnet SF/PF
2009 Magic Howard C
2008 Lakers Kobe SG
2007 Cavs James SF
2006 Mavericks Dirk PF
2005 Pistons Hamilton SG
2004 Lakers Kobe SG
2003 Nets Kidd PG
2002 Nets Kidd PG
2001 76ers Iverson PG
2000 Pacers Miller SG
1999 Knicks Ewing C
1998 Jazz Stockton/Malone PG/PF
1997 Jazz Stockton/Malone PG/PF
1996 Sonics Payton/Kemp PG/PF
1995 Magic Shaq C

We see a much higher concentration of point guards in teams who went almost all the way, but eventually came up short.

The point is, teams who are lead by their point guard don't win championships, at least not in the last 20 years.

This is what makes Curry and the Warriors so unique. Curry is by far their best player, an MVP, and he still some how makes his team so much better. He is able to facilitate the leauge's best offense while individually being in the top 10 in points per game (23.8), #1 in free throw % (.914), #4 in 3 point % (.439), #6 in assists per game (7.7) and #4 in steals (2.04).

Congrats to Curry and the Warriors.


Write365 2.0
2015-06-17

Today we're releasing Write365 2.0 for iOS, the first major update to the app since its initial release.

The entire UI has been updated, giving the app a new, fresh look. The app now features 1 main button to generate a prompt, and has been placed so it is easy to use one-handed. We're hoping the app is easier for users to use regardless of screen size.

We've also implemented new sharing and integration options leveraging the iOS9 share sheet. This will give users more options for sharing prompts with their friends, or with their favorite writing app.

Finally, we added a bunch of new prompts to the app. We're at around 450 prompts now so hopefully we can spark some interesting creative ideas for our users.

The app is still $.99 for new downloads and a free upgrade for existing users.

You can buy it here

For those interested in the technical side of the new version, read on.

This version of Write365 was written in Swift, being rewritten from Objective C.

Initially, I was hesitant about rewriting the app because I didn't want to break anything and be unable to fix it. The Swift community is still new, and things are changing rapidly.

Since this project has never been a money maker, and always more of a platform to learn on, I eventually threw caution to the wind and began to port it to Swift. The rewrite process was actually much easier than I thought.

Technically, after I imported the Objective C headers, rewriting the actual code in Swift was a breeze. Objective C was never a language I enjoyed working with, partly because it was hard to understand coming from a brief background in Python. But Apple's documentation along with tutorials and a helpful community made porting the app really easy.

Okay, enough with the boring stuff

Happy creating


Web Dev Cheatsheet for SEO
2015-05-19

Link: The Web Developer SEO Cheatsheet by Moz

This is a definite, must-download for anyone who does SEO or web development, or a mix of both

This would probably serve a new SEO or dev to your team well in familiarizing themselves with some of the more technical aspects of SEO.

The cheatsheet covers the follow topics:

  • Import HTML Elements (title tags, descriptions, headers, etc.)
  • Canonicalization
  • URL Best Practicies
  • Webmaster Tools (Bing, Google and Yandex
  • Robot Control Syntax
  • Important User Agents
  • Sitemap Syntax
  • Pagination
  • Social Metadata
  • Rich Snippets
  • Structured Data
  • Targeting Multiple languages
  • Mobile Web Development

  • Jim Lee Interview
    2015-05-16

    I've got a bit of a tradition of listening to this interview between Kevin Smith and Jim Lee every few months when I need some inspiration.

    The interview with Smith and Lee is inspiring as the two discuss Lee's early days of hustling and getting up everyday to go to work even when he didn't have a job, and drawing comics all day to trying to meet Marvel artists at local comic cons to show them his work. They discuss everything from his early career at Marvel, to founding Image Comics and eventually moving over to DC.

    The chemistry between Smith and Lee is great. Just a couple of friends talking about comics and life.

    My love of comics is tied to Jim Lee's work because the first comic book I ever bought was X-Men #1 by Lee in 1991.

    I didn't know anything about comics, artists or writers at the time. All I knew is that I loved X-men (because of the cartoon and toys) and this comic looked awesome.

    I stopped reading comics for most of the late 90's and all the way through the 2000's, picking it back up in 2011. Luckily I still had my X-Men #1 to go back to read immediately.

    If you're at all interested in comic books, art, entrepreneurship or just like to listen two a good conversation between passionate people, give it a listen. It's a two-parter, but well worth the 3-4 hours.


    MVP - Step Curry
    2015-05-03

    I can't remember an NBA MVP that I've enjoyed watching as much as Steph Curry.

    Maybe it's because when people say 'he's on fire' and hearken back to the famous line from NBA Jam, it makes me feel nostalgic.

    Or maybe it's because when I see Curry dribble the ball with complete mastery like it's an extension of his own hand I'm reminding of watching And1 Mixtapes with my friends, and then trying to mimmick the moves in a backyard.

    Regardless of why I enjoy watching Curry play, the fact of the matter is he's had a completely dominating year.

    Let's look at the facts supporting his MVP win:

    • Games Played: 80
    • Minutes Played: 2,983 (7th in the league)
    • Points: 1,900 (2nd in the league)
    • PPG: 23.8 (6th in the league)
    • FG%: 47%
    • 3p%: 44% (3rd in the league)
    • 3p Made: 286 (NBA record)
    • FT%: 91% (1st in the league)
    • APG: 7.7 (6th in the league)

    The thing about the way Curry plays is that he just looks like an MVP on the court, the stats are just the icing on the cake.

    Here is a glimpse of Curry's shot coverage for his MVP year

    There is no doubt Curry is on pace to be the greatest shooter in NBA history.

    As of this year, Curry is making $10,629,213 for the 2014-15 season, a complete steal if you ask me.

    Looking back at recent MVP winners and their salaries, the Warriors are getting a great deal.

    Player MVP Year Salary
    Curry 2014-2015 $10 million
    Durant 2013-2014 $17 million
    Lebron 2012-2013 $17 million
    Lebron 2011-2012 $16 million
    Rose 2010-2011 $5 million


    Automate The Boring Stuff with Python
    2015-04-25

    Link:Automate the Boring Stuff with Python

    I recently bought the Automate The Boring Stuff with Python book from Al Sweigart because I love tutorials or books that teach me how to do a few specific things, step-by-step, and thats what this book aims to do.

    I've only started to work through the PDF (I bought the physical book too, but that hasn't shipped yet) and I'm really enjoying it.

    The book basically teaches you how to automate very simple, but boring, tasks with Python, hopefully freeing you up to do more interesting things.

    The key to this book is that it's not teaching you abstract tasks, or theory that most people won't ever need. It's teaching you things that everyone who uses a computer can benefit from automating.

    Here is are some topics the book discusses:

    • web scraping
    • working with spreadsheets, pdfs, csv files
    • scheduling tasks
    • sending email
    • manipulating images

    Everyone I know who uses a computer could benefit from automating these types of things.

    For me, I work with spreadsheets everday at work, so anything I can automate (beyond what I already have setup) in that process will make me a happy, more productive person. I also tend to have resize a lot of images when submitting an app to the App Store, and that is usually a pain. I'm hoping this book will teach me an easy way to generate a bunch of images in specific sizes quickly.

    The book's examples are all in Python 3, which at first was discouraging because I'm still using Python 2.X, but this was a good reason to force me to try 3. I haven't found the changes to be too difficult to deal with yet, but I will admit I still forget the print thing nearly every time.

    Python 2.X

        
    print "hello world"

    Python 3.x

        
    print("hello world")

    I'm really excited to dive deeper into the book. I'm working through the basics section first as a reminder on how certain things work, or at least how they work in Python 3.

    Here's to automating all the things!


    How to Tweet a Page with a Changing Title
    2015-04-25

    I was recently building a page where the main text of the page changed every X seconds. I wanted to have a "Tweet" button on the page so that users could tweet whatever the current text on the page at the time.

    The problem with this is that the tweet button functionality didn't provide a straight forward way for me to do this (that I could find).

    Twitter does give you the option to tweet the Title of the page, so I decided to leverage this and just tweet the Title of the page. But that didn't solve my problem right away, as the Title of the page at this point was static.

    I decided to have the entire page reload, instead of just the container containing the text. I then had to make sure that when the page reloads, the title of the page reflects the current text on the page.

    Here is the javascript to generate the random text that displays to the screen

        
    var favorites = ["phrase 1", "phrase 2", "phrase 3", "phrase 4", "phrase 5" ]; var pick_fav = favorites[Math.floor(Math.random() * favorites.length)]; var post_choice = pick_fav

    I needed to set the document.title to the variable post_choice which contained the text I wanted to be tweeted.

    Doing this was easy

        
    document.title = post_choice

    Now every time the page reloads, the title resets to whatever random phrase was chosen with my javascript script above, and when the tweet button is clicked the current title is reflected in the tweet body.

    Sidenote, as an SEO I would never deploy a strategy like this on a page that I was trying to optimize. The problem with this is when your page is indexed by Google there is no way to tell which title tag will end up getting indexed for your page since it keeps changing, which could cause your page not to rank. I would only use this on a page where driving organic traffic to it was not a priority.


    The Magic in the 90's
    2015-04-19

    LINK: Blue Chips: An oral history of Shaq, Penny, and the Orlando Magic’s lost NBA dynasty.

    The Magic were one of my favorite teams to watch growing up. Shaq and Penny were Magic and Kareem to me. It's unfortunate Penny's career was plagued by injuries though.

    This also reminds me just how athletic Shaq was in his first few seasons. For a guy his size, he had grace, power and athleticism.

    If you liked this, I suggest checking out The Oral History of the Charlotte Hornets


    PyCon 2015 Videos
    2015-04-19

    LINK: PyCon 2015 Videos

    I love that the videos from PyCon are posted so quickly after the event. While a lot of what the presenters are doing really pushes my skill level and knowlege base of programming, they are also extremely inspiring. I can't help but dive into projects I've been working on, or go back to a concept or less that flew over my head, after watching these videos.

    I hope to attend PyCon 2015 in one of my favorite cities, Portland, OR.


    Plotting Data with Python and matplotlib
    2015-03-17

    I've recently become fascinated by data visualization, and how large sets of data can be distilled down to an easily consumed visualization.

    Luckily data visualization appears to be a great fit for my other learning interest, Python. I'm slowly working my through the different aspects of the language, and as it is my first language, I still have a long way to go. I find writing about the things I'm learning and experimenting with helps me retain the knowledge as well as finding errors or places for improvement.

    So, I've been playing around with Matplotlib and wanted to figure out a way to easily plot some data from an external file.

    I decided to create some fictitious comic book sales numbers for the past 60 or so years and then try to plot them on a standard line graph.

    Here's how I worked throug the problem...

    Creating My Fake Data

    My first issue was creating some fake data that I could plot.

    As a sidenote, I'm currently looking for some actual data to try this on, but this was just a quick project that I wanted to get done in an evening.

    First, I needed  to create the file where I was going to be writing the years and sales data to. Then I needed to generate the years between 1945 and 2014. You could type these out by hand, but that would take forever. So I used range()to speed up that process.

    Finally I needed to generate some fake sales numbers, and combine the years with their fake sales data. I did this using random.randrange().

        
    import random comicYears = open("comicsSold.txt", "a") years = range(1945, 2015) for year in years: sold = random.randrange(5000, 150000000) sold = str(sold) comicYears.write(str(year) + ',' + sold + '\n')

    Here I am using a for loop that creates a fake sales number for for each year, converts them to a string and concatanates the year and the fake sales data, seperated by a comma.

    Here's what the code looks like put together

        
    import random comicYears = open("comicsSold.txt", "a") years = range(1945, 2015) for year in years: sold = random.randrange(5000, 150000000) sold = str(sold) comicYears.write(str(year) + ',' + sold + '\n')

    Here's a gist of this code for easier readability

    link

    The output looks like this

        
    1945,114950089 1946,5327739 1947,92066212 1948,8359428 1949,104528851 1950,87344945 1951,111024866 1952,85318191 1953,146137175 1954,97641070 1955,144609067 1956,142349233 1957,64969373

    Now I've got my fake data that I will be plotting with matplotlib.

    Now it's time to start graphing!

    I'm going to use the popular Python library, matplotlib to do the heavy lifting of my graphing.

    Lets start by importing the matplotlib library so we can have access to it's modules. The plt.ion() will make our graph interactive.

        
    import matplotlib.pyplot as plt plt.ion() file_open = open('comicsSold.txt', 'r') file_read = file_open.read() years = [] sold = [] file_split = file_read.splitlines()

    So, now I've got a series of strings with a year and a sales number separated by a comma. Next, I'll need to add all my years to a list and all my sales figures to a sales list so that I can use them to plot.

        
    for line in file_split: year = line.split(',')[0] num = line.split(',')[1] years.append(year) sold.append(num)

    Next I want to set up the correct x axis that will display the range of years I'm working with. To do this I need to access the first year and last year in my list.

        
    first_year = years[0] last_year = years[-1]

    This last bit of code below sets my x axis to the range of the year I'm plotting. The reason I had to use +1 is because the range() function is exclusive so if I didn't include +1 then the last year in my year list would not get included.

    The problem with this is (besides my graph being inaccurate) you can only plot when you have the same number of x axis elements and y axis elements, or you'll get an error.+1 will make range() inclusive and get me that last year, 2014, making my 2 axis's equal.

        
    x = range(int(first_year), int(last_year)+1) plt.xlabel('Years') plt.ylabel('# of Comics Sold') plt.title('Comic Book Sales Data') plt.grid(True) plt.plot(x, sold) plt.show()

    Here is code all together

        

        import matplotlib.pyplot as plt
        plt.ion()
    
        file_open = open('comicsSold.txt', 'r')
        file_read = file_open.read()
    
        years = []
        sold = []
    
        file_split = file_read.splitlines()
    
        for line in file_split:
            year = line.split(',')[0]
            num = line.split(',')[1]
            years.append(year)
            sold.append(num)
    
        first_year = years[0]
        last_year = years[-1]
    
        x = range(int(first_year), int(last_year)+1)
    
        plt.xlabel('Years')
        plt.ylabel('# of Comics Sold')
        plt.title('Comic Book Sales Data')
        plt.grid(True)
    
        plt.plot(x, sold)
        plt.show()
    

    And here's the result

    Here's a gist of this script

    link

    I'm sure this code could be refactored down quite a bit, but this was a quick and dirty attempt at getting something plotted.


    Building My First iOS App
    2014-01-09

    What I Learned Building My First iOS App

    I recently released my first iOS app, called Write365. It’s an app to help writers get out of a rut or break writers block. It’s based on an ebook my girlfriend wrote and had some success with, so we figured it would be neat to have an app counterpart.

    I learned so much while building Write365. Considering I hadn’t ever written a line of objective C , or worked in Xcode, the entire process was an education. I can’t take all the credit though. The courses on iOS development at Treehouse were essential in getting me started. I also learned a lot from the Big Nerd Ranch book on Objective C. I also learned a lot from watching videos on Youtube and Vimeo. I’m extremely grateful that I live in a time where I can learn about things like computer programming even though I was told that “computer programming” is only for people who are “math people” while in school.

    Besides all the technical and business insights I learned during this process (submitting an app to the App Store was a whole learning experience on it’s own), I did learn a few general things about building a small product, finish it and get it out the door and in users hands.

    MAP OUT HOW YOU THINK YOUR APP SHOULD OR WILL WORK

    I have always found that when I can’t work out a difficult problem, or I need to approach a large project, mapping out my thoughts on paper seems to help to clear my head and give me some direction. When I was first conceptulaizing Write365 it was pretty daunting and at points I was getting discouraged. I eventually took to a small white board to write out how the logic of the app would work.

    What is the point of the app? How do I think it’s going to work? What features should be included?

    When I’m using a white board or paper I don’t really restrict what I’m writing, I just get it all out and then start to eliminate things. I write everything I think I will need to do, or use, eventually crossing stuff out as I figure out what I really need. This can be exceptionally useful if you’ve got a project with a lot of moving pieces that can be hard to keep track of.

    CONSULT A PROFESSIONAL WHEN YOU’RE OUT OF YOUR LEAGUE

    If this the processing of building an iOS app made me realize anything, it’s that I am not good at a lot of stuff and I sometimes need help. Saying my code is duct taped together isn’t too far off base and I wouldn’t wish it upon my worst enemies to have to look at my intial concepts for the app icon. With that said, I am not too proud to ask for help, nor am I above paying for the help I need. Between the super helpful folks in different development communities and the awesome designer I worked with, I was able to fill in the gaps where my own skills lapsed.

    Sometimes I wonder how many people could accomplish amazing things if they would just ask for help. I’ve never been above asking for help but I do have a couple of rules when asking for help though.

    Try to solve the problem yourself first. When asking for help, come prepared. If you’re asking a question about how to solve a programming question try to come to the table with what you’ve already tried and why you thought it would work and why you think it didn’t.This context could help whoever is helping you figure out a soultion quicker. It also demonstrates you’ve made an effort at fixing your own problems Say thank you. Say thank you to someone even if they couldn’t solve your problem. It’s better to say thank you to too many people rather than leaving one person hanging.

    THE PRODUCT IS MORE IMPORTANT THAN HOW IT’S BUILT

    Before I started building Write365 I was concerned that people wouldn’t like it because the code behind it was too simple. Being new to writing code, I am prone to being insecure about my abilities, so that was definitley in the back of my mind. But once I started to actually write the code, see the app in action and show it to a few people, those fears started to melt away.

    No one outside of another developer cares how my product was built. No one cares what framework I used, or how I built a custom library to do X and Y. I was excited to talk to people about how I did this or did that but their eyes would just glaze over. All they cared about was the end product. So I learned to focus all that energy I had been dedicating to being concerned about my dev rep to making the product more appealing to actual users.

    DON’T BE AFRAID TO LEAVE FEATURES ON THE TABLE

    Feature bloat or feature creep can cause projects to get drawn out, or cancelled all together. Don’t let a feature that isn’t core to the product hold up it’s release. The great thing about software is that you can always add things to it later.

    Forcing myself to leave features out of the app wasn’t neccessarily a big problem for me here. My lack of experience and technical skill kind of impeded my ability to build feature after feature, even if I wanted to. Since I would have to basically teach myself how to do everything on the fly, I really had to pick and choose which features to implement. Every feature needed to strike a balance between offering value to the app experience and the time/effort I would have to dedicate to getting the feature working.

    I did end up adding one feature that I hadn’t planned on including when I first started building the app. The email feature was tacked on at the end as a comprimise between a desire to include a full blown text editor and some social sharing features. I went with the email feature because it was quicker to deploy and provided a similar feature set as the some of my other potential features.

    I obviously learned so much more than I could express here, but those were some of the bigger, more general takeaways. Coming out of this experience I really enjoyed working on the iOS platform and plan to do a lot more of it in the future. I’ve also gained an all new level of respect for great iOS developers. I never really thought about some of the apps I was using before trying to build my own. I just assumed they “worked”, never really considering the immense time, skill, money and creativity that went into creating a great app.


    Keyword Permutator in Python
    2013-04-09

    I use a pretty great permutator tool at work that lets you enter endless numbers of keywords and making permutations of those keywords, but I didn’t have something at home I could use on OSX. That’s why I decided to put my limited Python skills to work to create this simple keyword permutator.

    It’s extremely basic but does the trick in a pinch. It works like this, grab the scrip from Github here, then run the script from the command line like:

    You need to have Python already installed on your computer for this to work.

    Open the Terminal Tool and CD into the directory where you downloaded the KeywordShakeup.py file.

        
    import sys def permutations(): list_1 = [i for i in sys.argv[1:]] list_2 = [i for i in sys.argv[1:]] for i in list_1: for x in list_2: if x != i: print i + " " + x

    Next it asks you to fill in your first keyword

    Name your keyword list -

    Currently you can enter up to 2 lists and 3 keywords each. Once you fill in all 6 keywords it will create a .txt with all the permutations of those 6 keywords named whatever you set it to name it a few steps back.

    enter your first keyword -

    As you can see it’s extremely limited, and there are probably better options out there but this was more of an exercise to help me with my Python by creating something useful for myself.

    In the future I’d like make the following up grades:

    -Ability to add endless amounts of keywords without having to edit the source -Have unbalanced numbers of keywords in each list, so maybe 5 in list 1 and 6 in list 2 -Ability to have more lists of keywords -Not have to edit the source code anytime I need additional keywords or lists

    It’s available on Github right now, so feel free to grab it and use it here. If you’re inclined please make it better!


    User Name Generator in Python
    2013-03-22

    I am constantly finding myself needing to generate usernames for random accounts I signup for. I used to use the same username for everything, but I've tried to stop doing that since a lot of these accounts are just to try something or to get a freebie, so I don't want a giant paper trail of every account I've signed up for following around usernames I use for more important sites.

    I used to use a few different websites to generate a user name, and those worked well, but they weren't quick enough for me. They usually forced me to choose from a number of categories like animals, cars or sports and it would create a unique name based off of my choices. That works well if I wanted a real looking user name, or something I planned on associating my online-self with, but most of the time I just want something quick that fits the necessary requirements set by the website for me to create a user name. These requirements usually include some or all of the following:

    • between 6 and 9 characters

    • contains at least 1 number and 1 character
    These seem like easy requirements, but when I'm asked to come up with a username I usually get frazzled and can't think of anything to put, so I decided to put together this little user name generator script to help me with this problem.

    This python script does one thing, provides you with a random username with at least 5 characters (one capitalized) selecting from A-Z and 4 numbers (0-9). Now, when I need a quick user name I run this script from the terminal and copy and paste the user name into whatever profile I am filling out.

    Here's how it works:

    First you need to import the neccessary libraries

    import string import random

    Next we set the number of characters (A-Z) we want to include in our user name. We're setting this user name to have 5 characters.

    First we're going to set the first letter of our user name name to be a capital. To do this first we need to set the number of characters we want to be capitalized. In my case I only want the 1 character to be a capital so I'll set it to you 1.

        
    upper_case = 1

    You can set this number to anything you want or name the variable you store it in whatever you want, but whatever number you set it to will generate a user name with that many capital letters.

    Next we need to set a variable that will contain all the possible capital letters that our script will randomly choose from (A-Z).

        
    name_upper_chars = string.ascii_uppercase

    Then we need to tell python to randomly select one upper case character from the possible choices (A-Z). We're using the random.choice method to randomly select 1 character from the variable name_upper_chars which holds all our available characters. Essentially we're selecting 1 character randomly from A-Z and storing it in a new variable.

        
    upper_name = ''.join(random.choice(name_upper_chars) for y in range(upper_case ))

    Next, we're basically doing the same thing as before but for lowercase characters.

    First we set the number of characters we want to get randomly generated

        
    name_size = 4

    Next we set a variable that will contain all the ascii lower case letters avaliable to use

        
    name_chars = string.ascii_lowercase

    Next we'll create the lowercase string part of our user name and store it in a variable to use later

        
    name = ''.join(random.choice(name_chars) for x in range(name_size))

    Next, we do the same thing as we did with the our uppercase and lowercase characters, but for the numbers that we want in our user name.

    Set the number of numbers we want to be randomly generated and store that in a variable. Then we store all the possible choices we have (0-9) in another variable. Finally, use the random.choice method on the variable digits_chars to randomly select a number from our variable holding all our possible choices.

        
    digits_size = 4 digits_chars = string.digits digits = ''.join(random.choice(digits_chars) for z in range(digits_size))
    This will give us a string of 4 random numbers, from 0-9. Finally we combine our letters and numbers and print them to the screen
        
    print uper_name + name + digits
    It's pretty easy and simple. You can find it on Github if you wanted to grab it here Initially, when I first started working on this script I was trying to use separate functions that would create the random string of letters and numbers, combine and print them. The problem with this ended up being that the variables I was creating within each individual function yielded variables I couldn't use in other functions. I think global variables would have solved this, but from what I understand, you can't create global variables within a function, they need to be declared outside of any function to be used globally. I then thought a class with my functions nested within it would work. This way I could use my variables freely, but I couldn't get this method to work either (I'm still working on it though). Finally, I realized it didn't need to be this complicated and I could simply create my random strings individually, store them as variables and then combine and print them.


    __________
    2012-03-17