The Economics of iOS software

There have been a number of posts recently in the iOS (née iPhone) development community about the shocking fact that app-store purchases follow a Pareto distribution. I assume this is shocking because developers don’t study economics, but I guess I had assumed that everyone in the internets had at least read shirky’s analysis of the same phenomena as regards weblog popularity.

From the perspective of the prospective iOS developer, the relevant question is: is it possible to make a living in the iOS space?

Sturgeon’s Law: 90% of everything is crud.

The first fallacy in analysis of the iOS market is that people take the market gross and divide by the number of apps and say “The average app makes $1,634 a year!” (or something to that effect).  This is not meaningful for an app developer, because it both includes the “superstars” that are making millions in a day, and the whole of the long tail.

So more intelligent analysts tend to cut off the top 1% or so. Unfortunately, this just makes the analysis worse. However, there is an additional fact that presents a more reasonable picture, and that is that 90% of everything is crud.

Now if we assume that iOS consumers are providing a loosely-coupled assessment of the cruddiness of a piece of software when they make a purchase, the iOS market starts to look a lot more reasonable.

In the simplest case, where the frequency of purchase is linearly associated with the cruddiness of the software, we can discard the bottom 90% of the app-store purchases from consideration. After all, you’re not going to make cruddy software, right? :) Now the graph starts to look a little better. We’ve discarded the top 1% of the sales chart and the bottom 90% of the sales chart.

The graph that results is a much more linear graph, with the top app in this zone selling a few thousand a day and the bottom selling several hundred to a thousand a day.  You can jigger the numbers to suit your preferences- for example, you could decide that some significant percentage of people have poor taste or don’t recognize quality – but most of the variants I came up with still amount to a survivable to comfortable revenue stream for a 3-5 person company.

This analysis is relatively simplistic. More advanced assessments would be based on revenue-per-app as opposed to sales-per-app.

Of course, you still have to make an app that isn’t judged as “crud”.

jquery.poll – a periodic polling plugin for jquery.

I needed to poll the server for another project we’re working on (to be announced soon). I started off using the PeriodicalUpdater from enfranchised mind, but I ran into some limitations that were problematic enough that I implemented a new version from scratch.

The problem that made me re-implement was that I was polling for new posts, and if the user made a new post I wanted the wait between poll attempts to go back to the minimum.

The main improvements of this version over the enfranchised mind version are:

  • Multiple active polls
  • Ability to modify the ajax settings after the poll has started
  • Can make a one-time change to the current polling interval.

You can download or contribute from the project page.

Usage:

//All poll options are optional.
var pollopts = {
  //A random name will be assigned if you don't assign one
  name: 'name-of-poll',
  //minimum wait between calls in msec
  min_wait: 6000, // default: 1000
  //maximum wait between calls in msec
  max_wait: 12000, // default: 30000
  // amount to multiply the wait by if the data is unchanged.
  wait_multiplier: 4, // default: 2
  // log poll events to console.log
  doLog: false, // default true
  // A function that overrides the default calculation
  // for how to change the wait if nothing has changed.
  // Should return an integer
  adjustWait: function(xhr, textStatus, current_wait) { ... }, .
};
// simplest way to start polling.
// ajaxopts are defined as per
// http://docs.jquery.com/Ajax/jQuery.ajax#toptions
var mypoll = $.poll(ajaxopts);
// start polling with custom poll options
var mypoll = $.poll(ajaxopts,pollopts);
// get a poll object, but don't start polling
var mypoll = $.poll(ajaxopts,pollopts,true);
// can also do $.poll(ajaxopts,null,true);
// stop the poll
mypoll.stop = true;
// make a one-time change to the poll wait interval
mypoll.setWait(500);
// change the ajax options for the live poll
mypoll.setAjaxOptions(ajaxopts);

who can has i be?

