Blog

So I was going to build a new game a few weeks back, but after a few feedback iterations, I couldn’t get the response that I wanted.

Since I don’t want to fall into the sunk cost fallacy trap I’ve decided to drop the production.

I could polish it with a better graphic but that requires time which I don’t have at the moment, you can still check it out here and play with the custom editor here.

Coming out with a simple yet extremely interesting game idea, is super hard.

The drawing was made by my daughter.

I have it.

I don’t know how to control it

It ruined my life several times

Update 2020/06/03 Well, we’ve finally ended it, 1.5 years collecting data, taking the photo of every single location, and making the MVP went down the drain.

But worry not, although I’m getting older, this will not be my last venture, as long I can work 16-18 hours a day someday I will have a business.


Hourtrip is a travel website that I did with a few of my friends although we are still struggling on the business side, I’m quite proud of the algorithm.

Have you gone on a trip and thought of “I only have 6 hours to spend where should I go?” well with Hourtrip you can! 

The concept is pretty simple, have you gone on a trip and thought of “I only have 6 hours to spend where should I go?” well with Hourtrip you can! and it’s smart enough to know whether it’s time for lunch or dinner, which places you should go to, determine what time you should go back, etc.

As an overview, the algorithm is pretty simple. Extract the user’s preference, use that data to filter the database, then show the recommended locations.

To show the recommended locations, it needs to iteratively calculate the closest location from the original location, the graph below explains roughly how the iteration works.

Check the weather
I use OpenWeatherMap API to get the info from, at this point, I only check whether it’s bad or good, in the future, I’m planning to check whether the weather is good enough for traveling.

For example, a drizzle might not stop you from going to that restaurant you like.

URL = "http://api.openweathermap.org/data/2.5/forecast/?units=metric&APPID=0cdde5a888c7dc5664225b6112dcd07d"
path = URL + "&lat=" + kwargs['origin']['lat'] + "&lon=" + kwargs['origin']['lng']
result = json.loads(urlopen(path).read().decode('utf-8'))

Check the preferences
Checking the preferences is simply a hash lookup.

if self.match_tags(self._types, v['tag']):
  di = DestinationItem(data=v)
  self._dest_list.append(di)

Check the walking duration and Location’s tiers
There are two components when checking the walking duration, the time to get from the current location to the next location, and the current location to the original point.

Determining the walking speed is quite tricky and I have to admit is a mixture of real data and hunch, according to Wikipedia, the average walking speed is 1.4 m/s but for tourists, they might walk longer than that, due to the traffic, pausing for the sights, having unruly kids, etc. so I add another 1 second to anticipate that.

WALKING_SPEED   = 2.4  #  +1 to anticipate sight seeing, traffic, etc.

def get_distance(self, node_origin, node_dest):

    origin  = self.get_latlng(node_origin)
    dest    = self.get_latlng(node_dest)
    dist    = round(geodesic(origin, dest).kilometers * 1000)

    return {
        'dist_from_source': dist, # meters
        'walking_time': round(dist/WALKING_SPEED)
    }

In the beginning, to calculate the nearest distance I use Google Map API, but boy was that expensive! Nearly bankrupt all of us so I use GeoPy library instead.

Once the walking duration is understood it’s easy to get the nearest location, now this has to be tied with the location’s tier (score value).

def get_shortest_dest(self, node_origin, tier, p_dist=None):

  dist    = None
  index   = -1
  arrival = None

  for i, v in enumerate(self._dest_list):

    if self.match_tags([v.tier], tier):

      d = self.get_distance(node_origin,v)
      # estimated arrival times
      # TODO: there's a variable for arrival_time, change tothat
      arrival = self._timestamp + datetime.timedelta(seconds=d['walking_time'])

      if v.is_open(arrival):

        if dist is None:
          dist = d['dist_from_source']

        if p_dist is None:

          if d['dist_from_source'] <= dist:
            dist    = d['dist_from_source']
            index   = i
        else:
          # if between dest_a and dest_b subtier exist then calculate
          if d['dist_from_source'] <= dist and d['dist_from_source'] <= p_dist:
            dist    = d['dist_from_source']
            index   = i

  return { 'index': index, 'dist': dist, 'arrival': arrival}

