Archive

Author Archive

Geek Cuisine — Eat your vegetables.

September 26th, 2013 No comments

20130926-170612.jpg

If my mamma could see me now….

Mom left us for a better place back in 1997. Here we are 16 years later and oh would she be so proud of me.

You see, I’m what’s known as a picky eater. Now looking me, you wouldn’t think food would be a problem, but the simple truth is I have a very limited pallet of things I will eat.

Early in my childhood, I would eat plain macaroni, no cheese please… just butter and milk. Even as a baby she would try and mix mashed potatoes in and I would just spit them back out (or so I’m told). Green beans? Onions? Blech. Spinach? Kale? Nope! Potatoes were only edible if they were “chipped” as in Ruffles and rice was only acceptable if it was Krispied, in particular if krispied into Square sugary treats.

It wasn’t until college where french fries became palatable. No form of tomato was allowed in my body until I discovered pizza and Gold Star chili while at college. Eventually I grew to be able to take on Spaghetti and meat sauce.

I married a fairly picky eater too with a pretty similar pallet, but she is still considerably less picky than I am. To prove this is genetic, both boys are even more picky than we are. Or perhaps it was us not making them eat things they didn’t like since we didn’t like people making us eat things…. Naw we will go with genetics.

Well fast forward to modern day. Somewhere in my old age, I’ve decided that it’s okay to try new things. Eventually the potatoes expanded to baked (still has to be covered in cheese, butter and most importantly bacon) and even to the **gasp** mashed variety. I’m pretty sure Mom never got to see that.

Only recently rice has come into my diet. Generally speaking Chinese food has always been a no-go. But with my wife slowly leading me to Mongolian beef and eventually trying General Tso’s chicken, it’s safe to say that today, it may be my new **crack** food. How did I go 50+ years without enjoying that stuff?

Somewhere over the past decade, even spinach has made it into my diet. Cooked? Oh hellz no. I still can’t stand cooked veggies (though I have been trying some lately. The texture still bugs me to no end, but I’m trying), but uncooked spinach leaves in those mixed green’s of a salad ain’t bad. I still don’t get my Popeye muscles on, but . . .

Then there is my new fascination… Broccoli. I started forcing myself to eat one small cluster a few months ago. Now I try to keep some on my desk to munch on throughout the day. I’m actually starting to like it.

Am I turning into a veg? No way. Carnivores rule! But that other stuff isn’t as bad as I’ve spent five decades thinking. So where does this pickiness spawn from? There are several factors:

1. Flavor

Flavor is a big cause. There are simply things that don’t taste good. Garlic is a good example for me. I’ve tried it. I’ve eaten a lot of foods with it, but at the end of the day, I don’t like it. I can put up with some, but too much… blech. Though with things like the spinach and brocoli, the more I eat it, the more the taste changes from uck to tolerable. It just takes time and time isn’t something I want to invest into food.

2. Texture

This is probably the most legitimate excuse that a picky eater has. There is no rhyme or reason behind it. Different pickiness will vary. A texture I might like, you might hate. For me, I don’t like slimy. That means, no dressings on my salad. I don’t like many sauces (ergo the avoidance of Chinese foods). I don’t like wet bread, so no condiments on my sandwiches. I’ve only recently begun to tolerate butter on bread.

3. Fear

At the end of the day, this is very likely the reason people are picky. Many people fear the unknown and new foods represent an unknown. I don’t know how it’s going to taste. I don’t know how those “red and green floaties” are going to affect the texture of that nice cheese sauce… (Wait, you said you don’t like sauces… I said I don’t like many! not all) Now I’ve learned of late the floaties really have little impact on either. The taste of those peppers is already in the cheese sauce and you generally don’t notice the texture against the crunchy nacho chip.

But at the end of the day, you do try new things and you find that the flavor and or texture are not to your liking. You should shouldn’t give up. It may take multiple times to work past these issues and give your brain a chance to adapt to the new things. That lesson was what my mom tried to teach me (as well as my father, sisters, family and friends) over the years. It’s taken over 50 years to get that lesson.

Moving forward, I’m probably still going to be a picky eater. No I don’t need to kill my salad with some slimy ranch dressing. Ketchup and mustard are not going to get on my hamburger’s ever. But you know, I probably should give green beans a chance (though it’s against my cooked vegetable rules).

Categories: Geek Cuisine Tags:

Math Meme’s

August 22nd, 2013 No comments

Occasionally you will see simple math problems posted on Facebook or other social networks with problems that look easy to solve, but test your understanding of algebraic operators.  One such post is:

3 + 3 x 3 – 3 + 3 =

This was asked today and there were several results that came back.   The answer is of course 12.  How so?  Well if we use algebraic operators, the multiply comes first.  It helps to use parenthesis to show the proper groupings….

3 + (3 x 3) – 3 + 3   =   3 + 9 – 3 + 3   =   12. 

We can quickly see the -3 and the +3 cancel each other out so you really end up with 3 + 9 or 12.  Well how did people come up with other values like 6, 15 and 18?  Again, it has to do with groupings.  Since there were no parenthesis in the original problem,  multiply and divide operations come first, left to right, then the add and subtract operations happen second.  Let’s get to the other numbers, which would be right if parenthesis were involved.

3 + (3 x 3) – (3 + 3) = 3 + 9 – 6 = 6

(3 + 3) x 3 – 3 + 3 = 6 x 3 – 3 + 3 = 18

3 + 3 x (3 – 3 )+ 3 = 3 + 3 x 0 + 3  = 6

With the parenthesis, these would be the right answers.  Honestly I couldn’t come up with a quick path to 15.   But since the original equation did not use these grouping methods, only the first option is mathematically correct.

 

Categories: Think Geek Tags:

Star Trek into Darkness… A review **SPOILERS**

June 3rd, 2013 No comments

I love Star Trek. I’ve seen just about every episode of every series and all of the movies. So with some delight, I finally got out to see the latest installment of the J. J. Abrams reboot. Trek fans like me had to make a leap of faith with the first installment in this franchise and when standing on it’s own, the 2009 “Star Trek” ended up being a solid movie.j

The casting was fantastic. The plot so-so. The whole series of movies has suffered from a villian of epic proportions problem and this sequel was no different. You should consider thee rest of this post filled with spoilers….

Spoilers

Rumors swirled before hand this was a remake of the Kahn story. I had hoped that it would just be eugenics, but a different storyline. But alas. It is Kahn. Okay, I’m cool with that. The story is different enough to stand on it’s own. But then we got to the end and all of the dialog starts mirroring “the Wrath of Kahn” but with the Kirk and Spock characters roles reversed. I sat there saying “Really???”

A surge of disappointment started to overwhelm an otherwise good movie. But I remembered this is an alternate timeline and if I let it stand on it’s own, I would probably like it more. I think I need to see it again trying to erase my old bias and try to appreciate it more.

If you haven’t seen it yet, go into it with an open mind.

One last comment… Carole Marcus for the win!

On being Omniscient

May 28th, 2013 1 comment

Being called a “Know-it-all” had a very negative connotation growing up.  Being the smarty pants comes off as elitist, egotistical and, well snooty.  No one likes to be made “a fool of” in front of their peers when their knowledge is called into question.  I some times wonder if that’s part of this country’s anti-science establishment?

Make no bones about it, I’m on a quest to become a Super Genius.  Battling age make this a tough quest.  Every day I grow wiser, but learning new things is getting harder.  But I must push on. 

At the same time, I am Omniscient.  I know everything.  “Bulls&*#” you say.  Here is my proof:

I know everything that I know.  Therefore I know everything that belongs to my universe.   Every day, new things enter my universe and when they do, I now know them.

Therefore, I know every thing.  I am Omniscient.

My universe, like the cosmic physical universe is ever expanding, growing larger each hour of each day.  Join me on my quest to enjoy a richer universe.

Being a know-it-all is really a good thing.

Categories: Uncategorized Tags:

Cold fire hydrant and other winter adventures.

February 28th, 2013 No comments

When I started this blog four years ago, my very first post The Long and Winding Road was the story of the journey of an Earthworm I encountered on my daily lunch time walks.

Those walks have gone by the wayside as my lunch is spent, fingers typing away, learning more about the world around me and trying to make the world a better place by my minor contributions (on the grand scale of life) to it.  This winter has been particularly cruel to me.  I’ve yet to have a photo shoot.  I spend my weekends on the computer, not hiking through the woods.  Earlier this week I decided to resume these walks.  It’s winter and today represented the first of those walks. 

One commentator on my early blog posts from my walks complained that there were no photos so today I now, 4 years later provide some photos from the walk, including a new encounter with the Earthworm. 

Earthworm struggles

Cold fire hydrant

20130228-132403.jpg

Inside a Crepe Myrtle

20130228-132302.jpg

Categories: Think Geek Tags: , , , ,

Balance

January 26th, 2013 No comments
Balance Scales

bal·ance /ˈbaləns/

Noun: An even distribution of weight enabling someone or something to remain upright and steady.

Verb: Keep or put (something) in a steady position so that it does not fall: “a mug that she balanced on her knee”.

When my brain got going this morning, it was churning on this week’s American politics: The President’s inauguration speech on Monday and the various 180° points of view emanating from the talking heads on the other side. What the American people want is something in between. We need balance.

Naturally I started thinking about issues like how too much government is bad but too little government is bad too. The ultimate in liberty and freedom is called anarchy. We have to have balance. My mind started coming up with analogies which are common place to help illustrate a point. But I decided that this blog was probably not the best outlet for doing a political post. After all, this is a Geek blog and we need to focus on all things geek and well discussing balance is something that can benefit everyone.

There is an old saying that too much of anything is bad. Candy is awesome. Too much candy and your teeth fall out (and a host of other problems) but living life in fear of the ills that candy can do to you would mean not being able to enjoy the pure joy that chocolate brings to your senses. Should I have a Snickers &tm; or M&M’s &tm; today?

Balance is important in all aspects of our life. Too much government? Police State; too little: Anarchy — Mad Max anyone? Too much sun? Sun burns; too little: depression, chronic fatigue, diabetes, heart disease, stroke and osteoporosis. Too much work: stress, burnout; not enough: boredom, laziness, poorness.