Every multi-user piece of software has an obligation to represent its users in some fashion; to provide for them a digital identity. Furthermore, as the de facto global communication system, the internet ultimately is the system that must represent everyone. The present internet does not provide an identity system that can represent everyone’s identity. To try to uncover one, this essay examines the extant notions of identity, and outlines a the characteristics a genuinely global identity system would require.

Version control in offline mode.

Having successfully built a pyxpcom xulrunner, I am in doubt whether it’s the way to proceed.

  • it’s heavy – like 50mb!
  • writing for it is not like writing a web app, though it has similarities.

Basically I think it won’t help us much with the “degraded” scenario – where someone has “only” a browser to interact with the system – and that’s kind of a non-starter.

So I started to think about what we *really* need on the local system.

Basically the only issue with being just a web app is that we need access to the local version control install. For the most part, this could be addressed by having “whatever we install locally” be itself a server. That seems like a good strategy, because then the remote/local difference is pretty arbitrary.

The user experience issue would be how we interact with external editors.  The only way around the security restrictions I see is for the local server to actually do the open-file-in-editor, and the web app just issues said instruction to the local app.

There are a bunch of value-adds to this – the “server” could be any of these “vcs in a bottle” systems that is nearby, while the “client” could be your phone or whatever.

So I think this is the approach we’ll take.

I’m now investigating mercurial instead of git (windows/mac installers are available) because it plays nicer with the use-cases I’m interested in supporting and it has more of an “API” – plus it’s in python so I can grok it.

Low Power Laser Multitouch, work in progress

Hi I’m Sean Stevens, and I like to make things.

Right now, one of my active projects is a low power LASER Multitouch device.

I was given the LASER idea by http://arbi.trario.us/2008/11/02/diy-laser-multi-touch-table/ and it made immediate sense to me.

Please wear appropriate Safety goggles! these lasers are invisible and can blind you, bad combo.

I’ll post a link to the cheaper goggles we found in the comments later.

So far have the basic physical/optical structure including:

  • Mitsubishi PK10 LED/DLP video projector (17 Watts)
  • Sony PS3 Eye Camera, with IR cut filter removed and replaced with 780nm bandpass (<2.5 watts)
  • MSI Wind netbook with Mac OS X Leopard (10-30 watts)
  • 3mm Polycarbonate screen (roughly 1Meter on diagonal) backed with tracing mylar to rear project onto

We still have to install the 4x 780nm 25mw IR lasers with line optics.

Right now we plan to use Reactivision for blob tracking, and may make it a hybrid blob/active backlit fiducial system.

One goal has been to keep things simple and quick to build, so this is the result from 7-8 hours of work, including swapping the filters.

Stay tuned for LASER installation, software and testing.

it's mostly made of empty space, just like the universe

what’s the difference?

One of the problems with using a real VCS for normal-human-being content management is that nobody understands diffs. Even if they do, the standard line-based differencing algorithms are useless or problematic, even for diff-comprehending folk, for most of the valuable use cases. Here I do a brief survey of the options for these use cases.

  • XML/XHTML differencing. DaisyDiff seems to address this problem. XML dialects rule structured documents these days, but line-comparison gives you bad results and often malformed documents. This good survey of XML differencing got me to DaisyDiff, and it links to other relevant issues.
  • Image differencing. Perceptual Diff compares raster images. Image diff is a nicely simple php image differencer. I can find nothing on higher-level image raster differencing ( comparing layers and whatnot ) and nothing at all about comparing vector images (though SVG might be amenable to xml differencing).
  • Video differencing. Not much here. Some papers, no open-source software I can find (not a surprise, as most of what I can find is related to digital restriction management and copyright enforcement). Current takeaway is if the video collection isn’t in the same format, you’ve not a prayer.
  • PDF differencing. Adobe offers pdf differencing. Not clear if it can readily be used in a server environment. Other tools I could find were windows only, and not geared towards generating the differences as a product itself.
  • “Office document” differencing. There are some scripts for open-office doc differencing. I suspect that using a good xml differ would be sufficient.