def get_next_dest(self, node_origin):

    result  = self.get_shortest_dest(node_origin, ['1','2'])
    i       = result['index']
    ii      = -1

    # 2. if tier [1,2] undefined, search [3,4]
    if i < 0:
        result  = self.get_shortest_dest(node_origin, ['3','4'])
        ii      = result['index']

    else:
        # if tier [1,2] exist, search for the closest [3,4] tier
        # since the last tier has already been removed, then automatically the next tier will be refered
        result  = self.get_shortest_dest(node_origin, ['3','4'], result['dist'])
        ii      = result['index']

    # return tier 3/4
    if ii >= 0 and len(self._result_dest) > 0:

        tmp_tier = self._dest_list[ii].tier
        tmp_all_tier = self._main_tmp.get_all_tier()

        # if tmp_tier not in tmp_all_tier:
        #     # ensure that each leg has only 1 3/4 tier
        #     self._main_tmp.add_tier(tmp_tier, ii)
        #     return self._dest_list.pop(ii)

        # TODO: this repetition, refactor
        if self._dest_list[ii].is_gluttony_time(result['arrival']):

            if tmp_tier not in tmp_all_tier:
                self._main_tmp.add_tier(tmp_tier, ii)
                return self._dest_list.pop(ii)

        else:

            if tmp_tier not in tmp_all_tier:
                self._main_tmp.add_tier(tmp_tier, ii)
                return self._dest_list.pop(ii)



    if i >= 0:
        # 1. save it to the main_temp for refference
        self._main_tmp = self._dest_list[i]
        return self._dest_list.pop(i)

    return None

Each trip will be distributed between 1 premium locations’ tier and 3 ordinary location’s tier so if the user still has time to visit other places then the same pattern will be repeated.

// Calculating the time budget

if(walking time + spending time + going home time < time budget) {
   repeat;
} else {
   return result;
}

And of course, the pattern may vary depending on distances and schedules.

Check schedules
There are 3 schedules I need to check, locations’ schedule, public transport schedule, and whether it’s time for lunch/dinner.

Checking it is a simple lookup table comparison.

def is_gluttony_time(self, time):

    # Restaurant 1100-1400, 1700-2100
    # Cafe 0700-1100, 1300-1700
    # Liquor 1700-2600
    time_int = int(time.strftime('%H%M'))
    time_slot = [
        {
            'open': [1100, 1700],
            'close': [1400, 2100],
            'tag': ['restaurant']
        },
        {
            'open': [700, 1300],
            'close': [1100, 1700],
            'tag': ['restaurant','cafe']
        },
        {
            'open': [1700],
            'close': [2600],
            'tag': ['liquor']
        }
    ]

    for i, data in enumerate(time_slot):

        a_open   = data['open']
        a_close  = data['close']

        for j, v in enumerate(a_open):
            if time_int > v and time_int < a_close[j]:

                # TODO: change self._types to tag
                check = self.match_tags(time_slot[j]['tag'], self._types)

                if check:
                    self._raw['is_gluttony'] = True

                return check

    return False

So that’s the gist of it, I still have the plan to expand it, find some investors and do what all startup founders do drown in money and be famous or have a mental breakdown, hahaha.

Icons made by dDara from www.flaticon.com
Icons made by catkuro from www.flaticon.com
Icons made by Smashicons from www.flaticon.com

It has been roughly 3 years since I wrote a blog post —yep, has been meditating quite a lot— and my interest has shifted, I love Technology but more on the business and growth side.

Although I haven’t completely abandon coding, I am building a new startup and still binging on those programming books!

This is a bit too late, but I had given a talk at Code Chrysalis which gotten a very positive response and thought I’d share the deck.

Let me know if you any feedback below and a big shout out to Kani and Yan 😉

A bit of intermezzo and belated post, this is my presentation deck for the Osaka Web Designers and Developer Meetup.

I talked about Creative Coding, a field that I have been trying to master for almost 10 years now.

Thank you to @leichtgewicht, Victor Trofin, @DrKenHo, and Benjamin Murden, who has given me the opportunity.

And to all the readers, hope you’ll like it 😉

I’ve recently worked on a pretty interesting project and thought perhaps I could share some of the processes.

Before I continue, a slight digression, I need to outline these 3 important components that in every digital creative production must have, which are time, scalability, and optimisation. I will explain those components succinctly.