Every where you turn too, on need to strive to balance out both sides of the equation. We can look to mathematics to help with the answer. To reach a state of equality, both sides of the equation have to balance out and well… be equal.

In Chinese philosophy there is the concept of “Yin and Yang” where life is filled with dualities: light and dark, wet and dry, hot and cold and so on. They represent opposing forces yet while seemingly contrary, they are very interrelated, interconnected and very dependent on each other.

It is your responsibility to work to maintain the balance in your life. Once you grow up, it’s not your parents job any more. You have to take responsibility to bring yourself back to center in every aspect of your life.

Balance.

Who won the election? Math did.

November 7th, 2012 No comments

It’s a Wednesday morning and I’m driving to work.  It’s no normal Wednesday, but the Wednesday after the 2012 Presidential Election.  It’s not my normal route, but my normal Wednesday route since I have to swap vehicles with my wife.  In front of me I see a car with a bumper sticker that reads, “I don’t believe the Liberal Media”.

It got me thinking…  and we all know how dangerous that can be.

Last night after President Obama was announced as having won, Facebook exploded with commentary.  In one status post discussion, all of the “President’s lies” was brought up, which of course I found humorous since the Romney/Ryan campaign set all kinds of records for lying. 

Politicians all lie in that they will distort facts to convince you to vote against the other guy.  It’s part of the game.  But in general, these distortions are somewhat based in fact.   As Obi-Wan Kenobi said in “Star Wars: The Empire Strikes Back”… Many of the truths we cling to depends on our point of view.  This “truth” is what allows politicians to get away with what they do.  But the Romney/Ryan ticket told flat out lies and when called out by the “Liberal Media’s **FACT CHECKERS**”, they doubled-down on the lie and turned it into a commercial.   There is “My point of view” and there is dishonesty. 

Many of the truths we cling to depends on our point of view – Obi-Wan Kinobi