General differencing

Current Conclusion

  • Biggest takeaway: constrain differencing to supported formats. I’m pretty close to convinced that we should not offer the ability to manage documents in unsupported formats at all, given how much the user experience of version control degrades when no differencing ability is present. Transcoding all input into supported formats for purpose of differencing is another option.
  • Most of the rich document comparison that chit (can has it together) should do can be done via xml. The devil, as it were, is in making meaningful user interfaces to the difference files thus generated.
  • PDF differencing can be bought, but no good OSS solution appears to exist. UI issues would still apply.
  • Video differencing is a rough field. Probably possible to buy algorithm engines for a big chunk o’ change. UI an issue that I haven’t seen addressed anywhere.

Gittish stuff

This is a brief run-down of projects using git for something other than code management.

Anyway, either nobody really has anything production ready or it’s swamped by the number of CMS/document management systems that use Git for their source code management.

No can has internets (offline use)

One of the issues with a distributed application is that you invariably need offline usage capability.

There are many use cases for this, but I’ll enumerate them, starting from ‘mostly connected’ to ‘mostly disconnected’:

  • Server/peer availability – in a distributed system, many computers will be participating in server roles. They won’t all have high availability, so being “offline” from one or more peer as you seek a new one needs to be not disruptive.
  • Transient connectivity quality – Even a highly connected individual experiences moments where their bandwidth is limited and/or expensive, and so ‘offline’ behaviour in those circumstances is helpful.
  • Intermittent outages – Many people do not have an ‘always on’ connection through a cell modem or something similar. These people frequently have decent access, but there are valuable periods where they are completely without bandwidth.
  • Frequent/predominant outages – There are many environments where transient connections are the norm. In these cases, offline use is predominant.

In all cases, what has to be addressed is not only the ‘simple’ technical requirement of maintaining a responsive UI and preserving state locally, but also the question of synchronizing the data when connectivity is restored. That issue is for a later post.

Offline options:

  • HTML5 offers a standards-based approach for offline usage that is supported by the latest browsers IE 8(!).
  • Google Gears offers offline storage as a plugin for older browsers, and it is built into Chrome.
  • The Pre, iPhone, and Android support the offline features of HTML5.

The data models provided

  • Web Storage allows for the preservation of key/value data, and offers ‘real’ session support. Keys are strings, and “Values can be any data type supported by the structured clone algorithm.”
  • A SQL storage . Basically in-browser SQLite.

Initial Use

The main thing we want to use it for to begin with is storing cryptographic keys for the user.

XulRunner – application target?

It is going to be very difficult to offer a “full” peer through ‘just’ a browser. There are bascic cryptography issues that need to be addressed. Additionally, the offline storage capabilities are fine for actual offline experience, but conflict resolution requires a more advanced approach that is unlikely to be performant within javascript.

However, at long last, XulRunner is on the 3.x firefox codebase, so it seems like this would be a great target for the application. It can be built for some smartphones.

So that would suggest that either we could get XulRunner to compile on iPhone/Android, or we could get the extra components we need (likely git, CouchDb, GnuPG) running on those platforms separately.

In-browser encryption

Encrypting information is key to the effective use of a distributed system. For a variety of reasons, stream-based encryption is rarely helpful for ensuring the security of data in a distributed system. What is important is for the endpoints (consumers/producers) of data in a distributed system encrypt the data they care about.

To achieve this in the browser, we must have a way of performing standard cryptographic techniques on data. Most of the existing cryptographic support in browsers is built around the Public Key Infrastructure, which basically boils down to “trust the corps that have root certificates”. Furthermore, it is entirely concerned with stream based encryption, and doesn’t help content-encryption.

  • JavaScrypt – an implementation of AES in javascript.
  • Enigform and FireGPG provide a firefox exension that allows GPG-based encryption of http content, as well as digital signatures, etc. This is essentially the feature requirement we’re looking for, but Firefox/Moz only.