Friday, October 16, 2015

The hello world web app of OAuth 2.0 client for Google App Engine

The sample project is here.

However, the missing installation and setup instructions for development server are:
(1) download the above project sample and say put it in project folder called helloworld
(2) install google-api-python-client in the project folder helloworld
(2a) Create a file in the project folder with the following contents
from google.appengine.ext import vendor

# Add any libraries installed in the "lib" folder.

(2b) Download google-api-python-client and related libraries into the lib sub-folder of the project folder
cd helloworld
mkdir lib
# if your Mac doesn't have pip do this -> sudo easy_install -U pip
pip install -t lib google-api-python-client

(3) Follow the instructions in here to setup OAuth 2.0 in the developer console for web app in Google App Engine Developer Console

(4) Make sure to enable Google+ API in the console or else you will get KeyError: 'id' when testing

(5) Fill in Authorised Javascript origins and Authorised redirect URIs in the developer console and click create or save

(6) copy the created Client ID and Client secret from the developer console and fill in the file client_secrets.json, like below

(7) Wait a few minutes and start the development server and test

Here is how to add other OAuth 2.0 apps such as Windows Live or facebook.
(1) Setup and revoke websites are :
# Google+ APIs
# Manage Application -
# Revoke Consent -
# OAuth 2.0 info

# Windows Live API
# Manage Application -
# Revoke Consent -
# OAuth 2.0 info

# Facebook auth apis
# Manage Application -
# Revoke Consent Procedure
# Log on to Facebook.
# Click the drop-down arrow in the upper right, then select "Settings"
# Select "Apps" on the left sidebar.
# Scan the list and click the "x" on the right of any app you want to clear.

(2.1) The client_secrets_windows_live.json file is like this
  "web": {
    "client_id": "0000000012345678",
    "client_secret": "abcdefg1lHiJK5HCnlZb-aaaaaXX",
    "redirect_uris": ["http://localhost:8080/windows_live_callback"],
    "auth_uri": "",
    "token_uri": ""

(2.2) The client_secrets_facebook.json files is like this
  "web": {
    "client_id": "123456789012345",
    "client_secret": "a1234567e123456bc4b123456ab6543g",
    "redirect_uris": ["http://localhost:8080/facebook_callback"],
    "auth_uri": "",
    "token_uri": ""

(3.1) The decorator_windows_live is like these
# Scopes are space-separated, e.g. 'wl.signin wl.basic'.
decorator_windows_live = appengine.oauth2decorator_from_clientsecrets( os.path.join(os.path.dirname(__file__), 'client_secrets_windows_live.json'), scope='wl.signin wl.basic', message=MISSING_CLIENT_SECRETS_MESSAGE)

(3.2) The decorator_facebook is like this
# Multiple Scopes should be comma-separated, e.g. 'user_about_me,email'.
decorator_facebook = appengine.oauth2decorator_from_clientsecrets( os.path.join(os.path.dirname(__file__), 'client_secrets_facebook.json'), scope='user_about_me,email', message=MISSING_CLIENT_SECRETS_MESSAGE)

Monday, October 12, 2015

The Hello World of Google Protocol RPC (javascript part)

The Hello World of Google Protocol RPC using python is here

with an example on Testing the Service from the Command Line

Here I add the javascript part on how to test the RPC service in the browser using the google app engine
templates/index.html    Select all
<!DOCTYPE html> <html><head><title>post service demo</title> <script src="//"></script> <script language="javascript" type="text/javascript"> function submitform() { $.ajax({ headers: { "Accept": "application/json", "Content-Type": "application/json" }, type: "POST", url : "/hello.hello", dataType : "json", data : JSON.stringify({"my_name": $("#my_name").val()}), error: function () { alert("loading Ajax failure"); }, onFailure: function () { alert("Ajax Failure"); }, statusCode: { 404: function() { alert("missing info"); } }, success: function (response) { alert("The server says: " + JSON.stringify(response)); } }) .done(function(data) { $("#result").text(data["hello"]); }); };</script></head> <body> <h1>Hello world!</h1><br> <p><form id="myform" method="post" action="/hello.hello"><input type="text" id="my_name" name="my_name" value="javacom"><input type="button" id="submit" value="submit" onclick="submitform();"></form></p> <p><div id="result"></div></p> </body> </html>    Select all
import os import jinja2 import webapp2 TEMPLATE_DIR = 'templates' JINJA_ENVIRONMENT = jinja2.Environment( loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__), TEMPLATE_DIR)), extensions=['jinja2.ext.autoescape'], autoescape=True) class MainHandler(webapp2.RequestHandler): def get(self): template = JINJA_ENVIRONMENT.get_template('index.html') self.response.write(template.render()) app = webapp2.WSGIApplication([ ('/', MainHandler) ], debug=True)