Time
Time is money, in a simplified instance perhaps it can be explained if you had project A, then you need to consider the production cost, for an agency it can be salaries, operational costs, tax, etc. and lastly you need a bit of margin to keep you cash-flow positive or perhaps for any miscalculation that may happen, so ultimately the shorter the time you spend on your production the more efficient the cost will be.
Although in can get complicated since shorter time means lower quality and in a competitive environment this will affect your business, and if I might add this condition does not apply, but I will reserve that discussion for another time.

Scalability
Idea and creativity are malleable, if you were working with complicated projects or difficult clients, the approval process can be a bit tedious or bureaucratic.
There ways to approach this systematically, one of which is managing the client expectations or using the design sprint methodology, but the least minimum approach is having a framework that can scale or reusable.

Optimisation
Optimisation is a hard thing to achieve, even large tech companies often had catastrophes and in digital agencies, you certainly cannot dedicate your undivided attention to the matter, but at the least is to have the minimum viable product.

But what is minimum can be a fickle thing, this will dependent on the product. A website and live installation projects will have different priorities, even certain client expectation can also become a factor.


Since now we have a clear topic confinement, let’s continue.

What’s the Concept
In short, it’s an online game site, where the goal is to find the hidden protagonist, sort of like Where’s Wally, and they can interact with the game by swiping or using the device orientation.

There’ll be several scenes variations where she’ll be hidden.

Production Flow
Let’s start with the production flow, have a look at the diagram below;

Building the Stage
The focal point is the stage, any changes to it will mostly affect the site, it needs a system where the it can be designed and modified in an instant.

Fortunately, Photoshop has script functionality plus (I’ve posted a blog a long time ago) the designer can use it with ease, now have a look at the diagram below.

This how the layers are laid out, the pink circles are the character or clickable object and cuts are the map, once the images have been exported the subsequent steps is to extract its information into the following JSON.

{
	"document": {
		"width": 11438,
		"height": 2048
	},
	"layers": {
		"miss_09_s_1": {
			"x": 10123,
			"y": 1569,
			"width": 10208,
			"height": 1711
		},
		"miss_09_s_2": {
			"x": 10149,
			"y": 1569,
			"width": 10238,
			"height": 1711
		},
		"success_01_s_1": {
			"x": 5608,
			"y": 1362,
			"width": 5718,
			"height": 1487
		},
		"success_01_s_2": {
			"x": 5608,
			"y": 1367,
			"width": 5702,
			"height": 1487
		},
		"map02": {
			"x": 4096,
			"y": 0,
			"width": 6144,
			"height": 2048
		},
		"map01": {
			"x": 2048,
			"y": 0,
			"width": 4096,
			"height": 2048
		},
		"map00": {
			"x": 0,
			"y": 0,
			"width": 2048,
			"height": 2048
		}
	}
}

The “document” key holds the entire stage dimensions, the “layers” key holds the graphic components information, this will then be processed and calculated in Javascript.

Consolidating the Assets
The last point is to consolidate all assets into one giant JSON, the purpose of this step is simply asset management and convenience, each asset will be loaded and utilized according to its purpose.

For instance, stage A will consist of certain images or audio that aren’t included on another stage.

I think that’s it for part 1, thank you for reading.

A slight detour here just wanted to talk about WordPress development —not actually cutting edge— but since I’ve been working on a few WordPress projects lately I thought I’d share some of my tips, plus remember if you’re good at WordPress you could make a decent amount of ¥¥¥.

Prerequisites
This is my enviroment.

  • Mac OSX v10.11.3 (El Capitan)
  • Homebrew 0.9.5
  • Docker 1.9.0
  • Docker Kitematic 0.9.3

Choosing the right Template
There are myriads of templates out there with varying difficulties.

Got a bit of learning curves
https://github.com/Obox/layerswp this one is quite unique since it extends the WordPress Customizer.
https://github.com/somerandomdude/Frank
https://github.com/roots/bedrock
https://github.com/roots/sage
https://github.com/Automattic/_s
https://github.com/mattbanks/WordPress-Starter-Theme

Just bare template
https://github.com/thethemefoundry/make

Most of them are already using the Gulp/Grunt combination so if you’re unfamiliar with it then get cracking.

