diff --git a/CNAME b/CNAME
new file mode 100644
index 0000000..a561a8d
--- /dev/null
+++ b/CNAME
@@ -0,0 +1 @@
+horaceyi.com
diff --git a/assets/img/DKCSL.png b/assets/img/DKCSL.png
new file mode 100644
index 0000000..fdf8b29
Binary files /dev/null and b/assets/img/DKCSL.png differ
diff --git a/assets/img/IAP.png b/assets/img/IAP.png
new file mode 100644
index 0000000..4b342fd
Binary files /dev/null and b/assets/img/IAP.png differ
diff --git a/assets/img/LinkedIn.png b/assets/img/LinkedIn.png
new file mode 100644
index 0000000..77c8ee4
Binary files /dev/null and b/assets/img/LinkedIn.png differ
diff --git a/assets/img/Outlook.png b/assets/img/Outlook.png
new file mode 100644
index 0000000..8418e54
Binary files /dev/null and b/assets/img/Outlook.png differ
diff --git a/assets/img/University_of_Alberta_logo.png b/assets/img/University_of_Alberta_logo.png
new file mode 100644
index 0000000..0d9f13e
Binary files /dev/null and b/assets/img/University_of_Alberta_logo.png differ
diff --git a/assets/img/bio.JPG b/assets/img/bio.JPG
new file mode 100644
index 0000000..1e38a2e
Binary files /dev/null and b/assets/img/bio.JPG differ
diff --git a/assets/img/blog.jpeg b/assets/img/blog.jpeg
new file mode 100644
index 0000000..006233f
Binary files /dev/null and b/assets/img/blog.jpeg differ
diff --git a/assets/img/coming.png b/assets/img/coming.png
new file mode 100644
index 0000000..95bb0d4
Binary files /dev/null and b/assets/img/coming.png differ
diff --git a/assets/img/cqu.png b/assets/img/cqu.png
new file mode 100644
index 0000000..bafa1fa
Binary files /dev/null and b/assets/img/cqu.png differ
diff --git a/assets/img/cqu_logo.png b/assets/img/cqu_logo.png
new file mode 100644
index 0000000..f6e2fc9
Binary files /dev/null and b/assets/img/cqu_logo.png differ
diff --git a/assets/img/cv.jpeg b/assets/img/cv.jpeg
new file mode 100644
index 0000000..be791be
Binary files /dev/null and b/assets/img/cv.jpeg differ
diff --git a/assets/img/github.jpeg b/assets/img/github.jpeg
new file mode 100644
index 0000000..02206e1
Binary files /dev/null and b/assets/img/github.jpeg differ
diff --git a/assets/img/github.png b/assets/img/github.png
new file mode 100644
index 0000000..44fedef
Binary files /dev/null and b/assets/img/github.png differ
diff --git a/assets/img/gmail.png b/assets/img/gmail.png
new file mode 100644
index 0000000..7cc9df4
Binary files /dev/null and b/assets/img/gmail.png differ
diff --git a/assets/img/imr.png b/assets/img/imr.png
new file mode 100644
index 0000000..daf2576
Binary files /dev/null and b/assets/img/imr.png differ
diff --git a/assets/img/jhu_logo.png b/assets/img/jhu_logo.png
new file mode 100644
index 0000000..7ba2a18
Binary files /dev/null and b/assets/img/jhu_logo.png differ
diff --git a/assets/img/mitacs.jpeg b/assets/img/mitacs.jpeg
new file mode 100644
index 0000000..a48ef58
Binary files /dev/null and b/assets/img/mitacs.jpeg differ
diff --git a/assets/img/sjtu.png b/assets/img/sjtu.png
new file mode 100644
index 0000000..9dfa9b0
Binary files /dev/null and b/assets/img/sjtu.png differ
diff --git a/assets/img/title.ico b/assets/img/title.ico
new file mode 100644
index 0000000..c831411
Binary files /dev/null and b/assets/img/title.ico differ
diff --git a/assets/img/uc.png b/assets/img/uc.png
new file mode 100644
index 0000000..ab56c5b
Binary files /dev/null and b/assets/img/uc.png differ
diff --git a/assets/img/uc_logo.png b/assets/img/uc_logo.png
new file mode 100644
index 0000000..b91c388
Binary files /dev/null and b/assets/img/uc_logo.png differ
diff --git a/assets/pdf/CV.pdf b/assets/pdf/CV.pdf
new file mode 100644
index 0000000..7e54d13
Binary files /dev/null and b/assets/pdf/CV.pdf differ
diff --git a/assets/pdf/PDF b/assets/pdf/PDF
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/assets/pdf/PDF
@@ -0,0 +1 @@
+
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..c0affa4
--- /dev/null
+++ b/index.html
@@ -0,0 +1,290 @@
+
+
+
+
+ '
+ % f.tablerow, l)
+
+ l2 = ''
+ col = 2
+ r2s = r2.split(l)
+ for x in r2s[:-1]:
+ l2 += x + (' | ' % col)
+ col += 1
+ l2 += r2s[-1]
+
+ b += l2
+
+ # Second to last, remove any remaining quoting backslashes.
+ b = re.sub(r'\\(?!\\)', '', b)
+
+ # Deal with literal backspaces.
+ b = re.sub('jemLITerl33talBS', r'\\', b)
+
+ # Also fix up DOUBLEOPEN and DOUBLECLOSEBRACES.
+ b = re.sub('DOUBLEOPENBRACE', '{{', b)
+ b = re.sub('DOUBLECLOSEBRACE', '}}', b)
+
+ return b
+
+
+def allreplace(b):
+ """Replacements that should be done on everything."""
+ r = re.compile(r"(?", re.M + re.S)
+ b = re.sub(r, r'>', b)
+
+ r = re.compile(r"(?\1', l)
+
+ if l.startswith('>>>'):
+ hb(f, '|\n', l)
+ else:
+ out(f, l + '\n')
+
+
+def putbsbs(l):
+ for i in range(len(l)):
+ l[i] = '\\b' + l[i] + '\\b'
+
+ return l
+
+
+def gethl(lang):
+ # disable comments by default, by choosing unlikely regex.
+ d = {'strings': False}
+ if lang in ('py', 'python'):
+ d['statement'] = ['break', 'continue', 'del', 'except', 'exec',
+ 'finally', 'pass', 'print', 'raise', 'return', 'try',
+ 'with', 'global', 'assert', 'lambda', 'yield', 'def',
+ 'class', 'for', 'while', 'if', 'elif', 'else',
+ 'import', 'from', 'as', 'assert']
+ d['builtin'] = ['True', 'False', 'set', 'open', 'frozenset',
+ 'enumerate', 'object', 'hasattr', 'getattr', 'filter',
+ 'eval', 'zip', 'vars', 'unicode', 'type', 'str',
+ 'repr', 'round', 'range', 'and', 'in', 'is', 'not',
+ 'or']
+ d['special'] = ['cols', 'optvar', 'param', 'problem', 'norm2', 'norm1',
+ 'value', 'minimize', 'maximize', 'rows', 'rand',
+ 'randn', 'printval', 'matrix']
+ d['error'] = ['\w*Error', ]
+ d['commentuntilend'] = '#'
+ d['strings'] = True
+ elif lang in ['c', 'c++', 'cpp']:
+ d['statement'] = ['if', 'else', 'printf', 'return', 'for']
+ d['builtin'] = ['static', 'typedef', 'int', 'float', 'double', 'void',
+ 'clock_t', 'struct', 'long', 'extern', 'char']
+ d['operator'] = ['#include.*', '#define', '@pyval{', '}@', '@pyif{',
+ '@py{']
+ d['error'] = ['\w*Error', ]
+ d['commentuntilend'] = ['//', '/*', ' * ', '*/']
+ elif lang in ('rb', 'ruby'):
+ d['statement'] = putbsbs(['while', 'until', 'unless', 'if', 'elsif',
+ 'when', 'then', 'else', 'end', 'begin',
+ 'rescue', 'class', 'def'])
+ d['operator'] = putbsbs(['and', 'not', 'or'])
+ d['builtin'] = putbsbs(['true', 'false', 'require', 'warn'])
+ d['special'] = putbsbs(['IO'])
+ d['error'] = putbsbs(['\w*Error', ])
+ d['commentuntilend'] = '#'
+ d['strings'] = True
+ d['strings'] = True
+ if lang in ['c++', 'cpp']:
+ d['builtin'] += ['bool', 'virtual']
+ d['statement'] += ['new', 'delete']
+ d['operator'] += ['<<', '>>']
+ d['special'] = ['public', 'private', 'protected', 'template',
+ 'ASSERT']
+ elif lang == 'sh':
+ d['statement'] = ['cd', 'ls', 'sudo', 'cat', 'alias', 'for', 'do',
+ 'done', 'in', ]
+ d['operator'] = ['>', r'\\', r'\|', ';', '2>', 'monolith>',
+ 'kiwi>', 'ant>', 'kakapo>', 'client>']
+ d['builtin'] = putbsbs(['gem', 'gcc', 'python', 'curl', 'wget', 'ssh',
+ 'latex', 'find', 'sed', 'gs', 'grep', 'tee',
+ 'gzip', 'killall', 'echo', 'touch',
+ 'ifconfig', 'git', '(?>', '~', '\.\.\.']
+ d['builtin'] = putbsbs(['csolve'])
+ d['commentuntilend'] = '%'
+ d['strings'] = True
+ elif lang == 'commented':
+ d['commentuntilend'] = '#'
+
+ # Add bsbs (whatever those are).
+ for x in ['statement', 'builtin', 'special', 'error']:
+ if x in d:
+ d[x] = putbsbs(d[x])
+
+ return d
+
+
+def language(f, l, hl):
+ l = l.rstrip()
+ l = allreplace(l)
+ # handle strings.
+ if hl['strings']:
+ r = re.compile(r'(".*?")')
+ l = r.sub(r'\1', l)
+ r = re.compile(r"('.*?')")
+ l = r.sub(r'\1', l)
+
+ if 'statement' in hl:
+ r = re.compile('(' + '|'.join(hl['statement']) + ')')
+ l = r.sub(r'\1', l)
+
+ if 'operator' in hl:
+ r = re.compile('(' + '|'.join(hl['operator']) + ')')
+ l = r.sub(r'\1', l)
+
+ if 'builtin' in hl:
+ r = re.compile('(' + '|'.join(hl['builtin']) + ')')
+ l = r.sub(r'\1', l)
+
+ if 'special' in hl:
+ r = re.compile('(' + '|'.join(hl['special']) + ')')
+ l = r.sub(r'\1', l)
+
+ if 'error' in hl:
+ r = re.compile('(' + '|'.join(hl['error']) + ')')
+ l = r.sub(r'\1', l)
+
+ l = re.sub('CLCLclass', 'class', l)
+
+ if 'commentuntilend' in hl:
+ cue = hl['commentuntilend']
+ if isinstance(cue, (list, tuple)):
+ for x in cue:
+ if l.strip().startswith(x):
+ hb(f, '\n', allreplace(l))
+ return
+ if '//' in cue: # Handle this separately.
+ r = re.compile(r'\/\/.*')
+ l = r.sub(r'', l)
+ elif cue == '#': # Handle this separately.
+ r = re.compile(r'#.*')
+ l = r.sub(r'', l)
+ elif cue == '%': # Handle this separately.
+ r = re.compile(r'%.*')
+ l = r.sub(r'', l)
+ elif l.strip().startswith(cue):
+ hb(f, '\n', allreplace(l))
+ return
+
+ out(f, l + '\n')
+
+
+def geneq(f, eq, dpi, wl, outname):
+ # First check if there is an existing file.
+ eqname = os.path.join(f.eqdir, outname + '.png')
+
+ eqdepths = {}
+ if f.eqcache:
+ try:
+ dc = open(os.path.join(f.eqdir, '.eqdepthcache'), 'rb')
+ for l in dc:
+ a = l.split()
+ eqdepths[a[0]] = int(a[1])
+ dc.close()
+
+ if os.path.exists(eqname) and eqname in eqdepths:
+ return (eqdepths[eqname], eqname)
+ except IOError:
+ print 'eqdepthcache read failed.'
+
+ # Open tex file.
+ tempdir = tempfile.gettempdir()
+ fd, texfile = tempfile.mkstemp('.tex', '', tempdir, True)
+ basefile = texfile[:-4]
+ g = os.fdopen(fd, 'wb')
+
+ preamble = '\documentclass{article}\n'
+ for p in f.eqpackages:
+ preamble += '\usepackage{%s}\n' % p
+ for p in f.texlines:
+ # Replace \{ and \} in p with { and }.
+ # XXX hack.
+ preamble += re.sub(r'\\(?=[{}])', '', p + '\n')
+ preamble += '\pagestyle{empty}\n\\begin{document}\n'
+ g.write(preamble)
+
+ # Write the equation itself.
+ if wl:
+ g.write('\\[%s\\]' % eq)
+ else:
+ g.write('$%s$' % eq)
+
+ # Finish off the tex file.
+ g.write('\n\\newpage\n\end{document}')
+ g.close()
+
+ exts = ['.tex', '.aux', '.dvi', '.log']
+ try:
+ # Generate the DVI file
+ latexcmd = 'latex -file-line-error-style -interaction=nonstopmode ' + \
+ '-output-directory %s %s' % (tempdir, texfile)
+ p = Popen(latexcmd, shell=True, stdout=PIPE)
+ rc = p.wait()
+ if rc != 0:
+ for l in p.stdout.readlines():
+ print ' ' + l.rstrip()
+ exts.remove('.tex')
+ raise Exception('latex error')
+
+ dvifile = basefile + '.dvi'
+ dvicmd = 'dvipng --freetype0 -Q 9 -z 3 --depth -q -T tight -D %i -bg Transparent -o %s %s' % (
+ dpi, eqname, dvifile)
+ # discard warnings, as well.
+ p = Popen(dvicmd, shell=True, stdout=PIPE, stderr=PIPE)
+ rc = p.wait()
+ if rc != 0:
+ print p.stderr.readlines()
+ raise Exception('dvipng error')
+ depth = int(p.stdout.readlines()[-1].split('=')[-1])
+ finally:
+ # Clean up.
+ for ext in exts:
+ g = basefile + ext
+ if os.path.exists(g):
+ os.remove(g)
+
+ # Update the cache if we're using it.
+ if f.eqcache and eqname not in eqdepths:
+ try:
+ dc = open(os.path.join(f.eqdir, '.eqdepthcache'), 'ab')
+ dc.write(eqname + ' ' + str(depth) + '\n')
+ dc.close()
+ except IOError:
+ print 'eqdepthcache update failed.'
+ return (depth, eqname)
+
+
+def dashlist(f, ordered=False):
+ level = 0
+
+ if ordered:
+ char = '.'
+ ul = 'ol'
+ else:
+ char = '-'
+ ul = 'ul'
+
+ while pc(f) == char:
+ (s, newlevel) = np(f, True, False)
+
+ # first adjust list number as appropriate.
+ if newlevel > level:
+ for i in range(newlevel - level):
+ if newlevel > 1:
+ out(f.outf, '\n')
+ out(f.outf, '<%s>\n' % ul)
+ elif newlevel < level:
+ out(f.outf, '\n')
+ for i in range(level - newlevel):
+ #out(f.outf, '\n%s>\n' % ul)
+ # demote means place '' in the file.
+ out(f.outf, '%s>\n' % ul)
+ #out(f.outf, '\n')
+ out(f.outf, '\n')
+ else:
+ # same level, make a new list item.
+ out(f.outf, '\n\n')
+
+ out(f.outf, ' ' + br(s, f) + ' ')
+ level = newlevel
+
+ for i in range(level):
+ out(f.outf, '\n\n%s>\n' % ul)
+
+
+def colonlist(f):
+ out(f.outf, '\n')
+ while pc(f) == ':':
+ s = np(f, eatblanks=False)
+ r = re.compile(r'\s*{(.*?)(?|\n', br(defpart, f))
+ hb(f.outf, '| \n', br(rest, f))
+
+ out(f.outf, ' \n')
+
+
+def codeblock(f, g):
+ if g[1] == 'raw':
+ raw = True
+ ext_prog = None
+ elif g[0] == 'filter_through':
+ # Filter through external program.
+ raw = False
+ ext_prog = g[1]
+ buff = ""
+ else:
+ ext_prog = None
+ raw = False
+ out(f.outf, f.conf['codeblock'])
+ if g[0]:
+ hb(f.outf, f.conf['blocktitle'], g[0])
+ if g[1] == 'jemdoc':
+ out(f.outf, f.conf['codeblockcontenttt'])
+ else:
+ out(f.outf, f.conf['codeblockcontent'])
+
+ # Now we are handling code.
+ # Handle \~ and ~ differently.
+ stringmode = False
+ while 1: # wait for EOF.
+ l = nl(f, codemode=True)
+ if not l:
+ break
+ elif l.startswith('~'):
+ break
+ elif l.startswith('\\~'):
+ l = l[1:]
+ elif l.startswith('\\{'):
+ l = l[1:]
+ elif ext_prog:
+ buff += l
+ continue
+ elif stringmode:
+ if l.rstrip().endswith('"""'):
+ out(f.outf, l + '')
+ stringmode = False
+ else:
+ out(f.outf, l)
+ continue
+
+ # jem revise pyint out of the picture.
+ if g[1] == 'pyint':
+ pyint(f.outf, l)
+ else:
+ if raw:
+ out(f.outf, l)
+ elif g[1] == 'jemdoc':
+ # doing this more nicely needs python 2.5.
+ for x in ('#', '~', '>>>', '\~', '{'):
+ if str(l).lstrip().startswith(x):
+ out(f.outf, '')
+ out(f.outf, l + ' ')
+ break
+ else:
+ for x in (':', '.', '-'):
+ if str(l).lstrip().startswith(x):
+ out(f.outf, ' ' + prependnbsps(l))
+ break
+ else:
+ if str(l).lstrip().startswith('='):
+ out(f.outf, prependnbsps(l) + ' ')
+ else:
+ out(f.outf, l)
+ else:
+ if l.startswith('\\#include{') or l.startswith('\\#includeraw{'):
+ out(f.outf, l[1:])
+ elif l.startswith('#') and doincludes(f, l[1:]):
+ continue
+ elif g[1] in ('python', 'py') and l.strip().startswith('"""'):
+ out(f.outf, '' + l)
+ stringmode = True
+ else:
+ language(f.outf, l, gethl(g[1]))
+
+ if raw:
+ return
+ elif ext_prog:
+ print 'filtering through %s...' % ext_prog
+
+ output, _ = Popen(ext_prog, shell=True, stdin=PIPE,
+ stdout=PIPE).communicate(buff)
+ out(f.outf, output)
+ else:
+ if g[1] == 'jemdoc':
+ out(f.outf, f.conf['codeblockendtt'])
+ else:
+ out(f.outf, f.conf['codeblockend'])
+
+
+def prependnbsps(l):
+ g = re.search('(^ *)(.*)', l).groups()
+ return g[0].replace(' ', ' ') + g[1]
+
+
+def inserttitle(f, t):
+ if t is not None:
+ hb(f.outf, f.conf['doctitle'], t)
+
+ # Look for a subtitle.
+ if pc(f) != '\n':
+ hb(f.outf, f.conf['subtitle'], br(np(f), f))
+
+ hb(f.outf, f.conf['doctitleend'], t)
+
+
+def procfile(f):
+ f.linenum = 0
+
+ menu = None
+ # convert these to a dictionary.
+ showfooter = True
+ showsourcelink = False
+ showlastupdated = True
+ showlastupdatedtime = True
+ nodefaultcss = False
+ fwtitle = False
+ css = []
+ js = []
+ title = None
+ while pc(f, False) == '#':
+ l = f.inf.readline()
+ f.linenum += 1
+ if doincludes(f, l[1:]):
+ continue
+ if l.startswith('# jemdoc:'):
+ l = l[len('# jemdoc:'):]
+ a = l.split(',')
+ # jem only handle one argument for now.
+ for b in a:
+ b = b.strip()
+ if b.startswith('menu'):
+ sidemenu = True
+ r = re.compile(r'(? 3 or len(g) < 2:
+ raise SyntaxError(
+ 'sidemenu error on line %d' % f.linenum)
+
+ if len(g) == 2:
+ menu = (f, g[0], g[1], '')
+ else:
+ menu = (f, g[0], g[1], g[2])
+
+ elif b.startswith('nofooter'):
+ showfooter = False
+
+ elif b.startswith('nodate'):
+ showlastupdated = False
+
+ elif b.startswith('notime'):
+ showlastupdatedtime = False
+
+ elif b.startswith('fwtitle'):
+ fwtitle = True
+
+ elif b.startswith('showsource'):
+ showsourcelink = True
+
+ elif b.startswith('nodefaultcss'):
+ nodefaultcss = True
+
+ elif b.startswith('addcss'):
+ r = re.compile(r'(?)|( ) *', ' ', t)
+ else:
+ t = None
+
+ # if title:
+ hb(f.outf, f.conf['windowtitle'], title)
+
+ out(f.outf, f.conf['bodystart'])
+
+ if f.analytics:
+ hb(f.outf, f.conf['analytics'], f.analytics)
+
+ if fwtitle:
+ out(f.outf, f.conf['fwtitlestart'])
+ inserttitle(f, t)
+ out(f.outf, f.conf['fwtitleend'])
+
+ if menu:
+ out(f.outf, f.conf['menustart'])
+ insertmenuitems(*menu)
+ out(f.outf, f.conf['menuend'])
+ else:
+ out(f.outf, f.conf['nomenu'])
+
+ if not fwtitle:
+ inserttitle(f, t)
+
+ infoblock = False
+ imgblock = False
+ tableblock = False
+ while 1: # wait for EOF.
+ p = pc(f)
+
+ if p == '':
+ break
+
+ elif p == '\\(':
+ if not (f.eqs and f.eqsupport):
+ break
+
+ s = nl(f)
+ # Quickly pull out the equation here:
+ # Check we don't already have the terminating character in a whole-line
+ # equation without linebreaks, eg \( Ax=b \):
+ if not s.strip().endswith('\)'):
+ while True:
+ l = nl(f, codemode=True)
+ if not l:
+ break
+ s += l
+ if l.strip() == '\)':
+ break
+ out(f.outf, br(s.strip(), f))
+
+ # look for lists.
+ elif p == '-':
+ dashlist(f, False)
+
+ elif p == '.':
+ dashlist(f, True)
+
+ elif p == ':':
+ colonlist(f)
+
+ # look for titles.
+ elif p == '=':
+ (s, c) = nl(f, True)
+ # trim trailing \n.
+ s = s[:-1]
+ hb(f.outf, '|\n' % (c, c), br(s, f))
+
+ # look for comments.
+ elif p == '#':
+ l = nl(f)
+
+ elif p == '\n':
+ nl(f)
+
+ # look for blocks.
+ elif p == '~':
+ nl(f)
+ if infoblock:
+ out(f.outf, f.conf['infoblockend'])
+ infoblock = False
+ nl(f)
+ continue
+ elif imgblock:
+ out(f.outf, ' |
\n')
+ imgblock = False
+ nl(f)
+ continue
+ elif tableblock:
+ out(f.outf, '\n')
+ tableblock = False
+ nl(f)
+ continue
+ else:
+ if pc(f) == '{':
+ l = allreplace(nl(f))
+ r = re.compile(r'(?= 1:
+ g[0] = br(g[0], f)
+
+ if len(g) in (0, 1): # info block.
+ out(f.outf, f.conf['infoblock'])
+ infoblock = True
+
+ if len(g) == 1: # info block.
+ hb(f.outf, f.conf['blocktitle'], g[0])
+
+ out(f.outf, f.conf['infoblockcontent'])
+
+ elif len(g) >= 2 and g[1] == 'table':
+ # handles
+ # {title}{table}{name}
+ # one | two ||
+ # three | four ||
+ name = ''
+ if len(g) >= 3 and g[2]:
+ name += ' id="%s"' % g[2]
+ out(f.outf, '