Sparkfun Free Day 2011

Blog — Dillon @ 6:09 pm

Tried filling out hours and hours of captchas while watching the newborn. It didn’t go so well. I got sore hands and didn’t get $100 of free stuff. I ended up ordering a new arduino r3 anyway and a stepper motor to hopefully build a quiet baby rocker. I built a few previous iterations of a baby rocker out of Lego technic pieces but the motor was a little bit too loud and I’ve scrapped the project.

Anyway, here’s a screenshot to remind me of the captcha fun.

Homebrew behind a proxy

Blog — Dillon @ 10:12 am

Git doesn’t work behind a proxy with homebrew (the macports new hotness). Because git:// is blocked at my office. There’s a patch here. Unfortunately, the drop-in replacement didn’t work for me (it’s an old commit).

Instead I made the modifications myself. Be warned, that this file will probably only work for the version I’m using (0.7.1), in which case you’ll have to look at the SVN commit yourself. :(


cd /usr/local/Library/Homebrew
cp download_strategy.rb download_strategy.rb.orig
wget http://squarism.com/files/download_strategy_proxy_fix.rb -O download_strategy.rb
export HOMEBREW_GIT_VIA_HTTP=1
brew install [something]

Any brew installs that use git should work now.

But then there’s curl. Curl doesn’t quite use the same env that others do. So solve it like this:

export http_proxy=http://proxy:80
export ALL_PROXY=$http_proxy

Curl likes that ALL_PROXY env for some reason.

After that, I was able to get my favorite homebrew apps installing:
brew install couchdb irssi git mysql watch lua p7zip htop openssl node npm nmap netcat

Update: If the above still doesn’t work for you (I had problems with Git URLs), try this:
cd /usr/local/Library/Homebrew
vi download_strategy.rb

Find the line when %r[^git://] then GitDownloadStrategy and replace (or comment it out) it with this:
when %r[^git://]
url.gsub!(/^git\:\/\//, ‘http://’)
GitDownloadStrategy

Git should use the http:// method of downloading code and brew install should work. Just to be clear, the relevant part of download_strategy.rb looks like this:

  when %r[^bzr://] then BazaarDownloadStrategy
  #when %r[^git://] then GitDownloadStrategy
  when %r[^git://]
        url.gsub!(/^git\:\/\//, 'http://')
        GitDownloadStrategy
  when %r[^hg://] then MercurialDownloadStrategy

Another thing to try is to edit ~/.curlrc to enable a SOCKS5 proxy if you have one.
socks5 = "yourserver:port"

Debugging Cucumber and Rails

Blog — Dillon @ 1:03 pm


I was working on my game store app and I had some TDD things I wanted to finish up before creating a rails3 branch. I discuss it kind of randomly in that post linked there. I had left it to languish because I got stuck and frustrated with cucumber. My app was working but the tests were failing (false negative). The biggest problem was trying to understand how to debug a cucumber step.

The first problem is logging. When cucumber runs webrat as a mock browser, I really expected to see the traffic in the server log (script/server). But it didn’t. Nothing. No traffic at all. The second problem was seeing what the browser sees. It was reporting back that my login was failing. The third problem is the problem itself. It was saying “invalid login”. I am using factorygirl to create mock users on the fly and authlogic for the authentication and so there was a possibility that something was wrong there.

Logging

So let’s go through this in order. First the log problem. The traffic I was not seeing in the script/server console was kind of confusing. Cucumber’s traffic is actually redirected to log/cucumber.log. So you can either tail -f that log or use the OSX console app (screenshot) to watch cucumber.log. Either way, the traffic and any puts or STDOUT text will be there. It’s pretty odd actually. I don’t know how they pull this off. The dev server (script/server) doesn’t even need to be running for the cucumber steps to work. See below, I stopped the server and ran the tests successfully:

box:game_store chris$ script/server
=> Booting WEBrick
=> Rails 2.3.8 application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2010-12-05 00:21:34] INFO WEBrick 1.3.1
[2010-12-05 00:21:34] INFO ruby 1.8.7 (2010-08-16) [i686-darwin10.4.0]
[2010-12-05 00:21:34] INFO WEBrick::HTTPServer#start: pid=23554 port=3000
^C[2010-12-05 14:38:43] INFO going to shutdown ...
[2010-12-05 14:38:43] INFO WEBrick::HTTPServer#start done.
Exiting

box:game_store chris$ cucumber features/user_sessions.feature
Using the default profile...
WARNING: Nokogiri was built against LibXML version 2.7.7, but has dynamically loaded 2.7.3
..........

2 scenarios (2 passed)
10 steps (10 passed)
0m0.508s

Debugging Webrat

Next, the “seeing what webrat sees” problem. The invalid login error was based on detecting text. In my test app, when you’re signed in you see the Logout link. When you’re signed out, you see the Login link. Webrat was telling me that it couldn’t sign in because Logout never appeared. I had to figure out if it was lying because the app in my dev environment was working fine. So I needed to see what webrat was seeing when launched from cucumber.

I had hunted down a function called save_and_open_page but it never worked for me. It’s supposed to take a snapshot of the webrat client and open the web page in your browser so you can see what it sees. It’s like debugging with puts. So if you’re stuck on a step, just save_and_open_page and investigate. Well unfortunately, I had left that option for dead a while ago because it wasn’t working. I had missed a key step:

Install the launchy gem.
gem install launchy

Now your default browser should launch with a simple snapshop of the page. It’s just a local file so you won’t be able to click on links back to your app (unless you have some awesome hardcoded urls everywhere that would take you back from anywhere). The idea here is to just look at what the client is seeing on a basic level. I was getting an invalid login error message so I was looking any evidence related to logins. You can see in the screenshot to the right that I have a Login link available. In my app, that means I’m not logged in. I put the save_and_open_page in the logout feature step of cucumber so this is a good thing.

Ok, so at this point my save_and_open_page was launching two pages. What? One was correct but the other one was incorrect. That is to say, one page was giving me an invalid login and the other one was signing in fine. So what is going on?

Factorygirl

A key to my problem was how I was using factorygirl to create mock users and misunderstanding a convention. First, here is the non-working features/step_definitions/user_session_steps.rb file:

require "authlogic/test_case"
require "factory_girl"
 
Factory.find_definitions
 
include Authlogic::TestCase
 
def user
  @user ||= Factory :user
end
 
def login
  user
  visit path_to("the homepage")
  click_link "Log in"
  fill_in "user_session_login", :with => "john" 
  fill_in "user_session_password", :with => "funkypass"
  click_button "Login"
end
 
 
def logout
  click_link "Logout"
  #save_and_open_page
  visit path_to("the homepage")
end
 
Given /^I am a registered user$/ do
  user
end
 
When /^I login$/ do
  login
end
 
Given /^I am logged in$/ do
  login
  visit path_to("the homepage")
end
 
When /^I logout$/ do
  logout
end

The login method is all about clicking the Log in link and filling in the username and password boxes. Now before you say, “what is john and funkypass?”. I tried many different variations of passwords. I tried my passwords out of my dev db, obviously this won’t work. I tried foo1/foobar which actually led to my one working and one not case.

So here’s what went wrong. My feature file defines two scenarios for one feature, logging in and logging out:

Feature: User Sessions
 
  So that I can blah, blah, blah
  As a registered user
  I want to log in and log out
 
  Scenario: log in
    Given I am a registered user
    And I am on the homepage
    When I login
    Then I should see "Login successful!"
    And I should see "Cart"
 
  Scenario: log out
    Given I am logged in
    And I am on the homepage
    When I logout
    Then I should see "Register"
    And I should see "Log In"

The “When I login” step fires the login method. But so does the “Given I am logged in” step. So there are my two save_and_open_page hits, the reason I see two pages open when debugging. But why would one work and the other one wouldn’t? I’m not changing anything.

The problem is factorygirl was creating a second user called foo2 for the log out scenario but rolling back the foo1 user that was created for the log in sceneario. I didn’t realize this when I hardcoded fill_in "user_session_login", :with => "foo1" during integration. So in the log out scenario, foo1 would log in but only foo2 would exist in the DB.

So I changed the login method to look like this:

def login
  @user ||= Factory :user
  visit path_to("the homepage")
 
  click_link "Log in"
 
  fill_in "user_session_login", :with => @user.login
  fill_in "user_session_password", :with => @user.password
 
  click_button "Login"
  #save_and_open_page
end

I really wanted to create a user once (what the ||= is trying to do) but I couldn’t figure out how to properly use instance variables in a test step. So I’ll just do it this way for now. Notice that I’m using the fields on @user so it’ll always work.

LibXML warning with Nokogiri

You may have noticed that I was receiving an warning here:
WARNING: Nokogiri was built against LibXML version 2.7.7, but has dynamically loaded 2.7.3
I’m on OSX and I’m not sure what OSX is using but xml2-config –version shows 2.7.3. So I’m pretty sure that it’s using the shipped OS version. Ok, no problem. I’m running homebrew (a macports/fink replacement). I’ll just install 2.7.7:

$ brew search xml
blahtexml libwbxml xml-tooling-c xmlrpc-c xmltoman
gccxml libxml2 xml2rfc xmlstarlet
html-xml-utils xml-security-c xmlformat xmlto
$ brew install libxml2
==> Downloading ftp://xmlsoft.org/libxml2/libxml2-2.7.7.tar.gz
######################################################################## 100.0%
==> ./configure --disable-dependency-tracking --prefix=/usr/local/Cellar/libxml2/2.7.7
==> make
==> make install
==> Caveats
...
$ brew info libxml2
libxml2 2.7.7

http://xmlsoft.org

/usr/local/Cellar/libxml2/2.7.7 (293 files, 12M)

http://github.com/mxcl/homebrew/commits/master/Library/Formula/libxml2.rb

Ok so it installed correctly. Now we need to reinstall nokogiri using the 2.7.7 libs.

gem install nokogiri -- --with-xml2-lib=/usr/local/Cellar/libxml2/2.7.7/lib --with-xml2-include=/usr/local/Cellar/libxml2/2.7.7/include

Now when we run cucumber, we won’t get the error. But here’s the problem. Brew provides a way to link to the brew version of libxml2 by default with the `brew link libxml2` command but issues a warning about doing this. The problem with using a path like /usr/local/Cellar/libxml2/2.7.7/lib is eventually brew will update it to 2.7.8 or something and it’s hard to say what the consequences will be. Most likely, some binary will fail with lib errors.

Wrapping up

Another note is that I was futzing with all of this in a git branch called “tdd”, a branch I used to integrate cucumber/rspec and anything else related to testing. I read some advice somewhere that a good practice is to branch a new feature and then roll it back into master when it’s done.

So I was already in the “tdd” branch had already committed everything. It was time to merge the branches and get rid of the tdd branch:
# switch back to master
git checkout master
# merge tdd into master
git merge tdd
# run the tests again for sanity
cucumber features/user_sessions.feature
# ok, passed, we don't need the tdd branch anymore
git branch -d tdd
# view branches
git branch
* master

After the merge, my code is up to date in the master branch and I can create a new branch called “rails3″, for example, if I want to play with upgrading the app to rails 3. Or I could create a branch called refactor if I was going to majorly overhaul code.

Geekcation

Blog — Dillon @ 2:01 pm

Recently, I’ve resigned from my position to pursue a more flexible and collegiate atmosphere at another company. I’m recklessly optimistic almost always but I feel like this is a good change for me. Not that there weren’t smart people at Oracle, it was just a little crazy at times and I needed free time cycles to move into more bleeding edge areas instead of picking up more and more enterprise software skills. Ok, enough about that. The important part is that I negotiated a month off at the new place for studying and ramping up on new technologies. Very awesome of them.

An interest of mine is NoSQL or alternative databases and scaling massive hashtables. There’s a possibility that I might be working with a dataset so large that it can’t be solved with an ETL style process. This is timely because I was just watching a video from Cloudera about Facebook having the same problems with large datasets on Oracle DB and then moving to Hive + Hadoop. Hopefully, I can hack on this to expand out my DB skills (as a dev) to a non-relational platform. There’s some guides on setting up a cheap cluster on EC2. Although I have some hardware, I think I’ll go that route. At the very least I’ll understand more about how Facebook scaled and how Mapreduce can be implemented. I hope to find a non-trivial problem to solve (ie: something beyond counting words).

In addition to that very new and complex goal, there’s some other things I want to hack on:

  • MongoDB, especially as a horizontal scaling DB
  • Rails3 upgrade and testing of new gems on my RSS analyzer project
  • Cleaning up said RSS project to the point that I can share a 0.1 on github or what-not
  • Continuing to hack on my Tatris port to Obj-C / iOS
  • Break into node.js some more. Play with websockets.
  • Amazon is giving away EC2 dev instances and I’ve never played with their weird command line tools and AMI thingies.

Of course there are distractions to all these very work relevant things. I have a languishing tetris clone that I haven’t touched since the summer and I never got around to adding sound effects to that. Producing the effects should be a problem but I’m not sure how hard it’s going to be to get back into that code. Thar be ghosts and cobwebs.

Game and graphics aren’t very work relevant (I haven’t found a simulation job). Even less so is playing around with my arduino. There are a few basics I want to get down and then possibly integrate them all into a functional thing. Something I would actually leave alone and serve some permanent purpose. I have a few ideas but I don’t want to foretell or foreblog. There’s also a RAD project I want to check out (Ruby on Arduino). I have no idea how it works or if it’s what I want to use.

Fit-PC2 and Ubuntu 10.04

Blog — Dillon @ 9:51 am

I had Ubuntu 9.04 running on my Fit-PC2 and I wanted to move up to 10.04. I ran: sudo apt-get update; sudo apt-get dist-upgrade and it chugged along doing the update. Install went fine and I was impressed that you can jump major revs like that.

Although there was one bit of weirdness: when I did the dist-upgrade I noticed that it was going to upgrade openoffice. I didn’t want openoffice at all on there so I was going to remove it before it upgraded. So I hit Ctrl-C which promptly locked the whole box. I thought it was heat related and so I got an ice pack and wrapped the Fit in ice. I tried it again, Ctrl-C locks the box. Like, the whole box. Caps lock dead. Anyway, I’ve never seen that before. When I let the dist-upgrade go, it worked fine.

When it booted 10.04, my display was set to 1280×1024 and was running slow. It was running the vesa driver. So I downloaded the paulsbo driver for the GMA500 (the ‘gpu’ that the Fit-PC2 uses) and although the module built fine, it really screwed up everything. The screen would blank, X would be trying to start, there’d be video garbage doing all kinds of weird things.

So I wiped the whole thing and installed 9.10 and followed the 9.10 installation instructions on the Fit wiki. I installed the netbook-remix distro (i386) and the install instructions still work. Now I just need to get rid of the netbook-remix gui. Too bad they don’t have desktop-switcher anymore.

Also, I was playing around with Xmonad which is interesting if not a bit understated. It reminds me of when I used Enlightenment back in 1999. The styles are different but the amount of config editing is the same.

Reversing sentences with Ruby.

Blog — Dillon @ 2:01 pm

A question came up today about how to reverse a sentence. Word by word, preserving periods etc. I’ve done stuff like this before but I really saw an opportunity to solve this contrived quiz type question with TDD. It’s perfect really. Tedious string checking? Screw it. Let my test tell me when I’m done.

Ok so I could have probably done this more comfortably in Java but it would have been more lines. I banged this out in Ruby, including “learning” test cases (it’s really easy) in about an hour. At one point I realized how easy string manipulation is in Ruby for this and I literally said, “holy shit Ruby is amazing”. And then the edge cases started happening. I was only handling periods and my algorithm fell over flat on three sentences because I was trying to do a string[start, end] when it’s really string[start, length]. I fixed it with learning the String#slice syntax.

Ok enough fanboi service. There’s two files. One’s the test and one’s the class. Run the test and not the class (ie: ruby tc_reverser.rb).

tc_reverser.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
require 'test/unit'
require 'reverser'
 
  # Be wary of newlines in the test and expected trings.
  # Do not try to word wrap with escapes.  It's very picky.
class TestReverser < Test::Unit::TestCase
  # Optional
  #def setup
  #end
 
  def teardown
    if @test_passed then
      puts "\n #{@r.reverse}"  # more verbose for successful passes
      puts "#{@method_name.upcase} OK.\n\n"
    else
      puts "#{@method_name.upcase} FAIL.\n\n"
    end
  end
 
  # simple test
  def test_reverser
    test = "You space bastard.  You killed my pine."
    expected = "Bastard space you.  Pine my killed you."
    @r = Reverser.new(test)
    assert_equal(expected, @r.reverse, "Fail.")        
  end
 
  # Test multiple sentence delimiters  
  def test_multiple_sentence_delimiters
    test = "Shape up, man.  You're a slacker.  Do you want to be a slacker for the rest of your life?"
    expected = "Man, up shape.  Slacker a you're.  Life your of rest the for slacker a be to want you do?"
    @r = Reverser.new(test)
    assert_equal(expected, @r.reverse, "Fail.")
  end
 
  # Test no periods, question mark and commas
  def test_question_comma
    test = "Then tell me, future boy, huh, who's president of the United States in 1985?"
    expected = "1985 in States United the of president who's, huh, boy future, me tell then?"
    @r = Reverser.new(test)
    assert_equal(expected, @r.reverse, "Fail.")
  end
 
  # Big test  
  def test_everything
    test = "Our first television set. Dad just picked it up today. Do you have a television? Well, yeah, you know, we have two of them. Wow! You must be rich. Oh, honey, he's teasing you. Nobody has two television sets."
    expected = "Set television first our.  Today up it picked just dad.  Television a have you do?  Them of two have we, know you, yeah, well.  Wow!  Rich be must you.  You teasing he's, honey, oh.  Sets television two has nobody."
    @r = Reverser.new(test)
    assert_equal(expected, @r.reverse, "Fail.")
  end
 
end

I have to apologize for the scrollbars in the above posted code. I tried many different ways of escaping carriage returns for better formatting but it would have required a lot of changes to deal with the \n and so on in the tests. I had something nicely formatted working but the tabs and spaces for alignment then screwed the test and broke the pretty formatting a different way.

reverser.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# A class that reverses sentences.
# "My dog has fleas." --> "Fleas has dog my."
 
class Reverser
 
  # tasty constructor, full of taste
  def initialize(text)
    @text = text
  end
 
  def reverse
    delim_location = 0  # char by char, remember !?. for sentence determination
    delim_last_location = 0  # allows us to move on to the next sentence
    delim_i = 0  # an iterator
 
    new_sentence = ""  # inits an empty string for string methods to work
 
    new_sentence_array = Array.new
    punc_array = Array.new  # list of punctuation marks in order
    @text.each_char do |char|
      delim_i += 1  # iterator
      if (char == "." || char == "?" || char == "!")
        # we hit a deliminter (?!.), remember it
        sentence = @text.slice(delim_last_location..delim_i) 
        sentence.strip!
        new_sentence_array.push(sentence)
        punc_array.push(char)             
        delim_last_location = delim_i  # remember our substring position
      end
    end
 
    i = 0
    new_sentence_array.each do |s|
        returned_sentence = do_reverse(s)  # reverse words sentence by sentence
        new_sentence += "#{returned_sentence}#{punc_array[i]}"  # append the delimiter back
 
        if (i+1 != new_sentence_array.length)  # look ahead for last sentence
          new_sentence += "  "  # only append spaces if this is not the last sentence
        end
        i += 1
 
    end
 
 
    new_sentence  # return new_sentence
 
  end
 
  def do_reverse(s)
    s.chop!  # trim delimiter
    text_array = s.split(" ")  # split on spaces to array
    text_array[0].downcase!  # downcase first word
    text_array.reverse!  # destructive reverse
 
    # need to move commas back
    text_array_i = 0
    text_array.each do |e|
       text_array_i += 1
        if e.include? ","
          e.chop!   # modify original array
          text_array[text_array_i - 2] += ","
        end
    end
 
    text_array[0].capitalize!
    text_array = text_array.join(" ")  # destructive join
    text_array.to_s  # return reversed array
  end
 
end

When you run the test case it looks like this:

Loaded suite ~/src/ruby/tc_reverser
Started

Set television first our. Today up it picked just dad. Television a have you do? Them of two have we, know you, yeah, well. Wow! Rich be must you. You teasing he’s, honey, oh. Sets television two has nobody.
TEST_EVERYTHING OK!

.
Man, up shape. Slacker a you’re. Life your of rest the for slacker a be to want you do?
TEST_MULTIPLE_SENTENCE_DELIMITERS OK!

.
1985 in States United the of president who’s, huh, boy future, me tell then?
TEST_QUESTION_COMMA OK!

.
Bastard space you. Pine my killed you.
TEST_REVERSER OK!

.
Finished in 0.003567 seconds.
4 tests, 4 assertions, 0 failures, 0 errors

Marty McFly would be proud. So some limitations. First, I don’t handle elipsis (…) characters at all. It splits on sentence delimiters which one is a period. The eplisis would cause major weirdness. I also don’t handle recapitalizing the word “Dad” as you can see in the “test_everything” test. This would require language parsing or a massive pick list. I also don’t handle slang or abbreviations. For example, “You told ‘em?” would turn into “‘em told you?” which might not be exactly right.

There are many other edge cases that this thing would fall flat on. My test case tests what functionality I wanted and nothing more.

Ruby’s String#slice was super handy on this as well as capitalize, reverse and even a regex split that I didn’t use (amazing!). You can see it here. It would split text into an array really easily:

sentence_array = @text.split(/[\.\!\?]/)  # split with regular expression
 
new_sentence_array = Array.new
sentence_array.each do |s|
    new_sentence_array.push(do_reverse(s))
end
 
puts sentence_array[2]
return

But then I’d lose the delimiter character (!?. etc) and would have to save it, search it or some other nonsense. Still, really neat that you can split on a regex.

iPadDC 2010

Blog — Dillon @ 10:26 pm

Some notes from the 2010 iPadDC conference, I typed as fast as I could. 2nd annual iPhone OS barcamp style un-conference with many good speakers and donuts. Yum.

Full slides might be available under the #iPadDC hashtag.

Rob Rhyne @capttaco

iPad UI Design

Walter Gropius, founded the Bauhaus.
He loved Claire De Lune from Ocean’s Eleven, builds up in fountain scene.
Find the simple.
Discover the hook and bust your ass to make your app enjoyable.
When in doubt, polish.
Demo’d his mock up/wireframe iPhone app Brief. Really looks nice. http://giveabrief.com/
Ruby based BS script for mock up movement.
Mentioned we should check out a Brett Victor mock up talk at WWDC. Video might be hard to find.

Nic Schlueter @schlu

Pleasing Everyone

blog.simpltry.com
Taxi Magic (super awesome), PM Android and WebOS
JSConf
Very cool taxi booking and payment app.
Order of market importance
iPhone -> Android -> Blackberry -> iPad -> WebOS -> WinMobile Phone 7 -> WinMobile 6.5
Basically WinMobile is dead.

Things to worry about
- Isms (metaphors per platform)
- Cross Device Within Platform
- Location
- Multitasking
- App Stores

Androidisms
Back button kills app. Home keeps it alive. These are hardware buttons so this is the way it is. You can’t disable this. Android phones don’t get latest versions of the OS. And they don’t care because they’re going to sell a newer phone. So you have to support old OS’s.

BlackBerryism
- Learn to love the menus
- Hardware back button
- T-Mobile users prepare for pain
- Blackberry users never upgrade their OS
- Very low expectations

WebOSisms
- hardware back
- software swipe down menu, supported by almost all apps
- most similar to iPhone

Platform Quirks (deep dive)
Android
- screen resolution
– biggest challenge
– must support landscape if you want cred!
– watch the font size
– large variety in PPI and resolution in phones
– so you have to use different pixel density features of fonts?
- Which OS to Target
– 1.6 unless you have a good reason
– 6-9 mo you can safely target 2.0 or 2.1
– expensive to test old devices (subscriptions)
– device manufacturers don’t make it a priority to update device OS

Blackberry
- layout manager not quite as flexible as Android, you have to do lots of detection on your end
- Currently a lot of resolutions
- In the future, should be less than Android
- Which OS to target. The Blackberry App World allows you to submit apps targeted from 4.2.1+.
- Enterprises might want you to target older devices.
- Too many threads bug
– 6-7 threads seem to be the max. Nasty. A problem on older BBs.

Future Proof
- build support into your price
– either the app is going to suck or you’ll be broke if you don’t
- unreleased phones will break your app

T-Mobile
- some crazy APN process to enable 3rd party internet support on your app

BB partner
$2000/year to be a partner. They’ll send source code. 1-on-1 support person. If you’re serious about BB, it’s worth it.

WebOS
- multi-resolutions, not that bad. It’s all CSS3.
- Bottom position sticky to the bottom.
- PDK makes games fairly trivial. C & C++ are easily portable.
- Single threaded, not a problem with Ajax async for network calls etc.
- Ares web based IDE developing in the browser.
- Is it worth it? Probably not. Still better than WindowsMobile! HAHA

iPhone location services are awesome, spoiled. Others aren’t as good. The Droid rate limits how frequently you can get a location. Even between app restarts. Check time on the last known location. Nasty behavior for him to figure out.

BB Location. Slow GPS only. Not on older phones.
WebOS Location is basically fine.

Multitasking
- Do not do things that kill the battery. Location or network.
- Consider the user experience if a user comes back to a screen days later.
Android
- full access
- prog con running
- save state when users leave app
- your app gets killed in low mem situtations
BB
- full access
- your prog con running
- do what you want (spawn, background, you can watch sms/email – poor man’s push)
WebOS
- full access
- won’t kill your app, prevents users from starting a new app if too much mem in use
- You must have a card or icon when running in bg, or prepare to be killed

App Stores
Apple – submit, wait, pray (14 days to 24 hours to 3 days). Apple is the only one with identifiers for betas. 70/30
Android – no permission, 325 character description limit, can only sell from certain countries. Money collected from Google Checkout. Betas run from your own server. Free to publish. 70/30
Blackberry – 3ish day approval time. $2.99 minimum price. Betas run through your own server. $200 per app. 80/20 split
WebOS – 5ish day approval. $50 per app. 70/30.

Dana Nuon @wdnuon

iBooks Page Curl in Six Lines of Code

Transforming page by page turning with deformation. Method returns a vector which is applied to a flat matrix. Each vertex in a matrix has an X/Y. The function adds a Z.

He basically showed how to implement the Apple iBook page turn effect in six lines of code using a Xerox algorithm from a one page PDF with some super heavy conic math. Super awesome demos he had. He’s been doing this stuff for a while. Very experienced, very nice chats after his talk.

Luis de la Rosa @louielouie

Seven Ways to Improve Your App with Servers

Pro: Access more data, differentiate
Con: More work, maintenance

JSON vs XML
JSON – smaller, more efficient – TouchJSON
XML – built-in, ubiquitous – TouchXML
runner-ups: plist (no server will recognize this), custom binary

API enables community (high score list). More processing power (upload image to amazon mechanical turk)

Debugging. Inspect traffic. Charles Proxy. Adjust WiFi proxy preference. Debug with proxy.

Push notification: Your Server -> Apple Push Server -> iPad -> Popup: Your App: Hello World!
- Registration
- Push message, badge, sound. Message 5lines, 24 char
- Best Practice, custom data to highlight item. Push some JSON to highlight.

In-App Purchase
Three types:
- Consumable (example: uBoot torpedos).
- Non-consumable (ie: uBoot levels) – usually built-in
- Subscriptions (magazine)

In-App Purchase Server Product Model
- App store handles CC but then passes it to you.
iPad -> App Store -> Your Server -> iPad

Sync
User data survives data / app loss. Or enable multiple devices per user. Out of scope: WiFi Sync (sync to mac) + GameKit (P2P)

Analytics
- Track usage
- Easy to setup
- Best practice: Send specific custom data (which level are people playing the most?)
- Best practice: Crash handler

Advertising
- Make money with free app
- Design: Dedicate some space
- Animation may help

How to implement
- Hire a consultant like Happy Apps
- DIY
- 3rd party providers like Millennial Media
- Apple (they don’t do much)

Christopher Brown

iPad Advertising

Answered questions and talked about how to do analytics, marketing, ads and what iAds might affect the space. He had solid metrics and graphs that I can’t type out like he did last year with his Tap Metrics talk.

David Smith

14 Days and 11 Apps Later

An amazing walkthrough his flurry of app submissions. He walked through ideas he and his team had for the iPad, demo’d his ELEVEN APPS and showed sales results. Shotgun approach gets a bit of cash but not really going to start a business. He had a lot of great insight like, “it’s not about making money but about getting your $99 worth and learning”. I’m not doing his talk justice. Cool guy.

James Norton @jnorton

OpenGL ES 2.0 & the OpenGL Shading Language

Graphics Pipeline
Why 2.0?
- Programmable shaders enable things that are difficult or impossible without them
- Computations in the GPU
- Can free up memory by replacing static textures

Shaders (introduced in 2.0)
- Vertex Shaders operate on vertex data (attributes)
– Enables CPU to offload many vertex computations to GPU
- Fragment Shaders operate on fragment (pixel) data
– Allow per-pixel effects like per-pixel lighting, procedural textures (bump mapping or env mapping), noise, etc

Shading Language
- Based on C
- Variables, structures, arrays, operators, functions, flow control
- Additional types to support gfx operations (vectors and matrices)

Differences from C
- Stricter type conversions
- No pointers
- Function parameters can be qualified with modification: in (default), inout, out
- For loopers require iteration count to be known at compile time
- Array indices must be constants

Variable Types
- Scalars – float, int, bool

Vectors and Matrices
- Ops work with vec and matrices too
- Multiplication op handles vec matrix and mat/matrix multiplies correctly
- Math ops likely to be HW accel
- Position component access

vec2 pos = vec2(0,1.0)
float xPost = pos.x;
float yPos = pos.y;

Variable Constructors
vec2 texCoord = vec2(0.5, 0.5);

Type conversion
int count = 4;
float fCount = float(count);

Flexible
vec3 pos = vec3(1.0,1.0,1.0);
vec2 something = vec2(pos);

Precision Qualifiers
lowp,mediump,highp (high precision)
highp vec4 color;
MUST declare default or per var precision for float in frag shaders

Type Modifiers
- Uniforms – readonly variables passed in by the application
- Attributes – per-vertex input to the vertex shader
- Varyings – user to communicate form vertex shaders to fragment shader

Simple Shaders
Vertex Shader
attribute vec4 position;
attribute vec2 texCoord;
varying vec2 fTexCoord;

void main(void) {
gl_Position = position; // no view transformation
fTexCoord = texCoord; // will be linearly interpolated
}

Fragment Shader
precision highp float;
varying vec2 fTexCoord;

uniform sampler2D myTextureSampler;

void main(void) {
gl_FragColor = texture2D(myTextureSampler,fTexCoord);
}

TV Noise Fade in Demo
Sigmoid Function: s(t) = 1 / (1 + e^ -f(t-t0) )
Vertex Shader simply passes position to gl_Position like before.

Fragment Shader preample
precision highp float; // use high p as defaulit for floats
uniforma smapler2D test_pattern_texture; // texture sampler for text patter
uniform highp float time; //time since animation start
varying highp vec2 vTexCoord;

void main() {
float weight = sigmoid(time);
float randStatic = rand(vTextCoord);
float randDynamic = rand(vec2(randStatic,weight));
vec4 texVal = texture2D(test_pattern_texture, vTexCoord);
//don't add noise to the black border
if(textVal != vec4(0,0,0,1)){
gl_FragColor = weight * texVal + (12.0 - weight) * randDynamic;
} else {
gl_FragColor = texVal;
}
}

// sigmoid function
float sigmoid(highp float t) {
float f = 10.0;
float t0 = 1.25;
return 1.0 / (1.0 + exp(f * -(t - t0)));
}

// pseudo random number generator
float rand(highp vec2 pos){
return fract(sin(dot(pos, vec2(12.0909, 78 ....
}

Final Thoughts
- OpenGL ES 2.0 allows developers more flexibility than OpenGL ES 1.1. Only will run on 3GS, iPad
- Gold book (the purple book).
- Orange book later for advanced.

How to pair a Bluetooth Keyboard with an iPad

Blog — Dillon @ 5:47 pm


I figured out something that was a bit unintuitive. I have an Apple Wireless Bluetooth keyboard paired with a Mac. I wanted to see if it works on my iPad. I went to Bluetooth->Disconnect on the Mac and the keyboard showed up in the iPad Bluetooth discovery screen but it wouldn’t pair.

I just happened to find a method to get this working:

  • Select disconnect on the Mac.
  • Turn off bluetooth completely on the Mac.
  • Hold down the power button on the keyboard to turn it off.
  • Press the power button once on the keyboard to turn it on.
  • The keyboard will show up in the iPad bluetooth list as before but now when you click it, the keyboard light will start flashing as it pairs.
  • The iPad will tell you to type a code and enter.
  • Good to go!

It works for text areas in the browser and email windows. The on-screen keyboard doesn’t appear. It’s way faster to enter a blog post like this (hehe). It doesn’t seem to work for navigating menus (with the arrow keys or anything). Think of it as a replacement for the on screen keyboard.

Also, be aware that you do have to unpair with the computer. Pairing means 1-to-1. Not 1-to-many. This is how bluetooth (even on PC) works unfortunately. If you want to broadcast keyboard strokes out to many computers you’ll have to use something like VNC. Unfortunately there isn’t a VNC server that I know of for the iPad yet (if ever). The iPhone versions of VNC require you to jailbreak your phone which can be a pain if you like “quick and easy”. I rarely use my bluetooth keyboard on my media center so I didn’t buy a second one. Your mileage may vary.

Hope this helps someone! Post a comment if it did.

iPadcolypse

Blog — Dillon @ 5:25 pm

The Wiff was using the yahoo tv guide (free app) and wants one. It’s got potential as a living room multitasker thingy. I got the 32gb. The 64gb is useless because you still have to pick your media you want to sync. Maybe the 16gb would have been better but I wanted to cram a bunch of stuff on it. If they had a 1TB one (lol) then you could sync your whole iTunes library and movies etc etc. I wish it had an SD slot and some other expansion stuff on it. Like it just mounting up as a disk.

But I did grab an app called “GoodReader”. It’ll probably be replaced by something better (a lot of apps are rushed first to market attempts) but it has DropBox download support (not sync). So I just threw my ebook PDFs (like from other publishers such as PragProg other than the Kindle) and that’s how I got PDFs on it.

Among the star apps so far:
- Kindle app (free), pretty nice. Nicer than the Kindle. I wish it had two page view like iBooks does. iBooks doesn’t have shit for selection right now. No tech books. All my tech books are in the Kindle store or PDF.
- Twitterific (widscreen is the best mode, probably more improvements later)
- NY Times (please release digital Wired mag like this)
- Yahoo Entertainment app
- ABC app, plays episodes in crappy SD but free
- Weatherbug (super slick Radar and forecast all in one huge data overload view)
- Evernote (online notebook). Not as slick as it should be. No formatting options while editing.
- BBC news (meh kinda redudant)
- Plants vs Zombies (PvZ), perfect port

All the official apps are super polished. I haven’t bought the iLife suite apps. I don’t think I need them (maybe I will at work?). I’m waiting for a few of my favorite devs to update their apps:
- Mint
- IRC chat called FlowChat
- Lux Touch (woo multitouch strategy)
- Some kind of SSH awesomeness.
- Ruler app (just because I could measure bigger things?)
- Official facebook app
- How about a WoW auction app?!?! COME ON! Even if I don’t play.

Many apps are $10. So I’m holding out for more free competition.

There’s a scrabble app that plays with your phone. You put your tiles on your phone as the tile rack so you can hide your letters. Everyone plays on the iPad. I haven’t tried it but what a great idea! I’d like to see the MS Surface stuff on these devices like that. Imagine some geeky strategy game or RPG. Or Battleship.

I have to figure out how to sync my calendar and all the stuff I set up on my phone. I’m trying to keep the two devices separate. For example, I don’t need any apps that scan barcodes because it doesn’t have a camera. :P

I’m surprised how fast this thing is. I see why so many games are coming out. Sorry for the short write-up but I’m in toy overload mode.

Dokuwiki April Fools 2010

Blog — Dillon @ 5:43 pm

I was checking out some syntax on dokuwiki’s website and suddenly a duck appeared from the right hand side. When I hovered over it, I got a web browser crosshair. When I clicked on it (*bang*), a bullet hole image appeared in the web page and the duck (*quack*) fell to the bottom of the browser window.

Duck hunt!

I didn’t see it blogged about yet so there ya go. Techcrunch has a good wrap-up of 2010 april fool’s jokes. This year didn’t seem as big as last year’s.

Next Page »
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.
(c) 2012 SQUARISM | powered by WordPress with Barecity