app.yaml    Select all
application: helloworld version: 1 runtime: python27 api_version: 1 threadsafe: yes handlers: - url: /hello.* script: - url: .* script: libraries: - name: webapp2 version: "2.5.2" - name: jinja2 version: "2.6"

Saturday, October 3, 2015

How to compile Quantlib and Boost under Windows 10

(1) Download and install Visual Studio Express 2015 for Windows Desktop. Note that Express comes in a variety of versions. The one needed to compile console programs is Express for Windows Desktop (neither Express for Web nor Express for Windows will do)

(2) Download and install boost Prebuilt windows binaries - boost_1_59_0-msvc-14.0-32.exe from
For 64 bit version, it is boost_1_59_0-msvc-14.0-64.exe
say install to D:\local\boost_1_59_0

(3) Download and unzip from
The updated version of QuantLib is 1.80

(4) Start Visual Studio Express 2015 and open project solution QuantLib_vc14.sln in the extracted quantlib folder.

(5) Multi-select all projects (except the solution) and click the setting icon to bring up the property page.

(6) Select All Configurations and All Platforms. Add D:\local\boost_1_59_0; to the Property Pages : VC++ Include directories.
And also add ;D:\local\boost_1_59_0\lib32-msvc-14.0; to the Library directories.

(7) Add /wd4819 to Command Line : Additional Options to disable C4819 warnings when compiling Quantlib.

(8) Build Debug / Release Win32 Solution using shortcut key (Fn-F7)
Choose Static Runtime Configurationif this is available

(9) After build, highlight the quantlib solution and edit the solution property pages by clicking the setting icon or use the shortcut key (Shift-Fn-F4)

(9.1) Choose a project say Bonds as startup project

(9.2) And then Debug / Release Run (Control-Fn-F5)
Choose Static Runtime Configurationif this is available

(9.3) If run test-suite, this command line argument should be added.
--log_level=message --build_info=yes --result_code=no --report_level=short