Using Docker for Development Environment
The zeitgeist! Docker can be seen in every corner at the moment and you can integrate it with any type of application and it’s easy, I had the Tensorflow set up within minutes, although there are a few quirks in using Docker and Kitematic so I recommend you to delve more since you’d be able to debug your environment lest something happens.

The first thing you have to do is download Docker Toolbox and Kitematic, you can go to their website and download it like when Windows 95 was still around or use brew cask.

$ brew cask install dockertoolbox
$ brew cask install kitematic

And afterward, just start Kinematic up! you’ll immediately be presented with this window.

Lovely UI isn’t, this is what sold me the first time!

Now that you have everything up and running, the next thing you need to do is to create the docker-compose.yml, start by opening up the CLI (at the bottom left) and type in the code below.

$ mkdir wordpress 
$ cd wordpress 
$ vi docker-compose.yml

And paste this code, I’ve added a very generic comment, again Docker is a broad topic so try to read their website.

And then build the container;

$ docker-compose -d

Once everything has been built, go to the Kitematic window and you’ll see the WordPress container listed, click the setting tab and then Ports, where you’ll find the IP address, click that and it’ll automatically open the WordPress site.

Once you finished you can click the stop button on the Kitematic window or start to initiate it.

Other Environments
There are alternatives besides Docker that you can choose the easiest one would be MAMP (A slight warning there’re a few system conflicts on El Capitan), another one would be Trellis which is based on Vagrant or if you’re adventurous you could install Centos and, of course, El Capitan comes with its own apache server.

Ajax Page Transition
The fun part in developing WordPress —well, relatively speaking— would be avoiding all the plugins peril, since a copious amount of it will bog down your site.

There are a lot of websites that talks about building your own plugin, but something that compelled me was Ajax Page Transition since you could create an uninterrupted experience plus is super-cool. (Some of you would probably snigger in disgust right now)

Before I start I need to remind you that the proper way to handle AJAX in WordPress is to use; register, enqueue and localize the JavaScript files using wp_enqueue_scripts instead of wp_print_scripts.

The system can be achieved with a simple Ajax and a hint of History API, have a look at the diagram below;

diagram

It’s pretty simple isn’t! Onwards with the code.

First, you need to structure the template accordingly so it’ll be easier to extract and/or overwrite the content later, like so;

<body>

     <!-- The content div would be used as a container -->
     <div id="content">
          <h1>About Us</h1>
          <p>Lorem ipsum..</p>
     </div>

</body>

Second, to change the URL path without refreshing the browser, utilize the history data.


// when the back button is pressed, each recorded history will be removed
// this listener will listen to that event
window.onpopstate = function(event) {
   // Update whatever you have on the page
    updatePage();
}

// This is just to illustrate the function
function callPage(url, pageData) {

  // If you're using old browser don't forget to add a fallback
  history.pushState(pageData, pageData.title,  url);

}

// Trigger this method through button click
callPage("/about/", { item: { title: "About us" } });

There’s not much to it, you can read it more here if you want and if you need a fallback you can use history.js.

Afterwards, call the page through Ajax.

function connectPage(url, data ) {

    $.ajax(
      // type: 'GET', // optional
      url: url, // pass the page url
      data: data // add this to pass data between content
      cache: false, //Setting cache to false will only work correctly with HEAD and GET requests. It works by appending "_={timestamp}" to the GET parameters
      // dataType: 'html',  //optional
      success: function(data) {

        if(data.length) {

          // Handle Error
          onError("Data empty");
        }

        // Handle success
        onSuccess(data);

      },
      error: function(errorThrown) {

        // Handle Error
        onError(errorThrown);

      }
    )

}

connectPage("/about/", {});

As you can see you probably could merge those two functions together.

Once the data is extracted, the next step would be isolating and attaching the HTML content.

function onSuccess(data) {

    data = data.split('id="content"')[1]; // the ID name can be anything you want.
    data = data.substring(data.indexOf('>') + 1);

    var depth   = 1,
    output      = '';

    while(depth > 0) {
      var temp = data.split('</div>')[0];
      var i = 0;
      var pos = temp.indexOf('<div');

      while(pos != -1) {
        i++;
        pos = temp.indexOf('<div', pos + 1);
      } 


      depth   = depth + i - 1;
      output  = output + data.split('</div>')[0] + '</div>';
      data    = data.substring(data.indexOf('</div>') + 6);
     
    }

    // attach the HTML output
    document.getElementById("content").innerHTML = output;

    // Update Google Analytics
    ga('set', { page: window.location.pathname })
    ga('send', 'pageview')

    // Update page
    updatePage();

}

