Path to Automatic Animation

Since there’re massive factors involved in animation development, automate the process may not be possible via a single animation engine (need to do a thorough review :P). Instead, automatically puzzle existing tools together may be more practical. Because we could get out the most of each tool. For example, if tool x is the best in painterly style, tool y is the best for animating, they are golden combination to produce film z, then it’d be nice to efficiently transfer the result between each other.

Migration Tips of Large-Scale iOS Project from Circle 1.0 to 2.0


  • The project uses Circle 1.0, i.e. has a circle.yml file on the root directory of the project

Execution Tips

  • How to obtain the ymal file of Circle 2.0, .circleci/config.yml
    • Use the 1.0 to 2.0 config-translation Endpoint to convert circle.yml to .circleci/config.yml. This is the most efficient way to get the correct yaml configuration of the project on Circle 2.0, because it accurately turns all implicit configurations in Circle 1.0 to explicit ones in Circle 2.0. Since Circle 2.0 removes support of implicit configurations, it’s hard to manually write the yml file for Circle 2.0 as it requires being aware of all implicit configurations on Circle 1.0, which could be 10 times slower than the endpoint
  • Code signing
    • “fastlane match”: Circle 2.0 only uses “fastlane match” for code signing, and, certificates and provisioning profiles uploaded to Circle 1.0 are banned on Circle 2.0. For this reason, it’s critical to validate all certificates and provisioning profiles on the git repo associated with “fastlane match” to correctly code signing
    • Keychain: Circle 2.0 uses a temporary keychain, “fastlane_tmp_keychain”, to interact with certificates and provisioning profiles fetched from the git repo associated with “fastlane match”, but it doesn’t have a way to delete the temporary keychain (“fastlane_tmp_keychain” is set by “setup_circle_ci” in the “before_all” lane of Fastfile). Although Circle suggests to call “setup_circle_ci” on the “before_all” lane, it leads to “duplicated keychain” error if two lanes are triggered in one job by “.circleci/config.yml”. For this reason, I suggest to call “setup_circle_ci” in the lane that does code signing to prevent the temporary keychain from being created multiple times when multiple lanes are triggered in one job
  • Minimize debugging time during migration
    • The biggest challenge during migration is debugging failed circle builds. It’s challenging because the long error log looks really scary – what errors are false positives? what errors actually matter? how to minimize the build time of the fix of an error on Circle? Look back to my painful experience of the migration, the following tips are ones I’d suggest to make life happier when doing migration:
      • Focus on the errors printed out, and get more details of logs of error to find the cause. An efficient way of getting detailed log is ssh into the build. For example, if it’s a code signing error, the first thing to check is to validate the certificate and provisioning profiles on the git repo associated with “fastlane match”, as well as code signing configurations of project settings. Trivial errors on the circle log, such as “invalid T” associated with circle machine goes after
      • Test lane locally. If a lane causes error, it’s faster to test locally than pushing to circle to run
      • Comment out unnecessary code. When fixing a particular error, a big time saver is commenting out unnecessary code of the error to save dev time

Now What?

I spent a month on the paper submission of Expressive 2018, which ended up well I guess – practice the writing helps me get clear about the project and contribution.

Now the question is, should I keep working on the paper to finish it, or spend more time on the startup?

There’re still a lot work to be done of the paper. I think it makes sense to finish the paper right now based on my friend’s notes, then refine it after receiving reviews from Expressive 2018.

Startup also requires a lot work:

  • Publish the website
  • Put up the prototype (glad it’s getting more detailed after talking to a lot people of the startup. Speak loudly is so important!)
  • Market research
    • pros and cons of existing 3D animation tools
    • what do non-professionals want based on the animation prototype
  • Resource: How to start a startup by Sam Altman

Maybe I can get up early in the morning to work on startup, then go for the full-time job, after that work on the paper..

Tree.. or Cat

If chance were different

Could I be a tree

Stay there

Waiting for the wind

Getting the rain

Wearing the snow

Besides of the quiet lake



A cat

Kept by kind people

Chocolate and coffee everyday

And sunshine



Whatever it Takes

I’m not sure what I’m chasing,

But it’s certainly something beautiful.

It’s there, just the shape is blurry.

It’s a beautiful feeling.

That makes up my whole world.

Brighten my sky.

Secure Gmail Access with OAuth2 and 2LO in Express Backend


Use Express backend to send email from a gmail account.


Use nodemailer to send email with OAuth2 for obtaining access token, during which “two-legged OAuth” (2LO) is used for signature, which directly obtain the access token without manual user consent.


  • A gmail account belonging to a G Suite Domain. We’ll configure the gmail account for 2LO and use it to send emails in the Express backend
  • A google project used to keep the service account we’ll create. The google project doesn’t necessarily the node project we’re talking about. The main purpose of creating a google project is to use it create a service account


  • “googleapis” for handling authentication and authorization using JWT [1]
  • “nodemailer” for sending email using the gmail account [2]


  • Create service account [7]
    • Select the google project demonstrated in the “Prerequisites” section during creating service account
    • Select “Service Account Token Creator” as the role for the service account as we’re using the service account to generate auth tokens
  • Authorize domain-wide authorization to the service account. The G Suite Account used in domain-wide authorization contains the gmail used to send email from Express backend [8]
  • Preparing to make an authorized API call with Google API Client Libraries:
    • Instruction: prepare to make an authorized API call [2]
    • Google API NodeJS Client Repo [1]
  • Send email from the gmail account with the created service account and access token obtained in the previous step
    • explanation of 2LO in nodemailer [3]
    • instruction of using access token [4]
    • example of using access token [5]
    • here’s a full example of NodeJS code of sending email with OAuth2 and 2LO:



[1] Google API NodeJS Client.

[2] Preparing to Make an Authorized API Call.

[3] Explanation of Two-Legged OAuth (2LO) in nodemailer.

[4] Using access token for HTTP request. “HTTP/REST” section of

[5] Example of using access token in nodemailer.

[6] Nodemailer.

[7] Create Service Account in Google.

[8] Authorize domain-wide authorization to the service account. The G Suite Account used in domain-wide authorization contains the gmail used to send email from Express backend.

Note of An Image Synthesizer

Ken Perlin. An Image Synthesizer.

The paper proposes the initial algorithm of Perlin Noise, and a few variations of the algorithm to simulate a variety of randomnesses in nature.

The technique produces organic randomness appears in nature. It proposes an algorithm to produce random look, which is made uniformly distributed by a narrow bandpass limit in frequency. This statistic character of the randomness maintains unchanged with varying domains. Because the algorithm satisfies statistical invariances under rotation and translation.

The most beautiful part of the paper is the description of Perlin Noise: an organized array, when associated with the gradient of the organized array and an augmentation value, both are stochastic, is transformed to a stochastic value which is used together with the gradient to interpolate areas between the stochastic value of the current organized array and the ones of other organized arrays. NOTE: the augmentation arguments for all organized arrays determines the generated stochastic values. The distribution of the augmentation arguments of all organized arrays determines the uniformness of the generated stochastic values.