vim +196 Packages/SwiftDate-1.0.0/SwiftDate/Term.swift    Select all
mkdir -p Frameworks/boost.framework/Versions/1.60.0/Resources cat > Frameworks/boost.framework/Versions/1.60.0/Resources/Info.plist <<EOF <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" ""> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>English</string> <key>CFBundleExecutable</key> <string>boost</string> <key>CFBundleIdentifier</key> <string>org.boost</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundlePackageType</key> <string>FMWK</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> <string>1.60.0</string> </dict> </plist> EOF ln -s ${HOME}/boost_1_60_0/boost Frameworks/boost.framework/Versions/1.60.0/Headers ln -s ${HOME}/boost_1_60_0/doc Frameworks/boost.framework/Versions/1.60.0/Documentation ar crus Frameworks/boost.framework/Versions/1.60.0/boost boost_1_60_0/stage/lib/libboost_*.a (cd Frameworks/boost.framework/Versions; ln -s 1.60.0 Current) (cd Frameworks/boost.framework; ln -s Versions/Current/* .) mkdir -p Frameworks/ql.framework/Versions/1.7/Resources cat > Frameworks/ql.framework/Versions/1.7/Resources/Info.plist <<EOF <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" ""> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>English</string> <key>CFBundleExecutable</key> <string>ql</string> <key>CFBundleIdentifier</key> <string>org.boost</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundlePackageType</key> <string>FMWK</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> <string>1.7</string> </dict> </plist> EOF ln -s ${HOME}/QuantLib-1.7/Docs Frameworks/ql.framework/Versions/1.7/Documentation ln -s ${HOME}/QuantLib-1.7/prefix/usr/local/include/ql Frameworks/ql.framework/Versions/1.7/Headers ln -s ${HOME}/QuantLib-1.7/prefix/usr/local/lib/libQuantLib.a Frameworks/ql.framework/Versions/1.7/ql (cd Frameworks/ql.framework/Versions; ln -s 1.7 Current) (cd Frameworks/ql.framework; ln -s Versions/Current/* .)

Wednesday, September 30, 2015

CCS Selector for iPhone 6s Reservation Submission Form

For the iPhone 6s Reservation Submission Form, the required javascript code for selectors and the flow are analysed below in red.

URL = iPhone 6s Reservation
(2) javascript for Chrome console (Cmd + Opt + J for Mac)
iphone6s.js    Select all
var isDebug = true; var isSubmit = false; var storeOrder = ["R409","R428","R499","R485"]; // R409=CWB銅鑼灣, R485=FW又一城, R428=IFC, R499=CantonRoad廣東道 var timeslotOrder = ["2:00 PM","11:30 AM","12:00 PM","12:30 PM","1:00 PM","1:30 PM","3:00 PM","4:00 PM"]; //var timeslotOrder = ["下午 2:00","上午 11:30","下午 12:00","下午 12:30","下午 1:00","下午 1:30","下午 3:00"]; var quantity = 2; // maximum 2 for quantity, 購買數量, 最多2部 var firstname = "javacom"; // First Name 名, 必需填寫 var lastname = "NAME"; // Last Name 姓, 必需填寫 var email = ""; // Email Address 電郵, 必需填寫 var phonenumber = "98765432"; // Phone Number 電話, 必需填寫 var govtIdType = 1; /* HK 1="idHongkongCard" 香港永久性居民身份證 Hong Kong ID Card 2="travelPermitTaiwan" 台灣居民來往內地通行證 Mainland Travel Permit for Taiwan residents 3="entryExitPass" 往來港澳通行證 Entry/Exit Permit to Hong Kong and Macau 4="macauIDCard" 澳門永久性居民身份證 Macau ID Card 5="passport" 國際旅遊護照 Passport (International Visitors) */ var govtId = "A123456(7)"; // Government ID No 證件號碼,必需填寫 function autoSelect() { if (isDebug) console.log("autoSelect()"); if (isDebug) console.log($("#main #storeView .select-store select option").eq(0).val()); if ($("#main #storeView .select-store select option").eq(0).val() > "") selectStore(); else if ($(".reservation .select-store select option").eq(0).text() > "") insertContactInfo(); } function selectStore() { if (isDebug) console.log("selectStore()"); var isSelectedStore = false; var storeSelection_length = $("#main #storeView .select-store select option").length; for(i=0;i<storeOrder.length;i++) { if (isDebug) console.log("Checking Store " + storeOrder[i].toString()); for(a=1;a<storeSelection_length;a++) { if (isDebug) console.log("Against " + $("#main #storeView .select-store select option").eq(a).text()); if ($("#main #storeView .select-store select option").eq(a).val() == storeOrder[i].toString()) { if (isDebug) console.log("Selected Store is " + storeOrder[i].toString()); $("#main #storeView .select-store select option").eq(a).select().attr("selected","selected"); console.log($("#main #availabilityView .section-copy .availability-available").text()); isSelectedStore = true; break; } } if(isSelectedStore) break; } if(isSelectedStore) { $(".form-cell button").click(); } else { console.log("Sorry !! unavailable for in-store pickup"); } } function insertContactInfo() { if ($("select[name='selectedQuantity'] option").eq(quantity-1).val() > "") { $("select[name='selectedQuantity'] option").eq(quantity-1).select().attr("selected","selected").change(); } else { $("select[name='selectedQuantity'] option:last").select().attr("selected","selected").change(); } var isSelectedTimeslot = false; var timeSlotSelection_length = $("select[name='selectedTimeSlotId'] option").length; for(i=0;i<timeslotOrder.length;i++) { if (isDebug) console.log("Checking Timeslot " + timeslotOrder[i].toString()); for(a=1;a<timeSlotSelection_length;a++) { if (isDebug) console.log("Against " + $("select[name='selectedTimeSlotId'] option").eq(a).text()); if ($("select[name='selectedTimeSlotId'] option").eq(a).text().indexOf(timeslotOrder[i].toString()) == 0) { $("select[name='selectedTimeSlotId'] option").eq(a).select().attr("selected","selected").change(); console.log($("select[name='selectedTimeSlotId'] option").eq(a).select().text()); isSelectedTimeslot = true; break; } } if(isSelectedTimeslot) break; } if (!isSelectedTimeslot) { $("select[name='selectedTimeSlotId'] option:last").select().attr("selected","selected").change(); console.log($("select[name='selectedTimeSlotId'] option:last").select().text()); } $("input[name='firstName']").val(firstname); $("input[name='lastName']").val(lastname); $("input[name='email']").val(email) $("input[name='phoneNumber']").val(phonenumber) $(".gov-id-info select[name='selectedGovtIdType'] option").eq(govtIdType).select().attr("selected","selected").change(); $("input[name='govtId']").val(govtId); console.log($(".schedule-copy").text()); if (isSubmit) $(".form-cell button").click(); } autoSelect();

Friday, May 29, 2015

Android Studio 1.3 Release

Android Studio 1.3 Release
Link ->

Android Studio 1.3 <Preview 2>
Windows: (266 MB)
Mac: (265 MB)
Linux: (264 MB)

Use /usr/libexec/java_home -v 1.7 command on a Mac's terminal shell to figure out where is your java 1.7 home directory

Need JDK7 for Mac OSX here, if not already installed

Gradle Offline mode is here
See here for building apk files
app/build.gradle    Select all
apply plugin: 'android' android { compileSdkVersion 22 buildToolsVersion "22.0.1" defaultConfig { applicationId "com.mycompany.PeamonCalculator" minSdkVersion 8 targetSdkVersion 16 versionCode 1 versionName "1.0" archivesBaseName = "PeamonCalculator" + versionName } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' } } }

This is another build.gradle for building and linking native_app_glue static library in ndk (ugly but works in pre Android Studio 1.3)
app/build.gradle    Select all
apply plugin: 'android' def ndkFolder = file(plugins.getPlugin('').sdkHandler.getNdkFolder()).absolutePath android { compileSdkVersion 22 buildToolsVersion "22.0.1" defaultConfig { applicationId "com.beginndkgamecode.hellodroid" minSdkVersion 8 targetSdkVersion 20 versionCode 1 versionName "1.0" archivesBaseName = "HELLODRIOD" + versionName ndk { abiFilters "x86, armeabi-v7a, armeabi" moduleName "hellodroid" cFlags "-I"+ndkFolder+"/sources/android/native_app_glue" ldLibs "EGL", "GLESv2", "android", "log", file(projectDir).absolutePath+"/libs/local/\$(TARGET_ARCH_ABI)/libandroid_native_app_glue.a" } } // call regular ndk-build script task staticLibBuild(type: Exec, description: 'Build Static Library files') { // for windows: commandLine ndkFolder+'/ndk-build.cmd', commandLine ndkFolder+'/ndk-build', 'APP_BUILD_SCRIPT='+ndkFolder+'/sources/android/native_app_glue/', 'NDK_APPLICATION_MK='+file(projectDir).absolutePath+'/src/main/jni/', 'NDK_PROJECT_PATH='+ndkFolder, 'NDK_OUT='+file(projectDir).absolutePath+'/libs' } tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn staticLibBuild } task cleanLibDir(type: Delete) { delete 'libs' } clean.dependsOn cleanLibDir productFlavors { x86 { ndk { abiFilters "x86" versionCode 2 } } armv7 { ndk { abiFilters "armeabi-v7a" versionCode 2 } } arm { ndk { abiFilters "armeabi" versionCode 2 } } } buildTypes { debug { minifyEnabled false zipAlignEnabled true jniDebuggable true renderscriptDebuggable true } release { minifyEnabled false zipAlignEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' } } }

C/C++ Debugging is very limited in the first few previews of Android Studio 1.3, so logging might be helpful in C/CC source files like this below.
main.cpp    Select all
#include <android/log.h> ... #define ALOG(...) ((void)__android_log_print(ANDROID_LOG_INFO, __FILE__, __VA_ARGS__)) ... ALOG("This message came from C at line %d.", __LINE__);

For the source code of HelloDroid and PeamonCalculator, please see here and here.

Want to change to the awesome dark background theme. It is here

Android Studio 1.3 Release & 1.4 Preview using gradle-experimental

app/build.gradle (Module)   Select all
apply plugin: '' model { android { compileSdkVersion = 23 buildToolsVersion = "23.0.0" defaultConfig.with { applicationId = "com.beginndkgamecode.hellodroid" minSdkVersion.apiLevel = 8 targetSdkVersion.apiLevel = 23 versionCode = 1 versionName = "1.0" archivesBaseName = "HELLODRIOD_" + versionName } } android.ndk { moduleName = "hellodroid" /* * Other ndk flags configurable here are * cppFlags += "-fno-rtti" * cppFlags += "-fno-exceptions" * ldLibs = ["android", "log"] * stl = "system" */ cppFlags += "-I${file("src/main/jni/native_app_glue")}".toString() ldLibs += ["android", "log", "EGL", "GLESv2"] } android.buildTypes { release { minifyEnabled = false proguardFiles += file('proguard-rules.txt') } debug { ndk.with { debuggable = true } } } android.productFlavors { // for detailed abiFilter descriptions, refer to "Supported ABIs" @ // create("arm") { ndk.abiFilters += "armeabi" } create("arm7") { ndk.abiFilters += "armeabi-v7a" } create("arm8") { ndk.abiFilters += "arm64-v8a" } create("x86") { ndk.abiFilters += "x86" } create("x86-64") { ndk.abiFilters += "x86_64" } // To include all cpu architectures, leaves abiFilters empty create("all") } }

app/build.gradle (Project)   Select all
// build.gradle // Classpath for the plugin is instead of // The current version is 0.2.0. // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() } dependencies { classpath '' } } allprojects { repositories { jcenter() } }

./gradle/wrapper/    Select all
#The new plugin supports only gradle-2.5. distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://

Monday, April 27, 2015

RQuantLib 0.4 example

R version 3.1
dependencies ‘Rcpp’, ‘rgl’, ‘zoo’, ‘RUnit’
bond1.R  Select all
#Simple call with a flat curve require(RQuantLib) bond <- list(faceAmount=100, settlementDays=1, issueDate=as.Date("2014-11-30"), redemption=100)
scheduleparams <- list(effectiveDate=as.Date("2014-11-30"), maturityDate=as.Date("2018-11-30"), period=2, calendar="UnitedStates", businessDayConvention = 4, terminationDateConvention=4, dateGeneration=1, endOfMonth=1, dayCounter = 'Thirty360')
coupon.rate <- c(0.02875)
params <- list(tradeDate=as.Date('2014-2-15'), settleDate=as.Date('2014-2-19'), dt=.25, interpWhat="discount", interpHow="loglinear")
discountCurve.flat <- DiscountCurve(params, list(flat=0.05))
FixedRateBond(bond=bond, rates=coupon.rate, schedule=scheduleparams, calc=list(dayCounter='ActualActual.ISMA',compounding='Compounded', freq='Annual', durationType='Modified'),discountCurve=discountCurve.flat)

FixedRateBondPriceByYield( settlementDays=1, yield=0.05127, faceAmount=100, effectiveDate=as.Date("2014-11-30"), maturityDate=as.Date("2018-11-30"), period=2, calendar="UnitedStates", rates=c(0.05), dayCounter=2, businessDayConvention=4, compound=0, redemption=100, issueDate=as.Date("2014-11-30"))

FixedRateBondYield( settlementDays=1, price=99.54593, faceAmount=100, effectiveDate=as.Date("2014-11-30"), maturityDate=as.Date("2018-11-30"), period=2, calendar="UnitedStates", rates=c(0.05), dayCounter=2, businessDayConvention=4, compound=0, redemption=100, issueDate=as.Date("2014-11-30"))

calendar ->
businessDayConvention ->
dayCounter ->
compounding ->
freq ->
duration ->

Bond Utilities
matchBDC(bdc = c("Following", "ModifiedFollowing", "Preceding", "ModifiedPreceding", "Unadjusted"))
matchCompounding(cp = c("Simple", "Compounded", "Continuous", "SimpleThenCompounded"))
matchDayCounter(daycounter = c("Actual360", "ActualFixed", "ActualActual", "Business252", "OneDayCounter", "SimpleDayCounter", "Thirty360", "Actual365NoLeap", "ActualActual.ISMA", "ActualActual.Bond", "ActualActual.ISDA", "ActualActual.Historical", "ActualActual.AFB", "ActualActual.Euro"))
matchDateGen(dg = c("Backward", "Forward", "Zero", "ThirdWednesday", "Twentieth", "TwentiethIMM"))
matchFrequency(freq = c("NoFrequency","Once", "Annual", "Semiannual", "EveryFourthMonth", "Quarterly", "Bimonthly", "EveryFourthWeek", "Biweekly", "Weekly", "Daily"))

For Mac OSX, only 0.3.12 is available and quantlib-config should in in your path and executable

/usr/local/bin/quantlib-config  Select all
#!/bin/sh prefix=/usr/local exec_prefix=${prefix} exec_prefix_set=no usage="\ Usage: quantlib-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cflags]" if test $# -eq 0; then echo "${usage}" 1>&2 exit 1 fi while test $# -gt 0; do case "$1" in -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac case $1 in --prefix=*) prefix=$optarg if test $exec_prefix_set = no ; then exec_prefix=$optarg fi ;; --prefix) echo $prefix ;; --exec-prefix=*) exec_prefix=$optarg exec_prefix_set=yes ;; --exec-prefix) echo $exec_prefix ;; --version) echo 1.4.1 ;; --cflags) echo -I${prefix}/include -I/usr/local/include ;; --libs) echo -L${exec_prefix}/lib -L/usr/local/lib -lQuantLib ;; *) echo "${usage}" 1>&2 exit 1 ;; esac shift done