Naturally I had to call out my friend and ask him “What lies?” And he brought back the mystery surrounding the Benghazi Embassy attack and for evidence he provided a URL to an article on The Daily Caller (http://dailycaller.com/2012/11/02/benghazi-cover-up-par-for-the-course-for-team-obama/).  I did not recognize the site.  It didn’t seem to me a major media outlet like NBC, CNN or the New York Times.  The site is owned by Tucker Carlson, one of the more Right Wing pundits who works for Fox News and one of the site’s main contributors is the infamous Ann Coulter who’s views are among the most extreme of the extreme right.   I torted back: “How about a source that’s not a right wing opinion blog?“ and of course my friend basically replied that when he found one “worth” reading he would reply. 

Is there really a “Liberal Media” or is it people don’t like what they hear and shun it?  I work in mass media and have for years and I can tell you those who report the news do their very best to be accurate and sometimes the facts can be “An Inconvenient Truth” as I steal the title from Al Gore’s movie on climate change.  That movie could not have been titled better.  It’s a truth that many people don’t want to here.  It’s easier to say “It’s just the spin” from “the other side” than to re-evaluate what you understand and believe and to accept that you are wrong.

This extends beyond media coverage that is “inconvenient” to your way of thinking. It impacts Science.  It’s easy to want to ignore science when it tells us that things are wrong.  A good example of this is how the North Carolina General Assembly (NCGA) reacted to a scientific report on how fast the ocean levels are rising.  North Carolina depends a lot on tourist economy from its coastal beaches, which are under a direct threat from sea level increases.  What did they do?  Instead of reacting to the science by enacting laws to protect coastal communities with more regulations and building codes, they tried to enacte a law telling scientists how they had to provide the data in a way that the data was modified to fit the needs as if these scientists were out to get the tourism business.  A variant of the bill passed.

Look at many of the “Red States” that are trying to discount evolution and science in favor of a more religious view at how we were created (and this is a blog post for another day, but the Bible never said **HOW** God created man. Science never tries to answer the **WHO** created man question. Can’t we get along already?) 

When we can’t understand something because science is hard or when that science tells us something that we don’t like, it’s easier to shoot the messenger than accept the message and say that the messenger is doing it for some political gain.  However, and this is the key understanding that you need to know about scientists… They are motivated to get it **right**.  Nothing is worse for a scientist to try and prove something only to be proven wrong.  Their motivation is different than most people.   They strive for accuracy and the science community is based on findings being analyzed by peers and that analysis being analyzed by other peers. 

Not everyone is motivated by money or power.  Many, including scientists and journalists, are motivated by the truth.  Lets look at a prime example in this election:  A young number crunching geek named Nate Silver.  He writes a blog for the New York Times (strike one, he works for the Liberal Media!) and he’s into numbers in a big way.  During this election cycle, his numbers provided a very inconvenient truth to the Romney/Ryan campaign in that they were going to loose (and badly in the Electoral College).   The Right Wing tried hard to dismiss his research and number crunching.  But as Bill Clinton simply spelled out in his convention speech.  “It’s Arithmetic”. 

The religious among you won’t want to hear this because God is infallible, but guess what?  Math is infallible.   Math is absolute.  It is accurate.  Of course with some areas of mathematics, in particular Probability and Statistics, there are unknowns involved and people can skew numbers to make the “numbers” say what they want.  But when you run into a person like Nate Silver, who has only one agenda… which is “To be right”, you have to look at his numbers and respect them.  His numbers were not going to elect President Obama.  If anything, they were likely to hurt the President by giving his voters the idea that he’s going to win and they don’t need to vote.

Nate Silver won this election.  Not for a Right Wing or a Left Wing.  Not for conservatives or for some socialist liberal agenda, but he won being “Right”.  He won for the data.  He won for Science … and for the Liberal Media. 

“Huh?  How’s that?” You ask?

Because Nate Silver is about the truth, however inconvenient that may be.  Science is about the truth too and so is mass media.  CNN wanted their election coverage to be accurate (though to be honest, I don’t want to see the Florida county map again for a long time… Thanks John King!).  Reporters want their facts to be accurate.  They want let you know the truth.

And truth isn’t a liberal concept… It’s a human concept.   You may not like it, but you can’t change it.

Who won this election?  The geeks did!  Math did!

 

My iPhone 5 . . . Its Here!!! Its Here!!!

September 21st, 2012 No comments

There will be plenty of sites doing the whole unboxing thing, so I’m not going to waste your time (or mine, I want to get to the phone too bad to take photos…… 

UPS arrived punctuational on time this morning around 9:12 or so, well before their 10:30 deadline.  I heard the truck pull up so I rushed to the door like a kid at Christmas and greeted the driver before he could push the doorbell.

He asked “How are you doing today?” but before I could answer, he added “I guess you excited now” as if he knew what it was he held in his hands.  As I scribbled my signature on his pad, he continued.. “Yea, we have a lot of these to deliver today.” 

The small brown corrugated paper box was covered with a UPS label on the top and a fairly plain white label on the bottom.  A single strap of 1.5″ packing tape held the opening side of the cardboard box closed.  Walking back into the family room, the first sharp thing I found was a pair of scissors in my wife’s couponing area.  How dare I use her scissors for my tech lust.  It felt so good slitting the tape and peeling back the box to reveal a quaint black box inside.

I looked around, very well done shrink wrap.  I pressed my (lack of) thumbnail into it to open it.  No Joy.  Seems my nail-biting habit is really a problem after all.  Try two, try three.   Damn.  So I got up and got a steak knife and carefully pierced the plastic wrap enough that I could tear the rest of the wrap off.  I don’t want to damage the packaging.

The phone itself is light and feels really good in my hands.  I peeled off the clear protective covers from the front and back, and when I flipped it over to see how ugly the two-tone back is, I was pleasantly surprised.  It looks pretty sharp.  The photos online look ugly, but the device itself looks pretty darn awesome.

Unpacking continued by removing the new ear pods from their hard plastic case, the new lighting-USB cable and the charging block, carefully putting their plastic protection back into the box.  I looked through the paperwork and found two Fan-Boy stickers in the paper work.  Woot!  Thumbed through the small manual, which was all about how to use it, which I promptly put back.  No instructions on setup.  How bad can it be?

My iPhone 4 had just finished syncing with iTunes to make it’s final backup.  I powered up the iPhone 5.  It had about 80% charge.  I plugged the USB connector into my Mac Book Pro, and slipped the lighting connector into the phone.  What a joy.  Nice fit, no worry about the connector becoming partially unplugged letting me brick it (which happened to my iPad yesterday installing iOS 6…..  It’s back but I lost all passwords, etc. and had to redo all my app pages)..  Yea it sucks for all those 30pin connectors you have but believe me in the end, you are going to be much happier with the new connector!

Painlessly, after setting up a wi-fi connection, getting it through the registration process was pretty easy.  And so the sync and restore process began.  Nice and painless. 

Did I say this thing is light and feels good in your hands?

Once the sync was finished, a quick run of Speed Test on my 3 bars of LTE gave me a 66ms ping time, 10.39mb down and 3.2mb up speeds.  That’s about what I get with my AT&T Uverse service (well I only get 1.5 up with it).  So for 3 bars, that’s pretty good.

Of course while I was syncing, I had to try out the ear pods.  I was never a fan of the ear buds that shipped with previous iDevices.  I found them uncomfortable and after a while my ears would hurt because they were just a bit large for my ears.   The first thing I noticed was how comfortable they are.  Instead of being round the are more oval and fit in my ears better.  I hardly notice them.

People have worried about the sound quality.  Sure, they are not some nice $500 Bose noise canceling headphones.  But the sound quality is “good enough”.  My volume on my Mac Book Pro is maybe at 5% and it’s sufficiently loud for my 51 year old ears.

“What about the cool iOS6 features?” “How is using it?”  It’s an iPhone.  It works just like my iPhone 4 did (and I’ve been running iOS 6 for some time since as a developer we get early access to it to test our apps on), so there is no “Newness” factor for me with regards to how to use the phone.

I’m looking forward to my upcoming trip, so I can give Passbook a go.  I should be able to use it for my United flights I have coming up.   Despite everyone’s dislike for the new maps, I find them quite good.  At least we have free turn-by-turn directions even though it may put you in the middle of a field from time to time (that’s okay Google maps puts you in the middle of fields too) and the vector based maps should draw faster than Google’s tile based maps when you’re in the middle of that field with practically no signal.

Coming from the iPhone 4 to the 5, Siri is something new to me, I’m just not sure how much I want to talk to my phone yet.  One of the coolest features of iOS6 is the change in the sharing menu.  Instead of rectangular buttons with text like “Email”, “Tweet”, etc.  You now have standard iOS looking icons to send pics to Facebook or Twitter. 

That’s it for now.  Hope you have an equally pleasant iPhone 5 day!

 

Categories: Tech Geek Tags:

Programming 101 Part 2 — Decision Making and Flow Control

June 20th, 2012 No comments

In Part 1 of this series about computer programming for beginners, we examined a simple program that added two numbers together and printed out the results, which isn’t all that useful. If we think back to the tire changing example, the steps we wrote are far from complete. We have to remove multiple lug nuts and it would be nice to use the same instructions for each lug nut. This is something referred to as a loop… executing the same code multiple times.

Normally loops should stop at some point, after all you run out of lug nuts. Loops that do not finish are called “Infinite Loops” and are generally considered bad for programming. Occasionally a programmer will want to have a loop that doesn’t terminate on purpose for programs that don’t end, though even though the loop itself doesn’t end, the program would repsond to some control that would force the program to exit properly.

Your programs will sometimes need to make decisions based on some conditions. You have to see if the tire is flat before changing it.

  • Is the front-driver side tire flat?
    • Yes: Change it!
    • No: Check the next tire

Lets start with decision making.

Decision Making

Remember that Algebra II class in high school you said you would never use? Well its time to use that class…

In Lua, there is really only one decision making statement, the “IF” statement. Other languages like C support other methods, like a “Switch” statement. Lua is a “Keep It Simple Silly” language, so we really only have the one decision maker.

To make use of the “IF” statement, you have to understand basic math and “Boolean” logic operators. These operators, when combined with variables or fixed values (called “Constants”) form a “Condition”. Condition’s are also used by some of the loop controls to determine when they are to exit.

Operators

The core mathematical operators that you need to know are:

  • == which means “is equal to”
  • < which means “less than”
  • > which menas “greater than”
  • <= which means “less than or equal to
  • >= which means “greater than or equal to
  • ~= which means “not equal too”

Here is an example:


a = 10
b = 20

if a == b then
print("a and b are equal")
end

In this test we check to see if variable “a” and variable “b” are equal. If they are, the we print a message. If they are not equal then we do nothing. What if you wanted a message saying they are not equal? The “IF” statement has an additional option called “ELSE”


a = 10
b = 20

if a == b then
print("a and b are equal")
else
print("a and be are not the same")
end

Or consider:

count = count - 1
if count < 0 then count = 0 end

The above example makes sure that count is never negative after the subtraction the line above. This is called range checking.

Using the above example, what if our code would also possibly add to count rather than in the example where we are doing a subtraction? We might want to make sure count never goes over a value of 10. We could write:


count = count + 1
if count < 0 then count = 0 end if count > 10 then
count = 10
end

Here we wrote the if statement twice. But we could do this more efficiently by writing a more complex condition. This is where the "Boolean" operators come into play. They are:

  • condition 1 AND condition 2
  • condition 1 OR condition 2

When the computer or device looks at the conditions like "count < 0", it evaluates to either "TRUE" or "FALSE". If count is less than 0, then that condition is TRUE. If it is not, it is FALSE. This is computers at their very basic, they only know 1 or 0, which is the same as TRUE or FALSE. We could rewrite our code like this:
count = count + 1
if count < 0 or count > 10 then
print("count is out of bounds")
else
print("count is in bounds")
end

This could have also been written:


count = count + 1
if count >= 0 and count <= 10 then print("count is in bounds") else print("count is out of bounds") end

For the AND operator, both conditions have to be TRUE before it will be treated as TRUE. In the case of the OR operator, if either condition is TRUE, then the whole statement is treated as TRUE.

There is also a NOT operator which will negate tests. In other words: NOT TRUE == FALSE and NOT FALSE == TRUE. As someone learning programming logical operators can be challenging.

Looping

Using an IF statement is a type of flow control known as "Branching". You test a condition and based on the result you go along one of two paths, like coming to a fork in the road. The condition is the "Decision Making" part of this: Do you go down the left fork or the right fork? Once you've decided and move on, you've now changed the flow of your program and different statements will execute.

Branching is only one type of flow control, the other is looping. Let's use an Indy Car race as an example. You're in Indianapolis on Memorial Day and you're racing in the Indy 500. It's a 500 mile race on a 2.5 mile track, so you are going to make 200 laps during the race.

As a driver you have to make many decisions during the race, but we are going to focus on two:

  1. Do I need to Pit Stop?
  2. Is the race over?

The first example, "Do I need to pit?" is a branching statement. If you do, you slow down, stop in your pit box, get new tires and some fuel and then resume the race, else you blast by the grandstand at 235mph. I know we covered that above, but good thinking. That is an IF statement.

But if you think about the race as a whole, its nothing but a series of 200 loops. Execute several left hand turns, passes, breaking etc. and come around to the start/finish line and ask? Have I run 200 laps yet? No, repeat the whole loop again, each time incrementing your lap counter. Pass the start/finish line again? Have I run 200 laps yet? No, keep going, yes head to victory lane if you're the winner (see an other Branch in the program, not the winner, go to the garage).

In programming languages we manage these loops with one of three main looping structures:

  • WHILE condition is true DO some block of code
  • REPEAT some block of code UNTIL condition is true
  • FOR some set number of iterations (laps!) DO some block of code

Using our race as an example of a WHILE loop (WHILE condition DO block END):

lapCounter = 0
while lapCounter < 200 do lapCounter = lapCounter + 1 end print("The race is over")

A while loop will execute over and over until it's condition becomes false, in this case, it will run 200 times. Since we are starting at 0, when we hit lap 199, we will have looped 200 times in actuality since lap 0 counts as a lap in this case. We come around and add one more to lapCounter and it becomes 200. The condition becomes true (200 is not less than 200) at which case the loop ends and we execute the next statement after the loop, in this case the print.

REPEAT block UNTIL condition is very similar to a while loop, but we test at the end of the loop rather than at the beginning:

lapCounter = 0
repeat
lapCounter = lapCounter + 1
until lapCounter = 200
print("The race is over")

You will notice the condition I tested for is different between the REPEAT and the WHILE loop. There are two very fundamental and important difference between the two loops.

First, A REPEAT loop is guaranteed to run at least once. With the WHILE loop example, if lapCounter had started at 300 then 300 is greater than 200 and the WHILE loop would never execute. With REPEAT we don't test until we've done the block's code (at the end of the loop instead of the beginning of the loop) and as such, lapCounter gets incremented before we test it, so instead of counting our loops 0 to 199 in the WHILE, we are going to end up counting 1 to 200 in the REPEAT example.

Secondly, a WHILE loop continues while the condition is TRUE. A REPEAT loop continues while the condition is FALSE.

What happens if the condition to exit the loop never happens? This is what is know as an "Infinite Loop". While there are some rare occurrences where it makes programming sense to have a loop that never ends (actually all loops end... the computer will eventually be shutdown..... and the operating system will exit the loop for you!), most of the time these never ending loops are a bug*.... a programmer's mistake.

The first computer bug...

was actually a physical bug. A moth got into the computer core and shorted out the vacuum tubes that ran the program and crashed the computer. The term "bug" stuck for any problem that affects the proper execution of a program...

And its a mistake you should avoid as it generally will lock up your application and you have to use the operating system to force kill your program.

FOR loops are the third type of looping and they may be the most useful since they count over a fixed number of iterations:


for lapCounter = 1, 200 do
-- do the stuff for each lap here
end
print("The race is over")

In this example, the loop itself manages the lap counting for us. We tell it a starting lap number and an ending lap number and it will execute that number of times, in this case, 200 times since we started at 1.

You will frequently (and I do mean very frequently) see that loop written like this:


for i = 1, 200 do
-- do the stuff for each lap here
end
print("The race is over")

Where did the "i" come from and what does it mean? Well "i" is shorthand for "index" which is basically a variable that keeps track of the number of times we have gone through the loop. In days of old, there was a popular language called BASIC (Beginners All-purpose Symbolic Instruction Code) which is very similar to Lua in many respects, but the rules for BASIC said all variable names were exactly one letter long. You only had 26 bins to store things in (A thru Z) and I became popular for the for loop index. And that has stuck with programming through out the years.

FOR loops may be the most popular looping structure because you generally know how many times you want to run. Need to create 10 blocks on the screen? A FOR loop is perfect for that:


for i = 1, 10 do
block = createBlock()
end

and volia! You have 10 blocks.

There is a second variant of the FOR loop that uses key-value pairs to iterate over a table of values, but it's difficult to talk about that until we have covered Arrays, Tables and Objects in Part III of this series.

Programming 101 Part 1 – What is programming?

June 5th, 2012 1 comment

What is a programmer?

The lure of creating a great mobile app or building your own website can captivate people to dig into the world of programming, only to be met with frustration because programming is different than most anything people have tried before.

Unlike your auto mechanic, who has something physical to work with like your engine, programming is more like art where the artist has a vision in their mind and with a stroke of a brush (well many strokes), bring that vision to life through a series of individual brush strokes, each one, while part of the whole, itself is an indistinguishable desecrate step to get there. Each stroke builds upon itself and the others to produce the final piece.

However programming takes that a step further. While the artist can see the brush strokes piling up on top of each other and see the vision start to form, programmers have to work with an abstract set of codes that themselves, resemble nothing in the final piece, but instruct the computer (or mobile device) do then draw the brush stroke. Imagine it like this…. The artist holds the brush, pallet of colors and has the canvas in front of them. You the programmer, without seeing the canvas at the moment instruct the artist to grab a dab of red paint, using a wide brush stroke, draw an arc from the lower left of the canvas, upward for 3 inches.

You repeat this process, with different instructions to the artist and then once you think you have enough on the canvas, you then take a peek. Return to where you can’t see the final product, instruct the artist on what need to be erased and done over. You repeat this process until the final pieces is done.

To make matters more challenging, that 3″ long red arc with a wide brush stroke is a pretty loose term that the artist would have to try and guess what you really meant. Which color red? There are hundreds of variations. How “wide” is “wide”? Is it 2 inches, 1 inch, 4 inches? You said 3 inches long, but you didn’t say anything about the curve of the arc. Is it balanced like say half a circle, or is it a curve that’s more pear shaped? Do the end points of the arc start as 2″ wide and stay 2″ wide for the stroke, or do you start with narrow points and build to a 2″ wide stroke at the apex of the arc?

Computers (and that iPhone in your pocket is a computer….) don’t guess. They can’t interpret your thoughts. To a computer, there is a huge difference between “Draw a Red 3″ long arc from the lower left upward” and “Draw an arc, starting at 3″ in from the left, 3″ up from the bottom to 6″ in from the left and 6″ up from the bottom, with an even curve, 2” wide from start to finish using a red that is slightly magenta.

To be a programmer you have to invision the instructions that will eventually lead to what is scene. It’s kind of a double-abstract way of thinking. You have to visualize the instructions for the single brush stroke in addition to how each of the single brush strokes will form the final piece. It’s not for everyone.

What is a program?

In it’s simplest form a program is an Algorithm or a set of rules that precisely defines a sequence of operations. So basically a program is a set of instructions to the computer in a sequence to get to a desired result.

Lets look at a common human task… changing a car tire. How would you tell someone how to change a tire?

  1. Get the Jack and tire iron out of the trunk
  2. Remove the lug-nuts
  3. Jack up the car
  4. Remove the tire
  5. Put the new tire on
  6. Put the lug-nuts back on
  7. Lower the jack
  8. Tighten the lug nuts
  9. Stow the jack and tire iron

That sounds like decent instructions. It’s step by step in an ordered sequence to perform a definite task.

However if you give that to a computer, you will likely have a mess on your hands and the computer will complain madly at you.

Where is the new tire? Where do I get it from? How do I get the jack out of the trunk? How do I jack up the car? How do I remove the lug nuts? What do I do with them? Is there a particular order I need to do them in? What do I do with the old tire?

In this example we could think of each step as a function. Each function has its own set of well ordered steps and instructions do to that finite, desecrate process.

Early in computer programming history you had to write the very finest of details. It would be hundreds of thousands of lines of instructions to cover the simple task of changing a tire.

Over time, we’ve learned to write reusable pieces of instructions and store them in a library so we don’t have to keep rewriting them. Think of “remove a single lug nut” as one of these functions that I can use 5 times to remove all 5 lug nuts. If the function is generic enough, I can give it information about which lug nut to remove and it’s size so we can use the right wrench.

Many of these libraries exist today depending on what you’re trying to do. Many computer languages have a library that provides a function that will draw an arc for you as long as you provide it a length, starting point and a radius and you don’t have the write the actually code to draw the arc.

For the remainder of this series, we will be using a programming language known as Lua which is used in games like World of Warcraft to allow people to taylor the game to their needs. It’s also used by a product known as Corona SDK from Ansca Mobile, which allows programmers to build mobile apps and games for both Apple iOS and Android with one set of code. Lua is also a fairly simple language to learn and it will make a good starting point for us.

Order Matters

Like the tire changing example above. We start with a series of instructions. These instructions are processed one at a time until they are done, in the specific order that they are listed. Thus, the first thing is to get the jack out of the trunk. Next you remove the lug nuts and so on.

If you get these out of order then the program won’t behave. For instance if you jack the car up before you at least loosen the lug nuts you risk having the car fall off the jack. The tire may spin on you making it very hard to remove the lug nuts. Or more clearly, you cannot put the new tire on before you take the old tire off.

Let’s look at something more “computer programming”.


a = 1
b = 5
sum = a + b
print(sum)

In this very simple program we define two variables, “a” and “b” and assign them values, 1 and 5 respectfully. Next we add the two numbers together and store the results in a 3rd variable we have named “sum”. Finally we use a function called print to show us the sum on our screen.

Variables, functions? Whaaa?

Remember those high school algebra classes you said you would never use? Well you are now using them.

Variables can be thought of as containers, like a bunch of Tupperware containers you may have in your cupboard. In programming languages, these containers can hold just one thing (okay, that’s a lie and we will get to that at a later point, but for now, think of it as one container can hold one thing….). That thing can be one of the following:

  • A Number… either an integer (whole number) or a floating point number (has decimal fractions, like 3.1425962)
  • A String… A collection of letters, numbers and symbols strung together, like this sentence. It could be a single letter, a single word, or a whole document. It could also be a text representation of a number. Strings are typically enclosed in quote marks like: “Barney came home to find Wilma at home”.
  • A Boolean… Okay, big word, but it just means the variable holds either True of False. Since computers really only know two things: 1 or 0, a Boolean is the smallest piece of data that represents either true or false. In most programming languages, ZERO (0) represents false, anything else represents true. In others, TRUE and FALSE are distinct names that you use.

Variables can also contain more complex types of data, such as functions, arrays and objects that we will cover in a future post.

In some languages, you have to specifically define what data type goes into a variable, in other languages, any variable can hold any type. Most modern languages, like Lua fall into the later category, were we don’t have to specify specifically what data type goes into its container.

Functions are pre-built sets of instructions that you can provide information to called “Parameters” that help the function work specifically for your needs. Functions are frequently written in a generic fashion so that many programmers can use it with their data and in different ways. You pass these parameters to the function, the function uses the data passed in these parameters to operate on.

In our sample above “print” is a function and we pass it our “sum” variable. That function has a bunch of instructions that knows how to output the variables passed to it to the console or your screen.

Depending on the function, it can possibly take multiple parameters. So we could have done:


print(a, " + ", b, " = ", sum)

to print the whole equation out. This should result in:


1 + 5 = 6

displayed on your console/screen. In this example we passed three variable, each containing a number and two strings, ” + ” and ” = ” to print the various parts.

The computer will start with the first instruction: Assign the number 1 to the variable “a” (put a 1 in the container). It then steps to the next instruction: put a 5 in “b”. Next it will add “a” and “b” together (1 + 5) and store the results in “sum”, finally it prints the results to the screen.

This is a very linear process. Each step, executed in order. When it gets to the last instruction the program is done.

Obviously if you want to write something that does more than add a couple of numbers together, we are going to have to have more control over how the program flows. In the next installment we will cover decision making and flow control.

Categories: Tech Geek Tags: , , ,

Why I hate my new (retina) iPad

April 18th, 2012 4 comments

white iPadI know that’s probably not what anyone would expect to hear about this incredibly amazing device. I mean the screen is freakin’ mind-blowing sharp.  The battery life is impressive.  It’s a great form factor to carry around and actually use.

That’s the problem.

You see, I’ve been in a two year, very hot relationship with my iPhone4.  Ever since the first iPhone came out in 2008, I have wanted to have one, but I couldn’t justify it.  My day job required me to use a crackberry, er. I mean Blackberry.  My youngest son jumped on board with the iPhone 3G and it made me lust for an iPhone even more.  My older son moved to a 3Gs and now of the three “boys” in the house, I was the last one to not have one.  Me, the major techno-geekdorknerd.  Me the person who lives and breaths the Internet with a major email addiction.

June 2010 roles around and Apple comes out with the retina iPhone4.  The youngest was ready for an upgrade and I would not be denied this time.  We both went and got our iPhone4’s the same day and my dreams were fulfilled.  

This device is simply amazing.  The screen is freakin’ mind-blowing sharp.  For as much as I use it, the battery life is impressive.  It’s a great form factor to use as a phone, carry in my pocket, and stay electronically connected.

I bank from it.  I PayPal, eBay and Craigslist from it.  I keep up to date on the weather and sports scores.  I find new music.  I play games.  I take photos with it.  I social network from it.  I travel alot and it’s my travel assistant and I even occasionally talk to someone on it.  I listen to music and watch an occasional YouTube video (I will neither confirm or deny allegations about viewing occasional adult oriented videos).  It’s my photo portfolio, its my model release and invoice maker.  About the only things I don’t do on it is program and post process images and photos.

I’ve babied this device.  I clean it.  I take care of it.  I nurture it.  I have never cared more for an electronic device.

Fast forward to Saturday April 14, 2012 at 4pmish.  That’s when a trip to the local AT&T store resulted in a little white new iPad with it’s 16GB of memory and it’s 4G capabilities came into my life.  This is my first iPad.

Did I say how impressive it is?

I spent the next several hours loading over all of my favorite apps from iTunes, buying a few that I needed like a good weather app (did you know the default Weather and Clock apps from the iPhone don’t appear to be present for the iPad?).  The first thing I had to try was Draw Something on the big screen.  My big fingers make drawing on the iPhone an interesting challenge.  What a different it makes.  

I eventually set up email on it (only getting 2 of the 5 accounts I’m loading on my iPhone) and what I found was that . . .

I’m not using my iPhone nearly as much.  I start it up to find dozens of emails sitting there waiting on me that I’ve already read on my iPad and archived in Thunderbird on my MacBook Pro.  Since I like to archive messages, I don’t use IMAP or any other “keep all my devices in sync” email process because I like to keep my phone (and now iPad) clean of mail and my MacBook to be my repository.  This is probably going to have to change because I cannot manage my email 3 times.

Besides play-testing my apps that I develop, I can honestly say I’ve been in Facebook once on my iPhone and I’ve used the flashlight app.  I feel like I’ve shunned a great trusty friend and lover over some other hot-sexy model with a gorgeous look and an alluring smile.  I’ve cheated on my best electronic friend.

Damn you iPad!

Now I have to figure out how to make this a working polygamous relationship (and keeping the now 4th wheel MacBook Pro happy.)

Using Corona SDK with REST API Services

April 15th, 2012 27 comments

People frequently ask on the Corona SDK forums about how to make their mobile apps connect with some Internet web service or if it’s even possible.  Corona SDK has various ways of interacting with Internet based services and depending on the service, you might want to use one over the other.

The three main ways that Corona SDK can communicate is broken down into three main categories:

  1. Socket communications.
  2. Synchronous Web Services.
  3. Asynchronous Web Services. 

Sockets are great for passing instantaneous data, like a multi-player game where what one player does on their device shows up almost immediately on their opponents computer.  Things like FTP and such would also tend to use sockets.  This is pretty low level programming and most people don’t want to get to that level.

This leaves us with Web based services.  In both cases, some webserver somewhere has a published API (Application Programming Interface) that defines how applications can interact with their services.    These API’s involve making a request to the server and then waiting for some response.

That waiting for a response can take time, so Corona SDK has two methods of waiting on the data:  Synchronous which means “Stop the app and wait until the data is done downloading” or Asynchronous which is “Hey, I need this data.. Let me know when it’s done and I’ll deal with it”.

In mobile apps, stopping and waiting on data, in particular if you’re downloading a large file like a photo, means your user can’t do anything else.  You generally don’t want to have your app “block” while waiting on data.  So we are going to focus on option 3 because it’s the simplest and easiest to work with.

Services will generally fall into three categories:  SOAP, REST and what I like to think:  Roll your own.  SOAP  or Simple Object Access Protocol is generally XML based and has overhead to start communications, maintain sessions and is generally not a simple approach despite the word “Simple” in it’s name.

REST or “Representational state transfer” on the other hand is generally easier to work with and can return data in the user’s choice of XML, JSON or other defined formats.

This tutorial is going to focus on a “Roll our own – based on REST” because, like SOAP, there is a lot to the server side of REST and frankly we don’t need that.  We just want to make a request and process the data and you don’t want to deal with the complexity of setting up a full REST service on your host. 

Before we get to the code here is what we are going to do.

On the server side, we are going to write a simple PHP based script to access a MySQL database to login a user to your server.  This script does nothing to create the user account nor are we going to go into setting up the database.

We are going to use HTTP GET requests to communicate with the server.  Sure in theory GET should be for getting things and POST for putting things, but in reality, GET is simpler and if your total data is less than 8Kbytes.

We are going to also use JSON to encode and decode our data so that it’s safe to transmit using HTTP requests.  This is  term called serialization.   We don’t need to know JSON.  We are going to let our PHP and Corona SDK libraries do the work for us.

So without further ado lets jump into some code.

SERVER SIDE

On the server side, we need some program that will process the HTTP GET request, contact a database, and then return some result to the application.  My language of choice is PHP for this and we are going to use a MySQL database.  This is probably the most common setup that almost every Web Hosting service offers to its customers.  You’re responsible for setting up your database, getting your database DSN (Data Set Name) or database name, the server name of the database (typically just the string “localhost”), and a Username/Password pair that lets your PHP script talk to your database.

You will need to setup a database with the following fields:

  • id — a integer (number) field, typically the Primary Index with an AUTOINCREMENT attribute.  Basically it’s a unique number for each user.
  • playername — you might want to call this username or userid.  Variable length character string probably 64 bytes long is good (VARCAR(64)).
  • password — another varchar string, 64 bytes long is sufficient.  We are going to use an MD5 hash process to one-way encrypt the passwords in the database, we won’t be using MySQL’s “Password” encryption.
  • Optional First and Last Names, again 64 byte varcar’s will be fine.
  • Last Login.  I’m old school unix guy, so I’m just going to make it an unsigned int and shove the unix time() number in the field.  MySQL offers a bunch of built in dates.  Don’t need them.

With that database setup and some accounts added, we are ready to go.  You probably should have some web page/form setup that lets users register for accounts and a PHP script that takes that form data and adds the users to the database, but that’s beyond the scope of this post.

Lets start by connecting to the database:


This script defines our database parameters for accessing the database. Then it checks to see if the special PHP Array (or Table in Lua terms) called $_GET exists. If this script was executed as an HTTP GET request will will exist and each table entry contains each parameter passed to it.

Let's look at what an HTTP GET request looks like. It's basically a URL with some parameters tacked on to the end, such as:

So we have our server name and URL to run login.php. Then there is a question mark, which start's a list of key-value pair parameters that will be passed. In this case we are passing a parameter named "playername" and it has a value of "my name". Then an ampersand (&) separates the next key-value pair, in this case a parameter named password with a value of letmein.

You might be asking what is that %20 in the playername value. Well its the encoding for a space character. Your parameters must be "URL Encoded" before you pass them to the server if they have spaces or ther special characters in them. In our example, instead of using the standard urlecode/urldecode method, we are going to use a technique called "base64 encoding" because it produces a web-safe string that also hides the data (so our passwords are not sent in the clear).

Depending on what variables you need to send to the server, these URL strings can get quite long and complex. We are just going to be sending two to the server. These variables will be magically decoded into a PHP Associative Array called $_GET for us.


if(isset($_GET)) {
$playername = base64_decode($_GET["playername"]);
$password = base64_decode($_GET["password"]);

We first check to make sure the table exists, then we create two PHP variables: playername and password from the $_GET table entries. Note that we are passing that data through PHP's built in base64_decode() functions to decrypt the data we will be sending.


$query = 'SELECT * FROM players WHERE playername="' . mysql_real_escape_string($playername) . '" or email="' . mysql_real_escape_string($loginid) . '"';
$dbresult = mysql_query($query, $link);
if (!$dbresult) {
//echo "query failed";
$result = array();
$result["result"] = 403;
$result["message"] = mysql_error();
echo json_encode($result);
mysql_free_result($dbresult);
exit;
}

This block of code will query the database for the player's record that matches that playername/password combination. Notice that we are calling a function "mysql_real_escape_string" on any string we send to the database. This is to protect against SQL Injection attacks where people send in SQL strings in an attempt to hack your database. Always escape any string sent to your database. User data cannot be trusted... Period...

If the query fails, we create a table called result, and add in some values to send back to your mobile app. The "echo json_encode()" will cause the table to be encoded into JSON magically for us and then the string is written out to the app.

This basic technique is how we are going to communicate with our app.

In the rest of the code, if the database query was successful, put the data from the query into a PHP table for us to use. Check to see if the password in the database matches ours (we are using md5() so we have to compare the database password with the results of md5(our password).

If that's all good, build up a table called $result. Put whatever variables you want in the table. Then echo json_encode($result) the table and now your app should have data to use. If the passwords don't match, send some result back to the app so it will know about the failure.

APP SIDE

We are going to use the Corona SDK network.request API call.

Using GET is pretty simple:


local mime = require("mime")
local json = require("json")

local playerName = "fflintstone"
local password = "I<3Wilma!" local URL = "http://yourserver.com/login.php?playername=" .. mime.b64(playerName) .. "&password=" .. mime.b64(password) network.request( URL, "GET", loginCallback )

At this point, we've required in two modules we need, mime and json. For our example I've hard coded the player name and password into Lua variables.

Construct the URL which is a simple URL GET string and then pass that to network.request.

Since we are doing this asynchronous, your app will continue on doing whatever it was doing. Mean while it will wait until the server responds. When it does a function that you write called "loginCallback" that will then handle the result.


local function loginCallback(event)
if ( event.isError ) then
print( "Network error!")
else
print ( "RESPONSE: " .. event.response )
local data = json.decode(event.response)
-- do with data what you want...
end
return true
end

At this point the Lua table "data" should contain entries for "result", "message", "playername", "firstname" and "lastname" that we had set in the PHP script.

You could simply check:


if data.result == "200" then
-- player logged in okay
print("Welcome back", data.firstname)
else
-- prompt them to login again
end

At this point you know you're logged in. It's up to you to decide what data you need to pass and how to use it within your app.

Most REST services work this way. You make requests... you get back JSON or XML data. You will need to make sense out of the API documents of the service that you are using. Some will be easier to digest than others. For instance, PARSE seems to be pretty straight forward. Amazon's SimpleDB made me ill trying to decode their API documents. But this is the basics. Have at it!

If you would like a complete Lua example, please check out the Corona Geek's implementation at: https://github.com/CoronaGeek/Corona-SDK-JSON-Example

Kindle Fire — A hands on review

March 31st, 2012 1 comment

I have been building mobile apps for over a year now and I’ve recently started building for Android as well as for Apple iOS. Android provides some interesting challenges since there are three major markets to sell your app: Google Play, Amazon.com and Barnes & Noble’s Nook Color/Tablet app store.

In addition to three markets with different rules, you have a host of devices you have to target. It makes programming for these devices an interesting exercise for sure.

Before any app developer releases apps or games to the wild they should test their apps on a device. No one could possibly own all the billion’s of different Android devices to test on. Given that the Android market’s are not known for generating a lot of sales income, most of have to be picky on which devices to get and test on.

For me, I was considering a refurbished Nook Color for $135. But this device has some hoops to jump through to get test apps on it. I considered some of the cheap 7″ Android tablets which can be found for under $80, but you never know if the processor is fast enough to provide a good test platform. Since I use Corona SDK, an armv7 processor is required. Used smartphones can either be too expensive or hard to find at a price cheap enough for a test device. Then there is the Kindle Fire, a $199 7″ tablet.

As one of the more expensive test platforms, I had really had a hard time pulling the trigger on this. I want to get an iPad and I felt that any 7″ tablet was going to reduce my need for the iPad. But when Amazon put refurbished Kindle Fire’s on sale this week for $139, it was time to hop on it. Priced at the same price point as the Nook refurbs and cheaper than I could get a used on on Craigslist, this seemed to be a no-brainer decision. I opted for 2 day delivery and was surprised when it arrived the next day. Excited to mess with it, I popped it open right away and dove in.

The box came with the Fire in a plastic sleeve and a power charger. No USB cable. No manuals. No fluff. I searched around to find the power button, which is located on the bottom of the device beside the USB charger point and the headphone jack. It powered up about the same speed it takes my iPhone 4 to power up and it was about 85% charged.

There are a billion reviews about this device on the Internet, so I’m going to try and say focused on using at a development platform for Corona SDK except for one thing.

I now understand why Apple says there will be no 7″ tablet. This is an awkward size. It’s just a little too big to hold like a phone in one hand, but its too small to be used 2 handed. Also when using it one handed, I tend to hit the power button too often. It’s a lot heaver that I thought it would be too.

On to using it as an app development platform for Android apps, in particular with Corona SDK.

You need to be able to install apps from your webserver unless you want to tether. The Fire by default is set to only allow you to install from Amazon. In the settings, there is an on-off switch you can toggle that will allow you to download from any source.

I already had an Android .apk file loaded to my webserver, so I bopped the Fire’s browser to the URL where the .apk file lived, it downloaded the file and then let me install it with ease. I was quite happy with the process. Right until I launched the App. It started up but immediately gave me an message that I needed to build specifically for Amazon/Kindle Fire. This appears to be a Corona SDK generated message.

The Fire has restricted hardware and by default Android apps are built with access to the telephone, which for Fire apps isn’t available, so Ansca is probably trying to protect us, but this shows the limits for using the Fire with its restricted hardware from being a good generic Android test platform.

Since I only have one app out, that requires hardware the Fire doesn’t offer, this really isn’t that big of an issue, I just have to build versions specifically for the Fire. I produced .apk’s for several of my apps and have installed them.

Here’s the lowdown…

Omniblaster, my first app: This runs like a dog on the Fire. The player’s ship moves based on the accelerometer. The ship moves smoothly on iOS devices, but on the fire, there were very noticeable pauses as you tilt the device to move.

Turkeys Revenge which is live in the Amazon store played pretty well. Not real complaints but one, which I’ll get to in a minute.

An un-released photo gallery app: Had all kinds of problems. This is a storyboard based app, so I’m fighting the “fixed” delays. There were noticeable pauses during scene transitions. When I used my zoom function to load a larger version of the photo into a scroll view, I couldn’t close the screen with a double tap. This same code worked flawlessly on my iPhone 4 and in the Corona simulator.

Regardless of which app, custom fonts just flat out don’t work. I can’t with 100% certainty say I know how to do custom fonts with Android, but from my testers, the fonts appear to work on Android phones. I wrote a simple test App that just prints out the name of the available fonts, which should show any TrueType fonts in the resource bundle along with installed fonts and my custom fonts just simply are not in the list. This is a huge turn off for the Kindle Fire as a test environment, though it’s important to know about the problem since how I know about this Fire behavior.

In conclusion, as a consumer of the device, if I was just interested in watching video or some casual web surfing or reading books and I’m an “Amazon” person, the Fire would be worth the $199. It is not a great replacement for a general tablet and it’s not that great as a Corona SDK test environment since there are clearly differences between what a general Android device will see and what the Fire will see. If you were one of the lucky ones to snag a refub then it’s probably a fair price to pay to see what your apps are going to be like to the Amazon customers.

Need to save your game data in Corona SDK? Check out this little bit of code.

February 23rd, 2012 43 comments

A very frequent question in the Corona SDK Forums is “How do I save my game data?”.  There are several published solutions in the Community Code and while I they are good, they don’t help you learn how to program or carry extra functions that you may not need.

I (and several other’s) frequently suggest “Just use JSON!”.  But in a recent post in the forums, I realized that as simple as this really is, the language encouraged people to go look up JSON with the concept that they needed to learn JSON.  JSON or JavaScript Object Notation, is a simple syntax for encoding data in a light-weight standard way.  You can dig into the guts of JSON at http://json.org.

The typical JSON file is considerably smaller than the same data encoded in XML and it’s a great way to represent table data like in a language like Lua, which Corona SDK.

If you click through to the json.org links above, you may be immediately intimidated, in fact so intimidated that you are turned off to the concept of using JSON.  But here is the beauty with Lua and Corona SDK, you don’t need to know JSON at all.  In fact it may be a bit better if you just accept that Corona provides you two API calls and assume that everything else is simply magic.

To see just how simple this is, check out this code.  But before I present this code, some of it may still be scary and that is the code to open a file and to read and write files.  However, it’s important to learn this code because as you work on other apps, you will need to read and write files to the file system.

Mobile applications run in a “Sandbox”, which is a protected area.  You can only access files inside your space only.  There are typically four specific locations where files are stored and retrieved from.  They include:

  • The Resource Folder (called a Directory)
  • The Documents Directory
  • The Temporary Directory
  • The Cache Directory

The Resources directory, which Corona SDK,  calls:  system.ResourcesDirectory,  is basically your application files that are “bundled” together and installed on your device.  This frequently referred to as the “app bundle”.  These file can be read only and not written to.  This is for security to prevent malware from infecting your app.

The Documents Directory is where you store your permanent files.  In Corona SDK, this is known as system.DocumentsDirectory.  Any file that your app needs to run that cannot be re-created gets saved here.  It should be noted that Apple with iOS 5 and iCloud, files in this folder get automatically backed up to iCloud.  Corona SDK currently does not give us an option to turn off those backups.  Apple is cracking down on downloaded files, that can be reproduced being saved in this directory since iCloud’s “free” space is limited and they don’t want it full of game code, graphics and other downloaded directory.

Because of this we now have the Caches directory or system.CachesDirectory.  This is a folder to store these downloaded files that can be re-downloaded.  In most senses, you “cache” files that you download that doesn’t change frequently and only download the files when they change.  Web browsers help websites load faster by keeping images, CSS and JavaScript files around on your computer so they don’t have to reload them over the Internet.  You’re app should do the same thing for files that you download.   Files in this folder **CAN** be deleted by the system if the overall file storage gets too low, but they for the most part should remain from session to session, but can be re-downloaded if necessary.

The final location to store files is the Temporary directory or system.TemproaryDiretory.  This is where you put files you don’t care about from session to session.

Files in general require three operations:

  • Open the file
  • Read or write data to/from the file
  • Close the file

Corona SDK uses some syntax for processing files that’s a bit confusing.  After a year of working with the product, I still have to look up the file operation API calls, so don’t worry if you don’t get this code right away.


-- load the JSON library.
local json = require("json")

-- Function to save a table.  Since game settings need to be saved from session to session, we will
-- use the Documents Directory

local json = require("json")
function saveTable(t, filename)
local path = system.pathForFile( filename, system.DocumentsDirectory)
local file = io.open(path, "w")
if file then
local contents = json.encode(t)
file:write( contents )
io.close( file )
return true
else
return false
end
end

function loadTable(filename)
local path = system.pathForFile( filename, system.DocumentsDirectory)
local contents = ""
local myTable = {}
local file = io.open( path, "r" )
if file then
-- read all contents of file into a string
local contents = file:read( "*a" )
myTable = json.decode(contents);
io.close( file )
return myTable
end
return nil
end

So while we are using JSON to format the data when we save it and read it back in, you have to learn ZERO JSON to use this. It magically turns a Lua table into a string that can be then written to a file. If you read that string back in, then decode it with json.decode you end up with the exact came table you started with.

Then to use this magic, you simply do:


myGameSettings = {}
myGameSettings.highScore = 1000
myGameSettings.soundOn = true
myGameSettings.musicOff = true
myGameSettings.playerName = "Barney Rubble"
saveTable(myGameSettings, "mygamesettings.json")

To read your game settings:


myGameSettings = loadTable("mygamesettings.json")

While you’re getting two very simple, easy to use calls that you really don’t have to think about, please take time to learn what those two functions are doing with regards to opening, reading, writing and closing files. You can save learning the JSON format until another day.

Corona SDK excels in letting you do complex tasks in simple easy ways. We don’t think twice about what’s under the hood of the display.newImageRect() API call. You don’t need to think about what’s under the hood with JSON either.

This code can be downloaded from Github.

Categories: Tech Geek Tags:

Geek Cuisine — Making Cornbread

January 14th, 2012 No comments
Cornbread!

Growing up in the heart of Kentucky farm land, a staple of our diet was Cornbread.

For those who have never had cornbread. it is really more cake like than bread.  You don’t slice it in to thin slices and put sandwich meat or peanut butter and jelly on it.  Instead its typically baked in an iron skillet or other cooking dish, cut into squares like cake.  Its consistency is very grainy and it tends to crumble easily.

Sometimes its made into pancakes  and other time into muffins and its typically a salty buttermilk type of cornbread or a sweet cornbread.  Its color tends to indicate the type, with buttermilk tending to be whiter and sweet tending to be more yellow in color.

But this blog post isn’t about that.  It’s about learning to cook it.

Stereotypes are what they are, stereotypes and I’m an unfortunate by product of that.  Boys learned to use tools and dig holes in the ground and pepper rabbits with buckshot on a farm.  Girls learned how to cook.  In an urban situation, the actions by gender may be different but at the end of the day, more girls learn to cook than boys do.

Usually when you grow up, you learn to love your mother’s cooking.  Other mom’s just don’t do it right and if things work out correctly, those recipes pass down through the generations.   When I left the nest and got married, my wife (following stereotypes again) tends to do the cooking.  Cornbread was not a staple of hers growing up in Louisville and she tried to learn how to but we’ve always fallen back to using prepared mixes, with Jiffy’s sweet corn muffin mix being the best.

I lost my mom in 1997 and my father passed in 2002.  I sit here today, like I have for the past 15 years (10 in Dad’s case) in regret that I didn’t spend more time learning their recipes.  Mom’s Coca-Cola cake was legendary.  She made the meanest fried corn and country fried steak.  Man could she cook.  Of course she would always over cook her pasta until it was mush (no one is perfect).  And her cornbread was amazing.  Well I should say Dad’s cornbread.  Honestly I’m not sure I could tell you the difference, their cornbread was nearly identical, but I tend to remember Dad cooking it more than Mom.

Now while my father was one of the toughest old manly-man codgers you would have ever met.  There wasn’t anything he couldn’t fix or build and he never let anything like work get in his way.  He hunted, fished, played sports, de-horned and de-boyed cows with the best of them.  He was rugged, strong and stubborn (He was quite loving and kind too, but he rarely let people see that).  He’s not the kind of person you would expect to have finesse in the kitchen.

I don’t know if he learned it from my grand-mother or not or if he picked up techniques from Mom, but I do know that during World War II, while fighting at places like the Battle of the Bulge, his military specialty besides dodging sniper bullets was a cook.  Well as a Staff Sergent, he probably was the boss of the cooks.  So in addition to knowing his concrete, his coal mining, his farming,  he was also a great cook.

Fast forward to modern times.  My wife, the Queen of Free, saves an enormous amount of money each year with her shopping savvy.  One of the rules that comes with that is you have to live with the brands that are on sale.  That means we don’t get a lot of Jiffy Corn Muffin mix any more.  Our pantry is ether loaded with Martha White mixes or bags of straight up corn meal, the main ingredient.

If I’m being honest, these non-JIffy mixes don’t measure up to the Jiffy mix and that doesn’t measure up to Mom and Dads.  Over the past few months, I’ve been trying to figure out just how to get to something closer to what I grew up with.  Being scientific in nature, I want a repeatable formula.  I’ve never tolerated a pinch of this and a dash of that.  Give me exact measurements, precise timings and I’m much happier.

I’ve observed.  I’ve experimented.  I’ve researched.

Here’s what I’ve learned.

1.  Pre-heating your oven is critical to the cooking time.  If the formula, er. recipe says 20-25 minutes,  that’s assuming you are starting at the prescribed 425 degrees F.  Our oven can take 10 minutes to pre-heat and if you’re taking that 10 minutes of cooking time out of your 20 total, then your food will be under cooked, meaning longer cook times which can lead to burning.

2.  At least for cornbread, pre-heating the pan seems to also be important.  We have always poured the mix into a cold glass baking dish (we gave up on iron skillets a long time ago.  The concept of not washing them was difficult to deal with, but the rust was harder…  You put your oil/spray/lard into the pan and let it melt, over the pan and let it heat up.   This way as soon as the mix hits the pan it starts cooking.  This makes it come out of the pan much easier.

3. My cook times are still taking longer than they should.  I suspect that my oven (nearing 15 years old) may not be heating to the set temperature.  Sounds like I need a new oven!

Now I’m still off on taste.  The last batch I made was very dry almost like all the liquid baked out of it and I was left with corn meal.  I followed the formula exactly.  It was using a Martha White buttermilk formula and it only called for water or milk to be added.  I felt like it needed an egg or something to give it some glue.   The Martha White sweet cornbread mix I had used previously was also a bit drier than I liked but it did hold together better (and was more tasty).

I have a new batch that is cooling now that was made with a Mrs. Butterworth brand corn meal mix.  It asked for oil, an egg, milk and a little sugar.   I can’t wait to check it out and see how well it turned out.  It took about four minutes longer than the formula called for.

I will someday find the right formula.  But with having two boys who have not spent time in the kitchen, I doubt I will be able to pass my recipes down to a new generation.

Do you have a favorite cornbread recipe?  Post it in the comments below!

 

Categories: Geek Cuisine Tags:

Happy Holidays!

December 25th, 2011 No comments

I’ve been trying to think of something good to write on.  Being a geek blog, it needs to be geeky and with my focus on mobile apps, my posts have all been on that topic lately, I don’t want to overwhelm the blog with those posts.  So I decided to venture into a dangerous ground.

Today we celebrate the birth of Jesus.  Well, “we” meaning Christianity.   “We” is a dangerous term given that only 1/3 of the people on the planet are Christian.  It is, however; the dominate religion in the United States, which many of you are from, so I’ll brave the term and go with “we”.

Take the Rick Perry “I’m a Christian and therefore Gay’s are Evil” ad that he’s running to try and become President as an example.  He’s targeting a group to blame for all the country’s problems and encouraging you to hate them because its the Christian thing to do.  “The Christian thing to do…..”

Jesus taught us to love not hate, yet it seems that message gets lost today.  “We” are anti-gay marriage (well anti-gay everything it seems.)  “We” are against a mosque being built down the street.  “We” are against the growing culture of Spanish speakers.  “We” are against socialists and communists.  “We” are against anything that isn’t like us.

Where does that come from?  It seems to me that we’ve forsaken Jesus’s message of love and tolerance and forgiveness to one of hate those that don’t believe in God.  Hate those who violate 4 verses in the Bible, 3 in the Old Testament and of which two are in the same writing as hurl rocks at your kids until they die for back talking you.  You know, the verses you cherry pick that gives you permission to hate the GLBT community.

Frequently this hate comes from a lack of familiarity with the people you are hating on.  Its a distrust formed because “they” are different and “we” are not comfortable with them or their culture.  Its easy for people to group together in common circles to protect your status quo.  But when that need to protect only stems from not knowing those outside your group, that’s when problems start.  War’s have started because of this.

For those who are Star Wars fans (obligatory geekism), you know that hate leads to the dark side.  The dark side is evil, therefor hate is evil.

Hate and distrust leads to bullying.  Many of us think of bullies as big kids beating up on weaklings.  That’s true, but its also people saying hurtful things about others.  Its about excluding people because they are different.  Its making fun of a kid because he prefers art over football.  Because she wears glasses.  Why is different wrong?  Why  must “we” do things to hurt people who are different?

Since this is a season of Love, Family, Giving, Sharing and as we move to the new year, one of resolve….   Lets not worry about how we got to a state of hate, but instead focus on love and tolerance.

I challenge each and every one of you as we move into 2012 to work to find some group/culture/faith that you “hate” or uncomfortable with  and try to learn something about them.  Maybe its learning a little bit about Chinese culture.   Perhaps its reading a few verses of the Koran.   Learn a little bit of Spanish.  Read about the origins of Kwanzaa.

Take this time and make it your New Years resolution.  Make it one you will keep.  It doesn’t take much.

If we all take a few steps towards love and tolerance then perhaps the world will be a better place.  A more peaceful place and one were different is a good quality not a bad one.

Collision detection without physics.

December 14th, 2011 10 comments

A frequent question that comes up in the Corona SDK forums is how to detect when two images on a screen hit each other. This is known as a “Collision”. The ability to determine when two things have bumped into each other is called “Collision Detection”.

Within Corona SDK, being that its an event driven system, we like the idea that we can have the system tell us when things hit each other and we just have to write the code to handle the interaction of the two. This is a cool concept and it works, but . . .

It requires using the Physics engine to do so.

Corona SDK uses a wonderful 2D Box model for physics and that model supports this event driven model and it works well. But if you’re game does not need physics and many apps don’t, like a card game where you move a card to a stack, its kind of silly and wasteful to include the overhead of the physics engine. You don’t need all of those angular momentum floating point mathematics going on in your game.

So how do I detect collisions? I don’t see any API calls to do that?

We really can’t use an event driven model like the physics engine, but there is a very simple method (well there are two) that use other features of Corona SDK, in particular using an “enterFrame” event on the Runtime listener.

Basically we have to write the code that the physics engine is doing for us and it’s not all that complex.

In my personal model, I typically have a table/array of all of my on screen objects and then I have my player’s avatar object.


local objects = {}
for i=1, 20, do
objects[i] = spawnEnemy() -- spawnEnemy creates on display objects and returns it.
end

local player = display.newImageRect("avatar.png", 64, 64) -- create me.

At this point we have a table of enemies in the “objects” table and my player object.

For the Runtime enterFrame event, you need a function to process the collision detection.


local function testCollisions()
for i=1, #objects do
if hasCollided(objects[i], player) then
-- do what you need to do if they hit each other
end
end
end

Runtime:addEventListener("enterFrame", testCollisions)

So we simply iterate over the list of objects and see if any have hit the player object using a function called hasCollided.

This is a function that you also have to write.

There are two main methods for doing this, one is based on rectangles overlapping each other. The other involves circle testing.


-- rectangle based
local function hasCollided(obj1, obj2)
if obj1 == nil then
return false
end
if obj2 == nil then
return false
end
local left = obj1.contentBounds.xMin <= obj2.contentBounds.xMin and obj1.contentBounds.xMax >= obj2.contentBounds.xMin
local right = obj1.contentBounds.xMin >= obj2.contentBounds.xMin and obj1.contentBounds.xMin <= obj2.contentBounds.xMax local up = obj1.contentBounds.yMin <= obj2.contentBounds.yMin and obj1.contentBounds.yMax >= obj2.contentBounds.yMin
local down = obj1.contentBounds.yMin >= obj2.contentBounds.yMin and obj1.contentBounds.yMin <= obj2.contentBounds.yMax return (left or right) and (up or down) end -- circle based local function hasCollidedCircle(obj1, obj2) if obj1 == nil then return false end if obj2 == nil then return false end local sqrt = math.sqrt local dx = obj1.x - obj2.x; local dy = obj1.y - obj2.y; local distance = sqrt(dx*dx + dy*dy); local objectSize = (obj2.contentWidth/2) + (obj1.contentWidth/2) if distance < objectSize then return true end return false end

Depending on the shape of your player and objects, you may find that circles work better or rectangles work better. In my game Omniblaster I used both methods depending on the objects. My space ship has rounded shields and my rocks were basically round, and my enemies were basically round, so using the hasCollidedCircle made more sense to use.

When I say rounded, the images have transparency that when using rectangles would cause the objects to hit before they looked like it.

Yet, when I fired my phasers or torpedoes, those graphics fit nicely into rectangles, so using the rectangle hasCollided method was a better choice.

One gotcha that you need to be aware of is that if your processing takes too long, (longer than 1/30th of a second or 1/60th depending on frame rate) then your collision detection will fire again before you finish, so I usually change my collision handler to something like this:


local isCheckingCollisions = false
local function testCollisions
if isCheckingCollisions then
return true
end
isCheckingCollisions = true
for i=1, #objects do
if hasCollided(objects[i], player) then
-- do what you need to do if they hit each other
end
end
isCheckingCollisions = false
return true
end

This should be a lighter weight collision detection system than the overhead of the physics engine. Though you don't get filters, being able to define polygon shapes unless you roll you're own!

Happy coding!

Understanding “SCOPE” for beginning programmers.

October 14th, 2011 4 comments

Scope is a term used to describe where a particular asset, be it a variable, object, array or function is available to be accessed. It’s an important concept that needs to be grasped to avoid bugs and reduce the amount of time you spend developing code.

Since the primary audience for this will be posting to the Corona SDK forums, we will be using the language “Lua” in our examples, but this holds true for almost every programming language in use today. Also, since scoping applies to different bits of your program, variables, objects, etc. We will be using the term variable in our code for simplicity, just keep in mind that all the above assets, even functions at the end of the day are variables.

There are a few key terms that we will be using:

  • Global – A global variable is available everywhere.
  • Local – A local variable only exists within the block or chunk of code where it’s defined.
  • Block – A generic term for a block of code. In Lua, these are sometimes referred to as chunks.
  • Namespace –namespace is a term applied to the area where a given variable’s name is active or in context.

Lets talk about blocks for a moment. When it comes to locality, the following programming constructs define blocks:

The file/module containing the code. Thus in lua, your “main.lua” file is one block. Any thing defined in that file is accessible to that file.

In this example, our entire main.lua file is one block. It contains a function, which itself is a block. The variables, characters, location and thisCharacter along with the function pickCharacter are available to be accessed anywhere within main.lua.

Inside the function pickCharacter, I was able to see, access and modify the variable “characters” because it was defined within the main.lua chunk above me.

Functions though are also blocks. Variables created within functions are only available to that function. Lets expand our example:

I made a very subtitle change to the pickCharacter function. I’ve declared a variable inside it called “choice” and I’ve assigned it the value of the random character chosen. I then return the value of that variable to the caller.

The difference here is now “choice” is defined within the block “pickCharacter” so it only exists or is available to that block of code. From my main.lua chunk, if I try to print the value of choice, I will get “nil” because that variable has not been created and initialized within my main.lua block, but within the pickCharacter function block.

Other things that are considered blocks with regards to scope include “IF” statements, “SWITCH” statements (Lua doesn’t support switches, but many other languages do) and your looping statements, “WHILE”, “REPEAT”, “FOR”, “FOREACH”, etc. Again Lua doesn’t support all of these, but you will run into them in other languages.

Not all languages let you declare variables inside these blocks either. For instance in ‘C’, your variables all have to be declared at the top of a function block, yet in ‘C++’, you can define them in the middle of a FOR loop.

Declaring Variables

In a language like C or Objective C, you have to be very explicit with your variable declarations:

If you do not declare a variable at the top of the function or in a valid place in C++/Objective C, the complier will give you an error and not build your program. When languages like JavaScript (which lead to Flash’s ActionScript) and PHP were developed (and Lua has this same behavior) variables no longer had a specific type and no longer had to be declared. You could just start using a variable:

I no longer had to tell the system if it was a string, number, table etc. I could just assign values and go on. An “optional” “var” tag is allowed.

This is where paying attention to scope becomes critical. The “var” isn’t optional. It controls the scope of the variable. In Lua, this is the same as putting the word “local” before a variable. What is the difference?

In Javascript and Lua if you DO NOT put the var or local in front of the variable the first time you reference it, it becomes a “Global Variable”. It is accessible anywhere with in your program. Cool, that means I don’t have to worry about passing my variables around or worrying about scope, I can just make everything global…..

Not so fast, there young padwan learner. Globals are very bad things if you treat theme without caution and careful regard.

Lets look at an example using the infamous “I” index variable:

The variable I changed from 10 to 12. Why? Well lets look at the code for the function myFunction:

The developer of myFunction didn’t localize the variable I (nor the variable count for that matter) and when myFunction runs, “I” is left at 12 when the for loop ends so you in your program expects “i” to still be 10, but its not because both your “i” and the function’s “i” are accessing the exact same variable. If you used a variable called count, it would get trashed too by the function.

Therefore it’s important that when you write functions that someone else may call later (if your working on a team) or for your own sanity, to make sure you localize variables and just not use globals because they are easy.

This problem would be solved by the function being written as:

Specifically within Lua when using modules, global variables are available to all modules. Lets say I have a variable I define in main.lua as:

and I’m in another module, say “level1.lua” and I print the value of “score”, I will get “100” printed. Lua supports a special table called _G which you can add member elements too for this purpose of passing around variables between modules. But don’t over use it. And its good to use _G instead of loose variables like the “score” example above since its visually intentional that you intended for that value to be globally available instead of just sloppy code.

Lua does you a favor and namespaces your variables for you behind the scenes. Lets look at this example:

You will get the following output:

Within the scope of myFunction, “count” is a unique variable to that block of code. When it returns, my original “count” variable remains untouched. This is an important concept to understand if you are unsure of when to use the word “local” in front of a variable or not. Lets look at the same example without the word “local” in the function:

You will get the following output:

In this case, we didn’t localize “count” to the function, so when it looked to find the variable “count”, it went up to the next higher level and found a variable within that chunk’s scope which is available to my function and the higher level “count” variable changed.

Of course avoiding using the same name variable in different places helps avoid these problems, but in languages like Lua were we can use untyped, undeclared variables, it’s critical to understand when variables are in scope and when they are not.

Hopefully this will help you understand the “local” tag and when you need to use it and help you avoid unnecessary headaches. Happy Coding!

Categories: Tech Geek Tags:

Why my SEO sucks.

September 9th, 2011 1 comment

Search Engine Optimization or SEO is the tricks that webmasters and content producers do to get their websites and articles to rank as high as possible in sites like Google, Bing and Yahoo when people put in words and phrases to find content.   Some people consider it an art form, others voodoo, but its magical, its technical and its ever changing.

My photography site, http://www.robmiracle.com is one of my prides and joy.  My day job is building websites and the company I work for spends a lot of energy making sure our sites and content have great SEO.  I have the pleasure to work with people who know what they are doing; and as a trainer, its my responsibility to know this stuff so I an instruct the people who are producing content and sites.  So while I don’t want to label myself as an SEO expert, I know what needs done and how to produce content and code sites that should rank rather well.

Yet for my photography site, my SEO sucks.  I decided one day to search for “Raleigh Wedding Photographer”.  I didn’t expect to be on the first page or realistically the 2nd.  I don’t do weddings full time and I would hope those shooting full time should rank above be.  But I would hope to show up by page 3 or 4 or 5 or 10.  Nope, didn’t even make it there.  In fact, I gave up looking for my site after I got 20+ pages deep.  I just wasn’t there.

After doing a little research and using Google’s “Webmaster Tools“, I quickly isolated a few problems.  I have very few backlinks (where people link to me).  That’s something I will have to fix over time.  Not all backlinks are created equally.  Higher rated sites that link to you are more valuable than less rated sites.  In fact, having a very high ranking site like CNN link to you is more valuable than a dozen personal blogs that link back to you.  So if I want to be seen, I need to join more directories.   But that’s hardly the problem.

I’m being burned by “keyword density”.  Basically for good SEO, you need to have your keywords show up on your page, in your headers and in your content.  One of these pieces of information, your pages <title> tag (some hidden code in the header) is one of the most critical parts of the page.  My title was:  “Rob Miracle Professional Photographer”.  At no point does that title tell you where my area of focus is (Raleigh-Durham, NC) nor does it tell you the type of photographer I am (Wedding, Fashion, etc.).

Likewise there is a <meta description> tag also located in the page header provides a text description about your website or that particular page.  My description contained Raleigh and Wedding, but it wasn’t written all that well and didn’t have other important keywords in it.  Keep in mind, this is what shows up on Google as the text under the title, so it should be something people will read, just not a list of random key words!

After that, my home page had no text on it, well, the menu and footer links were there.  I’m a photography site, so my site is all about pictures.  Photo sites like this are going to have a harder time than sites with some text on the page because there is little the search engines can extract from the page.  I spent a weekend editing every photo to make sure there was a caption in the IPTC meta data and changed my site’s program code to extract that caption and add it as the “alt” attribute on each <img> tag which greatly increased the “keyword density” on my front page.  It was important while writing these captions to make sure I got the right keywords in the captions.

So after providing better titles, descriptions and text on my page, I would think I would fair better….

NOT!

My site still sucks.  Using the Webmaster Tools, I see that Google has seen the increase in keyword density.  Raleigh is however, still the 81st most popular keyword on my site occurring 29 times.  “Wedding” shows up 14 times and is the 166th most popular keyword.  Wedding shows up 8 times on my front page, which seems like a lot.  Until you discover that “Kentucky”, “Model”, “twitter” and “tutorials” all show up well over 500 times!!!!

I’m being killed by my blog and photo tutorials.  These posts make up a bulk of the content on the site.  They are things I feel that are important to my photography friends as its how I give back to the photography community.  So it looks like I will be moving my blog content to another domain.

 

Categories: Tech Geek Tags: , , ,

The Beatles – Let it be! Music Perfection?

August 2nd, 2011 No comments

 

Like most people, I have several playlists for my Audio Collection.  I listen to a lot of music at work and I’ve dedicated playlists to each day of the week.  Monday is mostly dark and depressing songs (Daniel Powter’s “Bad day”, songs that reference Monday (Bangles “Manic Monday”).  Friday is loaded with beach and party tunes (Alan Jackson and Jimmy Buffett’s “It’s 5 o’clock somewhere”, etc.).   Well Tuesday’s happens to be love songs.  This particular Tuesday, I really didn’t want to listen to love songs all day.  I didn’t want to fall back to my “Current Stuff” list (not necessarily “current” with regards to when the music was created, but current as to when I added it in.)

So I decided to run my The Beatles playlist — 64 songs and almost 3.5 hours of play time.  Its by no means a complete The Beatles collection and its about 1/3 cover tunes, like Sarah McLachlan’s fantastic rendition of “Blackbird”.   One of the first song’s up today was “Let it Be”, the chilling and powerful song vocaled by Paul McCartney.

I started thinking about what makes this song so great.  Its more than a fantastic melody and important lyrics that are universally meaningful.  It’s more than McCartney’s voice and his keyboard work.  Its all these elements working together to form a fantastic song that lives through the ages.

But what many people may have not noticed is how the song builds from a quiet piano tune to a driving rock tune.  It starts out with just a single piano.  Then McCartney’s voice joins in through the first voice.  Quietly soft background voices are added at the first chorus.  Slowly during the 2nd verse Ringo Starr’s drums add in then a quiet bass guitar starts presumably from a studio artist building in the background.  Another studio player’s organ adds in, then comes in George Harrison and John Lennon with their stunning electric guitars following the melody when transforms into a powerful guitar solo. All of it orchestrates to a building crescendo of perfection and it eases out much like it started.

As these different elements add in, its subtle which drives the power behind this timeless song.

If you haven’t listened to it lately, watch the YouTube video above of find it your playlist.