Retreiving Post with Nonce

By using nonce (number used once) your site will be protected against cross-site request forgery.

For instance, if we wanted to retrieve a certain post, then we could do something like this.

Modify the Ajax call we had earlier.

connectPage("/about/", {
  action: 'get_post_ajax',
  postID: id, // The Wordrpess post ID
  security: <?php wp_create_nonce  ('blahblah'); ?>
});

Then on functions.php check for the value;

  function get_posts_ajax() {

      if ( isset($_REQUEST) ) {

          check_ajax_referer('blahblah', 'security' );

          $post_id    = sanitize_text_field($_REQUEST['postID']);
          $post_info  = get_post(intval($post_id));

          $cat        = get_the_category(intval($post_id));
          $cur_cat_ID = $cat[0]->cat_ID;
          $args       = array(
            'category'  => $cur_cat_ID,
            'orderby'   => 'post_date',
            'order'     => 'DESC'
          );

          $posts  = get_posts( $args );

          wp_send_json(array(
            'ID'                    => $post_info->ID,
            'post_author'           => $post_info->post_author,
            'post_date'             => $post_info->post_date,
            'post_date_gmt'         => $post_info->post_date_gmt,
            'post_content'          => $post_info->post_content,
            'post_title'            => strtoupper($post_info->post_title),
            'post_excerpt'          => $post_info->post_excerpt,
            'post_status'           => $post_info->post_status,
            'comment_status'        => $post_info->comment_status,
            'ping_status'           => $post_info->ping_status,
            'post_password'         => $post_info->post_password,
            'post_name'             => $post_info->post_name,
            'to_ping'               => $post_info->to_ping,
            'pinged'                => $post_info->pinged,
            'post_modified'         => $post_info->post_modified,
            'post_modified_gmt'     => $post_info->post_modified_gmt,
            'post_content_filtered' => $post_info->post_content_filtered,
            'post_parent'           => $post_info->post_parent,
            'guid'                  => $post_info->guid,
            'menu_order'            => $post_info->menu_order,
            'post_type'             => $post_info->post_type,
            'post_mime_type'        => $post_info->post_mime_type,
            'comment_count'         => $post_info->comment_count,
            'filter'                => $post_info->filter
            )
          );

      }

      wp_die();
  }

Conclusion
When working with WordPress the first thing that you always need to consider is the security aspect, its ubiquitousness attracts hacks, always follow the best practice (not guaranteed), learn about the basic security hacks, implement re-captcha, update the WordPress constantly, etc.

Another note also WordPress is notorious for its sluggishness but then again there is a trade-off that can be had, huge communities, endless plugins (but don’t use it too much), is great for obnoxious client 🙂 , but if speed is what you after then I suggest you try Amplify or Ghost.

Have been testing with my latest product! Using http://beyond-reality-face.com/ as the face recognition API

View post on imgur.com


I’ve been using TouchDesigner lately for the latest Adidas project.

I was intrigued by it when I first saw Gravity, their whole system seemed robust, so one thing leads to the other we ended up using it for a real project, I had to learn everything from the beginning, up to the actual project launch in 3 weeks time which was surprisingly easy to do.

Their system is similar with Quartz Composer if anybody still remember it that is.. there are 2 languages that you can use Python and TScript, obviously Python was the best choice because you can use common Python libraries.

test

It can seamlessly runs with almost any version of GLSL and on top of that you can throw in audio stream, OSC, Kinect, Arduino, Oculus, integrate it with redis or nodeJS or OpenCV and have a super-complex system that runs in real-time and yet -depending on how your code is- it will still chugs along without any problem.

We’ve had it running for 3 hours straight and the framerates didn’t once drop, although if you were unfortunate you’ll caught it when it’s collecting garbage apparently TouchDesigner doesn’t collect any garbage, so not sure what have had happenned then.

For anybody who want to learn TouchDesigner and have a hot minute to spare, I recommend to start from Matthew Ragan’s website his teaching is fantabulous!