Author: Matt

  • App Business Milestone

    With the recent addition of a new advertising platform for my apps the last few days have tipped the business passed a small milestone of having a $50 day. Even though it’s just a seasonal spike from all the advertising prices raising due to the holidays it’s still nice.

    Across all my apps there are now roughly 250,000+ sessions per month (# of times the app gets started)

  • New Living Room

    We made some design changes to the living room over the last while. Painted the walls and put up curtains.

    Before:
    IMG_20121215_113354

    After:
    IMG_20121220_180858

  • A Live Text Chat Server

    I’m facing the challenge of building a live chat server for use in a mobile app. It is an interesting bit of code to write and I’m finding myself learning a few new things to get it working.

    My first thought was to build it using websockets over HTTP but that looked too difficult to build on both the server side and client side.

    On the server side there you need to have a different kind of server. The standard Apache web server is just not going to cut it if there are 1000+ people in a realtime chat. It’s necessary to change things over to a service such as Node.js or a Python Twisted server.

    The overhead of websockets on the client side was also too high and it appears that JSON over straight sockets is the way to go.

    From a design perspective there is the issue of room size. If there are too many people talking at once it becomes difficult to follow any sort of conversation, and with too few people the community will feel dead and unresponsive. It’s important to separate people out into ‘rooms’ to avoid too much noise while not spreading them too thin so that there’s no one to talk to. It will be an interesting challenge to try and find the right balance to this.

    I’m hoping to have something functioning by next weekend.

  • A Productive Christmas Break?

    There’s just so much work to be done that I’m really going to have to strive for a very productive month of programming.

    I need to update all my apps for the new year and hopefully launch a few new ones.

    To that end I’m planning on taking some more time off work over the next couple weeks and months to push through some coding projects.

    In the pipeline now are one new website, a redesign of another website, update 7 of my iPhone Apps with improvements aimed at increasing retention and ad revenue, and making a lot of progress on my big social game.

    The social game is what has been on my mind the most and I have very high hopes that it is going to be amazing when finished. I expect I will have to hire some artists in March to help bring a level of polish I haven’t yet been able to achieve on my own.

    Will it be possible to have a productive Christmas break or will there be too many distractions?

  • Progress on New Game

    So the new game is going to be called Tycho City. It’s based on building a lunar base and battling other bases for the moon’s valuable resources. There’s a mix of two styles of gameplay the first is the simulation of the moon base with building and upgrading mines and energy collectors. The second is a defence game where you attack other bases by landing your troops/robots and taking on their defences.

    Unlike my previous games this time I’m taking some good advice and modeling other successful games. Rather than try to invent something brand new I am going to try to put my spin on a popular and profitable game concept.

    One thing about this type of game is just how much data there is to manage.

    This game will be heavily dependant on web servers to deliver almost everything. All of the costs, upgrade paths, graphics, assets, music, rules, build times, and store menus will be defined and controlled from my web backend. It will allow us to dynamically update and tweak the game play to optimize things after it’s released and keep it fresh with new content. But it’s a lot of Data. And that’s just on the static side of things. The server will also keep and save the game state of every player’s game in real-time.

    Organizing all of this information in a way that is going to be easy to understand and work with is not easy. But it’s a fun challenge.

    This game is going to take several more months to finish. But it’s going to be my best chance of getting a major hit.

  • iAd Download Script

    Unfortunately Apple doesn’t have a nice easy API for downloading your revenue numbers from iAds. The only way around that right now is screen scraping the information, or manually downloading the reports.

    Thanks to the awesome python requests library I was able to put something together in just 50 lines of code.

    It’s a function you can integrate with your project to download daily iAd report files.

    It is also simple enough that it should be relatively robust against future website changes by Apple. (hopefully)

    If you decide to use this I would recommend storing your account’s publisherID to avoid having to get it each time which will speed it up.

    (this code is also on github: https://github.com/mfwarren/iAdDownload)

    import requests
    import re, os, datetime
    
    url_base = 'https://itunesconnect.apple.com%s'
    signin_url = url_base % '/WebObjects/iTunesConnect.woa'
    download_csv_url = 'https://iad.apple.com/itcportal/generatecsv'
    
    def getPublisherID(session):
        """
        publisher ID is a number that is buried deep... lets hope
        this code doesn't break often
        """
        headers = {'Content-type': 'text/x-gwt-rpc; charset=UTF-8'}
        iad_service_url= 'https://iad.apple.com/itcportal/service/startup?requestId=GUEST_1331628761939_0__1331628761950__null'
        body = '5|0|4|https://iad.apple.com/itcportal/itcportal/|E8DB97D87973D76A7C9096DCF8A83BB5|com.qwapi.portal.itc.client.rpc.IITCStartupService|getStartupData|1|2|3|4|0|'
        r = session.post(iad_service_url, data=body, headers=headers)
        endpos = r.text.find('com.qwapi.portal.client.rpc.dto.UserDTO')
        endpos = r.text.find('"', endpos-4)
        startpos = r.text.rfind('"', endpos-20, endpos-4)
        pubID = r.text[startpos+1:endpos]
        if not int(pubID):
            raise Exception("Failed to get publisher ID")
        return pubID
    
    
    def downloadiAdFiles(appleId, password, publisherId=None, outputDirectory='.', daysToDownload=14, outputFormat='iAd_D_%m-%d-%Y.txt'):
    
        session = requests.session()  #session used to maintain cookies etc.
    
        #get signin page to find url for posting signin credentials
        r = session.get(signin_url)
        match = re.search('" action="(.*)"', r.text)
    
        #login to ITC
        params = {'theAccountName':appleId,
                'theAccountPW':password,
                '1.Continue.x':'10',
                '1.Continue.y':'10',
                'theAuxValue':''}
        r = session.post(url_base % match.group(1), params=params, headers={'Content-Length':'0'})
        r = session.get('https://iad.apple.com/itcportal')
    
        if publisherId is None:
            publisherId = getPublisherID(session)
    
        reportDates = [datetime.date.today() - datetime.timedelta(i + 1 ) for i in range(daysToDownload)]
    
        filenames = []
        for downloadReportDate in reportDates:
            filename = os.path.join(outputDirectory, downloadReportDate.strftime(outputFormat))
            if (os.path.exists(filename)):
                continue
    
            dateString = downloadReportDate.strftime('%m/%d/%Y')
            params = {'pageName': 'app_homepage',
                'dashboardType':'publisher',
                'publisherId':publisherId,
                'dateRange':'customDateRange',
                'searchTerms':'Search Apps',
                'adminFlag':'false',
                'fromDate':dateString,
                'toDate':dateString,
                'dataType':'byName'
            }
            r = session.get(download_csv_url, params=params)
            if r.status_code != 200:
                raise Exception("Script failed to dowload - check login credentials & publisher ID")
    
            with open(filename, 'wb') as f:
                f.write(r.content)
            filenames.extend([filename])
    
        return filenames
    
    
  • “Good Artists Copy, Great Artists Steal”

    That quote from Steve Jobs in 1996 holds true for more reasons than are apparent at first thought.

    I’m currently working towards completing my first ‘real’ game on iOS but with a 2 person team it will take an exhaustive amount of work to produce something that fulfils our vision.

    Cutting scope is the easiest thing to do but also shortsighted. Chopping off features limits your ability to compete in this highly competitive market. You need to ship something, but can’t afford to cut vital features.

    Originality is overrated. It is high risk and an uphill battle. People (for the most part) cling to the familiar so producing a game that is utterly unique and original is like trying to replace thanksgiving turkey dinner with tofu and seaweed salad. Thank you for trying but what I really wanted was turkey.

    The better approach is to take what you can from the existing best of the best and find areas you would like to improve upon and then work towards that goal. Having actual physical manifestations of similar products and features vastly reduces the burden of figuring out how to steal them for yourself.

    Starting with the reference for 90% of the work removes the need to communicate how every detail needs to work and so you can get right to implementing it. The few unique parts you bring to the table serve to evolve the platform and make your game even better.

  • Painted Living Room

    Sometimes all that’s needed is a little bit of paint.

    Last weekend Heather and I started painting our living room in an effort to make the space more liveable. By painting over the brown and beige walls with white the furniture becomes more of a focus and the room feels brighter and bigger.

    With a couple of new floor lamps, an airport express box for playing music, and possibly a new couch in the room it should get more use.

    We’ll put on the last coat of paint this weekend and I’ll post a picture.

  • Virility

    Having a game that naturally promotes itself is a challenge. The old techniques of tweeting your score or sharing the app on facebook are not enough to make something popular or have it go viral. The mechanic to make something go viral has to be much more deeply integrated.

    The virility of games like Draw Something was astounding, but it was also a natural extension of the type of gameplay. In order to play you needed to get your friends in the game. It’s growth was astounding because of that.

    I started to dissect another popular game recently called Clash Of Clans made by SuperCell which takes things to a new level. The live in game chat and team gameplay create a fascinating dynamic that works extremely well on a mobile device.

    It’s clear that the bar has been raised. Creating a top game now requires a complex server side backend, a massive amount of content, depth of gameplay which can attract new players but keep existing ones playing for a long time and a polished high quality look.

    Thinking now about creating a great game to be released in 6 months is a real challenge. How much more complexity will be expected by then?

    The added complexity of making a game naturally viral rather than tacking on twitter and facebook buttons is hard. It requires thought about how to change the game mechanics to work these things into the core of the game. Making games that are inherently social will be a fun challenge for game designers. A challenge I’m looking forward to.