[\s\S]*?)<\/div>\s*<(footer|\/article)>/ =~ input
+ return (content.nil?) ? input : content
+ end
+
+ # Escapes CDATA sections in post content
+ def cdata_escape(input)
+ input.gsub(//, ']]>')
+ end
+
+ # Replaces relative urls with full urls
+ def expand_urls(input, url='')
+ url ||= '/'
+ input.gsub /(\s+(href|src)\s*=\s*["|']{1})(\/[^\/>]{1}[^\"'>]*)/ do
+ $1+url+$3
+ end
+ end
+
+ # Improved version of Liquid's truncate:
+ # - Doesn't cut in the middle of a word.
+ # - Uses typographically correct ellipsis (…) insted of '...'
+ def truncate(input, length)
+ if input.length > length && input[0..(length-1)] =~ /(.+)\b.+$/im
+ $1.strip + ' …'
+ else
+ input
+ end
+ end
+
+ # Improved version of Liquid's truncatewords:
+ # - Uses typographically correct ellipsis (…) insted of '...'
+ def truncatewords(input, length)
+ truncate = input.split(' ')
+ if truncate.length > length
+ truncate[0..length-1].join(' ').strip + ' …'
+ else
+ input
+ end
+ end
+
+ # Condenses multiple spaces and tabs into a single space
+ def condense_spaces(input)
+ input.gsub(/\s{2,}/, ' ')
+ end
+
+ # Removes trailing forward slash from a string for easily appending url segments
+ def strip_slash(input)
+ if input =~ /(.+)\/$|^\/$/
+ input = $1
+ end
+ input
+ end
+
+ # Returns a url without the protocol (http://)
+ def shorthand_url(input)
+ input.gsub /(https?:\/\/)(\S+)/ do
+ $2
+ end
+ end
+
+ # Returns a title cased string based on John Gruber's title case http://daringfireball.net/2008/08/title_case_update
+ def titlecase(input)
+ input.titlecase
+ end
+
+end
+Liquid::Template.register_filter OctopressLiquidFilters
+
diff --git a/plugins/pullquote.rb b/plugins/pullquote.rb
new file mode 100644
index 0000000..3c65e66
--- /dev/null
+++ b/plugins/pullquote.rb
@@ -0,0 +1,45 @@
+#
+# Author: Brandon Mathis
+# Based on the semantic pullquote technique by Maykel Loomans at http://miekd.com/articles/pull-quotes-with-html5-and-css/
+#
+# Outputs a span with a data-pullquote attribute set from the marked pullquote. Example:
+#
+# {% pullquote %}
+# When writing longform posts, I find it helpful to include pullquotes, which help those scanning a post discern whether or not a post is helpful.
+# It is important to note, {" pullquotes are merely visual in presentation and should not appear twice in the text. "} That is why it is prefered
+# to use a CSS only technique for styling pullquotes.
+# {% endpullquote %}
+# ...will output...
+#
+#
+# When writing longform posts, I find it helpful to include pullquotes, which help those scanning a post discern whether or not a post is helpful.
+# It is important to note, pullquotes are merely visual in presentation and should not appear twice in the text. This is why a CSS only approach
+# for styling pullquotes is prefered.
+#
+#
+#
+# {% pullquote left %} will create a left-aligned pullquote instead.
+#
+# Note: this plugin now creates pullquotes with the class of pullquote-right by default
+
+module Jekyll
+
+ class PullquoteTag < Liquid::Block
+ def initialize(tag_name, markup, tokens)
+ @align = (markup =~ /left/i) ? "left" : "right"
+ super
+ end
+
+ def render(context)
+ output = super
+ if output =~ /\{"\s*(.+?)\s*"\}/m
+ @quote = RubyPants.new($1).to_html
+ "#{output.gsub(/\{"\s*|\s*"\}/, '')} "
+ else
+ return "Surround your pullquote like this {\" text to be quoted \"}"
+ end
+ end
+ end
+end
+
+Liquid::Template.register_tag('pullquote', Jekyll::PullquoteTag)
diff --git a/plugins/pygments_code.rb b/plugins/pygments_code.rb
new file mode 100644
index 0000000..c0f4de9
--- /dev/null
+++ b/plugins/pygments_code.rb
@@ -0,0 +1,45 @@
+require 'pygments'
+require 'fileutils'
+require 'digest/md5'
+
+PYGMENTS_CACHE_DIR = File.expand_path('../../.pygments-cache', __FILE__)
+FileUtils.mkdir_p(PYGMENTS_CACHE_DIR)
+
+module HighlightCode
+ def self.highlight(str, lang)
+ lang = 'ruby' if lang == 'ru'
+ lang = 'objc' if lang == 'm'
+ lang = 'perl' if lang == 'pl'
+ lang = 'yaml' if lang == 'yml'
+ str = pygments(str, lang).match(/(.+)<\/pre>/m)[1].to_s.gsub(/ *$/, '') #strip out divs
+ tableize_code(str, lang)
+ end
+
+ def self.pygments(code, lang)
+ if defined?(PYGMENTS_CACHE_DIR)
+ path = File.join(PYGMENTS_CACHE_DIR, "#{lang}-#{Digest::MD5.hexdigest(code)}.html")
+ if File.exist?(path)
+ highlighted_code = File.read(path)
+ else
+ begin
+ highlighted_code = Pygments.highlight(code, :lexer => lang, :formatter => 'html', :options => {:encoding => 'utf-8', :startinline => true})
+ rescue MentosError
+ raise "Pygments can't parse unknown language: #{lang}."
+ end
+ File.open(path, 'w') {|f| f.print(highlighted_code) }
+ end
+ else
+ highlighted_code = Pygments.highlight(code, :lexer => lang, :formatter => 'html', :options => {:encoding => 'utf-8', :startinline => true})
+ end
+ highlighted_code
+ end
+ def self.tableize_code (str, lang = '')
+ table = '
'
+ code = ''
+ str.lines.each_with_index do |line,index|
+ table += "#{index+1} \n"
+ code += "#{line} "
+ end
+ table += " #{code}
"
+ end
+end
diff --git a/plugins/raw.rb b/plugins/raw.rb
new file mode 100644
index 0000000..e97c945
--- /dev/null
+++ b/plugins/raw.rb
@@ -0,0 +1,40 @@
+# Author: Brandon Mathis
+# Description: Provides plugins with a method for wrapping and unwrapping input to prevent Markdown and Textile from parsing it.
+# Purpose: This is useful for preventing Markdown and Textile from being too aggressive and incorrectly parsing in-line HTML.
+module TemplateWrapper
+ # Wrap input with a
+ def self.safe_wrap(input)
+ "
#{input}
"
+ end
+ # This must be applied after the
+ def self.unwrap(input)
+ input.gsub /
(.+?)<\/notextile><\/div>/m do
+ $1
+ end
+ end
+end
+
+# Author: phaer, https://github.com/phaer
+# Source: https://gist.github.com/1020852
+# Description: Raw tag for jekyll. Keeps liquid from parsing text betweeen {% raw %} and {% endraw %}
+
+module Jekyll
+ class RawTag < Liquid::Block
+ def parse(tokens)
+ @nodelist ||= []
+ @nodelist.clear
+
+ while token = tokens.shift
+ if token =~ FullToken
+ if block_delimiter == $1
+ end_tag
+ return
+ end
+ end
+ @nodelist << token if not token.empty?
+ end
+ end
+ end
+end
+
+Liquid::Template.register_tag('raw', Jekyll::RawTag)
diff --git a/plugins/render_partial.rb b/plugins/render_partial.rb
new file mode 100644
index 0000000..b6ebfe8
--- /dev/null
+++ b/plugins/render_partial.rb
@@ -0,0 +1,69 @@
+# Title: Render Partial Tag for Jekyll
+# Author: Brandon Mathis http://brandonmathis.com
+# Description: Import files on your filesystem into any blog post and render them inline.
+# Note: Paths are relative to the source directory, if you import a file with yaml front matter, the yaml will be stripped out.
+#
+# Syntax {% render_partial path/to/file %}
+#
+# Example 1:
+# {% render_partial about/_bio.markdown %}
+#
+# This will import source/about/_bio.markdown and render it inline.
+# In this example I used an underscore at the beginning of the filename to prevent Jekyll
+# from generating an about/bio.html (Jekyll doesn't convert files beginning with underscores)
+#
+# Example 2:
+# {% render_partial ../README.markdown %}
+#
+# You can use relative pathnames, to include files outside of the source directory.
+# This might be useful if you want to have a page for a project's README without having
+# to duplicated the contents
+#
+#
+
+require 'pathname'
+require './plugins/octopress_filters'
+
+module Jekyll
+
+ class RenderPartialTag < Liquid::Tag
+ include OctopressFilters
+ def initialize(tag_name, markup, tokens)
+ @file = nil
+ @raw = false
+ if markup =~ /^(\S+)\s?(\w+)?/
+ @file = $1.strip
+ @raw = $2 == 'raw'
+ end
+ super
+ end
+
+ def render(context)
+ file_dir = (context.registers[:site].source || 'source')
+ file_path = Pathname.new(file_dir).expand_path
+ file = file_path + @file
+
+ unless file.file?
+ return "File #{file} could not be found"
+ end
+
+ Dir.chdir(file_path) do
+ contents = file.read
+ if contents =~ /\A-{3}.+[^\A]-{3}\n(.+)/m
+ contents = $1.lstrip
+ end
+ contents = pre_filter(contents)
+ if @raw
+ contents
+ else
+ partial = Liquid::Template.parse(contents)
+ context.stack do
+ partial.render(context)
+ end
+ end
+ end
+ end
+ end
+end
+
+Liquid::Template.register_tag('render_partial', Jekyll::RenderPartialTag)
diff --git a/plugins/rubypants.rb b/plugins/rubypants.rb
new file mode 100644
index 0000000..e4f4502
--- /dev/null
+++ b/plugins/rubypants.rb
@@ -0,0 +1,489 @@
+#
+# = RubyPants -- SmartyPants ported to Ruby
+#
+# Ported by Christian Neukirchen
+# Copyright (C) 2004 Christian Neukirchen
+#
+# Incooporates ideas, comments and documentation by Chad Miller
+# Copyright (C) 2004 Chad Miller
+#
+# Original SmartyPants by John Gruber
+# Copyright (C) 2003 John Gruber
+#
+
+#
+# = RubyPants -- SmartyPants ported to Ruby
+#
+# == Synopsis
+#
+# RubyPants is a Ruby port of the smart-quotes library SmartyPants.
+#
+# The original "SmartyPants" is a free web publishing plug-in for
+# Movable Type, Blosxom, and BBEdit that easily translates plain ASCII
+# punctuation characters into "smart" typographic punctuation HTML
+# entities.
+#
+#
+# == Description
+#
+# RubyPants can perform the following transformations:
+#
+# * Straight quotes (" and ' ) into "curly" quote
+# HTML entities
+# * Backticks-style quotes (``like this'' ) into "curly" quote
+# HTML entities
+# * Dashes (-- and --- ) into en- and em-dash
+# entities
+# * Three consecutive dots (... or . . . ) into an
+# ellipsis entity
+#
+# This means you can write, edit, and save your posts using plain old
+# ASCII straight quotes, plain dashes, and plain dots, but your
+# published posts (and final HTML output) will appear with smart
+# quotes, em-dashes, and proper ellipses.
+#
+# RubyPants does not modify characters within ,
+# , , or
+# tag blocks. Typically, these tags are used to
+# display text where smart quotes and other "smart punctuation" would
+# not be appropriate, such as source code or example markup.
+#
+#
+# == Backslash Escapes
+#
+# If you need to use literal straight quotes (or plain hyphens and
+# periods), RubyPants accepts the following backslash escape sequences
+# to force non-smart punctuation. It does so by transforming the
+# escape sequence into a decimal-encoded HTML entity:
+#
+# \\ \" \' \. \- \`
+#
+# This is useful, for example, when you want to use straight quotes as
+# foot and inch marks: 6'2" tall; a 17" iMac. (Use 6\'2\"
+# resp. 17\" .)
+#
+#
+# == Algorithmic Shortcomings
+#
+# One situation in which quotes will get curled the wrong way is when
+# apostrophes are used at the start of leading contractions. For
+# example:
+#
+# 'Twas the night before Christmas.
+#
+# In the case above, RubyPants will turn the apostrophe into an
+# opening single-quote, when in fact it should be a closing one. I
+# don't think this problem can be solved in the general case--every
+# word processor I've tried gets this wrong as well. In such cases,
+# it's best to use the proper HTML entity for closing single-quotes
+# ("’ ") by hand.
+#
+#
+# == Bugs
+#
+# To file bug reports or feature requests (except see above) please
+# send email to: mailto:chneukirchen@gmail.com
+#
+# If the bug involves quotes being curled the wrong way, please send
+# example text to illustrate.
+#
+#
+# == Authors
+#
+# John Gruber did all of the hard work of writing this software in
+# Perl for Movable Type and almost all of this useful documentation.
+# Chad Miller ported it to Python to use with Pyblosxom.
+#
+# Christian Neukirchen provided the Ruby port, as a general-purpose
+# library that follows the *Cloth API.
+#
+#
+# == Copyright and License
+#
+# === SmartyPants license:
+#
+# Copyright (c) 2003 John Gruber
+# (http://daringfireball.net)
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# * Neither the name "SmartyPants" nor the names of its contributors
+# may be used to endorse or promote products derived from this
+# software without specific prior written permission.
+#
+# This software is provided by the copyright holders and contributors
+# "as is" and any express or implied warranties, including, but not
+# limited to, the implied warranties of merchantability and fitness
+# for a particular purpose are disclaimed. In no event shall the
+# copyright owner or contributors be liable for any direct, indirect,
+# incidental, special, exemplary, or consequential damages (including,
+# but not limited to, procurement of substitute goods or services;
+# loss of use, data, or profits; or business interruption) however
+# caused and on any theory of liability, whether in contract, strict
+# liability, or tort (including negligence or otherwise) arising in
+# any way out of the use of this software, even if advised of the
+# possibility of such damage.
+#
+# === RubyPants license
+#
+# RubyPants is a derivative work of SmartyPants and smartypants.py.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# This software is provided by the copyright holders and contributors
+# "as is" and any express or implied warranties, including, but not
+# limited to, the implied warranties of merchantability and fitness
+# for a particular purpose are disclaimed. In no event shall the
+# copyright owner or contributors be liable for any direct, indirect,
+# incidental, special, exemplary, or consequential damages (including,
+# but not limited to, procurement of substitute goods or services;
+# loss of use, data, or profits; or business interruption) however
+# caused and on any theory of liability, whether in contract, strict
+# liability, or tort (including negligence or otherwise) arising in
+# any way out of the use of this software, even if advised of the
+# possibility of such damage.
+#
+#
+# == Links
+#
+# John Gruber:: http://daringfireball.net
+# SmartyPants:: http://daringfireball.net/projects/smartypants
+#
+# Chad Miller:: http://web.chad.org
+#
+# Christian Neukirchen:: http://kronavita.de/chris
+#
+
+
+class RubyPants < String
+
+ # Create a new RubyPants instance with the text in +string+.
+ #
+ # Allowed elements in the options array:
+ #
+ # 0 :: do nothing
+ # 1 :: enable all, using only em-dash shortcuts
+ # 2 :: enable all, using old school en- and em-dash shortcuts (*default*)
+ # 3 :: enable all, using inverted old school en and em-dash shortcuts
+ # -1 :: stupefy (translate HTML entities to their ASCII-counterparts)
+ #
+ # If you don't like any of these defaults, you can pass symbols to change
+ # RubyPants' behavior:
+ #
+ # :quotes :: quotes
+ # :backticks :: backtick quotes (``double'' only)
+ # :allbackticks :: backtick quotes (``double'' and `single')
+ # :dashes :: dashes
+ # :oldschool :: old school dashes
+ # :inverted :: inverted old school dashes
+ # :ellipses :: ellipses
+ # :convertquotes :: convert " entities to
+ # " for Dreamweaver users
+ # :stupefy :: translate RubyPants HTML entities
+ # to their ASCII counterparts.
+ #
+ def initialize(string, options=[2])
+ super string
+ @options = [*options]
+ end
+
+ # Apply SmartyPants transformations.
+ def to_html
+ do_quotes = do_backticks = do_dashes = do_ellipses = do_stupify = nil
+ convert_quotes = false
+
+ if @options.include? 0
+ # Do nothing.
+ return self
+ elsif @options.include? 1
+ # Do everything, turn all options on.
+ do_quotes = do_backticks = do_ellipses = true
+ do_dashes = :normal
+ elsif @options.include? 2
+ # Do everything, turn all options on, use old school dash shorthand.
+ do_quotes = do_backticks = do_ellipses = true
+ do_dashes = :oldschool
+ elsif @options.include? 3
+ # Do everything, turn all options on, use inverted old school
+ # dash shorthand.
+ do_quotes = do_backticks = do_ellipses = true
+ do_dashes = :inverted
+ elsif @options.include?(-1)
+ do_stupefy = true
+ else
+ do_quotes = @options.include? :quotes
+ do_backticks = @options.include? :backticks
+ do_backticks = :both if @options.include? :allbackticks
+ do_dashes = :normal if @options.include? :dashes
+ do_dashes = :oldschool if @options.include? :oldschool
+ do_dashes = :inverted if @options.include? :inverted
+ do_ellipses = @options.include? :ellipses
+ convert_quotes = @options.include? :convertquotes
+ do_stupefy = @options.include? :stupefy
+ end
+
+ # Parse the HTML
+ tokens = tokenize
+
+ # Keep track of when we're inside or tags.
+ in_pre = false
+
+ # Here is the result stored in.
+ result = ""
+
+ # This is a cheat, used to get some context for one-character
+ # tokens that consist of just a quote char. What we do is remember
+ # the last character of the previous text token, to use as context
+ # to curl single- character quote tokens correctly.
+ prev_token_last_char = nil
+
+ tokens.each { |token|
+ if token.first == :tag
+ result << token[1]
+ if token[1] =~ %r!<(/?)(?:pre|code|kbd|script|math)[\s>]!
+ in_pre = ($1 != "/") # Opening or closing tag?
+ end
+ else
+ t = token[1]
+
+ # Remember last char of this token before processing.
+ last_char = t[-1].chr
+
+ unless in_pre
+ t = process_escapes t
+
+ t.gsub!(/"/, '"') if convert_quotes
+
+ if do_dashes
+ t = educate_dashes t if do_dashes == :normal
+ t = educate_dashes_oldschool t if do_dashes == :oldschool
+ t = educate_dashes_inverted t if do_dashes == :inverted
+ end
+
+ t = educate_ellipses t if do_ellipses
+
+ # Note: backticks need to be processed before quotes.
+ if do_backticks
+ t = educate_backticks t
+ t = educate_single_backticks t if do_backticks == :both
+ end
+
+ if do_quotes
+ if t == "'"
+ # Special case: single-character ' token
+ if prev_token_last_char =~ /\S/
+ t = "’"
+ else
+ t = "‘"
+ end
+ elsif t == '"'
+ # Special case: single-character " token
+ if prev_token_last_char =~ /\S/
+ t = "”"
+ else
+ t = "“"
+ end
+ else
+ # Normal case:
+ t = educate_quotes t
+ end
+ end
+
+ t = stupefy_entities t if do_stupefy
+ end
+
+ prev_token_last_char = last_char
+ result << t
+ end
+ }
+
+ # Done
+ result
+ end
+
+ protected
+
+ # Return the string, with after processing the following backslash
+ # escape sequences. This is useful if you want to force a "dumb" quote
+ # or other character to appear.
+ #
+ # Escaped are:
+ # \\ \" \' \. \- \`
+ #
+ def process_escapes(str)
+ str.gsub('\\\\', '\').
+ gsub('\"', '"').
+ gsub("\\\'", ''').
+ gsub('\.', '.').
+ gsub('\-', '-').
+ gsub('\`', '`')
+ end
+
+ # The string, with each instance of "-- " translated to an
+ # em-dash HTML entity.
+ #
+ def educate_dashes(str)
+ str.gsub(/--/, '—')
+ end
+
+ # The string, with each instance of "-- " translated to an
+ # en-dash HTML entity, and each "--- " translated to an
+ # em-dash HTML entity.
+ #
+ def educate_dashes_oldschool(str)
+ str.gsub(/---/, '—').gsub(/--/, '–')
+ end
+
+ # Return the string, with each instance of "-- " translated
+ # to an em-dash HTML entity, and each "--- " translated to
+ # an en-dash HTML entity. Two reasons why: First, unlike the en- and
+ # em-dash syntax supported by +educate_dashes_oldschool+, it's
+ # compatible with existing entries written before SmartyPants 1.1,
+ # back when "-- " was only used for em-dashes. Second,
+ # em-dashes are more common than en-dashes, and so it sort of makes
+ # sense that the shortcut should be shorter to type. (Thanks to
+ # Aaron Swartz for the idea.)
+ #
+ def educate_dashes_inverted(str)
+ str.gsub(/---/, '–').gsub(/--/, '—')
+ end
+
+ # Return the string, with each instance of "... " translated
+ # to an ellipsis HTML entity. Also converts the case where there are
+ # spaces between the dots.
+ #
+ def educate_ellipses(str)
+ str.gsub('...', '…').gsub('. . .', '…')
+ end
+
+ # Return the string, with "``backticks'' "-style single quotes
+ # translated into HTML curly quote entities.
+ #
+ def educate_backticks(str)
+ str.gsub("``", '“').gsub("''", '”')
+ end
+
+ # Return the string, with "`backticks' "-style single quotes
+ # translated into HTML curly quote entities.
+ #
+ def educate_single_backticks(str)
+ str.gsub("`", '‘').gsub("'", '’')
+ end
+
+ # Return the string, with "educated" curly quote HTML entities.
+ #
+ def educate_quotes(str)
+ punct_class = '[!"#\$\%\'()*+,\-.\/:;<=>?\@\[\\\\\]\^_`{|}~]'
+
+ str = str.dup
+
+ # Special case if the very first character is a quote followed by
+ # punctuation at a non-word-break. Close the quotes by brute
+ # force:
+ str.gsub!(/^'(?=#{punct_class}\B)/, '’')
+ str.gsub!(/^"(?=#{punct_class}\B)/, '”')
+
+ # Special case for double sets of quotes, e.g.:
+ # He said, "'Quoted' words in a larger quote."
+ str.gsub!(/"'(?=\w)/, '“‘')
+ str.gsub!(/'"(?=\w)/, '‘“')
+
+ # Special case for decade abbreviations (the '80s):
+ str.gsub!(/'(?=\d\ds)/, '’')
+
+ close_class = %![^\ \t\r\n\\[\{\(\-]!
+ dec_dashes = '–|—'
+
+ # Get most opening single quotes:
+ str.gsub!(/(\s| |--|&[mn]dash;|#{dec_dashes}|ȁ[34];)'(?=\w)/,
+ '\1‘')
+ # Single closing quotes:
+ str.gsub!(/(#{close_class})'/, '\1’')
+ str.gsub!(/'(\s|s\b|$)/, '’\1')
+ # Any remaining single quotes should be opening ones:
+ str.gsub!(/'/, '‘')
+
+ # Get most opening double quotes:
+ str.gsub!(/(\s| |--|&[mn]dash;|#{dec_dashes}|ȁ[34];)"(?=\w)/,
+ '\1“')
+ # Double closing quotes:
+ str.gsub!(/(#{close_class})"/, '\1”')
+ str.gsub!(/"(\s|s\b|$)/, '”\1')
+ # Any remaining quotes should be opening ones:
+ str.gsub!(/"/, '“')
+
+ str
+ end
+
+ # Return the string, with each RubyPants HTML entity translated to
+ # its ASCII counterpart.
+ #
+ # Note: This is not reversible (but exactly the same as in SmartyPants)
+ #
+ def stupefy_entities(str)
+ str.
+ gsub(/–/, '-'). # en-dash
+ gsub(/—/, '--'). # em-dash
+
+ gsub(/‘/, "'"). # open single quote
+ gsub(/’/, "'"). # close single quote
+
+ gsub(/“/, '"'). # open double quote
+ gsub(/”/, '"'). # close double quote
+
+ gsub(/…/, '...') # ellipsis
+ end
+
+ # Return an array of the tokens comprising the string. Each token is
+ # either a tag (possibly with nested, tags contained therein, such
+ # as , or a run of text between
+ # tags. Each element of the array is a two-element array; the first
+ # is either :tag or :text; the second is the actual value.
+ #
+ # Based on the _tokenize() subroutine from Brad Choate's
+ # MTRegex plugin.
+ #
+ # This is actually the easier variant using tag_soup, as used by
+ # Chad Miller in the Python port of SmartyPants.
+ #
+ def tokenize
+ tag_soup = /([^<]*)(<[^>]*>)/
+
+ tokens = []
+
+ prev_end = 0
+ scan(tag_soup) {
+ tokens << [:text, $1] if $1 != ""
+ tokens << [:tag, $2]
+
+ prev_end = $~.end(0)
+ }
+
+ if prev_end < size
+ tokens << [:text, self[prev_end..-1]]
+ end
+
+ tokens
+ end
+end
diff --git a/plugins/titlecase.rb b/plugins/titlecase.rb
new file mode 100644
index 0000000..7648932
--- /dev/null
+++ b/plugins/titlecase.rb
@@ -0,0 +1,36 @@
+class String
+ def titlecase
+ small_words = %w(a an and as at but by en for if in of on or the to v v. via vs vs.)
+
+ x = split(" ").map do |word|
+ # note: word could contain non-word characters!
+ # downcase all small_words, capitalize the rest
+ small_words.include?(word.gsub(/\W/, "").downcase) ? word.downcase! : word.smart_capitalize!
+ word
+ end
+ # capitalize first and last words
+ x.first.to_s.smart_capitalize!
+ x.last.to_s.smart_capitalize!
+ # small words are capitalized after colon, period, exclamation mark, question mark
+ x.join(" ").gsub(/(:|\.|!|\?)\s?(\W*#{small_words.join("|")}\W*)\s/) { "#{$1} #{$2.smart_capitalize} " }
+ end
+
+ def titlecase!
+ replace(titlecase)
+ end
+
+ def smart_capitalize
+ # ignore any leading crazy characters and capitalize the first real character
+ if self =~ /^['"\(\[']*([a-z])/
+ i = index($1)
+ x = self[i,self.length]
+ # word with capitals and periods mid-word are left alone
+ self[i,1] = self[i,1].upcase unless x =~ /[A-Z]/ or x =~ /\.\w+/
+ end
+ self
+ end
+
+ def smart_capitalize!
+ replace(smart_capitalize)
+ end
+end
diff --git a/plugins/video_tag.rb b/plugins/video_tag.rb
new file mode 100644
index 0000000..c6e67b7
--- /dev/null
+++ b/plugins/video_tag.rb
@@ -0,0 +1,56 @@
+# Title: Simple Video tag for Jekyll
+# Author: Brandon Mathis http://brandonmathis.com
+# Description: Easily output MPEG4 HTML5 video with a flash backup.
+#
+# Syntax {% video url/to/video [width height] [url/to/poster] %}
+#
+# Example:
+# {% video http://site.com/video.mp4 720 480 http://site.com/poster-frame.jpg %}
+#
+# Output:
+#
+#
+#
+#
+
+module Jekyll
+
+ class VideoTag < Liquid::Tag
+ @video = nil
+ @poster = ''
+ @height = ''
+ @width = ''
+
+ def initialize(tag_name, markup, tokens)
+ if markup =~ /(https?:\S+)(\s+(https?:\S+))?(\s+(https?:\S+))?(\s+(\d+)\s(\d+))?(\s+(https?:\S+))?/i
+ @video = [$1, $3, $5].compact
+ @width = $7
+ @height = $8
+ @poster = $10
+ end
+ super
+ end
+
+ def render(context)
+ output = super
+ type = {
+ 'mp4' => "type='video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"'",
+ 'ogv' => "type='video/ogg; codecs=theora, vorbis'",
+ 'webm' => "type='video/webm; codecs=vp8, vorbis'"
+ }
+ if @video.size > 0
+ video = ""
+ @video.each do |v|
+ t = v.match(/([^\.]+)$/)[1]
+ video += ""
+ end
+ video += " "
+ else
+ "Error processing input, expected syntax: {% video url/to/video [url/to/video] [url/to/video] [width height] [url/to/poster] %}"
+ end
+ end
+ end
+end
+
+Liquid::Template.register_tag('video', Jekyll::VideoTag)
+
diff --git a/sass/_base.scss b/sass/_base.scss
new file mode 100644
index 0000000..05fdd00
--- /dev/null
+++ b/sass/_base.scss
@@ -0,0 +1,5 @@
+@import "base/utilities";
+@import "base/solarized";
+@import "base/theme";
+@import "base/typography";
+@import "base/layout";
diff --git a/sass/_partials.scss b/sass/_partials.scss
new file mode 100644
index 0000000..b996887
--- /dev/null
+++ b/sass/_partials.scss
@@ -0,0 +1,7 @@
+@import "partials/header";
+@import "partials/navigation";
+@import "partials/blog";
+@import "partials/sharing";
+@import "partials/syntax";
+@import "partials/archive";
+@import "partials/footer";
diff --git a/sass/_parts.scss b/sass/_parts.scss
new file mode 100644
index 0000000..b7ee304
--- /dev/null
+++ b/sass/_parts.scss
@@ -0,0 +1,9 @@
+@import "parts/header";
+@import "parts/index";
+@import "parts/article";
+@import "parts/post";
+@import "parts/archive";
+@import "parts/comment";
+@import "parts/footer";
+@import "parts/syntax";
+@import "parts/twitter";
\ No newline at end of file
diff --git a/sass/_plugins.scss b/sass/_plugins.scss
new file mode 100644
index 0000000..cf82d1c
--- /dev/null
+++ b/sass/_plugins.scss
@@ -0,0 +1 @@
+@import "plugins/fancybox";
\ No newline at end of file
diff --git a/sass/base/_color.scss b/sass/base/_color.scss
new file mode 100644
index 0000000..e1a3d07
--- /dev/null
+++ b/sass/base/_color.scss
@@ -0,0 +1,8 @@
+$color-background: #eee !default;
+$color-main: #258fb8 !default;
+$color-gray01: #666 !default;
+$color-gray02: #999 !default;
+$color-gray03: #ccc !default;
+$color-gray04: #ddd !default;
+$color-gray05: #fff !default;
+
diff --git a/sass/base/_font.scss b/sass/base/_font.scss
new file mode 100644
index 0000000..6a26fe6
--- /dev/null
+++ b/sass/base/_font.scss
@@ -0,0 +1,17 @@
+$font-default: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, sans-serif !default;
+$font-mono: Menlo, Monaco, "Andale Mono", "lucida console", "Courier New", monospace !default;
+
+$font-icon: FontAwesome;
+$font-icon-path: "/font/fontawesome-webfont";
+
+@font-face {
+ font-family: 'FontAwesome';
+ src: url('#{$font-icon-path}.eot');
+ src: url('#{$font-icon-path}.eot?#iefix') format('embedded-opentype'),
+ url('#{$font-icon-path}.woff') format('woff'),
+ url('#{$font-icon-path}.ttf') format('truetype'),
+ url('#{$font-icon-path}.svgz#FontAwesomeRegular') format('svg'),
+ url('#{$font-icon-path}.svg#FontAwesomeRegular') format('svg');
+ font-weight: normal;
+ font-style: normal;
+}
diff --git a/sass/base/_layout.scss b/sass/base/_layout.scss
new file mode 100644
index 0000000..6eff7b4
--- /dev/null
+++ b/sass/base/_layout.scss
@@ -0,0 +1,182 @@
+$max-width: 960px !default;
+
+// Padding used for layout margins
+$pad-min: 18px !default;
+$pad-narrow: 25px !default;
+$pad-medium: 35px !default;
+$pad-wide: 55px !default;
+
+// Sidebar widths used in media queries
+$sidebar-width-medium: 240px !default;
+$sidebar-pad-medium: 15px !default;
+$sidebar-pad-wide: 20px !default;
+$sidebar-width-wide: 300px !default;
+
+$indented-lists: false !default;
+
+$header-font-size: 1em !default;
+$header-padding-top: 1.5em !default;
+$header-padding-bottom: 1.5em !default;
+
+.group { @include pie-clearfix; }
+
+@mixin collapse-sidebar {
+ float: none;
+ width: auto;
+ clear: left;
+ margin: 0;
+ padding: 0 $pad-medium 1px;
+ background-color: lighten($sidebar-bg, 2);
+ border-top: 1px solid lighten($sidebar-border, 4);
+ section {
+ &.odd, &.even { float: left; width: 48%; }
+ &.odd { margin-left: 0; }
+ &.even { margin-left: 4%; }
+ }
+ &.thirds section {
+ width: 30%;
+ margin-left: 5%;
+ &.first {
+ margin-left: 0;
+ clear: both;
+ }
+ }
+}
+
+body {
+ -webkit-text-size-adjust: none;
+ max-width: $max-width;
+ position: relative;
+ margin: 0 auto;
+ > header, > nav, > footer, #content > article, #content > div > article, #content > div > section {
+ @extend .group;
+ margin-left: $pad-min;
+ margin-right: $pad-min;
+ @media only screen and (min-width: 480px) {
+ margin-left: $pad-narrow;
+ margin-right: $pad-narrow;
+ }
+ @media only screen and (min-width: 768px) {
+ margin-left: $pad-medium;
+ margin-right: $pad-medium;
+ }
+ @media only screen and (min-width: 992px) {
+ margin-left: $pad-wide;
+ margin-right: $pad-wide;
+ }
+ }
+ div.pagination {
+ @extend .group;
+ margin-left: $pad-min;
+ margin-right: $pad-min;
+ @media only screen and (min-width: 480px) {
+ margin-left: $pad-narrow;
+ margin-right: $pad-narrow;
+ }
+ @media only screen and (min-width: 768px) {
+ margin-left: $pad-medium;
+ margin-right: $pad-medium;
+ }
+ @media only screen and (min-width: 992px) {
+ margin-left: $pad-wide;
+ margin-right: $pad-wide;
+ }
+ }
+ > header {
+ text-align: center;
+ font-size: $header-font-size;
+ padding-top: $header-padding-top;
+ padding-bottom: $header-padding-bottom;
+ }
+}
+
+#content {
+ overflow: hidden;
+ > div, > article { width: 100%; }
+}
+
+aside.sidebar {
+ float: none;
+ padding: 0 $pad-min 1px;
+ border-top: 1px solid $sidebar-border;
+ @extend .group;
+}
+
+.flex-content { max-width: 100%; height: auto; }
+
+.basic-alignment {
+ &.left { float: left; margin-right: 1.5em; }
+ &.right { float: right; margin-left: 1.5em; }
+ &.center { display:block; margin: 0 auto 1.5em; }
+ &.left, &.right { margin-bottom: .8em; }
+}
+
+.toggle-sidebar { &, .no-sidebar & { display: none; }}
+
+body.sidebar-footer {
+ @media only screen and (min-width: 750px) {
+ aside.sidebar{ @include collapse-sidebar; }
+ }
+ #content { margin-right: 0px; }
+ .toggle-sidebar { display: none; }
+}
+
+@media only screen and (min-width: 550px) {
+ body > header { font-size: $header-font-size; }
+}
+@media only screen and (min-width: 750px) {
+ aside.sidebar { @include collapse-sidebar; }
+}
+#main, #content, .sidebar {
+ @extend .group;
+}
+@media only screen and (min-width: 768px) {
+ body { -webkit-text-size-adjust: auto; }
+ body > header { font-size: $header-font-size * 1.2; }
+ #main {
+ padding: 0;
+ margin: 0 auto;
+ }
+ #content {
+ overflow: visible;
+ margin-right: $sidebar-width-medium;
+ position: relative;
+ .no-sidebar & { margin-right: 0; border-right: 0; }
+ .collapse-sidebar & { margin-right: 20px; }
+ > div, > article {
+ text-align:justify;
+ float: left;
+ }
+ article { padding-top: 3.3em; }
+ }
+ aside.sidebar {
+ width: $sidebar-width-medium - $sidebar-pad-medium*2;
+ padding: 0 $sidebar-pad-medium $sidebar-pad-medium;
+ background: none;
+ clear: none;
+ float: left;
+ margin: 0 -100% 0 0;
+ section {
+ width: auto; margin-left: 0;
+ &.odd, &.even { float: none; width: auto; margin-left: 0; }
+ }
+ .collapse-sidebar & {
+ @include collapse-sidebar;
+ }
+ }
+}
+
+@media only screen and (min-width: 992px) {
+ body > header { font-size: $header-font-size * 1.3; }
+ #content {
+ margin-right: $sidebar-width-wide;
+ article { padding-top: 4em; }
+ }
+ aside.sidebar {
+ width: $sidebar-width-wide - $sidebar-pad-wide*2;
+ padding: 1.2em $sidebar-pad-wide $sidebar-pad-wide;
+ .collapse-sidebar & {
+ padding: { left: $pad-wide; right: $pad-wide; }
+ }
+ }
+}
diff --git a/sass/base/_solarized.scss b/sass/base/_solarized.scss
new file mode 100644
index 0000000..485916b
--- /dev/null
+++ b/sass/base/_solarized.scss
@@ -0,0 +1,46 @@
+$base03: #002b36 !default; //darkest blue
+$base02: #073642 !default; //dark blue
+$base01: #4f4f4f !default; //darkest gray
+$base00: #657b83 !default; //dark gray
+$base0: #839496 !default; //medium gray
+$base1: #93a1a1 !default; //medium light gray
+$base2: #f8f8f8 !default; //cream
+$base3: #f3f3f3 !default; //white
+$solar-yellow: #b58900 !default;
+$solar-orange: #cb4b16 !default;
+$solar-red: #dc322f !default;
+$solar-magenta: #d33682 !default;
+$solar-violet: #6c71c4 !default;
+$solar-blue: #268bd2 !default;
+$solar-cyan: #2aa198 !default;
+$solar-green: #35a900 !default;
+
+$solarized: light!default;
+
+@if $solarized == light {
+
+ $_base03: $base03;
+ $_base02: $base02;
+ $_base01: $base01;
+ $_base00: $base00;
+ $_base0: $base0;
+ $_base1: $base1;
+ $_base2: $base2;
+ $_base3: $base3;
+
+ $base03: $_base3;
+ $base02: $_base2;
+ $base01: $_base1;
+ $base00: $_base0;
+ $base0: $_base00;
+ $base1: $_base01;
+ $base2: $_base02;
+ $base3: $_base03;
+}
+
+/* non highlighted code colors */
+$pre-bg: $base03 !default;
+$pre-border: darken($base02, 5) !default;
+$pre-color: $base1 !default;
+
+
diff --git a/sass/base/_theme.scss b/sass/base/_theme.scss
new file mode 100644
index 0000000..6579472
--- /dev/null
+++ b/sass/base/_theme.scss
@@ -0,0 +1,85 @@
+$img-border: inline-image('dotted-border.png');
+
+// Main Link Colors
+$link-color: #195ea2 !default;
+$link-color-hover: adjust-color($link-color, $lightness: 10, $saturation: 25) !default;
+$link-color-visited: adjust-color($link-color, $saturation: -20, $lightness: -4) !default;
+$link-color-active: adjust-color($link-color-hover, $lightness: -15) !default;
+
+// Main Section Colors
+$main-bg: #f8f8f8 !default;
+$page-bg: #fff !default;
+$article-border: #eeeeee !default;
+
+$header-bg: #fff !default;
+$header-border: lighten($header-bg, 15) !default;
+$title-color: #777777 !default;
+$subtitle-color: lighten($title-color, 25) !default;
+
+// Main Text Colors
+$subheader-color: lighten($title-color, 5) !default;
+$text-color: #222 !default;
+$text-color-light: lighten($text-color, 60) !default;
+$type-border: #ddd !default;
+
+/* Navigation */
+$nav-bg: #fff !default;
+$nav-bg-back: linear-gradient(lighten($nav-bg, 8), $nav-bg, darken($nav-bg, 11)) !default;
+$nav-color: darken($nav-bg, 55) !default;
+$nav-color-hover: darken($nav-color, 35) !default;
+$nav-placeholder: desaturate(darken($nav-bg, 10), 15) !default;
+$nav-border: darken($nav-bg, 10) !default;
+$nav-border-top: darken($nav-bg, 5) !default;
+$nav-border-bottom: darken($nav-bg, 5) !default;
+$nav-border-left: darken($nav-bg, 11) !default;
+$nav-border-right: lighten($nav-bg, 7) !default;
+
+/* Sidebar colors */
+$sidebar-bg: #fff !default;
+$sidebar-link-color: $link-color !default;
+$sidebar-link-color-hover: $link-color-hover !default;
+$sidebar-link-color-active: $link-color-active !default;
+$sidebar-color: change-color(mix($text-color, $sidebar-bg, 80), $hue: hue($sidebar-bg), $saturation: saturation($sidebar-bg)/2) !default;
+$sidebar-border: desaturate(darken($sidebar-bg, 7), 10) !default;
+$sidebar-border-hover: darken($sidebar-bg, 7) !default;
+$sidebar-link-color-subdued: lighten($sidebar-color, 20) !default;
+$sidebar-link-color-subdued-hover: $sidebar-link-color-hover !default;
+
+$footer-color: #888 !default;
+$footer-bg: #ccc !default;
+$footer-bg-back: linear-gradient(lighten($footer-bg, 8), $footer-bg, darken($footer-bg, 11)) !default;
+$footer-color: darken($footer-bg, 38) !default;
+$footer-color-hover: darken($footer-color, 10) !default;
+$footer-border-top: lighten($footer-bg, 15) !default;
+$footer-border-bottom: darken($footer-bg, 15) !default;
+$footer-link-color: darken($footer-bg, 38) !default;
+$footer-link-color-hover: darken($footer-color, 25) !default;
+$page-border-bottom: darken($footer-bg, 5) !default;
+
+
+/* Core theme application */
+
+a {
+ @include link-colors($link-color, $hover: $link-color-hover, $focus: $link-color-hover, $visited: $link-color-visited, $active: $link-color-active);
+}
+aside.sidebar a {
+ @include link-colors($sidebar-link-color, $hover: $sidebar-link-color-hover, $focus: $sidebar-link-color-hover, $active: $sidebar-link-color-active);
+}
+a {
+ @include transition(color .3s);
+}
+
+html {
+ background: $page-bg;
+ overflow-y: scroll;
+}
+body {
+ > div#main {
+ background: $page-bg;
+ border-bottom: 0;
+ > div {
+ background: $page-bg;
+ border-right: 0;
+ }
+ }
+}
diff --git a/sass/base/_typography.scss b/sass/base/_typography.scss
new file mode 100644
index 0000000..f1771e0
--- /dev/null
+++ b/sass/base/_typography.scss
@@ -0,0 +1,166 @@
+$blockquote: $type-border !default;
+
+// Fonts
+$sans: "Open Sans","Helvetica Neue", Arial, NanumBarunGothic, "Apple SD Gothic Neo", AppleGothic, "Malgun Gothic", DotumChe, sans-serif !default;
+$serif: "PT Serif", Georgia, Times, "Times New Roman", serif !default;
+$mono: Menlo, Monaco, "Andale Mono", "lucida console", "Courier New", DotumChe, monospace !default;
+$heading-font-family: "Lato", "Fontdiner Swanky", "Fjalla One", "Georgia", "Helvetica Neue", Arial, NanumBarunGothic, "Apple SD Gothic Neo", AppleGothic, "Malgun Gothic", DotumChe, sans-serif !default;
+$header-title-font-family: $heading-font-family !default;
+$header-subtitle-font-family: $serif !default;
+
+.heading {
+ font-family: $heading-font-family;
+}
+.sans { font-family: $sans; }
+.serif { font-family: $serif; }
+.mono { font-family: $mono; }
+
+body > header h1 {
+ font-size: 2.2em;
+ @extend .heading;
+ font-family: $header-title-font-family;
+ font-weight: normal;
+ line-height: 1.2em;
+ margin-bottom: 0.6667em;
+}
+body > header h2 {
+ font-family: $header-subtitle-font-family;
+}
+
+body {
+ line-height: 1.5em;
+ color: $text-color;
+ @extend .sans;
+ font-size: 1.2em;
+}
+h1 {
+ font-size: 2.2em;
+ line-height: 1.2em;
+}
+
+#{headings()}{
+ @extend .heading;
+ text-rendering: optimizelegibility;
+ margin-bottom: 1em;
+ font-weight: bold;
+}
+h2, section h1 {
+ font-size: 1.5em;
+ font-weight: bold;
+}
+h3, section h2, section section h1 {
+ font-size: 1.3em;
+ color: $subheader-color;
+ font-weight: bold;
+}
+h4, section h3, section section h2, section section section h1 {
+ font-size: 1em;
+ color: $subheader-color;
+}
+h5, section h4, section section h3 {
+ font-size: .9em;
+ color: $subheader-color;
+}
+h6, section h5, section section h4, section section section h3 {
+ font-size: .8em;
+ color: $subheader-color;
+}
+
+p, article blockquote, ul, ol { margin-bottom: 1.5em; }
+
+ul { list-style-type: disc;
+ ul { list-style-type: circle; margin-bottom: 0px;
+ ul { list-style-type: square; margin-bottom: 0px; }}}
+
+ol { list-style-type: decimal;
+ ol { list-style-type: lower-alpha; margin-bottom: 0px;
+ ol { list-style-type: lower-roman; margin-bottom: 0px; }}}
+
+ul, ol { &, ul, ol { margin-left: 2em; }}
+ul, ol { ul, ol { margin-bottom: 0em; }}
+
+strong { font-weight: bold; }
+
+em { font-style: italic; }
+
+sup, sub { font-size: 0.8em; position: relative; display: inline-block; }
+sup { top: -.5em; }
+sub { bottom: -.5em; }
+
+q { font-style: italic;
+ &:before { content: "\201C"; }
+ &:after { content: "\201D"; }
+}
+
+em, dfn { font-style: italic; }
+
+strong, dfn { font-weight: bold; }
+
+del, s { text-decoration: line-through; }
+
+abbr, acronym { border-bottom: 1px dotted; cursor: help; }
+
+pre, code, tt { @extend .mono; }
+
+sub, sup { line-height: 0; }
+
+hr { margin-bottom: 0.2em; }
+
+small { font-size: .8em; }
+
+big { font-size: 1.2em; }
+
+article blockquote {
+ $bq-margin: 1.2em;
+ font-style: italic;
+ position: relative;
+ font-size: 1.2em;
+ line-height: 1.5em;
+ padding-left: 1em;
+ border-left: 4px solid rgba($text-color-light, .5);
+ cite {
+ font-style: italic;
+ a { color: $text-color-light !important; word-wrap: break-word; }
+ &:before { content: '\2014'; padding:{right: .3em; left: .3em;} color: $text-color-light; }
+ }
+ @media only screen and (min-width: 992px) {
+ padding-left: 1.5em;
+ border-left-width: 4px;
+ }
+}
+
+.pullquote-right:before,
+.pullquote-left:before {
+ /* Reset metrics. */
+ padding: 0;
+ border: none;
+
+ /* Content */
+ content: attr(data-pullquote);
+
+ /* Pull out to the right, modular scale based margins. */
+ float: right;
+ width: 45%;
+ margin: .5em 0 1em 1.5em;
+
+ /* Baseline correction */
+ position: relative;
+ top: 7px;
+ font-size: 1.4em;
+ line-height: 1.45em;
+}
+
+.pullquote-left:before {
+ /* Make left pullquotes align properly. */
+ float: left;
+ margin: .5em 1.5em 1em 0;
+}
+
+/* @extend this to force long lines of continuous text to wrap */
+.force-wrap {
+ white-space: -moz-pre-wrap;
+ white-space: -pre-wrap;
+ white-space: -o-pre-wrap;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+}
diff --git a/sass/base/_utilities.scss b/sass/base/_utilities.scss
new file mode 100644
index 0000000..2d49e65
--- /dev/null
+++ b/sass/base/_utilities.scss
@@ -0,0 +1,28 @@
+@mixin mask-image($img, $repeat: no-repeat){
+ @include experimental(mask-image, image-url($img), -webkit, -moz, -o, -ms);
+ @include experimental(mask-repeat, $repeat, -webkit, -moz, -o, -ms);
+ width: image-width($img);
+ height: image-height($img);
+}
+
+@mixin shadow-box($border: #fff .5em solid, $shadow: rgba(#000, .15) 0 1px 4px, $border-radius: .3em) {
+ @include border-radius($border-radius);
+ @include box-shadow($shadow);
+ @include box-sizing(border-box);
+ border: $border;
+}
+
+@mixin selection($bg, $color: inherit, $text-shadow: none){
+ * {
+ &::-moz-selection { background: $bg; color: $color; text-shadow: $text-shadow; }
+ &::-webkit-selection { background: $bg; color: $color; text-shadow: $text-shadow; }
+ &::selection { background: $bg; color: $color; text-shadow: $text-shadow; }
+ }
+}
+
+@function text-color($color, $dark: dark, $light: light){
+ $text-color: ( (red($color)*299) + (green($color)*587) + (blue($color)*114) ) / 1000;
+ $text-color: if($text-color >= 150, $dark, $light);
+ @return $text-color;
+}
+
diff --git a/sass/custom/_color.scss b/sass/custom/_color.scss
new file mode 100644
index 0000000..7e3c604
--- /dev/null
+++ b/sass/custom/_color.scss
@@ -0,0 +1,7 @@
+// $color-background: #eee;
+// $color-main: #258fb8;
+// $color-gray01: #666;
+// $color-gray02: #999;
+// $color-gray03: #ccc;
+// $color-gray04: #ddd;
+// $color-gray05: #fff;
\ No newline at end of file
diff --git a/sass/custom/_colors.scss b/sass/custom/_colors.scss
new file mode 100644
index 0000000..d2a575a
--- /dev/null
+++ b/sass/custom/_colors.scss
@@ -0,0 +1,68 @@
+// Here you can easily change your sites's color scheme.
+// To give it a try, uncomment some of the lines below rebuild your blog, and see how it works.
+// If you need a handy color picker try http://hslpicker.com
+
+//$header-bg: #263347;
+//$subtitle-color: lighten($header-bg, 58);
+//$nav-bg: desaturate(lighten(#8fc17a, 18), 5);
+//$nav-bg-back: linear-gradient(lighten($nav-bg, 8), $nav-bg, darken($nav-bg, 11));
+//$sidebar-bg: desaturate(#eceff5, 8);
+//$sidebar-link-color: saturate(#526f9a, 10);
+//$sidebar-link-color-hover: darken(#7ab662, 9);
+//$footer-bg: #ccc !default;
+//$footer-bg-back: linear-gradient(lighten($footer-bg, 8), $footer-bg, darken($footer-bg, 11));
+
+
+/* To use the light Solarized highlighting theme uncomment the following line */
+//$solarized: light;
+
+/* If you want to tweak the Solarized colors you can do that here */
+//$base03: #002b36; //darkest blue
+//$base02: #073642; //dark blue
+//$base01: #586e75; //darkest gray
+//$base00: #657b83; //dark gray
+//$base0: #839496; //medium gray
+//$base1: #93a1a1; //medium light gray
+//$base2: #eee8d5; //cream
+//$base3: #fdf6e3; //white
+//$solar-yellow: #b58900;
+//$solar-orange: #cb4b16;
+//$solar-red: #dc322f;
+//$solar-magenta: #d33682;
+//$solar-violet: #6c71c4;
+//$solar-blue: #268bd2;
+//$solar-cyan: #2aa198;
+//$solar-green: #859900;
+
+
+/* Non highlighted code colors */
+//$pre-bg: $base03;
+//$pre-border: darken($base02, 5);
+//$pre-color: $base1;
+
+
+
+
+// ////////////////////////////////////////
+// change the header colors
+//
+$header-bg: #fff;
+$title-color: #000000 !default;
+$text-color: #333 !default;
+$text-color-light: #777 !default;
+$subtitle-color: darken($header-bg, 58);
+
+// ////////////////////////////////////////
+// change the footer
+//
+$footer-color: #888 !default;
+$footer-bg: #fff !default;
+$footer-bg-front: #fff !default;
+$footer-bg-back: #fff !default;
+$footer-color: darken($footer-bg, 38) !default;
+$footer-color-hover: darken($footer-color, 10) !default;
+$footer-border-top: lighten($footer-bg, 15) !default;
+$footer-border-bottom: darken($footer-bg, 15) !default;
+$footer-link-color: darken($footer-bg, 38) !default;
+$footer-link-color-hover: darken($footer-color, 25) !default;
+$page-border-bottom: darken($footer-bg, 5) !default;
diff --git a/sass/custom/_fonts.scss b/sass/custom/_fonts.scss
new file mode 100644
index 0000000..213062e
--- /dev/null
+++ b/sass/custom/_fonts.scss
@@ -0,0 +1,10 @@
+// Here you can easily change font faces which are used in your site.
+// To give it a try, uncomment some of the lines below rebuild your blog, and see how it works. your sites's.
+// If you love to use Web Fonts, you also need to add some lines to source/_includes/custom/head.html
+
+// $sans: "Open Sans","Helvetica Neue", Arial, sans-serif !default;
+// $serif: "PT Serif", Georgia, Times, "Times New Roman", serif !default;
+// $mono: Menlo, Monaco, "Andale Mono", "lucida console", "Courier New", monospace !default;
+// $heading-font-family: "Fjalla One", "Georgia", "Helvetica Neue", Arial, sans-serif !default;
+// $header-title-font-family: $heading-font-family !default;
+// $header-subtitle-font-family: $serif !default;
diff --git a/sass/custom/_layout.scss b/sass/custom/_layout.scss
new file mode 100644
index 0000000..2a80f25
--- /dev/null
+++ b/sass/custom/_layout.scss
@@ -0,0 +1,21 @@
+// Here you can easily change your sites's layout.
+// To give it a try, uncomment some of the lines below, make changes, rebuild your blog, and see how it works.
+
+//$header-font-size: 1em;
+//$header-padding-top: 1.5em;
+//$header-padding-bottom: 1.5em;
+
+$max-width: 900px;
+$indented-lists: true;
+
+// Padding used for layout margins
+$pad-min: 18px;
+$pad-narrow: 25px;
+$pad-medium: 35px;
+$pad-wide: 55px;
+
+// Sidebar widths used in media queries
+//$sidebar-width-medium: 240px;
+//$sidebar-pad-medium: 15px;
+//$sidebar-pad-wide: 20px;
+//$sidebar-width-wide: 300px;
diff --git a/sass/custom/_styles.scss b/sass/custom/_styles.scss
new file mode 100644
index 0000000..26c0e93
--- /dev/null
+++ b/sass/custom/_styles.scss
@@ -0,0 +1,5 @@
+// This File is imported last, and will override other styles in the cascade
+// Add styles here to customize your blog
+// By default this file should be EMPTY!!!
+// Please edit specifications in place if you are building an other theme!
+
diff --git a/sass/partials/_archive.scss b/sass/partials/_archive.scss
new file mode 100644
index 0000000..9ef1e82
--- /dev/null
+++ b/sass/partials/_archive.scss
@@ -0,0 +1,72 @@
+#archive {
+ #content > div { &, > article { padding-top: 0; } }
+}
+#blog-archives {
+ article {
+ padding: 1em 0 1em;
+ position: relative;
+ background: $img-border bottom left repeat-x;
+ &:last-child {
+ background: none;
+ }
+ footer { padding: 0; margin: 0;}
+ }
+ h1 { color: $text-color; margin-bottom: .3em; }
+ h2 { display: none; }
+ h1 {
+ font-size: 1.5em;
+ a {
+ @include hover-link;
+ color: inherit;
+ &:hover { color: $link-color-hover; }
+ font-weight: normal;
+ display: inline-block;
+ }
+ }
+ a.category, time {
+ @extend .sans;
+ color: $text-color-light;
+ }
+ color: $text-color-light;
+ .entry-content { display: none; }
+ time {
+ font-size: .9em;
+ line-height: 1.2em;
+ .month, .day { display: inline-block; }
+ .month { text-transform: uppercase; }
+ }
+ p { margin-bottom: 1em; }
+ &, .entry-content { a { @include link-colors(inherit, $link-color-hover); }}
+ a:hover { color: $link-color-hover; }
+ @media only screen and (min-width: 550px) {
+ article { margin-left: 5em; }
+ h2 {
+ margin-bottom: .3em;
+ font-weight: normal;
+ display: inline-block;
+ position: relative; top: -1px;
+ float: left;
+ &:first-child { padding-top: .75em; }
+ }
+ time {
+ position: absolute;
+ text-align: right;
+ left: 0em;
+ top: 1.8em;
+ }
+ .year { display: none; }
+ article {
+ padding:{left: 4.5em; bottom: .7em;}
+ }
+ a.category {
+ line-height: 1.1em;
+ }
+ }
+}
+#content > .category {
+ article {
+ margin-left: 0;
+ padding-left: 6.8em;
+ }
+ .year { display: inline; }
+}
diff --git a/sass/partials/_blog.scss b/sass/partials/_blog.scss
new file mode 100644
index 0000000..2bbcf9b
--- /dev/null
+++ b/sass/partials/_blog.scss
@@ -0,0 +1,150 @@
+article {
+ padding-top: 2.3em;
+ a { @extend .force-wrap;
+ &, &:visited, &:active, &:hover { text-decoration: none; }
+ }
+ header {
+ position: relative;
+ padding-top: 2em;
+ padding-bottom: 1em;
+ padding-left: 0;
+ padding-right: 0;
+ margin-bottom: 1em;
+ background: $img-border bottom left repeat-x;
+ h1 {
+ margin: 0;
+ font-weight: 400;
+ a { text-decoration: none;
+ @include link-colors($text-color, $visited: $text-color);
+ }
+ }
+ p {
+ font-size: .9em;
+ color: $text-color-light;
+ margin: 0;
+ &.meta {
+ @extend .sans;
+ text-transform: uppercase;
+ position: absolute; top: 0;
+ }
+ }
+ @media only screen and (min-width: 768px) {
+ margin-bottom: 1.5em;
+ padding-bottom: 1em;
+ background: $img-border bottom left repeat-x;
+ }
+ }
+ h2 {
+ padding-top: 0.8em;
+ background: $img-border top left repeat-x;
+ }
+ .entry-content & h2:first-child, header + h2 { padding-top: 0; }
+ h2:first-child, header + h2 { background: none; }
+ .feature {
+ padding-top: .5em;
+ margin-bottom: 1em;
+ padding-bottom: 1em;
+ background: $img-border bottom left repeat-x;
+ font-size: 2.0em; font-style: italic;
+ line-height: 1.3em;
+ }
+ img, video, .flash-video {
+ @extend .flex-content;
+ @extend .basic-alignment;
+ @include shadow-box;
+ }
+ video, .flash-video { margin: 0 auto 1.5em; }
+ video { display: block; width: 100%; }
+ .flash-video {
+ > div {
+ position: relative;
+ display: block;
+ padding-bottom: 56.25%;
+ padding-top: 1px;
+ height: 0;
+ overflow: hidden;
+ iframe, object, embed {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ }
+ }
+ }
+ > footer {
+ padding-bottom: 2.5em;
+ margin-top: 2em;
+ @extend .sans;
+ p.meta {
+ margin-bottom: .8em;
+ font-size: .85em;
+ clear: both;
+ overflow: hidden;
+ }
+ .byline + time:before, time +time:before, .comments:before, .byline ~ .categories:before {
+ @extend .separator;
+ }
+ }
+
+}
+article + article {
+ .blog-index & {
+ background: $img-border top left repeat-x;
+ }
+}
+#content .blog-index {
+ padding: { top: 0; bottom: 0; }
+ article header { background: none; padding-bottom: 0; }
+ article h1 {
+ font-size: 2.2em;
+ a { color: inherit; &:hover { color: $link-color-hover; } }
+ }
+ a[rel=full-article] {
+ background: darken($main-bg, 5);
+ display: inline-block;
+ padding: .4em .8em;
+ margin-right: .5em;
+ text-decoration: none;
+ color: mix($text-color, $text-color-light);
+ @extend .serif;
+ @include transition(background-color .5s);
+ &:hover {
+ background: $link-color-hover;
+ text-shadow: none;
+ color: $main-bg;
+ }
+ }
+ footer {
+ @extend .sans;
+ margin-top: 1em;
+ }
+}
+
+.separator {
+ content: "\2022 ";
+ padding: 0 .4em 0 .2em;
+ display: inline-block;
+}
+
+#content div.pagination {
+ text-align: center;
+ font-size: .95em;
+ position: relative;
+ background: none repeat scroll 0 0 transparent;
+ margin-top: 4em;
+ margin-bottom: 0;
+ padding: {top: 1.5em; bottom: 1.5em;}
+ border-top: dotted 1px #D1D1D1;
+ border-bottom: dotted 1px #D1D1D1;
+ a {
+ text-decoration: none;
+ color: $text-color-light;
+ &.prev { position: absolute; left: 0; }
+ &.next { position: absolute; right: 0; }
+ &:hover { color: $link-color-hover; }
+ &[href*=archive] {
+ &:before, &:after { content: '\2014'; padding: 0 .3em; }
+ }
+ }
+}
diff --git a/sass/partials/_footer.scss b/sass/partials/_footer.scss
new file mode 100644
index 0000000..60093dc
--- /dev/null
+++ b/sass/partials/_footer.scss
@@ -0,0 +1,17 @@
+body > footer {
+ @extend .sans;
+ text-align: center;
+ font-size: .8em;
+ color: $footer-color;
+ background-color: #FFF;
+ position: relative;
+ padding-top: 1em;
+ padding-bottom: 1em;
+ margin-bottom: 3em;
+ @include border-bottom-radius(.4em);
+ z-index: 1;
+ a {
+ @include link-colors($footer-link-color, $footer-link-color-hover, $visited: $footer-link-color);
+ }
+ p:last-child { margin-bottom: 0; }
+}
diff --git a/sass/partials/_header.scss b/sass/partials/_header.scss
new file mode 100644
index 0000000..91f27d5
--- /dev/null
+++ b/sass/partials/_header.scss
@@ -0,0 +1,18 @@
+body > header {
+ background: $header-bg;
+ h1 {
+ display: inline-block;
+ margin: 0;
+ a, a:visited, a:hover {
+ color: $title-color;
+ text-decoration: none;
+ }
+ }
+ h2 {
+ margin: .2em 0 0;
+ @extend .sans;
+ font-size: 1em;
+ color: $subtitle-color;
+ font-weight: normal;
+ }
+}
diff --git a/sass/partials/_navigation.scss b/sass/partials/_navigation.scss
new file mode 100644
index 0000000..2e95adf
--- /dev/null
+++ b/sass/partials/_navigation.scss
@@ -0,0 +1,162 @@
+body > nav {
+ position: relative;
+ background-color: $nav-bg;
+ border: {
+ top: 1px solid $nav-border-top;
+ bottom: 1px solid $nav-border-bottom; }
+ padding-top: .35em;
+ padding-bottom: .35em;
+ padding-left: 5px;
+ padding-right: 5px;
+ form {
+ @include background-clip(padding-box);
+ margin: 0; padding: 0;
+ .search {
+ padding: .3em .5em 0;
+ font-size: .85em;
+ font-family: $sans;
+ line-height: 1.1em;
+ width: 95%;
+ @include border-radius(.5em);
+ @include background-clip(padding-box);
+ @include box-shadow(lighten($nav-bg, 2) 0 1px);
+ border: 1px solid $nav-border;
+ background-color: $nav-border-top;
+ border-radius: 0.2em 0.2em 0.2em 0.2em;
+ box-shadow: none;
+ border: 0px;
+ padding-top: 0.3em;
+ padding-bottom: 0.3em;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ &:focus {
+ color: #444;
+ border-color: #80b1df;
+ @include box-shadow(#80b1df 0 0 4px, #80b1df 0 0 3px inset);
+ background-color: #fff;
+ outline: none;
+ }
+ }
+ }
+ fieldset[role=search]{ float: right; width: 48%; }
+ fieldset.mobile-nav{ float: left; width: 48%;
+ select{ width: 100%; font-size: .8em; border: 1px solid #888;}
+ }
+ ul { display: none; }
+ @media only screen and (min-width: 550px) {
+ font-size: .9em;
+ ul {
+ @include horizontal-list(0);
+ float: left;
+ display: block;
+ padding-top: .15em;
+ }
+ ul.subscription {
+ margin-left: .8em;
+ float: right;
+ li:last-child a { padding-right: 0; }
+ }
+ ul li {
+ margin: 0;
+ }
+ a {
+ @include link-colors($nav-color, $nav-color-hover, $visited: $nav-color);
+ font-family: $sans;
+ text-shadow: darken($nav-bg, 3) 0 1px;
+ float: left;
+ text-decoration: none;
+ font-size: .9em;
+ padding: .3em 0 .1em;
+ line-height: 1.5em;
+ }
+ li + li {
+ border-left: 0;
+ margin-left: .8em;
+ a {
+ padding-left: .8em;
+ border-left: 1px solid $nav-border-right;
+ }
+ }
+ form {
+ float: right;
+ text-align: left;
+ padding-left: .8em;
+ width: $sidebar-width-medium - $pad-medium*2 - $sidebar-pad-medium + 20px;
+ .search {
+ width: 93%;
+ font-size: .95em;
+ line-height: 1.2em;
+ }
+ }
+ ul[data-subscription$=email] + form {
+ width: $sidebar-width-medium - $pad-medium*2 - $sidebar-pad-medium - 58px;
+ .search { width: 91%; }
+ }
+ fieldset.mobile-nav { display: none; }
+ fieldset[role=search]{ width: 99%; }
+ }
+ @media only screen and (min-width: 992px) {
+ form {
+ width: $sidebar-width-wide - $pad-wide - $sidebar-pad-wide*2 + 10px;
+ }
+ ul[data-subscription$=email] + form {
+ width: $sidebar-width-wide - $pad-wide - $sidebar-pad-wide*2 - 58px;
+ }
+ }
+}
+.no-placeholder {
+ body > nav .search {
+ background: lighten($nav-bg, 15) image-url('search.png') .3em .25em no-repeat;
+ text-indent: 1.3em;
+ }
+}
+@mixin whitespace-subscription-button($feed){
+ position: relative; top: 0px;
+ text-indent: -999999em;
+ border: 0;
+ padding: 0;
+ &,&:after { @include mask-image($feed); }
+ &:after {
+ content: "";
+ position: absolute; top: 0; left: 0;
+ background-color: lighten($nav-color, 15);
+ }
+ &:hover:after { background-color: lighten($nav-color, 20); }
+}
+@mixin mask-subscription-nav($feed: 'rss.png'){
+ position: relative; top: 1px;
+ text-indent: -999999em;
+ background-color: $nav-border-right;
+ border: 0;
+ padding: 0;
+ &,&:after { @include mask-image($feed); }
+ &:after {
+ content: "";
+ position: absolute; top: -1px; left: 0;
+ background-color: lighten($nav-color, 15);
+ }
+ &:hover:after { background-color: lighten($nav-color, 20); }
+}
+.maskImage {
+ body > nav {
+ @media only screen and (min-width: 550px) {
+ ul[data-subscription$=email] + form {
+ width: $sidebar-width-medium - $pad-medium*2 - $sidebar-pad-medium - 32px;
+ }
+ }
+ @media only screen and (min-width: 992px) {
+ ul[data-subscription$=email] + form {
+ width: $sidebar-width-wide - $pad-wide - $sidebar-pad-wide*2 - 32px;
+ }
+ }
+ }
+ ul.subscription { position: relative; top: .2em; li, a { border: 0; padding: 0; }}
+ a[rel=subscribe-bitbucket]{ @include whitespace-subscription-button('bitbucket_22_gray.png'); }
+ a[rel=subscribe-github]{ @include whitespace-subscription-button('github_22_gray.png'); }
+ a[rel=subscribe-delicious]{ @include whitespace-subscription-button('delicious_22_gray.png'); }
+ a[rel=subscribe-pinboard]{ @include whitespace-subscription-button('pinboard_22_gray.png'); }
+ a[rel=publisher]{ @include whitespace-subscription-button('gprofile_22_gray.png'); }
+ a[rel=subscribe-rss]{ @include mask-subscription-nav('rss.png'); }
+ a[rel=subscribe-email]{ @include mask-subscription-nav('email.png'); }
+}
+
diff --git a/sass/partials/_sharing.scss b/sass/partials/_sharing.scss
new file mode 100644
index 0000000..bc0105d
--- /dev/null
+++ b/sass/partials/_sharing.scss
@@ -0,0 +1,12 @@
+.sharing {
+ p.meta + & {
+ padding: { top: 1em; left: 0; }
+ background: $img-border top left repeat-x;
+ }
+}
+
+#fb-root { display: none; }
+
+.fb-like.fb_iframe_widget span {
+ vertical-align: baseline !important;
+}
diff --git a/sass/partials/_sidebar.scss b/sass/partials/_sidebar.scss
new file mode 100644
index 0000000..e69de29
diff --git a/sass/partials/_syntax.scss b/sass/partials/_syntax.scss
new file mode 100644
index 0000000..b1eaa81
--- /dev/null
+++ b/sass/partials/_syntax.scss
@@ -0,0 +1,258 @@
+.highlight, html .gist .gist-file .gist-syntax .gist-highlight {
+ table td.code, td.line-data { width: 100%; }
+ border: 1px solid $pre-border !important;
+}
+.highlight .line-numbers, html .gist .gist-file .gist-syntax .highlight .line_numbers {
+ text-align: right;
+ font-size: 13px;
+ line-height: 1.45em;
+ @if $solarized == light {
+ background: lighten($base03, 1) !important;
+ border-right: 1px solid darken($base02, 2) !important;
+ @include box-shadow(lighten($base03, 2) -1px 0 inset);
+ text-shadow: lighten($base02, 2) 0 -1px;
+ } @else {
+ background: $base02 !important;
+ border-right: 1px solid darken($base03, 2) !important;
+ @include box-shadow(lighten($base02, 2) -1px 0 inset);
+ text-shadow: darken($base02, 10) 0 -1px;
+ }
+ span { color: $base01 !important; }
+ padding: .8em !important;
+ @include border-radius(0);
+}
+
+figure.code, .gist-file, pre {
+ @include box-shadow(rgba(#000, .06) 0 0 10px);
+ .highlight pre { @include box-shadow(none); }
+}
+
+html .gist .gist-file {
+ margin-bottom: 1.8em;
+ position: relative;
+ border: none;
+ padding-top: image-height("code_bg.png") !important;
+ .highlight {
+ margin-bottom: 0;
+ }
+ .gist-syntax {
+ border-bottom: 0 !important;
+ background: none !important;
+ .gist-highlight {
+ background: $base03 !important;
+ }
+ .highlight pre {
+ @extend .pre-code;
+ font-size: 13px;
+ padding: 0;
+ }
+ }
+ .gist-meta {
+ padding: .6em 0.8em;
+ border: 1px solid lighten($base02, 2) !important;
+ color: $base01;
+ font-size: .7em !important;
+ @if $solarized == light {
+ background: lighten($base03, 2);
+ border: 1px solid $pre-border !important;
+ border-top: 1px solid lighten($base03, 2) !important;
+ } @else {
+ background: $base02;
+ }
+ @extend .sans;
+ line-height: 1.5em;
+ a {
+ color: mix($base1, $base01) !important;
+ @include hover-link;
+ &:hover { color: $base1 !important; }
+ }
+ a[href*='#file'] {
+ position: absolute; top: 0; left:0; right:0;
+ color: #474747 !important;
+ @extend .code-title;
+ &:hover { color: $link-color !important; }
+ }
+ a[href*=raw]{
+ @extend .download-source;
+ top: .4em;
+ }
+ }
+}
+pre {
+ background: $pre-bg;
+ @include border-radius(.4em);
+ @extend .mono;
+ border: 1px solid $pre-border;
+ line-height: 1.45em;
+ font-size: 13px;
+ margin-bottom: 2.1em;
+ padding: .8em 1em;
+ color: $pre-color;
+ overflow: auto;
+}
+h3.filename {
+ @extend .code-title;
+ + pre { @include border-top-radius(0px); }
+}
+
+p, li {
+ code {
+ @extend .mono;
+ display: inline;
+ word-wrap: break-word;
+ background: #fff;
+ font-size: .8em;
+ line-height: 1.5em;
+ color: #555;
+ border: 1px solid #ddd;
+ @include border-radius(.4em);
+ padding: 0 .3em;
+ margin: -1px 0;
+ }
+ pre code { font-size: 1em !important; background: none; border: none; }
+}
+
+.pre-code {
+ font-family: $mono !important;
+ overflow: scroll;
+ overflow-y: hidden;
+ display: block;
+ padding: .8em;
+ overflow-x: auto;
+ line-height: 1.45em;
+ background: $base03 !important;
+ color: $base1 !important;
+ span { color: $base1 !important; }
+ span { font-style: normal !important; font-weight: normal !important; }
+
+ .c { color: $base01 !important; font-style: italic !important; } /* Comment */
+ .cm { color: $base01 !important; font-style: italic !important; } /* Comment.Multiline */
+ .cp { color: $base01 !important; font-style: italic !important; } /* Comment.Preproc */
+ .c1 { color: $base01 !important; font-style: italic !important; } /* Comment.Single */
+ .cs { color: $base01 !important; font-weight: bold !important; font-style: italic !important; } /* Comment.Special */
+ .err { color: $solar-red !important; background: none !important; } /* Error */
+ .k { color: $solar-orange !important; } /* Keyword */
+ .o { color: $base1 !important; font-weight: bold !important; } /* Operator */
+ .p { color: $base1 !important; } /* Operator */
+ .ow { color: $solar-cyan !important; font-weight: bold !important; } /* Operator.Word */
+ .gd { color: $base1 !important; background-color: mix($solar-red, $base03, 25%) !important; display: inline-block; } /* Generic.Deleted */
+ .gd .x { color: $base1 !important; background-color: mix($solar-red, $base03, 35%) !important; display: inline-block; } /* Generic.Deleted.Specific */
+ .ge { color: $base1 !important; font-style: italic !important; } /* Generic.Emph */
+ //.gr { color: #aa0000 } /* Generic.Error */
+ .gh { color: $base01 !important; } /* Generic.Heading */
+ .gi { color: $base1 !important; background-color: mix($solar-green, $base03, 20%) !important; display: inline-block; } /* Generic.Inserted */
+ .gi .x { color: $base1 !important; background-color: mix($solar-green, $base03, 40%) !important; display: inline-block; } /* Generic.Inserted.Specific */
+ //.go { color: #888888 } /* Generic.Output */
+ //.gp { color: #555555 } /* Generic.Prompt */
+ .gs { color: $base1 !important; font-weight: bold !important; } /* Generic.Strong */
+ .gu { color: $solar-violet !important; } /* Generic.Subheading */
+ //.gt { color: #aa0000 } /* Generic.Traceback */
+ .kc { color: $solar-green !important; font-weight: bold !important; } /* Keyword.Constant */
+ .kd { color: $solar-blue !important; } /* Keyword.Declaration */
+ .kp { color: $solar-orange !important; font-weight: bold !important; } /* Keyword.Pseudo */
+ .kr { color: $solar-magenta !important; font-weight: bold !important; } /* Keyword.Reserved */
+ .kt { color: $solar-cyan !important; } /* Keyword.Type */
+ .n { color: $solar-blue !important; }
+ .na { color: $solar-blue !important; } /* Name.Attribute */
+ .nb { color: $solar-green !important; } /* Name.Builtin */
+ .nc { color: $solar-magenta !important;} /* Name.Class */
+ .no { color: $solar-yellow !important; } /* Name.Constant */
+ //.ni { color: #800080 } /* Name.Entity */
+ .nl { color: $solar-green !important; }
+ .ne { color: $solar-blue !important; font-weight: bold !important; } /* Name.Exception */
+ .nf { color: $solar-blue !important; font-weight: bold !important; } /* Name.Function */
+ .nn { color: $solar-yellow !important; } /* Name.Namespace */
+ .nt { color: $solar-blue !important; font-weight: bold !important; } /* Name.Tag */
+ .nx { color: $solar-yellow !Important; }
+ //.bp { color: #999999 } /* Name.Builtin.Pseudo */
+ //.vc { color: #008080 } /* Name.Variable.Class */
+ .vg { color: $solar-blue !important; } /* Name.Variable.Global */
+ .vi { color: $solar-blue !important; } /* Name.Variable.Instance */
+ .nv { color: $solar-blue !important; } /* Name.Variable */
+ //.w { color: #bbbbbb } /* Text.Whitespace */
+ .mf { color: $solar-cyan !important; } /* Literal.Number.Float */
+ .m { color: $solar-cyan !important; } /* Literal.Number */
+ .mh { color: $solar-cyan !important; } /* Literal.Number.Hex */
+ .mi { color: $solar-cyan !important; } /* Literal.Number.Integer */
+ //.mo { color: #009999 } /* Literal.Number.Oct */
+ .s { color: $solar-cyan !important; } /* Literal.String */
+ //.sb { color: #d14 } /* Literal.String.Backtick */
+ //.sc { color: #d14 } /* Literal.String.Char */
+ .sd { color: $solar-cyan !important; } /* Literal.String.Doc */
+ .s2 { color: $solar-cyan !important; } /* Literal.String.Double */
+ .se { color: $solar-red !important; } /* Literal.String.Escape */
+ //.sh { color: #d14 } /* Literal.String.Heredoc */
+ .si { color: $solar-blue !important; } /* Literal.String.Interpol */
+ //.sx { color: #d14 } /* Literal.String.Other */
+ .sr { color: $solar-cyan !important; } /* Literal.String.Regex */
+ .s1 { color: $solar-cyan !important; } /* Literal.String.Single */
+ //.ss { color: #990073 } /* Literal.String.Symbol */
+ //.il { color: #009999 } /* Literal.Number.Integer.Long */
+ div { .gd, .gd .x, .gi, .gi .x { display: inline-block; width: 100%; }}
+}
+
+.highlight, .gist-highlight {
+ pre { background: none; @include border-radius(0px); border: none; padding: 0; margin-bottom: 0; }
+ margin-bottom: 1.8em;
+ background: $base03;
+ overflow-y: hidden;
+ overflow-x: auto;
+}
+
+$solar-scroll-bg: rgba(#fff, .15);
+$solar-scroll-thumb: rgba(#fff, .2);
+@if $solarized == light {
+ $solar-scroll-bg: rgba(#000, .15);
+ $solar-scroll-thumb: rgba(#000, .15);
+}
+
+pre, .highlight, .gist-highlight {
+ &::-webkit-scrollbar { height: .5em; background: $solar-scroll-bg; }
+ &::-webkit-scrollbar-thumb:horizontal { background: $solar-scroll-thumb; -webkit-border-radius: 4px; border-radius: 4px }
+}
+
+.highlight code {
+ @extend .pre-code; background: #000;
+}
+figure.code {
+ background: none;
+ padding: 0;
+ border: 0;
+ margin-bottom: 1.5em;
+ pre { margin-bottom: 0; }
+ figcaption {
+ position: relative;
+ @extend .code-title;
+ a { @extend .download-source; }
+ }
+ .highlight {
+ margin-bottom: 0;
+ }
+}
+
+.code-title {
+ text-align: center;
+ font-size: 13px;
+ line-height: 2em;
+ text-shadow: #cbcccc 0 1px 0;
+ color: #474747;
+ font-weight: normal;
+ margin-bottom: 0;
+ @include border-top-radius(5px);
+ font-family: $sans;
+ background: #cccccc image-url("code_bg.png") top repeat-x;
+ border-top-color: #cbcbcb;
+ border-left-color: #a5a5a5;
+ border-right-color: #a5a5a5;
+ border-bottom: 0;
+}
+
+.download-source {
+ position: absolute; right: .8em;
+ @include hover-link;
+ color: #666 !important;
+ z-index: 1;
+ font-size: 13px;
+ text-shadow: #cbcccc 0 1px 0;
+ padding-left: 3em;
+}
diff --git a/sass/partials/sidebar/_base.scss b/sass/partials/sidebar/_base.scss
new file mode 100644
index 0000000..e69de29
diff --git a/sass/partials/sidebar/_delicious.scss b/sass/partials/sidebar/_delicious.scss
new file mode 100644
index 0000000..e69de29
diff --git a/sass/partials/sidebar/_googleplus.scss b/sass/partials/sidebar/_googleplus.scss
new file mode 100644
index 0000000..e69de29
diff --git a/sass/partials/sidebar/_pinboard.scss b/sass/partials/sidebar/_pinboard.scss
new file mode 100644
index 0000000..e69de29
diff --git a/sass/parts/_archive.scss b/sass/parts/_archive.scss
new file mode 100644
index 0000000..81c7789
--- /dev/null
+++ b/sass/parts/_archive.scss
@@ -0,0 +1,76 @@
+.archives{
+ position: relative;
+ &:last-of-type{
+ &:before{
+ content: "";
+ position: absolute;
+ bottom: 0;
+ width: 200px;
+ border-top: 1px solid $color-gray04;
+ }
+ }
+ .year{
+ line-height: 35px;
+ width: 200px;
+ position: absolute;
+ top: 0;
+ padding-top: 15px;
+ border-top: 1px solid #fff;
+ &:before{
+ content: "";
+ position: absolute;
+ top: -2px;
+ width: 100%;
+ border-top: 1px solid $color-gray04;
+ }
+ @media screen and (max-width: 600px){
+ position: relative;
+ width: 100%;
+ }
+ }
+ article{
+ margin-left: 200px;
+ padding: 15px 0;
+ @media screen and (max-width: 600px){
+ margin-left: 0;
+ &:first-of-type{
+ border-top: none;
+ padding-top: 30px;
+ }
+ }
+ .title{
+ margin-bottom: 0;
+ }
+ .meta{
+ line-height: 2;
+ font-size: 0.9em;
+ color: $color-gray02;
+ margin-top: 15px;
+ @media screen and (max-width: 600px){
+ display: none;
+ }
+ a{
+ @include link-colors($color-gray02, $color-gray01);
+ @include transition(0.3s);
+ }
+ .date, .tags, .comments{
+ padding-left: 30px;
+ position: relative;
+ &:before{
+ color: $color-gray03;
+ font: 1.3em $font-icon;
+ line-height: 1.6em;
+ position: absolute;
+ left: 0;
+ }
+ @media screen and (max-width: 600px){
+ @include inline-block;
+ margin-right: 30px;
+ }
+ }
+ .date:before{content: "\f073";}
+ .tags:before{content: "\f02c";}
+ .comments:before{content: "\f075";}
+ }
+ }
+}
diff --git a/sass/parts/_article.scss b/sass/parts/_article.scss
new file mode 100644
index 0000000..77b9712
--- /dev/null
+++ b/sass/parts/_article.scss
@@ -0,0 +1,141 @@
+article{
+ border-bottom: 1px solid $color-gray04;
+ border-top: 1px solid $color-gray05;
+ padding: 30px 0;
+ position: relative;
+ @media screen and (max-width: 800px){
+ padding-bottom: 15px;
+ }
+ @media screen and (max-width: 600px){
+ padding: 15px 0;
+ }
+ h2.title{
+ font-size: 1.8em;
+ font-weight: 300;
+ line-height: 35px;
+ margin-bottom: 20px;
+ a{
+ color: $color-gray01;
+ }
+ }
+ .entry-content{
+ line-height: 2;
+ text-align: justify;
+ a{
+ &:hover{
+ text-decoration: underline;
+ }
+ }
+ .more-link{
+ display: block;
+ margin-top: 16px;
+ padding-left: 30px;
+ position: relative;
+ &:before{
+ content: "\f061";
+ font: 1.3em $font-icon;
+ line-height: 1.6em;
+ position: absolute;
+ left: 0;
+ }
+ }
+ p, blockquote, ul, ol, dl, table, iframe, h1, h2, h3, h4, h5, h6, .video-container{
+ margin-top: 10px;
+ }
+ ul, ol, dl{
+ margin-left: 20px;
+ ul, ol, dl{
+ margin-top: 0;
+ }
+ }
+ strong{
+ font-weight: bold;
+ }
+ em{
+ font-style: italic;
+ }
+ p{
+ margin-top: 10px;
+ }
+ h2{
+ font-weight: 300;
+ border-bottom: 1px solid $color-gray04;
+ position: relative;
+ &:before{
+ content: "";
+ position: absolute;
+ bottom: -2px;
+ border-bottom: 1px solid $color-gray05;
+ width: 100%;
+ }
+ }
+ img, video{
+ max-width: 100%;
+ height: auto;
+ }
+ blockquote{
+ background: $color-gray04;
+ border-left: 5px solid $color-gray03;
+ padding: 15px 20px;
+ margin-top: 10px;
+ & > p:first-of-type{
+ margin-top: 0;
+ }
+ }
+ iframe{
+ border: none;
+ }
+ table{
+ background: $color-gray04;
+ border: 1px solid $color-gray03;
+ border-spacing: 0;
+ margin-top: 10px;
+ th{
+ background: $color-gray03;
+ padding: 0 15px;
+ }
+ td{
+ text-align: center;
+ }
+ tr{
+ &:nth-of-type(2n){
+ background: #d5d5d5;
+ }
+ }
+ }
+ .caption{
+ display: block;
+ font-size: 0.9em;
+ color: $color-gray02;
+ padding-left: 25px;
+ position: relative;
+ &:before{
+ content: "\f040";
+ color: $color-gray03;
+ font: 1.3em $font-icon;
+ line-height: 1.6em;
+ position: absolute;
+ left: 0;
+ }
+ }
+ .video-container{
+ position: relative;
+ padding-bottom: 56.25%;
+ padding-top: 30px;
+ height: 0;
+ overflow: hidden;
+ iframe, object, embed{
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ margin-top: 0;
+ }
+ }
+ }
+}
+.share{
+ padding: 15px 0;
+ @include border-shadow();
+}
\ No newline at end of file
diff --git a/sass/parts/_comment.scss b/sass/parts/_comment.scss
new file mode 100644
index 0000000..05fa598
--- /dev/null
+++ b/sass/parts/_comment.scss
@@ -0,0 +1,10 @@
+#comment{
+ padding: 30px 0;
+ @include border-shadow();
+ h2.title{
+ font-size: 25px;
+ font-weight: 300;
+ line-height: 35px;
+ margin-bottom: 20px;
+ }
+}
\ No newline at end of file
diff --git a/sass/parts/_footer.scss b/sass/parts/_footer.scss
new file mode 100644
index 0000000..6d47846
--- /dev/null
+++ b/sass/parts/_footer.scss
@@ -0,0 +1,6 @@
+footer{
+ padding: 15px 0;
+ border-top: 1px solid $color-gray05;
+ text-align: center;
+ font-size: 0.9em;
+}
\ No newline at end of file
diff --git a/sass/parts/_header.scss b/sass/parts/_header.scss
new file mode 100644
index 0000000..972a0b7
--- /dev/null
+++ b/sass/parts/_header.scss
@@ -0,0 +1,402 @@
+$header-height: 30px;
+
+#header{
+ height: $header-height;
+ padding: 30px 0;
+ border-bottom: 1px solid $color-gray04;
+ line-height: $header-height;
+ @media screen and (max-width: 1040px){
+ height: auto;
+ position: relative;
+ padding-bottom: 10px;
+ }
+ a{
+ color: $color-gray01;
+ @include transition(color 0.3s);
+ &:hover{
+ color: $color-main;
+ }
+ }
+ h1{
+ float: left;
+ font-weight: 300;
+ font-size: 30px;
+ @media screen and (max-width: 1040px){
+ float: none;
+ }
+ }
+}
+#main-nav{
+ float: left;
+ margin-left: 30px;
+ @media screen and (max-width: 1040px){
+ float: none;
+ margin-left: 0;
+ margin-top: 15px;
+ }
+ >ul{
+ @media screen and (max-width: 600px){
+ display: none;
+ }
+ >li{
+ margin-left: 50px;
+ @include inline-block;
+ @media screen and (max-width: 1040px){
+ margin-left: 0;
+ margin-right: 50px;
+ &:last-of-type{
+ margin-right: 0;
+ }
+ }
+ &:hover{
+ >a{
+ color: $color-main;
+ }
+ }
+ >a{
+ padding: 38px 0;
+ margin-top: -38px;
+ &:after{
+ content: "\f078";
+ color: $color-gray03;
+ font: 12px $font-icon;
+ padding-left: 10px;
+ }
+ &:only-child{
+ &:after{
+ content: "";
+ }
+ }
+ @media screen and (max-width: 1040px){
+ padding: 18px 0;
+ }
+ }
+ }
+ ul{
+ position: absolute;
+ top: 60px;
+ left: -15px;
+ z-index: 10;
+ white-space: nowrap;
+ background: $color-gray04;
+ border: 1px solid $color-gray03;
+ list-style: none;
+ display: none;
+ @media screen and (max-width: 1040px){
+ top: 40px;
+ }
+ @include box-shadow(0 4px 8px rgba(0,0,0,0.1));
+ @include border-radius(0 0 5px 5px);
+ ul{
+ @include border-radius(0 5px 5px 5px);
+ }
+ li{
+ @include border-shadow($color-background, $color-gray03);
+ &:hover{
+ background: #d5d5d5;
+ }
+ &:first-of-type{
+ border-top: none;
+ ul{
+ @include border-radius(0 0 5px 5px);
+ }
+ }
+ &:last-of-type{
+ border-bottom: none;
+ }
+ >a{
+ display: block;
+ padding: 5px 15px;
+ &:after{
+ content: "\f054";
+ color: $color-gray02;
+ font: 12px $font-icon;
+ padding-left: 10px;
+ }
+ &:hover{
+ color: $color-gray01;
+ }
+ &:only-child{
+ &:after{
+ content: "";
+ }
+ }
+ }
+ }
+ ul{
+ top: 0;
+ left: 100%;
+ }
+ }
+ li{
+ position: relative;
+ &:hover{
+ >ul{
+ display: block;
+ }
+ }
+ }
+ }
+ select{
+ display: none;
+ margin-bottom: 10px;
+ @media screen and (max-width: 600px){
+ display: block;
+ }
+ }
+}
+#mobile-nav{
+ display: none;
+ height: 37px;
+ position: relative;
+ @media screen and (max-width: 600px){
+ display: block;
+ }
+ a{
+ display: block;
+ }
+ .button{
+ cursor: pointer;
+ }
+ .container{
+ display: none;
+ }
+ .menu{
+ position: relative;
+ width: 100%;
+ .button{
+ background: #f2f2f2;
+ border: 1px solid $color-gray04;
+ color: #999;
+ padding: 0 60px 0 10px;
+ position: relative;
+ @include border-radius(5px);
+ &:hover{
+ color: #999;
+ }
+ &.on{
+ color: #666;
+ @include border-radius(5px 5px 5px 0);
+ &:before{
+ content: "\f077";
+ }
+ }
+ &:before{
+ content: "\f078";
+ color: $color-gray04;
+ font: 16px $font-icon;
+ line-height: 30px;
+ position: absolute;
+ top: 0;
+ right: 40px;
+ }
+ }
+ .container{
+ background: #f2f2f2;
+ border: 1px solid #ddd;
+ border-top: none;
+ position: absolute;
+ top: 31px;
+ z-index: 1;
+ @include border-radius(0 0 5px 5px);
+ ul{
+ list-style: none;
+ ul{
+ margin-left: 20px;
+ }
+ }
+ a{
+ padding: 0 10px;
+ }
+ }
+ }
+ .search{
+ position: absolute;
+ top: 0;
+ right: 0;
+ .button{
+ background: $color-gray04;
+ width: 30px;
+ height: 30px;
+ position: absolute;
+ top: 1px;
+ right: -1px;
+ @include border-radius(0 5px 5px 0);
+ &:before{
+ content: "\f002";
+ color: #f2f2f2;
+ font: 20px $font-icon;
+ line-height: 30px;
+ position: absolute;
+ top: 0;
+ left: 7px;
+ }
+ &.on{
+ background: $color-gray03;
+ &:before{
+ content: "\f00d";
+ }
+ }
+ }
+ .container{
+ position: absolute;
+ right: 51px;
+ z-index: 1;
+ }
+ input[type="text"]{
+ background: #fff;
+ border: 1px solid $color-gray04;
+ border-right: none;
+ color: $color-gray02;
+ font: 13px $font-default;
+ height: 30px;
+ width: 100%;
+ padding: 0 10px;
+ @include border-radius(5px 0 0 5px);
+ }
+ }
+}
+#sub-nav{
+ @media screen and (max-width: 1040px){
+ position: absolute;
+ top: 30px;
+ right: 0;
+ }
+ @media screen and (max-width: 600px){
+ display: none;
+ }
+ .search{
+ float: left;
+ margin-top: 1px;
+ position: relative;
+ @media screen and (max-width: 1040px){
+ float: none;
+ margin-top: 15px;
+ }
+ &:before{
+ content: "\f002";
+ color: $color-gray03;
+ font: 18px $font-icon;
+ line-height: 30px;
+ position: absolute;
+ top: 0;
+ right: 125px;
+ }
+ input[type="text"]{
+ background: #f2f2f2;
+ color: $color-gray02;
+ border: 1px solid $color-gray04;
+ font: 13px $font-default;
+ padding: 6px 15px 6px 35px;
+ width: 100px;
+ @include transition(0.3s);
+ @include border-radius(15px);
+ &:focus, &:active{
+ background: #fff;
+ border-top: 1px solid $color-gray03;
+ color: $color-gray01;
+ outline: none;
+ }
+ }
+ }
+ .social{
+ float: left;
+ margin-right: 15px;
+ @media screen and (max-width: 1040px){
+ float: none;
+ margin-right: 0;
+ a:last-of-type{
+ margin-right: 0;
+ }
+ }
+ a{
+ @include border-radius(50%);
+ @include inline-block;
+ text-indent: -9999px;
+ margin-right: 15px;
+ opacity: 0.5;
+ @include square(28px);
+ @include transition(0.3s);
+ &:hover{
+ opacity: 1;
+ }
+ &.facebook{
+ background: image-url('social/facebook.png') center no-repeat #3B5998;
+ border: 1px solid #3B5998;
+ &:hover{
+ border: 1px solid darken(#3B5998, 10%);
+ }
+ }
+ &.google{
+ background: image-url('social/google.png') center no-repeat #C83D20;
+ border: 1px solid #C83D20;
+ &:hover{
+ border: 1px solid darken(#C83D20, 10%);
+ }
+ }
+ &.twitter{
+ background: image-url('social/twitter.png') center no-repeat #55CFF8;
+ border: 1px solid #55CFF8;
+ &:hover{
+ border: 1px solid darken(#55CFF8, 10%);
+ }
+ }
+ &.github{
+ background: image-url('social/github.png') center no-repeat rgb(175,182,202);
+ border: 1px solid rgb(175,182,202);
+ &:hover{
+ border: 1px solid darken(rgb(175,182,202), 10%);
+ }
+ }
+ &.coderwall{
+ background: image-url('social/coderwall.png') center no-repeat rgb(58,114,159);
+ border: 1px solid rgb(58,114,159);
+ &:hover{
+ border: 1px solid darken(rgb(58,114,159), 10%);
+ }
+ }
+ &.pinboard{
+ background: image-url('social/pinboard.png') center no-repeat rgb(0,102,200);
+ border: 1px solid rgb(58,114,159);
+ &:hover{
+ border: 1px solid darken(rgb(0,102,255), 10%);
+ }
+ }
+ &.linkedin{
+ background: image-url('social/linkedin.png') center no-repeat #005A87;
+ border: 1px solid #005A87;
+ &:hover{
+ border: 1px solid darken(#005A87, 10%);
+ }
+ }
+ &.pinterest{
+ background: image-url('social/pinterest.png') center no-repeat rgb(190,64,55);
+ border: 1px solid rgb(190,64,55);
+ &:hover{
+ border: 1px solid darken(rgb(190,64,55), 10%);
+ }
+ }
+ &.delicious{
+ background: image-url('social/delicious.png') center no-repeat rgb(50,113,203);
+ border: 1px solid rgb(50,113,203);
+ &:hover{
+ border: 1px solid darken(rgb(50,113,203), 10%);
+ }
+ }
+ &.rss{
+ background: image-url('social/rss.png') center no-repeat #ef7522;
+ border: 1px solid #ef7522;
+ &:hover{
+ border: 1px solid darken(#ef7522, 10%);
+ }
+ }
+ &.instagram{
+ background: image-url('social/instagram.png') center no-repeat rgb(64,110,149);
+ border: 1px solid rgb(64,110,149);
+ &:hover{
+ border: 1px solid darken(rgb(64,110,149), 10%);
+ }
+ }
+ }
+ }
+}
diff --git a/sass/parts/_index.scss b/sass/parts/_index.scss
new file mode 100644
index 0000000..833bf02
--- /dev/null
+++ b/sass/parts/_index.scss
@@ -0,0 +1,43 @@
+#pagenavi{
+ padding: 20px 0;
+ height: 20px;
+ line-height: 20px;
+ position: relative;
+ @include border-shadow();
+ a{
+ &:hover{
+ text-decoration: underline;
+ }
+ }
+ .prev, .next{
+ position: absolute;
+ }
+ .prev{
+ padding-left: 30px;
+ left: 0;
+ &:before{
+ content: "\f060";
+ font: 1.3em $font-icon;
+ position: absolute;
+ left: 0;
+ }
+ }
+ .next{
+ padding-right: 30px;
+ right: 0;
+ &:before{
+ content: "\f061";
+ font: 1.3em $font-icon;
+ position: absolute;
+ right: 0;
+ }
+ }
+ .center{
+ text-align: center;
+ width: 100%;
+ display: block;
+ @media screen and (max-width: 400px){
+ display: none;
+ }
+ }
+}
\ No newline at end of file
diff --git a/sass/parts/_post.scss b/sass/parts/_post.scss
new file mode 100644
index 0000000..cfad01f
--- /dev/null
+++ b/sass/parts/_post.scss
@@ -0,0 +1,43 @@
+.post{
+ h2.title, .entry-content{
+ margin-left: 200px;
+ @media screen and (max-width: 800px){
+ margin-left: 0;
+ }
+ }
+ .meta{
+ position: absolute;
+ top: 85px;
+ line-height: 2;
+ font-size: 0.9em;
+ color: $color-gray02;
+ width: 170px;
+ @media screen and (max-width: 800px){
+ margin-top: 15px;
+ position: static;
+ width: auto;
+ }
+ a{
+ @include link-colors($color-gray02, $color-gray01);
+ @include transition(0.3s);
+ }
+ .date, .tags, .comments{
+ padding-left: 30px;
+ position: relative;
+ &:before{
+ color: $color-gray03;
+ font: 1.3em $font-icon;
+ line-height: 1.6em;
+ position: absolute;
+ left: 0;
+ }
+ @media screen and (max-width: 800px){
+ @include inline-block;
+ margin-right: 30px;
+ }
+ }
+ .date:before{content: "\f073";}
+ .tags:before{content: "\f02c";}
+ .comments:before{content: "\f075";}
+ }
+}
\ No newline at end of file
diff --git a/sass/parts/_syntax.scss b/sass/parts/_syntax.scss
new file mode 100644
index 0000000..9f320aa
--- /dev/null
+++ b/sass/parts/_syntax.scss
@@ -0,0 +1,388 @@
+$base03: #002b36 !default; //darkest blue
+$base02: #073642 !default; //dark blue
+$base01: #586e75 !default; //darkest gray
+$base00: #657b83 !default; //dark gray
+$base0: #839496 !default; //medium gray
+$base1: #93a1a1 !default; //medium light gray
+$base2: #eee8d5 !default; //cream
+$base3: #fdf6e3 !default; //white
+$solar-yellow: #b58900 !default;
+$solar-orange: #cb4b16 !default;
+$solar-red: #dc322f !default;
+$solar-magenta: #d33682 !default;
+$solar-violet: #6c71c4 !default;
+$solar-blue: #268bd2 !default;
+$solar-cyan: #2aa198 !default;
+$solar-green: #859900 !default;
+
+$solarized: light !default;
+
+@if $solarized == light {
+
+ $_base03: $base03;
+ $_base02: $base02;
+ $_base01: $base01;
+ $_base00: $base00;
+ $_base0: $base0;
+ $_base1: $base1;
+ $_base2: $base2;
+ $_base3: $base3;
+
+ $base03: $_base3;
+ $base02: $_base2;
+ $base01: $_base1;
+ $base00: $_base0;
+ $base0: $_base00;
+ $base1: $_base01;
+ $base2: $_base02;
+ $base3: $_base03;
+}
+
+$pre-bg: $color-gray04;
+$pre-border: $color-gray03;
+
+article{
+ code, pre{
+ background: $pre-bg;
+ border: 1px solid $pre-border;
+ font-family: $font-mono;
+ }
+ code{
+ font-size: 0.9em;
+ padding: 1px 3px;
+ margin: 0 3px;
+ @include border-radius(5px);
+ }
+ pre{
+ font-size: 1 / 0.9em;
+ line-height: 1.5;
+ margin-top: 10px;
+ padding: 5px 15px;
+ overflow-x: auto;
+ @include border-radius(5px);
+ code{
+ background: none;
+ border: none;
+ padding: 0;
+ margin: 0;
+ @include border-radius(0);
+ }
+ }
+}
+
+figure.code{
+ background: $pre-bg;
+ border: 1px solid $pre-border;
+ margin-top: 10px;
+ padding: 5px 15px;
+ @include border-radius(5px);
+ figcaption{
+ font-size: 0.9em;
+ position: relative;
+ span{
+ margin: -5px -15px 0;
+ padding: 5px 15px;
+ display: block;
+ @include background(linear-gradient(top, $pre-border, $pre-bg));
+ &:empty{
+ display: none;
+ }
+ }
+ a{
+ position: absolute;
+ top: 5px;
+ right: 0;
+ }
+ }
+ code, pre{
+ background: none;
+ border: none;
+ padding: 0;
+ margin: 0;
+ @include border-radius(0);
+ }
+ .highlight{
+ overflow-x: auto;
+ }
+ .line-numbers{
+ border-right: 1px solid $pre-border;
+ font-family: $font-mono;
+ padding-right: 15px;
+ text-align: right;
+ }
+ table{
+ border: none;
+ text-align: left;
+ margin-top: 0;
+ td{
+ text-align: left;
+ }
+ }
+ td.code{
+ width: 100%;
+ padding-left: 15px;
+ overflow-x: auto;
+ }
+}
+.entry-content .gist{
+ background: $pre-bg;
+ color: $color-gray01;
+ padding: 30px 15px 5px;
+ margin-top: 10px;
+ border: 1px solid $pre-border;
+ position: relative;
+ overflow: hidden;
+ @include border-radius(5px);
+ .gist-file{
+ margin: 0;
+ .gist-data{
+ background: none;
+ border: none;
+ pre{
+ font: $font-mono;
+ line-height: inherit;
+ text-align: left;
+ }
+ }
+ .gist-meta{
+ font: 300 0.9em $font-default;
+ line-height: 1.5;
+ margin: 0 -16px -6px;
+ padding: 5px 15px;
+ @include background(linear-gradient(top, $pre-bg, $pre-border));
+ a{
+ color: $color-main;
+ &:first-of-type{
+ position: absolute;
+ top: 5px;
+ right: 15px;
+ z-index: 1;
+ }
+ &:nth-of-type(2){
+ position: absolute;
+ top: 0;
+ left: 0;
+ padding: 5px 15px;
+ width: 100%;
+ @include background(linear-gradient(top, $pre-border, $pre-bg));
+ }
+ }
+ }
+ }
+}
+figure.code, .gist-highlight{
+ .c {
+ color:$base01 !important;
+ font-style: italic !important;
+ }
+ /* Comment */
+ .cm {
+ color:$base01 !important;
+ font-style: italic !important;
+ }
+ /* Comment.Multiline */
+ .cp {
+ color:$base01 !important;
+ font-style: italic !important;
+ }
+ /* Comment.Preproc */
+ .c1 {
+ color:$base01 !important;
+ font-style: italic !important;
+ }
+ /* Comment.Single */
+ .cs {
+ color:$base01 !important;
+ font-weight:bold !important;
+ font-style: italic !important;
+ }
+ /* Comment.Special */
+ .err {
+ color:$solar-red !important;
+ background: none !important;
+ }
+ /* Error */
+ .k {
+ color: $solar-orange !important;
+ }
+ /* Keyword */
+ .o {
+ color:$base1 !important;
+ font-weight: bold !important;
+ }
+ /* Operator */
+ .p {
+ color: $base1 !important;
+ }
+ /* Operator */
+ .ow {
+ color:$solar-cyan !important;
+ font-weight: bold !important;
+ }
+ /* Operator.Word */
+ .gd {
+ color:$base1 !important;
+ background-color:mix($solar-red,$base03,25%) !important;
+ display: inline-block;
+ }
+ /* Generic.Deleted */
+ .gd .x {
+ color:$base1 !important;
+ background-color:mix($solar-red,$base03,35%) !important;
+ display: inline-block;
+ }
+ /* Generic.Deleted.Specific */
+ .ge {
+ color:$base1 !important;
+ font-style: italic !important;
+ }
+ /* Generic.Emph */
+ .gh {
+ color: $base01 !important;
+ }
+ /* Generic.Heading */
+ .gi {
+ color:$base1 !important;
+ background-color:mix($solar-green,$base03,20%) !important;
+ display: inline-block;
+ }
+ /* Generic.Inserted */
+ .gi .x {
+ color:$base1 !important;
+ background-color:mix($solar-green,$base03,40%) !important;
+ display: inline-block;
+ }
+ /* Generic.Inserted.Specific */
+ .gs {
+ color:$base1 !important;
+ font-weight: bold !important;
+ }
+ /* Generic.Strong */
+ .gu {
+ color: $solar-violet !important;
+ }
+ /* Generic.Subheading */
+ .kc {
+ color:$solar-green !important;
+ font-weight: bold !important;
+ }
+ /* Keyword.Constant */
+ .kd {
+ color: $solar-blue !important;
+ }
+ /* Keyword.Declaration */
+ .kp {
+ color:$solar-orange !important;
+ font-weight: bold !important;
+ }
+ /* Keyword.Pseudo */
+ .kr {
+ color:$solar-magenta !important;
+ font-weight: bold !important;
+ }
+ /* Keyword.Reserved */
+ .kt {
+ color: $solar-cyan !important;
+ }
+ /* Keyword.Type */
+ .n {
+ color:$solar-blue !important;
+ }
+ .na {
+ color: $solar-blue !important;
+ }
+ /* Name.Attribute */
+ .nb {
+ color: $solar-green !important;
+ }
+ /* Name.Builtin */
+ .nc {
+ color: $solar-magenta !important;
+ }
+ /* Name.Class */
+ .no {
+ color: $solar-yellow !important;
+ }
+ /* Name.Constant */
+ .nl {
+ color:$solar-green !important;
+ }
+ .ne {
+ color:$solar-blue !important;
+ font-weight: bold !important;
+ }
+ /* Name.Exception */
+ .nf {
+ color:$solar-blue !important;
+ font-weight: bold !important;
+ }
+ /* Name.Function */
+ .nn {
+ color: $solar-yellow !important;
+ }
+ /* Name.Namespace */
+ .nt {
+ color:$solar-blue !important;
+ font-weight: bold !important;
+ }
+ /* Name.Tag */
+ .nx {
+ color:$solar-yellow !Important;
+ }
+ .vg {
+ color: $solar-blue !important;
+ }
+ /* Name.Variable.Global */
+ .vi {
+ color: $solar-blue !important;
+ }
+ /* Name.Variable.Instance */
+ .nv {
+ color: $solar-blue !important;
+ }
+ /* Name.Variable */
+ .mf {
+ color: $solar-cyan !important;
+ }
+ /* Literal.Number.Float */
+ .m {
+ color: $solar-cyan !important;
+ }
+ /* Literal.Number */
+ .mh {
+ color: $solar-cyan !important;
+ }
+ /* Literal.Number.Hex */
+ .mi {
+ color: $solar-cyan !important;
+ }
+ /* Literal.Number.Integer */
+ .s {
+ color: $solar-cyan !important;
+ }
+ /* Literal.String */
+ .sd {
+ color: $solar-cyan !important;
+ }
+ /* Literal.String.Doc */
+ .s2 {
+ color: $solar-cyan !important;
+ }
+ /* Literal.String.Double */
+ .se {
+ color: $solar-red !important;
+ }
+ /* Literal.String.Escape */
+ .si {
+ color: $solar-blue !important;
+ }
+ /* Literal.String.Interpol */
+ .sr {
+ color: $solar-cyan !important;
+ }
+ /* Literal.String.Regex */
+ .s1 {
+ color: $solar-cyan !important;
+ }
+ /* Literal.String.Single */
+}
diff --git a/sass/parts/_twitter.scss b/sass/parts/_twitter.scss
new file mode 100644
index 0000000..6a8e6a1
--- /dev/null
+++ b/sass/parts/_twitter.scss
@@ -0,0 +1,49 @@
+#banner{
+ color: $color-gray02;
+ padding: 30px 0;
+ line-height: 30px;
+ text-align: center;
+ position: relative;
+ display: none;
+ @include border-shadow();
+ &:hover{
+ a{
+ color: $color-main;
+ }
+ }
+ a{
+ color: $color-gray02;
+ @include transition(0.3s);
+ &:hover{
+ text-decoration: underline;
+ }
+ }
+ small{
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ }
+ .loading{
+ background: image-url('loading_pacman.gif') center no-repeat;
+ text-indent: -9999px;
+ }
+ .container{
+ height: 30px;
+ overflow: hidden;
+ position: relative;
+ display: none;
+ .feed{
+ list-style: none;
+ position: absolute;
+ top: 0;
+ width: 100%;
+ li{
+ position: relative;
+ small{
+ position: absolute;
+ right: 0;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/sass/plugins/_fancybox.scss b/sass/plugins/_fancybox.scss
new file mode 100644
index 0000000..20a9437
--- /dev/null
+++ b/sass/plugins/_fancybox.scss
@@ -0,0 +1,228 @@
+/*! fancyBox v2.0.6 fancyapps.com | fancyapps.com/fancybox/#license */
+.fancybox-tmp iframe, .fancybox-tmp object {
+ vertical-align: top;
+ padding: 0;
+ margin: 0;
+}
+
+.fancybox-wrap {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 8020;
+}
+
+.fancybox-skin {
+ position: relative;
+ padding: 0;
+ margin: 0;
+ background: #f9f9f9;
+ color: #444;
+ text-shadow: none;
+ @include border-radius(4px);
+}
+
+.fancybox-opened {
+ z-index: 8030;
+}
+
+.fancybox-opened .fancybox-skin {
+ @include box-shadow(0 10px 25px rgba(0, 0, 0, 0.5));
+}
+
+.fancybox-outer, .fancybox-inner {
+ padding: 0;
+ margin: 0;
+ position: relative;
+ outline: none;
+}
+
+.fancybox-inner {
+ overflow: hidden;
+}
+
+.fancybox-type-iframe .fancybox-inner {
+ -webkit-overflow-scrolling: touch;
+}
+
+.fancybox-error {
+ color: #444;
+ font: 14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;
+ margin: 0;
+ padding: 10px;
+}
+
+.fancybox-image, .fancybox-iframe {
+ display: block;
+ width: 100%;
+ height: 100%;
+ border: 0;
+ padding: 0;
+ margin: 0;
+ vertical-align: top;
+}
+
+.fancybox-image {
+ max-width: 100%;
+ max-height: 100%;
+}
+
+#fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span {
+ background-image: image-url('fancybox/fancybox_sprite.png');
+}
+
+#fancybox-loading {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ margin-top: -22px;
+ margin-left: -22px;
+ background-position: 0 -108px;
+ opacity: 0.8;
+ cursor: pointer;
+ z-index: 8020;
+}
+
+#fancybox-loading div {
+ width: 44px;
+ height: 44px;
+ background: image-url('fancybox/fancybox_loading.gif') center center no-repeat;
+}
+
+.fancybox-close {
+ position: absolute;
+ top: -18px;
+ right: -18px;
+ width: 36px;
+ height: 36px;
+ cursor: pointer;
+ z-index: 8040;
+}
+
+.fancybox-nav {
+ position: absolute;
+ top: 0;
+ width: 40%;
+ height: 100%;
+ cursor: pointer;
+ background: transparent image-url('fancybox/blank.gif'); /* helps IE */
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
+ z-index: 8040;
+}
+
+.fancybox-prev {
+ left: 0;
+}
+
+.fancybox-next {
+ right: 0;
+}
+
+.fancybox-nav span {
+ position: absolute;
+ top: 50%;
+ width: 36px;
+ height: 34px;
+ margin-top: -18px;
+ cursor: pointer;
+ z-index: 8040;
+ visibility: hidden;
+}
+
+.fancybox-prev span {
+ left: 20px;
+ background-position: 0 -36px;
+}
+
+.fancybox-next span {
+ right: 20px;
+ background-position: 0 -72px;
+}
+
+.fancybox-nav:hover span {
+ visibility: visible;
+}
+
+.fancybox-tmp {
+ position: absolute;
+ top: -9999px;
+ left: -9999px;
+ padding: 0;
+ overflow: visible;
+ visibility: hidden;
+}
+
+/* Overlay helper */
+
+#fancybox-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ overflow: hidden;
+ display: none;
+ z-index: 8010;
+ background: #000;
+}
+
+#fancybox-overlay.overlay-fixed {
+ position: fixed;
+ bottom: 0;
+ right: 0;
+}
+
+/* Title helper */
+
+.fancybox-title {
+ visibility: hidden;
+ font: normal 13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;
+ position: relative;
+ text-shadow: none;
+ z-index: 8050;
+}
+
+.fancybox-opened .fancybox-title {
+ visibility: visible;
+}
+
+.fancybox-title-float-wrap {
+ position: absolute;
+ bottom: 0;
+ right: 50%;
+ margin-bottom: -35px;
+ z-index: 8030;
+ text-align: center;
+}
+
+.fancybox-title-float-wrap .child {
+ display: inline-block;
+ margin-right: -100%;
+ padding: 2px 20px;
+ background: transparent; /* Fallback for web browsers that doesn't support RGBa */
+ background: rgba(0, 0, 0, 0.8);
+ text-shadow: 0 1px 2px #222;
+ color: #FFF;
+ font-weight: bold;
+ line-height: 24px;
+ white-space: nowrap;
+ @include border-radius(15px);
+}
+
+.fancybox-title-outside-wrap {
+ position: relative;
+ margin-top: 10px;
+ color: #fff;
+}
+
+.fancybox-title-inside-wrap {
+ margin-top: 10px;
+}
+
+.fancybox-title-over-wrap {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ color: #fff;
+ padding: 10px;
+ background: #000;
+ background: rgba(0, 0, 0, .8);
+}
\ No newline at end of file
diff --git a/sass/plugins/_plugins.scss b/sass/plugins/_plugins.scss
new file mode 100644
index 0000000..3b4ba0b
--- /dev/null
+++ b/sass/plugins/_plugins.scss
@@ -0,0 +1,6 @@
+/*
+ Add plugin stylesheets to this directory and they will be automatically
+ Imported. Load order is alphabetical and styles can be overriden in
+ custom/_style.scss which is loaded after all plugin stylesheets.
+*/
+
diff --git a/sass/screen.scss b/sass/screen.scss
new file mode 100644
index 0000000..155e81e
--- /dev/null
+++ b/sass/screen.scss
@@ -0,0 +1,11 @@
+@import "compass";
+@include global-reset;
+@include reset-html5;
+
+@import "custom/colors";
+@import "custom/fonts";
+@import "custom/layout";
+@import "base";
+@import "partials";
+@import "plugins/**/*";
+@import "custom/styles";
diff --git a/source/_includes/after_footer.html b/source/_includes/after_footer.html
new file mode 100644
index 0000000..42b0bda
--- /dev/null
+++ b/source/_includes/after_footer.html
@@ -0,0 +1,6 @@
+{% include disqus.html %}
+{% include juvia.html %}
+{% include facebook_like.html %}
+{% include google_plus_one.html %}
+{% include twitter_sharing.html %}
+{% include custom/after_footer.html %}
diff --git a/source/_includes/archive_post.html b/source/_includes/archive_post.html
new file mode 100644
index 0000000..b4a5d24
--- /dev/null
+++ b/source/_includes/archive_post.html
@@ -0,0 +1,8 @@
+{% capture category %}{{ post.categories | size }}{% endcapture %}
+
+{{ post.date | date: "%b %d %Y "}}
+{% if category != '0' %}
+
+ posted in {{ post.categories | category_links }}
+
+{% endif %}
diff --git a/source/_includes/article.html b/source/_includes/article.html
new file mode 100644
index 0000000..47c7d06
--- /dev/null
+++ b/source/_includes/article.html
@@ -0,0 +1,33 @@
+{% unless page.no_header %}
+
+{% endunless %}
+{% if index %}
+ {{ content | excerpt }}
+ {% capture excerpted %}{{ content | has_excerpt }}{% endcapture %}
+ {% if excerpted == 'true' %}
+
+ {% endif %}
+{% else %}
+{{ content }}
+{% endif %}
diff --git a/source/_includes/asides/delicious.html b/source/_includes/asides/delicious.html
new file mode 100644
index 0000000..e69de29
diff --git a/source/_includes/asides/github.html b/source/_includes/asides/github.html
new file mode 100644
index 0000000..e69de29
diff --git a/source/_includes/asides/googleplus.html b/source/_includes/asides/googleplus.html
new file mode 100644
index 0000000..e69de29
diff --git a/source/_includes/asides/pinboard.html b/source/_includes/asides/pinboard.html
new file mode 100644
index 0000000..e69de29
diff --git a/source/_includes/asides/recent_posts.html b/source/_includes/asides/recent_posts.html
new file mode 100644
index 0000000..e69de29
diff --git a/source/_includes/banner.html b/source/_includes/banner.html
new file mode 100644
index 0000000..af38f03
--- /dev/null
+++ b/source/_includes/banner.html
@@ -0,0 +1,15 @@
+{% if site.twitter_user and site.twitter_tweet_count > 0 %}
+
+
+
+{% endif %}
\ No newline at end of file
diff --git a/source/_includes/custom/after_footer.html b/source/_includes/custom/after_footer.html
new file mode 100644
index 0000000..bce25dd
--- /dev/null
+++ b/source/_includes/custom/after_footer.html
@@ -0,0 +1,3 @@
+{% comment %}
+ Add content to be output at the bottom of each page. (You might use this for analytics scripts, for example)
+{% endcomment %}
diff --git a/source/_includes/custom/asides/about.html b/source/_includes/custom/asides/about.html
new file mode 100644
index 0000000..59d309e
--- /dev/null
+++ b/source/_includes/custom/asides/about.html
@@ -0,0 +1,4 @@
+
+ About Me
+ A little something about me.
+
diff --git a/source/_includes/custom/category_feed.xml b/source/_includes/custom/category_feed.xml
new file mode 100644
index 0000000..8c93ed3
--- /dev/null
+++ b/source/_includes/custom/category_feed.xml
@@ -0,0 +1,27 @@
+---
+layout: null
+---
+
+
+
+
+
+
+ {{ site.time | date_to_xmlschema }}
+ {{ site.url }}/
+
+
+ {% if site.email %} {% endif %}
+
+ Octopress
+
+ {% for post in site.categories[page.category] limit: 5 %}
+
+
+
+ {{ post.date | date_to_xmlschema }}
+ {{ site.url }}{{ post.id }}
+
+
+ {% endfor %}
+
diff --git a/source/_includes/custom/footer.html b/source/_includes/custom/footer.html
new file mode 100644
index 0000000..6b2763d
--- /dev/null
+++ b/source/_includes/custom/footer.html
@@ -0,0 +1,5 @@
+
+ Copyright © {{ site.time | date: "%Y" }} - {{ site.author }}
+
+
diff --git a/source/_includes/custom/head.html b/source/_includes/custom/head.html
new file mode 100644
index 0000000..5587944
--- /dev/null
+++ b/source/_includes/custom/head.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/_includes/custom/header.html b/source/_includes/custom/header.html
new file mode 100644
index 0000000..35f9c05
--- /dev/null
+++ b/source/_includes/custom/header.html
@@ -0,0 +1,6 @@
+
+
+ {% if site.subtitle %}
+ {{ site.subtitle }}
+ {% endif %}
+
diff --git a/source/_includes/custom/navigation.html b/source/_includes/custom/navigation.html
new file mode 100644
index 0000000..23a8cde
--- /dev/null
+++ b/source/_includes/custom/navigation.html
@@ -0,0 +1,6 @@
+
diff --git a/source/_includes/disqus.html b/source/_includes/disqus.html
new file mode 100644
index 0000000..883dd29
--- /dev/null
+++ b/source/_includes/disqus.html
@@ -0,0 +1,21 @@
+{% comment %} Load script if disquss comments are enabled and `page.comments` is either empty (index) or set to true {% endcomment %}
+{% if site.disqus_short_name and page.comments != false %}
+
+{% endif %}
diff --git a/source/_includes/facebook_like.html b/source/_includes/facebook_like.html
new file mode 100644
index 0000000..d263e6d
--- /dev/null
+++ b/source/_includes/facebook_like.html
@@ -0,0 +1,10 @@
+{% if site.facebook_like %}
+
+
+{% endif %}
diff --git a/source/_includes/fancybox.html b/source/_includes/fancybox.html
new file mode 100644
index 0000000..fd5bcfd
--- /dev/null
+++ b/source/_includes/fancybox.html
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/source/_includes/footer.html b/source/_includes/footer.html
new file mode 100644
index 0000000..3a8c768
--- /dev/null
+++ b/source/_includes/footer.html
@@ -0,0 +1 @@
+{% include custom/footer.html %}
diff --git a/source/_includes/google_analytics.html b/source/_includes/google_analytics.html
new file mode 100644
index 0000000..b86ac1f
--- /dev/null
+++ b/source/_includes/google_analytics.html
@@ -0,0 +1,13 @@
+{% if site.google_analytics_tracking_id %}
+
+{% endif %}
diff --git a/source/_includes/google_plus_one.html b/source/_includes/google_plus_one.html
new file mode 100644
index 0000000..b69ddae
--- /dev/null
+++ b/source/_includes/google_plus_one.html
@@ -0,0 +1,9 @@
+{% if site.google_plus_one %}
+
+{% endif %}
diff --git a/source/_includes/head.html b/source/_includes/head.html
new file mode 100644
index 0000000..7d748a5
--- /dev/null
+++ b/source/_includes/head.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+ {% if page.title %}{% if site.titlecase %}{{ page.title | titlecase }}{% else %}{{ page.title }}{% endif %} - {% endif %}{{ site.title }}
+
+
+ {% capture description %}{% if page.description %}{{ page.description }}{% else %}{{ content | raw_content }}{% endif %}{% endcapture %}
+
+ {% if page.keywords %} {% endif %}
+
+
+
+
+
+
+ {% capture canonical %}{{ site.url }}{% if site.permalink contains '.html' %}{{ page.url }}{% else %}{{ page.url | remove:'index.html' | strip_slash }}{% endif %}{% endcapture %}
+
+
+
+
+
+
+
+
+
+
+ {% include custom/head.html %}
+ {% include google_analytics.html %}
+
diff --git a/source/_includes/header.html b/source/_includes/header.html
new file mode 100644
index 0000000..524de65
--- /dev/null
+++ b/source/_includes/header.html
@@ -0,0 +1 @@
+{% include custom/header.html %}
diff --git a/source/_includes/juvia.html b/source/_includes/juvia.html
new file mode 100644
index 0000000..0da2b27
--- /dev/null
+++ b/source/_includes/juvia.html
@@ -0,0 +1,52 @@
+{% comment %} Load script if Juvia comments are enabled and `page.comments` is either empty (index) or set to true {% endcomment %}
+{% if site.juvia_site_key and site.juvia_host and page.comments != false %}
+
+
+{% endif %}
diff --git a/source/_includes/navigation.html b/source/_includes/navigation.html
new file mode 100644
index 0000000..d182e34
--- /dev/null
+++ b/source/_includes/navigation.html
@@ -0,0 +1,44 @@
+
+ RSS
+ {% if site.subscribe_email %}
+ Email
+ {% endif %}
+
+ {% if site.googleplus_user %}
+ {% unless site.googleplus_hidden %}
+
+ {% endunless %}
+ {% endif %}
+ {% if site.pinboard_user %}
+
+ {% endif %}
+ {% if site.delicious_user %}
+
+ {% endif %}
+ {% if site.github_user %}
+ {% if site.github_show_profile_link %}
+
+ {% endif %}
+ {% endif %}
+ {% if site.bitbucket_user %}
+
+ {% endif %}
+ {% if site.simple_search %}
+
+ {% endif %}
+{% include custom/navigation.html %}
diff --git a/source/_includes/post/author.html b/source/_includes/post/author.html
new file mode 100644
index 0000000..da92624
--- /dev/null
+++ b/source/_includes/post/author.html
@@ -0,0 +1,23 @@
+{% if post.author %}
+ {% assign author = post.author %}
+{% elsif page.author %}
+ {% assign author = page.author %}
+{% else %}
+ {% assign author = site.author %}
+{% endif %}
+{% if post.googleplus_user %}
+ {% assign googleplus_user = post.googleplus_user | downcase %}
+{% elsif page.googleplus_user %}
+ {% assign googleplus_user = page.googleplus_user | downcase %}
+{% elsif site.googleplus_user %}
+ {% assign googleplus_user = site.googleplus_user | downcase %}
+{% endif %}
+{% if author %}
+ Authored by
+ {% if googleplus_user and googleplus_user != "ignore" %}
+ {{ author }}
+ {% else %}
+ {{ author }}
+ {% endif %}
+
+{% endif %}
diff --git a/source/_includes/post/categories.html b/source/_includes/post/categories.html
new file mode 100644
index 0000000..4a98b29
--- /dev/null
+++ b/source/_includes/post/categories.html
@@ -0,0 +1,10 @@
+{% capture category %}{% if post %}{{ post.categories | category_links | size }}{% else %}{{ page.categories | category_links | size }}{% endif %}{% endcapture %}
+{% unless category == '0' %}
+
+ {% if post %}
+ {{ post.categories | category_links }}
+ {% else %}
+ {{ page.categories | category_links }}
+ {% endif %}
+
+{% endunless %}
diff --git a/source/_includes/post/date.html b/source/_includes/post/date.html
new file mode 100644
index 0000000..a86953c
--- /dev/null
+++ b/source/_includes/post/date.html
@@ -0,0 +1,5 @@
+{% if page.date %}{% capture time %}{{ page.date_time_html }}{% endcapture %}{% endif %}
+{% if post.date %}{% capture time %}{{ post.date_time_html }}{% endcapture %}{% endif %}
+
+{% if page.updated %}{% capture updated %}{{ page.date_time_updated_html }}{% endcapture %}{% endif %}
+{% if post.updated %}{% capture updated %}{{ post.date_time_updated_html }}{% endcapture %}{% endif %}
diff --git a/source/_includes/post/disqus_thread.html b/source/_includes/post/disqus_thread.html
new file mode 100644
index 0000000..b1acd8c
--- /dev/null
+++ b/source/_includes/post/disqus_thread.html
@@ -0,0 +1 @@
+Please enable JavaScript to view the comments powered by Disqus.
diff --git a/source/_includes/post/juvia_thread.html b/source/_includes/post/juvia_thread.html
new file mode 100644
index 0000000..dd17cc6
--- /dev/null
+++ b/source/_includes/post/juvia_thread.html
@@ -0,0 +1 @@
+Please enable JavaScript to view the comments powered by Juvia.
diff --git a/source/_includes/post/sharing.html b/source/_includes/post/sharing.html
new file mode 100644
index 0000000..92cd710
--- /dev/null
+++ b/source/_includes/post/sharing.html
@@ -0,0 +1,11 @@
+
+ {% if site.twitter_tweet_button %}
+
+ {% endif %}
+ {% if site.google_plus_one %}
+
+ {% endif %}
+ {% if site.facebook_like %}
+
+ {% endif %}
+
diff --git a/source/_includes/twitter_sharing.html b/source/_includes/twitter_sharing.html
new file mode 100644
index 0000000..7cd5fbc
--- /dev/null
+++ b/source/_includes/twitter_sharing.html
@@ -0,0 +1,11 @@
+{% if site.twitter_follow_button or site.twitter_tweet_button %}
+
+{% endif %}
diff --git a/source/_layouts/category_index.html b/source/_layouts/category_index.html
new file mode 100644
index 0000000..85a6307
--- /dev/null
+++ b/source/_layouts/category_index.html
@@ -0,0 +1,17 @@
+---
+layout: page
+footer: false
+---
+
+
+{% for post in site.categories[page.category] %}
+{% capture this_year %}{{ post.date | date: "%Y" }}{% endcapture %}
+{% unless year == this_year %}
+ {% assign year = this_year %}
+
{{ year }}
+{% endunless %}
+
+ {% include archive_post.html %}
+
+{% endfor %}
+
diff --git a/source/_layouts/default.html b/source/_layouts/default.html
new file mode 100644
index 0000000..c241ffd
--- /dev/null
+++ b/source/_layouts/default.html
@@ -0,0 +1,14 @@
+{% capture root_url %}{{ site.root | strip_slash }}{% endcapture %}
+{% include head.html %}
+
+ {% include header.html %}
+ {% include navigation.html %}
+
+
+ {{ content | expand_urls: root_url }}
+
+
+ {% include footer.html %}
+ {% include after_footer.html %}
+
+
diff --git a/source/_layouts/page.html b/source/_layouts/page.html
new file mode 100644
index 0000000..8a3efb5
--- /dev/null
+++ b/source/_layouts/page.html
@@ -0,0 +1,48 @@
+---
+layout: default
+---
+
+
+
+ {% if page.title %}
+
+ {% endif %}
+ {{ content }}
+ {% unless page.footer == false %}
+
+ {% endunless %}
+
+{% if site.disqus_short_name and page.comments == true %}
+
+{% endif %}
+{% if site.juvia_site_key and page.comments == true %}
+
+ Comments
+ {% include post/juvia_thread.html %}
+
+{% endif %}
+
+{% unless page.sidebar == false %}
+
+{% endunless %}
diff --git a/source/_layouts/post.html b/source/_layouts/post.html
new file mode 100644
index 0000000..576c301
--- /dev/null
+++ b/source/_layouts/post.html
@@ -0,0 +1,49 @@
+---
+layout: default
+single: true
+---
+
+
+
+ {% include article.html %}
+
+
+ {% include post/author.html %}
+ {% include post/date.html %}{% if updated %}{{ updated }}{% else %}{{ time }}{% endif %}
+ {% include post/categories.html %}
+
+ {% unless page.sharing == false %}
+ {% include post/sharing.html %}
+ {% endunless %}
+
+ {% if page.previous.url %}
+ « {{page.previous.title}}
+ {% endif %}
+ {% if page.next.url %}
+ {{page.next.title}} »
+ {% endif %}
+
+
+
+{% if site.disqus_short_name and page.comments == true %}
+
+{% endif %}
+{% if site.juvia_site_key and page.comments == true %}
+
+ Comments
+ {% include post/juvia_thread.html %}
+
+{% endif %}
+
+{% unless page.sidebar == false %}
+
+{% endunless %}
diff --git a/source/_posts/2014-10-15-functional-playground-solving-rush-hour-game-in-haskell.markdown b/source/_posts/2014-10-15-functional-playground-solving-rush-hour-game-in-haskell.markdown
new file mode 100644
index 0000000..c2b6ef8
--- /dev/null
+++ b/source/_posts/2014-10-15-functional-playground-solving-rush-hour-game-in-haskell.markdown
@@ -0,0 +1,309 @@
+---
+layout: post
+title: "Functional playground: solving the Rush Hour game in Haskell"
+date: 2014-10-16 17:01:36 -0700
+comments: false
+sharing: true
+categories: haskell functional tutorials puzzles
+---
+{% img right /images/rushhour.png 250 250 %}
+In this blog post, I will demonstrate the functional way of solving problems using the popular [Rush Hour](http://www.thinkfun.com/rushhour) board game as an example. I will employ simple yet powerful language features that Haskell provides to produce expressive and modular programs, which are:
+
+- Types and abstractions
+- Pattern matching and recursions
+- Higher-order functions and combinators
+- Function composition and currying
+
+
+## Rush Hour: the game
+
+The Rush Hour game consists of a traffic grid in which some cars and trucks are laid out. The goal is to find a path for the Red Car to exit by moving the other blocking vehicles out of its way. Created by Nob Yoshigahara in the 70's, this game has kept people entertained and puzzled with its several levels of difficulty.
+
+
+
+In Rush Hour, each vehicle can move only in either horizontally or vertically. At the start, the Red Car is placed horizontally on the 3rd line from the top. The other cars and trucks are blocking Red Car's straight path to the Exit.
+
+Now, let's see how functional programming can be of help to solve the Rush Hour puzzle.
+
+
+
+## Game abstraction
+Thinking about the game, we can capture the locations and orientations of all vehicles at any instant as a state. Our objective is to find a state in which the Red Car is placed just in front of the Exit. Let's call such state a _goal state_. To that, we transition from the initial state to a goal state through a sequence of moves. In each move, we move a car in a specific direction. The move is valid if the new location of the car does not land off the grid and does not overlap with another car. Ok, that's enough English we can translate to Haskell. So let's create some data types and type synonyms to abstract the cars, the states and the moves.
+
+{% codeblock lang:haskell %}
+data Orientation = H | V deriving (Show, Eq)
+data Direction = L | R | U | D deriving (Show)
+data Car = Car {
+ x :: Int, -- x-coordinate: from top-left corner of grid
+ y :: Int, -- y-coordinate
+ o :: Orientation, -- Vertical or Horizontal
+ sz :: Int -- Car vs Truck
+ } deriving (Show, Eq)
+type Line = String
+type CarLetter = Char -- Representation of vehicle
+type State = Map CarLetter Car -- State of grid: Map with CarLetter/Car pairs
+type Move = (CarLetter, Direction)
+{% endcodeblock %}
+
+Now, let's create some functions for moving cars. The first function `moveCar` takes a car and a direction to move and returns another car with the same orientation and size but at a new location.
+
+{% codeblock lang:haskell %}
+moveCar :: Car -> Direction -> Car
+moveCar (Car xpos ypos H size) L = Car (xpos-1) ypos H size
+moveCar (Car xpos ypos H size) R = Car (xpos+1) ypos H size
+moveCar (Car xpos ypos V size) U = Car xpos (ypos-1) V size
+moveCar (Car xpos ypos V size) D = Car xpos (ypos+1) V size
+moveCar car _ = car
+{% endcodeblock %}
+
+The next function `move` takes a State and a Move then returns a new State.
+
+{% codeblock lang:haskell %}
+move :: State -> Move -> State
+move state (key, dir) = Map.insert key newCar state where
+ newCar :: Car
+ newCar = moveCar (state ! key) dir
+{% endcodeblock %}
+
+In `move`, we assume that the Move is a valid one. To make sure we respect the rules of the game, we need two functions that tell us whether two cars are overlapping in the grid and whether a Car is off the grid.
+
+{% codeblock lang:haskell %}
+isOverlapping :: Car -> Car -> Bool
+isOverlapping (Car x y H sz) (Car xnew ynew H sznew)
+ | y /= ynew = False
+ | y < ynew && y+sz-1 < ynew = False
+ | ynew < y && ynew+sznew-1 < y = False
+ | otherwise = True
+isOverlapping (Car x y V sz) (Car xnew ynew V sznew)
+ | x /= xnew = False
+ | x < xnew && x+sz-1 < xnew = False
+ | xnew < x && xnew+sznew-1 < x = False
+ | otherwise = True
+isOverlapping (Car x y H sz) (Car xnew ynew V sznew)
+ | xnew < x || xnew > x+sz-1 = False
+ | ynew > y = False
+ | ynew < y && ynew+sznew-1 < y = False
+ | otherwise = True
+isOverlapping (Car x y V sz) (Car xnew ynew H sznew)
+ | x < xnew || x > xnew+sznew-1 = False
+ | y > ynew = False
+ | y < ynew && y+sz-1 < ynew = False
+ | otherwise = True
+
+isOffgrid :: Car -> Bool
+isOffgrid (Car x y H size)
+ | x+size-1 > gridSize = True
+ | x < 1 = True
+ | y < 1 || y > gridSize = True
+isOffgrid (Car x y V size)
+ | y+size-1 > gridSize = True
+ | y < 1 = True
+ | x < 1 || x > gridSize = True
+isOffgrid _ = False
+{% endcodeblock %}
+
+## State-Space search
+There are two ways to measure our ability to play the game. The first one is the number of moves that you make to exit the Red Car. The fewest moves you make, the more impressed your friends will be. The second one is the amount of time it takes to actually find the path to the exit. No matter how short the path you find, your friends will not be very impressed if you ask them to wait for hours. Since, we are going to cheat twice by using a computer and also Haskell, we will not be as much concerned about the amount of time to find a path. Instead, we will focus on finding the shortest path. So how are we going to tell Haskell to do that for us?
+
+The mechanism to solve Rush Hour and other similar puzzles is [State Space search](http://en.wikipedia.org/wiki/State_space_search). At any instant of the game, we can actually imagine ourselves lost in an "invisible" directed graph where each node is a State and each edge is a Move. Two States `fromState` and `toState` are linked by a Move `move` whenever we can legally move a car in `fromState` and obtain the new state `toState`. Since we are interested to find the shortest path to exit, we'll use a depth-first approach.
+
+Beginning with the end in mind, let's declare the function `statesearch`. It takes the following three inputs:
+
+1. An initial State
+2. A list of States that have already been explored
+3. A list of Paths to be explored
+
+Then, `statesearch` returns a Path to the exit as output. A path is simply a tuple composed of the current state and a list of moves that led to that state from the initial one.
+
+{% codeblock lang:haskell %}
+type Path = (State, [Move])
+{% endcodeblock %}
+
+For clarity, let's give some meaningul names to the types of the last two inputs of `statesearch` as follows:
+
+{% codeblock lang:haskell %}
+type ExploredStates = [State]
+type UnexploredPaths = [Path]
+{% endcodeblock %}
+
+In our state-space search, we also need a function `solved` that checks if for a given state we have reached our goal. We assume that the key for the Red Car is the character `'X'`. So here, we just check if it is already in front of the exit.
+
+{% codeblock lang:haskell %}
+gridSize = 6
+solved :: State -> Bool
+solved state = (x xcar + sz xcar - 1 == gridSize) where
+ xcar = state ! 'X'
+{% endcodeblock %}
+
+Another helper function that will be useful in the state-space is `generateNewMoves`, which produces a list of possible move for each car in a given state and then concatenates all possible moves.
+
+{% codeblock lang:haskell %}
+generateNewMoves :: State -> [Move]
+generateNewMoves state = concat $ map generateNew (Map.keys state) where
+ generateNew :: CarLetter -> [Move]
+ generateNew key
+ | o (state ! key) == H = [(key, L), (key,R)]
+ | otherwise = [(key, U), (key,D)]
+{% endcodeblock %}
+
+The generated moves do not have to be valid yet. We just make sure to generate moves that correspond to the orientation of each moved car. In other words, a horizontally oriented car cannot be moved up or down and vice versa. However, we will still need later to filter the valid moves.
+
+### Our depth-first state-space search
+Now, let's present the state-space search with depth-first traversal strategy:
+
+{% codeblock lang:haskell %}
+statesearch :: ExploredStates -> UnexploredPaths -> Maybe Path
+statesearch _ [] = Nothing
+statesearch explored (p@(state, mvs) : paths)
+ | solved state = Just p
+ | state `elem` explored = statesearch explored paths
+ | otherwise = statesearch
+ (state:explored)
+ (paths ++ nextPaths) where
+ nextPaths :: [Path]
+ nextPaths = [(move state m, mvs ++ [m]) | m <- generateNewMoves state, isValid state m]
+{% endcodeblock %}
+
+To find a solution form a state `start`, we call the above function as follows:
+
+{% codeblock lang:haskell %}
+solve :: State -> Maybe Path
+solve start = statesearch [] [(start,[])]
+{% endcodeblock %}
+
+In `solve`, we initialize the list of unexplored paths to `[(start,[])`. On the other hand, the list of explored states is initially empty.
+
+`statesearch` is implemented using pattern matching and recursion. The first thing it does is looking at the list of unexplored paths. If there is no more path to explore, the function returns `Nothing` which means there is no solution to the puzzle. Otherwise, we continue the search by evaluating the next path named `p@(state, mvs)` which is the head of the unexplored paths using the pattern matching:
+
+{% codeblock lang:haskell %}
+statesearch explored (p@(state, mvs) : paths)
+{% endcodeblock %}
+
+If the final `state` in the currently evaluated path is a _goal state_, then the function declares success by returning just that path `p`.
+
+Next, let's look at what happens if we have not yet reached our goal. `statesearch` then checks whether the current `state` has already been explored before. In that case, the path or list of moves that led us to `state` is no good. So, we simply discard that path and move on to the next one otherwise we will fall into a cycle. This is done through the recursive call `statesearch explored paths`.
+
+Now, suppose that the current `state` is not a `goal state` and it has not yet been explored. Then, we continue our search by generating some valid moves. For each valid move `m`, we produce an updated state `move state m` and an updated list of moves `mvs ++ [m]` and combine these into the current path `p`. We do that for each valid move and then we concatenate the generated paths to the list of path to be explored. Note that because we adopt a breadth-first search, we must append these paths at the end of the list. If we did otherwise, it is very unlikely that we would have found the shortest path to the exit.
+After evaluating the previous state, we add it to the list of explored states and make the recursive call:
+
+{% codeblock lang:haskell %}
+statesearch (state:explored) (paths ++ nextPaths) where
+ nextPaths :: [Path]
+ nextPaths = [(move state m, mvs ++ [m]) | m <- generateNewMoves state, isValid state m]
+{% endcodeblock %}
+So that's how elegant a state-space search can be implemented in Haskell. `statesearch` is the core function to solve the puzzle. The rest is a representation of the problem and helper functions.
+
+## Time to play
+Well, before we can show some descent user-interface to this puzzle. We'll need helpers functions that converts a string representation of the grid to a State and vice versa. So, we define the following functions:
+
+{% codeblock lang:haskell %}
+type Line = String
+stateToLines :: State -> [Line]
+linesToState :: [Line] -> State
+{% endcodeblock %}
+
+Let's illustrate how these would work with an example without showing their implementations. Suppose our initial state prints like this:
+
+{% codeblock%}
+-A----
+-A---D
+XXXC-D
+---C-D
+-BBB--
+------
+{% endcodeblock %}
+
+Then, the function `linesToState` would return the following State when applied to the above `[Line]` representation:
+
+{% codeblock lang:haskell %}
+Map.fromList [('A',Car {x = 2, y = 1, o = V, sz = 2}),
+ ('B',Car {x = 2, y = 5, o = H, sz = 3}),
+ ('C',Car {x = 4, y = 3, o = V, sz = 2}),
+ ('D',Car {x = 6, y = 2, o = V, sz = 3}),
+ ('X',Car {x = 1, y = 3, o = H, sz = 3})]
+{% endcodeblock %}
+
+Solving this _beginner level_ puzzle with Haskell and your supercomputer would be a real overkill. But for the sake of fun, here is the output:
+
+{% codeblock%}
+-A----
+-A---D
+XXXC-D
+---C-D
+-BBB--
+------
+
+-A----
+-A---D
+XXXC-D
+---C-D
+BBB---
+------
+
+-A----
+-A---D
+XXX--D
+---C-D
+BBBC--
+------
+
+-A----
+-A----
+XXX--D
+---C-D
+BBBC-D
+------
+
+-A----
+-A----
+XXX---
+---C-D
+BBBC-D
+-----D
+
+-A----
+-A----
+-XXX--
+---C-D
+BBBC-D
+-----D
+
+-A----
+-A----
+--XXX-
+---C-D
+BBBC-D
+-----D
+
+-A----
+-A----
+---XXX
+---C-D
+BBBC-D
+-----D
+{% endcodeblock %}
+
+Yay! Now, try it with a super tough challenge.
+
+
+
+
+
+
+
diff --git a/source/_posts/2014-10-16-scala-flavors-a-tasting-tour.markdown b/source/_posts/2014-10-16-scala-flavors-a-tasting-tour.markdown
new file mode 100644
index 0000000..3e1e113
--- /dev/null
+++ b/source/_posts/2014-10-16-scala-flavors-a-tasting-tour.markdown
@@ -0,0 +1,317 @@
+---
+layout: post
+title: "Scala Flavors: a tasting tour Part 1"
+date: 2014-10-15 17:50:32 -0700
+comments: false
+categories: scala tutorials
+---
+
+This a is the first part on a series of tutorials on Scala's language features. This series are written for anyone who are new to Scala, knows its syntax a bit but are excited and scared at the same type by the bipolarity of this `beautiful` language. In this first part, we will cover two points: {% img left ../images/scalabovolo.png 200 300 %}
+
+
+- Scala's type system
+- Scala's purely object-oriented language features
+
+
+## Starting strong and safe
+
+Scala's type system is strong, static and safe. What does that mean?
+
+### Values, variables and Types
+
+There are two possible ways to associate a name to a value or an expression. The first one is `val`, which is used to permanently bind a value to an indentifier. Once a val is set, its value can no longer be reassigned. In other words, vals are like constants.
+
+
+
+{% codeblock lang:scala %}
+scala> val y = 5.0
+y: Double = 5.0
+scala> val message = "Holla scala"
+message: String = Holla scala
+{% endcodeblock %}
+
+Changing the content of `message` to _"Bye scala"_ is not possible. Instead, it will generate a compilation error because of a reassignment to a val.
+
+The second one is `var`. You use a var for variables. Unlike vals, the value that a `var` refers to can be changed or reassigned in the future. For example, the `numberOfRabbits` enrolled to your farming program will probably keep growing.
+
+{% codeblock lang:scala %}
+scala> var numberOfRabbits = 6
+numberOfRabbits: Int = 10
+scala> numberOfRabbits = numberOfRabbits * 4
+numberOfRabbits: Int = 40
+scala> numberOfRabbits = numberOfRabbits * 4
+numberOfRabbits: Int = 160
+{% endcodeblock %}
+
+Once a var is declared, its type however cannot be modified. In other words, numberOfRabbits can only contain an integer. Reassigning a string to it will not compile.
+
+{% codeblock lang:scala %}
+numberOfRabbits = "will not compile"
+// Expression of type String doesn't comform to expected type Int.
+{% endcodeblock %}
+
+We have not yet explained what these types are about. Since Scala is a statically typed language, any values and variables are initialized with their type and content. Looking at the REPL outputs above, we did not declare any type when defining `y`, `message` or `numberOfRabbits`. So how did Scala know? Well, Scala is smart enough to infer the type from the right hand side of the assignment. Scala understood that "Holla scala" is definitely a string whereas the decimal 5.0 looks like a Double.
+
+In principle, a formal way to define vals and vars is like this.
+
+{% codeblock lang:scala %}
+// The right side must return a value of the declared type.
+val identifier: type = expression
+{% endcodeblock %}
+
+In some situations, we want to declare vals and vars without giving them an initial value. In that case, the type declaration is mandatory. Otherwise, the rule of thumb is to omit the types when they can be readily inferred with a glimpse and to declare them to add clarity to your code.
+
+{% codeblock lang:scala %}
+val z: Boolean; // Scala follows you
+val w; // Scala will cry out loud
+{% endcodeblock %}
+
+You must be still asking yourself why we need vals when we can use vars. Be patient as we will come back to this question when we will later discuss the choice between mutable and immutable data. For now, let's get our feet wet by reviewing some basic types and operators.
+
+### Basic Scala types and operators
+There are 3 types of operators:
+
+- binary operators which take two operands on their left and right sides
+- unary prefix operators which are applied to one operand on its right
+- unary postix operators which have one operand on its left
+
+Here are some examples of binary and unary operators for the basic numeric types.
+
+{% codeblock lang:scala %}
+// Binary operators
+scala> 20 * 1.20
+Double = 24.0
+
+scala> 3 / 2
+Int = 1
+
+scala> val larger = 3 max 7
+larger: Int = 7
+
+scala> val remainder = 11 % 3
+remainder: Int = 2
+
+// A unary prefix operator
+scala> val decimalNumber = - 102.876
+Double = - 102.876
+
+// A unary postfix operator
+decimalNumber toInt
+Int = - 102
+{% endcodeblock %}
+
+
+Similarly, logical operators on Boolean values can be either unary or binary.
+
+{% codeblock lang:scala %}
+
+scala> val veracity = true
+veracity: Boolean = true
+
+scala> var lie = ! veracity // a prefix operator
+lie: Boolean = false
+
+scala> veracity && lie
+Boolean = false
+
+scala> val halftruth = veracity || lie
+halftruth: Boolean = true
+{% endcodeblock %}
+
+
+In the following, let's shed some lights on the real nature of values, types and operators in Scala. Ready? Unveil!
+
+## Objects orient Scala's type system
+Behind the curtain, Scala is a purely object-oriented programming language. In fact, every value is an object of some type. Each type is represented by a class which serves as a blueprint for all values of that type. Moreover, every operation in Scala is a method call on some object.
+
+{% blockquote %}
+Types are classes. Values are objects. Operations are method calls.
+{% endblockquote %}
+
+
+Primitive types such as String and Double are wrapper classes for Java's primitive types. Let's look at some string concatenation examples to understand this.
+
+{% codeblock lang:scala %}
+//String concatenations
+scala> "apples" + " oranges"
+String = apples oranges
+
+scala> o * 3
+String = oranges oranges oranges
+
+scala> 3 + " oranges"
+3 oranges
+{% endcodeblock %}
+
+If Scala was not awesome, we would have to rewrite the above concatenations as formal method calls:
+
+{% codeblock lang:scala%}
+// More verbose concatenations
+scala> "apples".+(" oranges")
+scala> "oranges".*(3)
+scala> 3.+(" oranges")
+{% endcodeblock %}
+
+Luckily, any methods with single parameters can be written in Scala as if they were built-in infix operators. Therefore, we can omit the `.` notation and the parentheses enclosing the single parameter. Instead, we add a space before and after the method name. The cool thing about that is the flexibility to name your binary operations in any way you want as long as the name is a valid identifier.
+
+
+### Method overloading
+
+Since Scala is object-oriented, it supports method overloading so that different methods with the same name can be defined provided their signatures are different.
+
+Looking at `"apples".+(" oranges")`, we see that the concatenation is performed by calling the method `+` defined on the String object _"apples"_ with the string parameter _" oranges"_. What gets return is the new String object _"apples oranges"_. Furthermore, many other signatures exist for the same operator `+`.
+When it comes to `"oranges".*(3)`, `*` is another method defined on String and it returns the _"oranges"_ string concatenated 3 times. If you look at the Scala documentation for StringOps, you will find the signature of this method to be `def *(n: Int): String`.
+
+Of course, Scala will complain if you call a method on one object and the method signature is not present in the class definition.
+
+{% codeblock lang:scala%}
+scala> "apples" * 3.0
+error: def *(x: Double): String cannot be resolved on String object
+
+scala> 3 * "oranges"
+error: def *(s: String): String cannot be resolved on Int object
+{% endcodeblock %}
+
+The only exception to this rule is if an _implicit conversion_ is defined for the corresponding type, then the method call can be forwarded to the converted type. But let's keep things simple for now and perhaps, we'll discuss about implicits later on.
+
+
+
+### Create Abstract Data Types with Classes
+It is time to create your own types. Classes are used to abstract and parameterize data types that serve as building blocks for your Scala program.
+
+**Class definition:** you define a class using the `class` keyword followed by the class name and class parameters. Optionally, you can add statements and expressions in the class body delimited by a `{}` block to do one of the following:
+
+- declare and initialize value and variable fields
+- define public methods
+- define private methods helper or nested classes
+- execute some code, e.g. I/O actions
+
+
+Let's look at a culinary example in which we first define a _Recipe_ class.
+
+{% codeblock lang:scala %}
+class Recipe(n: String, s: Int = 1, instructions: List[String] = Nil) {
+ // some val and var fiels declarations and initializations
+ val name = n
+ val serves = s
+
+ var description: String = ""
+ var ingredients: Map[String, (Double, String)] = _
+}
+{% endcodeblock %}
+
+**Class constructor** asks you to specify the parameters `s`, `n`, and `instructions` to create the `Recipe` objects. For example, you call the constructor method and pass the name, the number of serves and instruction list. As a result, you get a new _easyNoodleRecipe_ object.
+
+{% codeblock lang:scala %}
+var easyNoodleRecipe = new Recipe("Hot Instant Noodle", 4, List("Boil water", "Cook noodle", "Serve"))
+{% endcodeblock %}
+
+Scala also allows us to define default values for some of these parameters so that when we create _Recipe_ objects that have these default values, we no longer need to specify the corresponding parameters when calling the constructor. Behind the scene, Scala simply generates additional constructors during compilation to support this.
+For example, we specified a default value of 1 for `s` and a default empty list for `instructions` in the class definition. Therefore, we can create an _healthySaladRecipe_ that serves 1 by passing only the other two parameters.
+
+{% codeblock lang:scala %}
+val healthySaladRecipe = new Recipe("Healthy green salad", instructions = List("Put greens in a bowl", "Add dressing", "Mix"))
+{% endcodeblock %}
+
+Similarly, we can create a _lazyBurgerRecipe_ that serves one and has an empty instruction by passing only one parameter, its name.
+
+{% codeblock lang:scala %}
+var lazyBurgerRecipe = new Recipe("Big Mac Burger")
+{% endcodeblock %}
+
+**Class parameters vs. Class fields:** there is an important difference about the scope of class parameters and var/val fields. Class parameters are not publicly visible unless they are defined with the keyword `var` or `val`. In such cases, a getter and/or a setter is generated correspondingly. In contrast, a class field is always defined with one of these keywords. Thus, Scala makes them accessible publicly. Here are some simple rules about the accessibility and visibility of class parameters and fields:
+
+1. **Class parameters defined *without var/val* keyword:** can only be read within the class body definition.
+2. **Class parameters defined *with val*:** a getter is created and the parameter _can be read_ by a user of the class, by the object itself or by another instance of the same class.
+3. **Class parameters defined *with var*:** a getter and a setter are generated so the parameter _can be read and also reassigned_ by a user of the class, by the object itself or by another instance of the same class.
+
+**Methods vs Functions**
+In Scala, methods and functions are defined in the same way using the syntax:
+
+{% codeblock lang:scala %}
+def methodName(parameter1: Type1, Parameter2: Type2, ...): OutputType = {
+ ...
+ result_expression
+}
+{% endcodeblock %}
+
+The difference between methods and functions in Scala is similar to that of instance methods and static methods in Java. In Scala, methods are invoked on an object instance with some parameters and are defined inside the class constructor. On the other hand, functions are not invoked on any object; they are simply called with some inputs and return an output. Furthermore, there are two ways to define functions in Scala. First, functions are usually defined inside a singleton object module. If that object is a companion of a class with the same name, then we can make the analogy with static methods in Java. Second, functions can alternatively be defined on the go using functions literals and assigned to a `val`.
+
+As previously mentionned, when a method is invoked in Scala with a single parameter, it can be interpreted as a binary operation. In fact, we can ommit the dot notation in that case when calling the method and replacing it with spaces between the object, the method name and the parameters. On the other hand, a parameterless method is usually written with a dot notation as if we access a field of the object on which we invoke the method. This programming style is known as _universal access principle_.
+
+Let's define some examples by defining two methods in the class Recipe's constructor.
+
+{% codeblock lang:scala %}
+class Recipe(val n: String, val s: Int = 1, instructions: List[String] = Nil) {
+ var description: String = ""
+ var ingredients: Map[String, (Double, String)] = _
+
+ // New methods
+ def hasNuts: Boolean = ingredients.keys.toList contains "nuts"
+
+ def serve(p: Int): Map[String, (Double, String)] = this.ingredients mapValues (v => (v._1 * p, v._2))
+}
+{% endcodeblock %}
+
+Now, we can test this in the Scala shell. Let's go back to our `healthySaladRecipe` and add its ingredients.
+
+{% codeblock lang:scala %}
+scala> healthySaladRecipe.ingredients = List("Tomatoes","Cucumber","Dressing","Feta cheese") zip List((1.0,"unit"), (1.0,"unit"), (1.0,"unit"),(50.0,"grams")) toMap
+healthySaladRecipe.ingredients: Map[String,(Double, String)] = Map(Tomatoes -> (1.0,unit), Cucumber -> (1.0,unit), Dressing -> (1.0,unit), Feta cheese -> (50.0,grams))
+{% endcodeblock %}
+
+Remember that `healthySaladRecipe` was defined as a `val`. However, it had fields defined as `var` such as ingredients. That means that `healthySaladRecipe` has a mutable state. This is a key distinction that is important in Scala. Even though an object is bound to a val. It can still changes state even the class of that object has mutable state. Mutable state is definitely to be avoided if we follow the functional programming principles. Here, we simply use this as an example to show that there is a key difference between `var` vs. `var` and `mutability` vs. `immutability`. In the second part of this tutorial, we will get into more details on this matter.
+
+> A `val` that is bound to an object cannot be reassigned to another object. But that does not imply that the object does not have a mutable state!
+
+In the above code, we created a map of ingredients from a list of ingredients and a list of quantity. To do that, we invoked the method `zip` which is defined in `scala.collection.immutable.List` on the first list and passed the second list as parameter. This is an example of method invocation as binary operator in Scala. Then, we used a parameterless method `toMap` which is invoked on a list of pairs to create a Map.
+
+By default, any Recipe object will serve one person. Let's check this in the shell.
+
+{% codeblock lang:scala %}
+scala> healthySaladRecipe.serves
+res: Int = 1
+{% endcodeblock %}
+
+So now, what if you invite two of your friends for lunch and you make a healthy salad for the three of you. Well, you can now invoke the `serve` method that we previously defined for that. What you will obtain is a new list of ingredients with the right quantity for each ingredient.
+
+{% codeblock lang:scala %}
+scala> healthySaladRecipe.serve(3)
+res: Map[String,(Double, String)] = Map(Tomatoes -> (3.0,unit), Cucumber -> (3.0,unit), Dressing -> (3.0,unit), Feta cheese -> (150.0,grams))
+{% endcodeblock %}
+
+Let's look closely at the implementation of the `serve` method.
+
+{% codeblock lang:scala %}
+def serve(p: Int): Map[String, (Double, String)] = this.ingredients mapValues (v => (v._1 * p, v._2))
+{% endcodeblock %}
+
+We accessed the list of ingredients of `healthySaladRecipe` and invoked a method `mapValues` which is defined in `scala.collection.immutable.Map`. This method takes a function value as parameter and applies that function to each value of the element in the map ingredients. Above, we used a function literal, also called anonymous or lambda function, using scala's syntax:
+
+{% codeblock lang:scala %}
+v => (v._1 * p, v._2)
+{% endcodeblock %}
+
+This function literal takes as input `v`, which has a type of a two-element tuple `(Double, String)`. Then, it returns of a value of the same type but with the ingredient quantity scaled by the number of serving `p`. We did not to specify the type signature of the function since Scala could infer to type of `v` from the type of `this.ingredients`.
+
+
+We have reached the end of the Part 1 of this tour on "Scala flavors". In Part 2, we will revisit some Scala object-oriented features including _case classes_ and _companion objects_. We'll also get a taste of _first-class functions_ in Scala. Finally, we'll touch on immutability vs. mutability in Scala.
+
+
+{% if page.comments %}
+
+
+Please enable JavaScript to view the comments powered by Disqus.
+comments powered by
+
+{% endif%}
\ No newline at end of file
diff --git a/source/_posts/2015-08-02-functional-database-programming-with-slick.markdown b/source/_posts/2015-08-02-functional-database-programming-with-slick.markdown
new file mode 100644
index 0000000..fe3bf50
--- /dev/null
+++ b/source/_posts/2015-08-02-functional-database-programming-with-slick.markdown
@@ -0,0 +1,395 @@
+---
+layout: post
+title: "Slick Database Programming in Scala"
+date: 2015-06-02 19:38:49 -0700
+comments: false
+categories:
+---
+
+
+## Awesome are Scala Collections.
+Working with Scala collections is simply a joy and apparently effortless! Their interfaces are rich, consistent and nicely separated from implementation. Yet, we have many to choose from and each collection offers different characteristics in terms of performance, mutability and laziness. {% img right ./images/slick.png 260 260 %}Chances are you will find the right tool for the job. In addition, Scala collections work great with for-comprehensions. With Scala, not only do we have power but also we have a flexibility to express our computations: either in a Map-Reduce-Filter pattern or simply using a for expression. With Scala collections, we can always get rid of boilerplate and understand performance.
+
+###So is Slick!
+With the Slick library, database programming would also enjoy such simplicity. Slick is a cool library that enable to query and access relational databases in plain Scala. Slick enables us to treat database tables almost as if they were Scala collections. In addition, it also gives us full control over when a database access happens and which data is transferred. In addition to its functional relational mapping features, Slick queries are type safe expressions. In other words, the compiler can catch inconsistencies at compile-time. Furthermore, we can compose simple queries into more complex ones and we can do so before even running them against the database. Apart from that, Slick also simplifies database management tasks such as describing schema, creating data models, managing connections and building transactions.
+
+In this tutorial, I will highlight Slick's functional features and use the wine database of _Scala Vino Restaurant_ as an illustrative example.
+
+
+
+
+## Getting Started with Slick
+
+Programming a Slick database application consists of the following steps:
+
+1. Configuring the database driver dependencies in SBT.
+2. Defining the database schema.
+3. Creating Slick queries
+4. Connecting to the database
+5. Run the queries or CRUD operations
+
+Let's go through these steps in detail.
+
+###Configuring Build Dependencies
+
+We start by creating an SBT Scala project and configure the build settings in build.sbt:
+
+```scala
+name := "wine-slick-example"
+
+version := "1.0"
+
+scalaVersion := "2.11.6"
+
+libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
+
+libraryDependencies ++= List(
+ "com.typesafe.slick" %% "slick" % "2.1.0",
+ "com.h2database" % "h2" % "1.3.0",
+ "ch.qos.logback" % "logback-classic" % "1.1.2"
+)
+```
+
+This file declares the library dependencies that a Slick project at least needs: the Slick library, the database driver library and a logging library. Here, we have chosen H2 database for simplicity. If you were to use MySQL or PostgreSQL, then the H2 dependency should be replaced by the corresponding JDBC driver.
+
+Once the SBT configurations are set, we can build our Slick application and start by importing the H2 Library:
+
+```
+
+import scala.slick.driver.H2Driver
+import scala.slick.driver.H2Driver.simple._
+
+```
+
+These help Slick to understand the functions provided by the database-specific driver (e.g. H2 driver here). It is convenient to import everything from `H2Driver.simple` to make sure all required implicit conversions and extension methods are in place when Slick needs them.
+
+### Describing the Database Schema
+
+After these simple configurations, we need define the database table and the type of each row in the table. In our example, we will only define one table of wines. Therefore, let's create a case class `Wine` and define its properties:
+
+```scala
+// Message type
+final case class Wine(color: String, maker: String, name: String, year: Int,
+ country: String, price: Double, id: Long = 0L){
+ override def toString = f"$name $year ($country ~ $color)"
+}
+```
+
+Next, let's define the table `WineTable`:
+
+```scala
+// Define a Table[Wine]
+final class WineTable(tag: Tag) extends Table[Wine](tag, "wine") {
+ def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
+ def color = column[String]("color")
+ def maker = column[String]("maker")
+ def name = column[String]("name")
+ def year = column[Int]("year")
+ def country = column[String]("country")
+ def price = column[Double]("price")
+
+ def * = (color, maker, name, year, country, price, id) <> (Wine.tupled, Wine.unapply)
+}
+```
+
+In the above code, we tell Slick three important things:
+
+- First, we tell Slick to define a table of wine by extending the abstract class `Table` with the type parameter `Wine`. By convention (since Slick 2.0), we also need to pass an extra tag argument with the table name. Note that the tag is however automatically passed by Slick and we do not need to specify it.
+- Second, we specify the type, name and any constraint for each column in the table by defining a get method for each property of `Wine`. For example, we add the constraint for `id` to be an auto-incrementing primary key.
+- Finally, the projecion operator `*` is defined to map each row in `WineTable` to the Scala class `Wine` using `Wine`'s default `tupled` and `unapply` method.
+
+
+###Creating queries
+
+In Slick, we can create queries even before connecting to the database. To start, let us create a `TableQuery` object `wines` that select all wines listed in our database.
+
+
+```scala
+// Create a query to select the whole table
+lazy val wines = TableQuery[WineTable]
+```
+
+This is the starting point of every other query and it is a convention to define `wines` as a `lazy val`. At this time, we do not want to run the query yet. Now, we can define other queries using operators such as `filter`. For example, let's define queries for red wines or Canadian wines:
+
+```scala
+// Another query for red wines
+val redWines = wines.filter(_.color === "Red")
+
+// Canadian wines
+val canadianWines = wines.filter(_.country === "Canada")
+```
+
+**Warning:**
+Note the use of `===` instead of `==` for comparing two values for equality and `=!=` instead of `!=` for inequality. The other comparison operators are the same as in standard Scala code: `<`, `<=`, `>=`, `>`. If you accidentally use `==` instead of `===`, it will compile fine but your query results will be empty!
+
+For each `Query` or `TableQuery`, there exist handy methods called `selectStatement` that prints the SQL code that will be run. For instance, we can quickly check into SBT console for the above queries:
+
+```scala
+scala> wines.selectStatement
+res: String = select x2."color", x2."maker", x2."name", x2."year", x2."country", x2."price", x2."id" from "wine" x2
+
+scala> canadianWines.selectStatement
+res: String = select x2."color", x2."maker", x2."name", x2."year", x2."country", x2."price", x2."id" from "wine" x2 where x2."country" = 'Canada'
+```
+
+### Connecting to the database and running the queries
+
+Since we do not have yet a database, let's use the function `Database.forURL` and pass the database URL and the corresponding driver to create a `Database` object:
+
+```scala
+// Create a H2 in-memory database
+def db = Database.forURL(
+ url = "jdbc:h2:mem:chat-database;DB_CLOSE_DELAY=-1",
+ driver = "org.h2.Driver"
+)
+```
+
+Now, we can connect to the database by opening a new session with the method `withSession`. Within the sesssion, we are going to:
+
+- Create our wine table using `wines.ddl.create`.
+- Insert the list of wines we got before into the new table.
+- Run the queries we previously created.
+
+All these must be done within the session. Moreover, the session argument must be set as implicit, otherwise we would have to specify it explicitly everytime we access and query the database. If we do not, we will run into an error that reads like this: __error: could not find implicit value for parameter session: scala.slick.jdbc.JdbcBackend#SessionDef__
+
+```scala
+db.withSession { implicit session =>
+
+ // Create the wine table:
+ println("Creating wine database")
+ wines.ddl.create
+
+ // Create and insert our selection of data:
+ println("\nInserting wine data")
+ wines ++= wineData
+
+ // Run the test query and print the results:
+ println("\nPrinting all wines:")
+ wines.run.foreach(println)
+
+ println("\nThese are the wines from Canada:")
+ canadianWines.run.foreach(println)
+}
+```
+
+Here what the results look like on standard output:
+
+```text
+Printing all wines:
+
+Malbec Reserva 2009 (Argentina ~ Red)
+Cote de Sambre et Meusu Pinot Gris 2013 (France ~ White)
+Whispering Angel Rosé 2014 (France ~ Rosé)
+Cabernet Sauvignon 2005 (United States ~ Red)
+Mcgregor Shiraz 2009 (South Africa ~ Red)
+Marlborough Sauvignon Blanc 2014 (New Zealand ~ White)
+Rosé Sec VQA Cave Spring 2010 (Canada ~ Rosé)
+Paragon Edna Valley Riesling 2012 (United States ~ White)
+Conca del Riu Anoia Barcelona de Nit 2011 (Spain ~ White)
+Amarone della Valpolicella Riserva Classico Sergio 2009 (Italy ~ Red)
+The Prisoner 2013 (United States ~ Red)
+Ice wine Vidal Inniskillin 2012 (Canada ~ Red)
+Vin de glace Cabernet 2013 (Canada ~ Red)
+Pinot Grigio Rosé Folonari 2014 (Italy ~ Rosé)
+
+These are the wines from Canada:
+
+Rosé Sec VQA Cave Spring 2010 (Canada ~ Rosé)
+Ice wine Vidal Inniskillin 2012 (Canada ~ Red)
+Vin de glace Cabernet 2013 (Canada ~ Red)
+```
+
+## More CRUD wines with Slick
+
+###Select statement
+
+In our previous queries, we got back a sequence of `Wine`. What if all we need is the list of French winemakers? For such kind of SELECT queries, we use the `map` operator and pass a function to select whatever we can access from the table.
+
+```scala
+// List of French winemakers
+val frenchWinemakers = wines.filter(_.country === "France").
+ map(_.maker)
+
+// Corresponding SQL statement
+// select x2."maker" from "wine" x2 where x2."country" = 'France'
+
+// Run within session
+frenchWinemakers.run.foreach(println)
+Château Bon-Baron
+Chateau d'Esclans
+```
+
+In the above session, we assumed that we run the queries within `db.withSession{}`. If you want to run queries in the console, you can either use ``db.withSession{anotherQuery.run}` everytime or create an implicit session as follows:
+
+```scala
+implicit val session = db.createSession
+```
+Note that this is only useful for experimentation purpose within Scala REPL. It is recommended not to create session manually. Instead, use `db.withSession` so that the resources are managed by Slick automatically.
+
+###For Comprehensions When You Need it
+As I mentionned in the beginning, working with Slick tables are very similar to handling Scala collections. In addition to the combinators such as `map` and `filter`, we can also rely on _for comprehensions` to express queries. A valid alternative to getting the french makers is:
+
+```scala
+val frenchWinemakers =
+ for {
+ w <- wines
+ if w.country === "France"
+ } yield w.maker
+}
+```
+
+Which one should you use totally depends on your taste and needs.
+
+###Inserting rows
+
+Imagine our restaurant just received a nice selection of Australina wines. We can ask Slick to insert them into the database using `insert`:
+
+```scala
+ val aussies = Seq(
+ Wine("Red", "Chandon", "Chandon Australia Heathcote Shiraz", 2001, "Australia", 45.0 ),
+ Wine("Rosé", "Jacob's Creek", "Sparkling Moscato Rosé", 2014, "Australia", 24.0),
+ Wine("Red", "Chandon", "Vintage Collection Cuvée 500", 2008, "Australia", 59.95),
+ Wine("Red", "Cranswick", "Riverina Cabernet Merlot", 1999, "Australia", 24.0)
+ )
+
+ db.withSession { implicit session =>
+ // Insert Australian selection into wines table
+ wines ++= aussies
+
+ // Insert one wine
+ wines += Wine("Red", "Castle Glen Australia", "Montepulicano", 2002, "Australia", 39)
+
+ // Showing all australian wines
+ wines.filter(_.country === "Australia").run.foreach(println)
+ }
+```
+
+Here is the output:
+
+```text
+Chandon Australia Heathcote Shiraz 2001 (Australia ~ Red)
+Sparkling Moscato Rosé 2014 (Australia ~ Rosé)
+Vintage Collection Cuvée 500 2008 (Australia ~ Red)
+Riverina Cabernet Merlot 1999 (Australia ~ Red)
+Montepulicano 2002 (Australia ~ Red)
+```
+
+###Updating rows
+
+Our restaurant is making a summer holiday promotion to Italian wine bottles. We are asked to update the price with 10% discount. Updating is done with a succession of `map` and `update` calls. Here, we first need to select the price to be updated and call `update` to update them. Unfortunately, it is not yet possible to update with scalar expression or transformations of the price value.
+
+```scala
+// Discount all french wine bottles between $20 and $40 to $20
+val frenchWines = wines.filter(_.country === "France")
+db.withSession { implicit session =>
+
+ val selectedPrices =
+ for {
+ w <- wines
+ if (w.country === "France")
+ if (w.price >= 20.0 && w.price <= 40.0)
+ } yield w.price
+ selectedPrices.update(20.0)
+}
+```
+
+Here are the French wines before discount:
+
+```text
+Cote de Sambre et Meusu Pinot Gris 2013 (France ~ White ~ 27.0)
+Whispering Angel Rosé 2014 (France ~ Rosé ~ 35.0)
+```
+
+And after the discount:
+
+```text
+Cote de Sambre et Meusu Pinot Gris 2013 (France ~ White ~ 20.0)
+Whispering Angel Rosé 2014 (France ~ Rosé ~ 20.0)
+```
+
+###Sorting and limiting results
+
+Slick also provide mechanisms for ordering and limiting the results of queries. These are the standard collection methods `sortBy`, `take` and `drop`. For instance, let us query the 3 least expensive wines in our selection:
+
+```scala
+// 3 least expensive
+val cheapWines = wines.sortBy(_.price).take(3)
+
+// Wines by country sorted by price
+val winesByCountry = wines.sortBy(w => (w.country, w.price))
+db.withSession { implicit session =>
+
+ println("\n>> Our cheapest wines:\n")
+ cheapWines.run.foreach(println)
+
+ println("\n>> Wines by Country:\n")
+ winesByCountry.run.foreach(println)
+}
+```
+
+Here are the results:
+
+```text
+>> Our cheapest wines:
+
+Pinot Grigio Rosé Folonari 2014 (Italy ~ Rosé ~ 11.9)
+Mcgregor Shiraz 2009 (South Africa ~ Red ~ 14.0)
+Rosé Sec VQA Cave Spring 2010 (Canada ~ Rosé ~ 14.95)
+
+>> Wines by Country sorted by country and region:
+
+Malbec Reserva 2009 (Argentina ~ Red ~ 38.0)
+Sparkling Moscato Rosé 2014 (Australia ~ Rosé ~ 24.0)
+Riverina Cabernet Merlot 1999 (Australia ~ Red ~ 24.0)
+Montepulicano 2002 (Australia ~ Red ~ 39.0)
+Chandon Australia Heathcote Shiraz 2001 (Australia ~ Red ~ 45.0)
+Vintage Collection Cuvée 500 2008 (Australia ~ Red ~ 59.95)
+Rosé Sec VQA Cave Spring 2010 (Canada ~ Rosé ~ 14.95)
+Vin de glace Cabernet 2013 (Canada ~ Red ~ 39.95)
+Ice wine Vidal Inniskillin 2012 (Canada ~ Red ~ 49.95)
+Cote de Sambre et Meusu Pinot Gris 2013 (France ~ White ~ 20.0)
+Whispering Angel Rosé 2014 (France ~ Rosé ~ 20.0)
+Pinot Grigio Rosé Folonari 2014 (Italy ~ Rosé ~ 11.9)
+Amarone della Valpolicella Riserva Classico Sergio 2009 (Italy ~ Red ~ 50.0)
+Marlborough Sauvignon Blanc 2014 (New Zealand ~ White ~ 23.0)
+Mcgregor Shiraz 2009 (South Africa ~ Red ~ 14.0)
+Conca del Riu Anoia Barcelona de Nit 2011 (Spain ~ White ~ 40.0)
+Paragon Edna Valley Riesling 2012 (United States ~ White ~ 26.0)
+Cabernet Sauvignon 2005 (United States ~ Red ~ 28.0)
+The Prisoner 2013 (United States ~ Red ~ 51.0)
+```
+
+
+###Deleting rows
+
+Deleting rows are simply done through a sequence of `filter` and `delete`. For example, if we decide not to sell Italian wines anymore, we could use:
+
+```scala
+wines.filter(_.country === "Italy").delete”
+```
+Delete returns the number of deleted rows.
+
+###Transactions and rollback
+
+When we run queries with `db.withSession`, each query runs independently. Hence, it is possible for some queries to faile while for some others to succeed. In many applications, we often want to combine queries within a transaction so that either all queries succeed or all fail. This is done simply by wrapping the queries within a `session.withTransaction` block inside `db.withSession`. For instance, we can perform a batch of price updates together as follows:
+
+```scala
+// Select the prices between lo and hi
+def discount(lo: Double, hi: Double) =
+ wines.filter(w => w.price >= lo && w.price >= hi).map(_.price)
+
+db.withSession { implicit session =>
+ session.withTransaction {
+ discount(20.0, 30.0).update(20.0)
+ discount(30.0, 35,0).update(30.0)
+ discount(40.0, 50.0).update(50.0)
+ }
+ wines.run
+}
+```
+
+The block passed to `withTransaction` is executed as a single transaction. If an exception is thrown, Slick rolls back the transaction at the end of the block. Note that Slick only rolls back the database operations. The remaining Scala code are executed and their effects are not rolled back.
+
+### Summary
+
+We are going to stop here for now. But, there are still a lot to cover about this cool library. To summarize, handling database access and queries is very smooth and effortless with Slick. Using a lifted embedding approach, we can define queries and run them later after we connect to the database. Slick database operations are very similar to Scala collection methods. We select rows and columns with `filter` and `map`. Then, we can order and limit our results with `sortBy`, `take` and `drop`. Updating, deleting and inserting rows are also a breeze. In addition, we can use for expression to write complex queries or compose simple ones. In my next post, I hope to explore more about Slick's type system, other operations such as joins and aggregates as well as the new reactive streams support in Slick 3.0. I hope you could appreciate the functional aspects of database programming in Slick and use some of these in your applications.
\ No newline at end of file
diff --git a/source/_posts/sample b/source/_posts/sample
new file mode 100644
index 0000000..042d975
--- /dev/null
+++ b/source/_posts/sample
@@ -0,0 +1,56 @@
+["--B---","--B---","XXB---","--AA--","------","------"],
+["--B---","--B---","XXB---","-AA---","------","------"],
+["--B---","--B---","XXB---","---AA-","------","------"],
+["--B---","--B---","XXB---","AA----","------","------"],
+["--B---","--B---","XXB---","----AA","------","------"],
+["------","--B---","XXB---","--BAA-","------","------"],
+["------","--B---","XXB---","AAB---","------","------"],
+["------","--B---","XXB---","--B-AA","------","------"],
+["------","------","XXB---","--BAA-","--B---","------"],
+["------","------","XXB---","AAB---","--B---","------"],
+["------","------","XXB---","--B-AA","--B---","------"],
+["------","------","XX----","--BAA-","--B---","--B---"],
+["------","------","XX----","AAB---","--B---","--B---"],
+["------","------","XX----","--B-AA","--B---","--B---"],
+["------","------","-XX---","--BAA-","--B---","--B---"],
+["------","------","-XX---","AAB---","--B---","--B---"],
+["------","------","-XX---","--B-AA","--B---","--B---"],
+["------","------","--XX--","--BAA-","--B---","--B---"],
+["------","------","--XX--","AAB---","--B---","--B---"],
+["------","------","--XX--","--B-AA","--B---","--B---"],
+["------","------","---XX-","--BAA-","--B---","--B---"],
+["------","------","---XX-","AAB---","--B---","--B---"],
+["------","------","---XX-","--B-AA","--B---","--B---"],
+["------","------","--BXX-","--BAA-","--B---","------"],
+["------","------","----XX","--BAA-","--B---","--B---"]]
+
+
+["--B---",
+ "--B---",
+ "XXB---",
+ "--AA--",
+ "------",
+ "------"],
+
+
+["--B---",
+ "--B---",
+ "XXB---",
+ "-AA---",
+ "------",
+ "------"],
+
+["------",
+"------",
+"---XX-",
+"AAB---",
+"--B---",
+"--B---"],
+
+["------","------","--BXX-","AAB---","--B---","------"],
+["------","--B---","--BXX-","AAB---","------","------"],
+["--B---","--B---","--BXX-","AA----","------","------"],
+["------","------","--XX--","--BAA-","--B---","--B---"],
+["------","------","-XX---","--B-AA","--B---","--B---"],
+["------","------","XX----","--BAA-","--B---","--B---"],
+["------","------","XXB---","--B-AA","--B---","------"]]
\ No newline at end of file
diff --git a/source/about/index.markdown b/source/about/index.markdown
new file mode 100644
index 0000000..e70b18e
--- /dev/null
+++ b/source/about/index.markdown
@@ -0,0 +1,24 @@
+---
+layout: page
+title: "About Me"
+date:
+comments: false
+sharing: true
+footer: true
+---
+
+My name is Rindra. And I'm delighted to share my interests on software programming, data science and machine learning in this blog.
+
+I am currently wrapping up my PhD program at the [University of British Columbia](https://www.ubc.ca/). My thesis project focused on designing new algorithms to improve the energy efficiency of the next-generation 5G wireless networks. My main tools are optimization, statistics and algorithm design.
+
+My passion is to build analytics softwares that solve real-world problems or answer important business questions. I believe the future of software will belong within the intersection Big Data and [Internet of Everything (IoE)](https://en.wikipedia.org/wiki/Internet_of_Things) applications. In some of [**my projects**](http://giocode.github.io/projects/index.html), I have been involved in:
+
+- building novel anomaly detection techniques for real-time data,
+- investigating new techniques to better train deep learning models,
+- and using Apache Spark for scalable graph processing.
+
+I am proficient in Scala, Java, and R and have basic working knowledge of Python and Javascript. I like learning different programming paradigms such as functional, logic and declarative to be able to write better programs.
+
+Besides learning the latest technologies, I also love sharing my knowledge and interests to like-minded people on [this blog](http://giocode.github.io/). So, happy reading and drop me some comments!
+
+You can connect with me on [LinkedIn](https://www.linkedin.com/in/rindranirina) or email me at rindra "AT" ece "DOT" ubc "DOT" ca.
\ No newline at end of file
diff --git a/source/assets/jwplayer/glow/controlbar/background.png b/source/assets/jwplayer/glow/controlbar/background.png
new file mode 100644
index 0000000..c2824cc
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/background.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/blankButton.png b/source/assets/jwplayer/glow/controlbar/blankButton.png
new file mode 100644
index 0000000..010159f
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/blankButton.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/divider.png b/source/assets/jwplayer/glow/controlbar/divider.png
new file mode 100644
index 0000000..77cd829
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/divider.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/fullscreenButton.png b/source/assets/jwplayer/glow/controlbar/fullscreenButton.png
new file mode 100644
index 0000000..e06aa50
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/fullscreenButton.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/fullscreenButtonOver.png b/source/assets/jwplayer/glow/controlbar/fullscreenButtonOver.png
new file mode 100644
index 0000000..d2bc4fc
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/fullscreenButtonOver.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/muteButton.png b/source/assets/jwplayer/glow/controlbar/muteButton.png
new file mode 100644
index 0000000..40c40ab
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/muteButton.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/muteButtonOver.png b/source/assets/jwplayer/glow/controlbar/muteButtonOver.png
new file mode 100644
index 0000000..96fe7bb
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/muteButtonOver.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/normalscreenButton.png b/source/assets/jwplayer/glow/controlbar/normalscreenButton.png
new file mode 100644
index 0000000..2229507
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/normalscreenButton.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/normalscreenButtonOver.png b/source/assets/jwplayer/glow/controlbar/normalscreenButtonOver.png
new file mode 100644
index 0000000..15db44d
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/normalscreenButtonOver.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/pauseButton.png b/source/assets/jwplayer/glow/controlbar/pauseButton.png
new file mode 100644
index 0000000..e399bf3
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/pauseButton.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/pauseButtonOver.png b/source/assets/jwplayer/glow/controlbar/pauseButtonOver.png
new file mode 100644
index 0000000..409d89d
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/pauseButtonOver.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/playButton.png b/source/assets/jwplayer/glow/controlbar/playButton.png
new file mode 100644
index 0000000..f8d9a00
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/playButton.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/playButtonOver.png b/source/assets/jwplayer/glow/controlbar/playButtonOver.png
new file mode 100644
index 0000000..3fe2848
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/playButtonOver.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/timeSliderBuffer.png b/source/assets/jwplayer/glow/controlbar/timeSliderBuffer.png
new file mode 100644
index 0000000..73b371a
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/timeSliderBuffer.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/timeSliderCapLeft.png b/source/assets/jwplayer/glow/controlbar/timeSliderCapLeft.png
new file mode 100644
index 0000000..7232217
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/timeSliderCapLeft.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/timeSliderCapRight.png b/source/assets/jwplayer/glow/controlbar/timeSliderCapRight.png
new file mode 100644
index 0000000..626444a
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/timeSliderCapRight.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/timeSliderProgress.png b/source/assets/jwplayer/glow/controlbar/timeSliderProgress.png
new file mode 100644
index 0000000..132a8e7
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/timeSliderProgress.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/timeSliderRail.png b/source/assets/jwplayer/glow/controlbar/timeSliderRail.png
new file mode 100644
index 0000000..27851df
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/timeSliderRail.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/unmuteButton.png b/source/assets/jwplayer/glow/controlbar/unmuteButton.png
new file mode 100644
index 0000000..3658453
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/unmuteButton.png differ
diff --git a/source/assets/jwplayer/glow/controlbar/unmuteButtonOver.png b/source/assets/jwplayer/glow/controlbar/unmuteButtonOver.png
new file mode 100644
index 0000000..138ebb3
Binary files /dev/null and b/source/assets/jwplayer/glow/controlbar/unmuteButtonOver.png differ
diff --git a/source/assets/jwplayer/glow/display/background.png b/source/assets/jwplayer/glow/display/background.png
new file mode 100644
index 0000000..391152f
Binary files /dev/null and b/source/assets/jwplayer/glow/display/background.png differ
diff --git a/source/assets/jwplayer/glow/display/bufferIcon.png b/source/assets/jwplayer/glow/display/bufferIcon.png
new file mode 100644
index 0000000..a3819c1
Binary files /dev/null and b/source/assets/jwplayer/glow/display/bufferIcon.png differ
diff --git a/source/assets/jwplayer/glow/display/muteIcon.png b/source/assets/jwplayer/glow/display/muteIcon.png
new file mode 100644
index 0000000..e0408bb
Binary files /dev/null and b/source/assets/jwplayer/glow/display/muteIcon.png differ
diff --git a/source/assets/jwplayer/glow/display/playIcon.png b/source/assets/jwplayer/glow/display/playIcon.png
new file mode 100644
index 0000000..cb38427
Binary files /dev/null and b/source/assets/jwplayer/glow/display/playIcon.png differ
diff --git a/source/assets/jwplayer/glow/dock/button.png b/source/assets/jwplayer/glow/dock/button.png
new file mode 100644
index 0000000..391152f
Binary files /dev/null and b/source/assets/jwplayer/glow/dock/button.png differ
diff --git a/source/assets/jwplayer/glow/glow.xml b/source/assets/jwplayer/glow/glow.xml
new file mode 100644
index 0000000..70b0fe0
--- /dev/null
+++ b/source/assets/jwplayer/glow/glow.xml
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/assets/jwplayer/glow/playlist/item.png b/source/assets/jwplayer/glow/playlist/item.png
new file mode 100644
index 0000000..812592c
Binary files /dev/null and b/source/assets/jwplayer/glow/playlist/item.png differ
diff --git a/source/assets/jwplayer/glow/playlist/itemOver.png b/source/assets/jwplayer/glow/playlist/itemOver.png
new file mode 100644
index 0000000..549f372
Binary files /dev/null and b/source/assets/jwplayer/glow/playlist/itemOver.png differ
diff --git a/source/assets/jwplayer/glow/playlist/sliderCapBottom.png b/source/assets/jwplayer/glow/playlist/sliderCapBottom.png
new file mode 100644
index 0000000..048cc62
Binary files /dev/null and b/source/assets/jwplayer/glow/playlist/sliderCapBottom.png differ
diff --git a/source/assets/jwplayer/glow/playlist/sliderCapTop.png b/source/assets/jwplayer/glow/playlist/sliderCapTop.png
new file mode 100644
index 0000000..65c463a
Binary files /dev/null and b/source/assets/jwplayer/glow/playlist/sliderCapTop.png differ
diff --git a/source/assets/jwplayer/glow/playlist/sliderRail.png b/source/assets/jwplayer/glow/playlist/sliderRail.png
new file mode 100644
index 0000000..121778a
Binary files /dev/null and b/source/assets/jwplayer/glow/playlist/sliderRail.png differ
diff --git a/source/assets/jwplayer/glow/playlist/sliderThumb.png b/source/assets/jwplayer/glow/playlist/sliderThumb.png
new file mode 100644
index 0000000..118c3e0
Binary files /dev/null and b/source/assets/jwplayer/glow/playlist/sliderThumb.png differ
diff --git a/source/assets/jwplayer/glow/sharing/embedIcon.png b/source/assets/jwplayer/glow/sharing/embedIcon.png
new file mode 100644
index 0000000..3394ac9
Binary files /dev/null and b/source/assets/jwplayer/glow/sharing/embedIcon.png differ
diff --git a/source/assets/jwplayer/glow/sharing/embedScreen.png b/source/assets/jwplayer/glow/sharing/embedScreen.png
new file mode 100644
index 0000000..b405975
Binary files /dev/null and b/source/assets/jwplayer/glow/sharing/embedScreen.png differ
diff --git a/source/assets/jwplayer/glow/sharing/shareIcon.png b/source/assets/jwplayer/glow/sharing/shareIcon.png
new file mode 100644
index 0000000..eae1d4e
Binary files /dev/null and b/source/assets/jwplayer/glow/sharing/shareIcon.png differ
diff --git a/source/assets/jwplayer/glow/sharing/shareScreen.png b/source/assets/jwplayer/glow/sharing/shareScreen.png
new file mode 100644
index 0000000..695ec94
Binary files /dev/null and b/source/assets/jwplayer/glow/sharing/shareScreen.png differ
diff --git a/source/assets/jwplayer/player.swf b/source/assets/jwplayer/player.swf
new file mode 100644
index 0000000..0eee379
Binary files /dev/null and b/source/assets/jwplayer/player.swf differ
diff --git a/source/atom.xml b/source/atom.xml
new file mode 100644
index 0000000..c36201b
--- /dev/null
+++ b/source/atom.xml
@@ -0,0 +1,27 @@
+---
+layout: null
+---
+
+
+
+
+
+
+ {{ site.time | date_to_xmlschema }}
+ {{ site.url }}/
+
+
+ {% if site.email %} {% endif %}
+
+ Octopress
+
+ {% for post in site.posts limit: 20 %}
+
+
+
+ {{ post.date | date_to_xmlschema }}
+ {{ site.url }}{{ post.id }}
+
+
+ {% endfor %}
+
diff --git a/source/blog/archives/index.html b/source/blog/archives/index.html
new file mode 100644
index 0000000..f1d9cee
--- /dev/null
+++ b/source/blog/archives/index.html
@@ -0,0 +1,18 @@
+---
+layout: page
+title: Blog Archive
+footer: false
+---
+
+
+{% for post in site.posts reverse %}
+{% capture this_year %}{{ post.date | date: "%Y" }}{% endcapture %}
+{% unless year == this_year %}
+ {% assign year = this_year %}
+
{{ year }}
+{% endunless %}
+
+ {% include archive_post.html %}
+
+{% endfor %}
+
diff --git a/source/blog/index.html b/source/blog/index.html
new file mode 100644
index 0000000..64b665e
--- /dev/null
+++ b/source/blog/index.html
@@ -0,0 +1,29 @@
+---
+layout: default
+---
+
+
+ {% assign index = true %}
+ {% for post in paginator.posts %}
+ {% assign content = post.content %}
+
+ {% include article.html %}
+
+ {% endfor %}
+
+
+
diff --git a/source/data/index.html b/source/data/index.html
new file mode 100644
index 0000000..e3b4446
--- /dev/null
+++ b/source/data/index.html
@@ -0,0 +1,17 @@
+---
+layout: page
+title: "index"
+date: 2015-08-01 13:03
+comments: true
+sharing: true
+footer: true
+---
+
+# Data processing projects
+
+1. Spark Graph Processing
+2.
+
+
+
+
diff --git a/source/favicon.png b/source/favicon.png
new file mode 100644
index 0000000..0f25067
Binary files /dev/null and b/source/favicon.png differ
diff --git a/source/font/fontawesome-webfont.eot b/source/font/fontawesome-webfont.eot
new file mode 100755
index 0000000..3f669a7
Binary files /dev/null and b/source/font/fontawesome-webfont.eot differ
diff --git a/source/font/fontawesome-webfont.svg b/source/font/fontawesome-webfont.svg
new file mode 100755
index 0000000..73c0ad9
--- /dev/null
+++ b/source/font/fontawesome-webfont.svg
@@ -0,0 +1,175 @@
+
+
+
+
+This is a custom SVG webfont generated by Font Squirrel.
+Designer : Dave Gandy
+Foundry : Fort Awesome
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/font/fontawesome-webfont.svgz b/source/font/fontawesome-webfont.svgz
new file mode 100755
index 0000000..2a73cd7
Binary files /dev/null and b/source/font/fontawesome-webfont.svgz differ
diff --git a/source/font/fontawesome-webfont.ttf b/source/font/fontawesome-webfont.ttf
new file mode 100755
index 0000000..4972eb4
Binary files /dev/null and b/source/font/fontawesome-webfont.ttf differ
diff --git a/source/font/fontawesome-webfont.woff b/source/font/fontawesome-webfont.woff
new file mode 100755
index 0000000..6e4cb41
Binary files /dev/null and b/source/font/fontawesome-webfont.woff differ
diff --git a/source/images/bird_32_gray.png b/source/images/bird_32_gray.png
new file mode 100644
index 0000000..574f210
Binary files /dev/null and b/source/images/bird_32_gray.png differ
diff --git a/source/images/bird_32_gray_fail.png b/source/images/bird_32_gray_fail.png
new file mode 100644
index 0000000..8337d10
Binary files /dev/null and b/source/images/bird_32_gray_fail.png differ
diff --git a/source/images/bitbucket_22_gray.png b/source/images/bitbucket_22_gray.png
new file mode 100644
index 0000000..66d6e3f
Binary files /dev/null and b/source/images/bitbucket_22_gray.png differ
diff --git a/source/images/code_bg.png b/source/images/code_bg.png
new file mode 100644
index 0000000..a57bab5
Binary files /dev/null and b/source/images/code_bg.png differ
diff --git a/source/images/delicious_22_gray.png b/source/images/delicious_22_gray.png
new file mode 100644
index 0000000..3546d57
Binary files /dev/null and b/source/images/delicious_22_gray.png differ
diff --git a/source/images/dotted-border.png b/source/images/dotted-border.png
new file mode 100644
index 0000000..57f9907
Binary files /dev/null and b/source/images/dotted-border.png differ
diff --git a/source/images/email.png b/source/images/email.png
new file mode 100644
index 0000000..e55473f
Binary files /dev/null and b/source/images/email.png differ
diff --git a/source/images/fancybox/blank.gif b/source/images/fancybox/blank.gif
new file mode 100644
index 0000000..35d42e8
Binary files /dev/null and b/source/images/fancybox/blank.gif differ
diff --git a/source/images/fancybox/fancybox_loading.gif b/source/images/fancybox/fancybox_loading.gif
new file mode 100644
index 0000000..0158617
Binary files /dev/null and b/source/images/fancybox/fancybox_loading.gif differ
diff --git a/source/images/fancybox/fancybox_sprite.png b/source/images/fancybox/fancybox_sprite.png
new file mode 100644
index 0000000..3ef3229
Binary files /dev/null and b/source/images/fancybox/fancybox_sprite.png differ
diff --git a/source/images/forward.png b/source/images/forward.png
new file mode 100644
index 0000000..a04391a
Binary files /dev/null and b/source/images/forward.png differ
diff --git a/source/images/github_22_gray.png b/source/images/github_22_gray.png
new file mode 100644
index 0000000..e1593d1
Binary files /dev/null and b/source/images/github_22_gray.png differ
diff --git a/source/images/gprofile_22_gray.png b/source/images/gprofile_22_gray.png
new file mode 100644
index 0000000..b3e0d07
Binary files /dev/null and b/source/images/gprofile_22_gray.png differ
diff --git a/source/images/line-tile.png b/source/images/line-tile.png
new file mode 100644
index 0000000..f67ee19
Binary files /dev/null and b/source/images/line-tile.png differ
diff --git a/source/images/loading_gray.gif b/source/images/loading_gray.gif
new file mode 100644
index 0000000..2865fc6
Binary files /dev/null and b/source/images/loading_gray.gif differ
diff --git a/source/images/loading_pacman.gif b/source/images/loading_pacman.gif
new file mode 100644
index 0000000..54c61fa
Binary files /dev/null and b/source/images/loading_pacman.gif differ
diff --git a/source/images/net.png b/source/images/net.png
new file mode 100644
index 0000000..0c273bb
Binary files /dev/null and b/source/images/net.png differ
diff --git a/source/images/neural/dropout.png b/source/images/neural/dropout.png
new file mode 100644
index 0000000..c371a8d
Binary files /dev/null and b/source/images/neural/dropout.png differ
diff --git a/source/images/neural/errors.png b/source/images/neural/errors.png
new file mode 100644
index 0000000..99731b8
Binary files /dev/null and b/source/images/neural/errors.png differ
diff --git a/source/images/neural/featuresminst.png b/source/images/neural/featuresminst.png
new file mode 100644
index 0000000..94cd10e
Binary files /dev/null and b/source/images/neural/featuresminst.png differ
diff --git a/source/images/neural/forward.png b/source/images/neural/forward.png
new file mode 100644
index 0000000..a04391a
Binary files /dev/null and b/source/images/neural/forward.png differ
diff --git a/source/images/neural/net.png b/source/images/neural/net.png
new file mode 100644
index 0000000..0c273bb
Binary files /dev/null and b/source/images/neural/net.png differ
diff --git a/source/images/neural/result.png b/source/images/neural/result.png
new file mode 100644
index 0000000..a6b721c
Binary files /dev/null and b/source/images/neural/result.png differ
diff --git a/source/images/neural/table1.png b/source/images/neural/table1.png
new file mode 100644
index 0000000..716d2c7
Binary files /dev/null and b/source/images/neural/table1.png differ
diff --git a/source/images/neural/table2.png b/source/images/neural/table2.png
new file mode 100644
index 0000000..a0d5f37
Binary files /dev/null and b/source/images/neural/table2.png differ
diff --git a/source/images/noise.png b/source/images/noise.png
new file mode 100644
index 0000000..432e05b
Binary files /dev/null and b/source/images/noise.png differ
diff --git a/source/images/pinboard_22_gray.png b/source/images/pinboard_22_gray.png
new file mode 100644
index 0000000..7dee45f
Binary files /dev/null and b/source/images/pinboard_22_gray.png differ
diff --git a/source/images/rss.png b/source/images/rss.png
new file mode 100644
index 0000000..151ae71
Binary files /dev/null and b/source/images/rss.png differ
diff --git a/source/images/rushhour.png b/source/images/rushhour.png
new file mode 100644
index 0000000..9f67f45
Binary files /dev/null and b/source/images/rushhour.png differ
diff --git a/source/images/scalabovolo.png b/source/images/scalabovolo.png
new file mode 100644
index 0000000..6fd58cb
Binary files /dev/null and b/source/images/scalabovolo.png differ
diff --git a/source/images/search.png b/source/images/search.png
new file mode 100644
index 0000000..1220ff4
Binary files /dev/null and b/source/images/search.png differ
diff --git a/source/images/slick.png b/source/images/slick.png
new file mode 100644
index 0000000..dc1f6a4
Binary files /dev/null and b/source/images/slick.png differ
diff --git a/source/images/social/coderwall.png b/source/images/social/coderwall.png
new file mode 100644
index 0000000..e57ecd4
Binary files /dev/null and b/source/images/social/coderwall.png differ
diff --git a/source/images/social/delicious.png b/source/images/social/delicious.png
new file mode 100644
index 0000000..bb471cf
Binary files /dev/null and b/source/images/social/delicious.png differ
diff --git a/source/images/social/facebook.png b/source/images/social/facebook.png
new file mode 100644
index 0000000..6ef1dc6
Binary files /dev/null and b/source/images/social/facebook.png differ
diff --git a/source/images/social/github.png b/source/images/social/github.png
new file mode 100644
index 0000000..1703336
Binary files /dev/null and b/source/images/social/github.png differ
diff --git a/source/images/social/google.png b/source/images/social/google.png
new file mode 100644
index 0000000..f820089
Binary files /dev/null and b/source/images/social/google.png differ
diff --git a/source/images/social/instagram.png b/source/images/social/instagram.png
new file mode 100644
index 0000000..3c2379c
Binary files /dev/null and b/source/images/social/instagram.png differ
diff --git a/source/images/social/linkedin.png b/source/images/social/linkedin.png
new file mode 100644
index 0000000..85645cd
Binary files /dev/null and b/source/images/social/linkedin.png differ
diff --git a/source/images/social/pinboard.png b/source/images/social/pinboard.png
new file mode 100644
index 0000000..aa872e0
Binary files /dev/null and b/source/images/social/pinboard.png differ
diff --git a/source/images/social/pinterest.png b/source/images/social/pinterest.png
new file mode 100644
index 0000000..0207f84
Binary files /dev/null and b/source/images/social/pinterest.png differ
diff --git a/source/images/social/rss.png b/source/images/social/rss.png
new file mode 100644
index 0000000..01e1b3e
Binary files /dev/null and b/source/images/social/rss.png differ
diff --git a/source/images/social/twitter.png b/source/images/social/twitter.png
new file mode 100644
index 0000000..efe09a0
Binary files /dev/null and b/source/images/social/twitter.png differ
diff --git a/source/images/table-1.png b/source/images/table-1.png
new file mode 100644
index 0000000..716d2c7
Binary files /dev/null and b/source/images/table-1.png differ
diff --git a/source/images/table2.png b/source/images/table2.png
new file mode 100644
index 0000000..a0d5f37
Binary files /dev/null and b/source/images/table2.png differ
diff --git a/source/index.html b/source/index.html
new file mode 100644
index 0000000..64b665e
--- /dev/null
+++ b/source/index.html
@@ -0,0 +1,29 @@
+---
+layout: default
+---
+
+
+ {% assign index = true %}
+ {% for post in paginator.posts %}
+ {% assign content = post.content %}
+
+ {% include article.html %}
+
+ {% endfor %}
+
+
+
diff --git a/source/javascripts/github.js b/source/javascripts/github.js
new file mode 100644
index 0000000..fc2bb12
--- /dev/null
+++ b/source/javascripts/github.js
@@ -0,0 +1,32 @@
+var github = (function(){
+ function escapeHtml(str) {
+ return $('
').text(str).html();
+ }
+ function render(target, repos){
+ var i = 0, fragment = '', t = $(target)[0];
+
+ for(i = 0; i < repos.length; i++) {
+ fragment += ''+repos[i].name+' '+escapeHtml(repos[i].description||'')+'
';
+ }
+ t.innerHTML = fragment;
+ }
+ return {
+ showRepos: function(options){
+ $.ajax({
+ url: "https://api.github.com/users/"+options.user+"/repos?sort=pushed&callback=?"
+ , dataType: 'jsonp'
+ , error: function (err) { $(options.target + ' li.loading').addClass('error').text("Error loading feed"); }
+ , success: function(data) {
+ var repos = [];
+ if (!data || !data.data) { return; }
+ for (var i = 0; i < data.data.length; i++) {
+ if (options.skip_forks && data.data[i].fork) { continue; }
+ repos.push(data.data[i]);
+ }
+ if (options.count) { repos.splice(options.count); }
+ render(options.target, repos);
+ }
+ });
+ }
+ };
+})();
diff --git a/source/javascripts/jquery.fancybox.pack.js b/source/javascripts/jquery.fancybox.pack.js
new file mode 100644
index 0000000..6521c21
--- /dev/null
+++ b/source/javascripts/jquery.fancybox.pack.js
@@ -0,0 +1,35 @@
+/*! fancyBox v2.0.6 fancyapps.com | fancyapps.com/fancybox/#license */
+(function(s,l,d,t){var m=d(s),q=d(l),a=d.fancybox=function(){a.open.apply(this,arguments)},u=!1,k=l.createTouch!==t,o=function(a){return"string"===d.type(a)},n=function(b,c){c&&o(b)&&0 ',image:'
',iframe:'
",swf:'
',error:'
The requested content cannot be loaded. Please try again later.
',
+closeBtn:'
',next:'
',prev:'
'},openEffect:"fade",openSpeed:300,openEasing:"swing",openOpacity:!0,openMethod:"zoomIn",closeEffect:"fade",closeSpeed:300,closeEasing:"swing",closeOpacity:!0,closeMethod:"zoomOut",nextEffect:"elastic",nextSpeed:300,nextEasing:"swing",nextMethod:"changeIn",prevEffect:"elastic",
+prevSpeed:300,prevEasing:"swing",prevMethod:"changeOut",helpers:{overlay:{speedIn:0,speedOut:300,opacity:0.8,css:{cursor:"pointer"},closeClick:!0},title:{type:"float"}}},group:{},opts:{},coming:null,current:null,isOpen:!1,isOpened:!1,player:{timer:null,isActive:!1},ajaxLoad:null,imgPreload:null,transitions:{},helpers:{},open:function(b,c){a.close(!0);b&&!d.isArray(b)&&(b=b instanceof d?d(b).get():[b]);a.isActive=!0;a.opts=d.extend(!0,{},a.defaults,c);d.isPlainObject(c)&&c.keys!==t&&(a.opts.keys=c.keys?
+d.extend({},a.defaults.keys,c.keys):!1);a.group=b;a._start(a.opts.index||0)},cancel:function(){a.coming&&!1===a.trigger("onCancel")||(a.coming=null,a.hideLoading(),a.ajaxLoad&&a.ajaxLoad.abort(),a.ajaxLoad=null,a.imgPreload&&(a.imgPreload.onload=a.imgPreload.onabort=a.imgPreload.onerror=null))},close:function(b){a.cancel();a.current&&!1!==a.trigger("beforeClose")&&(a.unbindEvents(),!a.isOpen||b&&!0===b[0]?(d(".fancybox-wrap").stop().trigger("onReset").remove(),a._afterZoomOut()):(a.isOpen=a.isOpened=
+!1,d(".fancybox-item, .fancybox-nav").remove(),a.wrap.stop(!0).removeClass("fancybox-opened"),a.inner.css("overflow","hidden"),a.transitions[a.current.closeMethod]()))},play:function(b){var c=function(){clearTimeout(a.player.timer)},e=function(){c();a.current&&a.player.isActive&&(a.player.timer=setTimeout(a.next,a.current.playSpeed))},f=function(){c();d("body").unbind(".player");a.player.isActive=!1;a.trigger("onPlayEnd")};if(a.player.isActive||b&&!1===b[0])f();else if(a.current&&(a.current.loop||
+a.current.index
=a.group.length?b=0:0>b&&(b=a.group.length-1)),a.group[b]!==t&&(a.cancel(),a._start(b)))},reposition:function(b,
+c){var e;a.isOpen&&(e=a._getPosition(c),b&&"scroll"===b.type?(delete e.position,a.wrap.stop(!0,!0).animate(e,200)):a.wrap.css(e))},update:function(b){a.isOpen&&(u||setTimeout(function(){var c=a.current,e=!b||b&&"orientationchange"===b.type;if(u&&(u=!1,c)){if(!b||"scroll"!==b.type||e)c.autoSize&&"iframe"!==c.type&&(a.inner.height("auto"),c.height=a.inner.height()),(c.autoResize||e)&&a._setDimension(),c.canGrow&&"iframe"!==c.type&&a.inner.height("auto");(c.autoCenter||e)&&a.reposition(b);a.trigger("onUpdate")}},
+200),u=!0)},toggle:function(){a.isOpen&&(a.current.fitToView=!a.current.fitToView,a.update())},hideLoading:function(){q.unbind("keypress.fb");d("#fancybox-loading").remove()},showLoading:function(){a.hideLoading();q.bind("keypress.fb",function(b){27===b.keyCode&&(b.preventDefault(),a.cancel())});d('').click(a.cancel).appendTo("body")},getViewport:function(){return{x:m.scrollLeft(),y:m.scrollTop(),w:k&&s.innerWidth?s.innerWidth:m.width(),h:k&&s.innerHeight?
+s.innerHeight:m.height()}},unbindEvents:function(){a.wrap&&a.wrap.unbind(".fb");q.unbind(".fb");m.unbind(".fb")},bindEvents:function(){var b=a.current,c=b.keys;b&&(m.bind("resize.fb orientationchange.fb"+(b.autoCenter&&!b.fixed?" scroll.fb":""),a.update),c&&q.bind("keydown.fb",function(b){var f;f=b.target||b.srcElement;if(!b.ctrlKey&&!b.altKey&&!b.shiftKey&&!b.metaKey&&(!f||!f.type&&!d(f).is("[contenteditable]")))f=b.keyCode,-1b.length))for(i=1;i<=h;i+=1)if(f=b[(c.index+i)%e],g=f.href||d(f).attr("href")||f,"image"===f.type||a.isImage(g))(new Image).src=g},_afterLoad:function(){a.hideLoading();
+!a.coming||!1===a.trigger("afterLoad",a.current)?a.coming=!1:(a.isOpened?(d(".fancybox-item, .fancybox-nav").remove(),a.wrap.stop(!0).removeClass("fancybox-opened"),a.inner.css("overflow","hidden"),a.transitions[a.current.prevMethod]()):(d(".fancybox-wrap").stop().trigger("onReset").remove(),a.trigger("afterClose")),a.unbindEvents(),a.isOpen=!1,a.current=a.coming,a.wrap=d(a.current.tpl.wrap).addClass("fancybox-"+(k?"mobile":"desktop")+" fancybox-type-"+a.current.type+" fancybox-tmp "+a.current.wrapCSS).appendTo("body"),
+a.skin=d(".fancybox-skin",a.wrap).css("padding",n(a.current.padding)),a.outer=d(".fancybox-outer",a.wrap),a.inner=d(".fancybox-inner",a.wrap),a._setContent())},_setContent:function(){var b=a.current,c=b.content,e=b.type,f=b.minWidth,g=b.minHeight,i=b.maxWidth,h=b.maxHeight;switch(e){case "inline":case "ajax":case "html":b.selector?c=d("").html(c).find(b.selector):c instanceof d&&(c.parent().hasClass("fancybox-inner")&&c.parents(".fancybox-wrap").unbind("onReset"),c=c.show().detach(),d(a.wrap).bind("onReset",
+function(){c.appendTo("body").hide()}));b.autoSize&&(f=d('
').appendTo("body").css({minWidth:n(f,"w"),minHeight:n(g,"h"),maxWidth:n(i,"w"),maxHeight:n(h,"h")}).append(c),b.width=f.width(),b.height=f.height(),f.width(a.current.width),f.height()>b.height&&(f.width(b.width+1),b.width=f.width(),b.height=f.height()),c=f.contents().detach(),f.remove());break;case "image":c=b.tpl.image.replace("{href}",b.href);b.aspectRatio=!0;break;case "swf":c=
+b.tpl.swf.replace(/\{width\}/g,b.width).replace(/\{height\}/g,b.height).replace(/\{href\}/g,b.href);break;case "iframe":c=d(b.tpl.iframe.replace("{rnd}",(new Date).getTime())).attr("scrolling",b.scrolling).attr("src",b.href),b.scrolling=k?"scroll":"auto"}if("image"===e||"swf"===e)b.autoSize=!1,b.scrolling="visible";"iframe"===e&&b.autoSize?(a.showLoading(),a._setDimension(),a.inner.css("overflow",b.scrolling),c.bind({onCancel:function(){d(this).unbind();a._afterZoomOut()},load:function(){a.hideLoading();
+try{this.contentWindow.document.location&&(a.current.height=d(this).contents().find("body").height())}catch(b){a.current.autoSize=!1}a[a.isOpen?"_afterZoomIn":"_beforeShow"]()}}).appendTo(a.inner)):(a.inner.append(c),a._beforeShow())},_beforeShow:function(){a.coming=null;a.trigger("beforeShow");a._setDimension();a.wrap.hide().removeClass("fancybox-tmp");a.bindEvents();a._preloadImages();a.transitions[a.isOpened?a.current.nextMethod:a.current.openMethod]()},_setDimension:function(){var b=a.wrap,c=
+a.inner,e=a.current,f=a.getViewport(),g=e.margin,i=2*e.padding,h=e.width,j=e.height,r=e.maxWidth+i,k=e.maxHeight+i,l=e.minWidth+i,m=e.minHeight+i,p;f.w-=g[1]+g[3];f.h-=g[0]+g[2];o(h)&&0
r&&(h=r,j=(h-i)/g+i),j>k&&(j=k,h=(j-i)*g+i),hr||p>k)for(;(h>r||p>k)&&h>l&&p>m;)j-=10,e.aspectRatio?(h=Math.round((j-i)*g+i),hm&&jf.w||p>f.h)&&h>l&&j>m)e.canShrink=!0;a.innerSpace=p-i-
+c.height()},_getPosition:function(b){var c=a.current,e=a.getViewport(),f=c.margin,d=a.wrap.width()+f[1]+f[3],i=a.wrap.height()+f[0]+f[2],h={position:"absolute",top:f[0]+e.y,left:f[3]+e.x};c.autoCenter&&c.fixed&&!b&&i<=e.h&&d<=e.w&&(h={position:"fixed",top:f[0],left:f[3]});h.top=n(Math.max(h.top,h.top+(e.h-i)*c.topRatio));h.left=n(Math.max(h.left,h.left+0.5*(e.w-d)));return h},_afterZoomIn:function(){var b=a.current,c=b?b.scrolling:"no";if(b&&(a.isOpen=a.isOpened=!0,a.wrap.addClass("fancybox-opened"),
+a.inner.css("overflow","yes"===c?"scroll":"no"===c?"hidden":c),a.trigger("afterShow"),a.update(),(b.closeClick||b.nextClick)&&a.inner.css("cursor","pointer").bind("click.fb",function(c){if(!d(c.target).is("a")&&!d(c.target).parent().is("a"))a[b.closeClick?"close":"next"]()}),b.closeBtn&&d(b.tpl.closeBtn).appendTo(a.skin).bind("click.fb",a.close),b.arrows&&1c.end&&(g=1-g),d-=a.innerSpace*g),a.inner[e](d)},zoomIn:function(){var b=a.wrap,c=a.current,e=c.openEffect,f="elastic"===e,g=d.extend({},c.dim,
+a._getPosition(f)),i=d.extend({opacity:1},g);delete i.position;f?(g=this.getOrigPosition(),c.openOpacity&&(g.opacity=0),a.outer.add(a.inner).width("auto").height("auto")):"fade"===e&&(g.opacity=0);b.css(g).show().animate(i,{duration:"none"===e?0:c.openSpeed,easing:c.openEasing,step:f?this.step:null,complete:a._afterZoomIn})},zoomOut:function(){var b=a.wrap,c=a.current,d=c.openEffect,f="elastic"===d,g={opacity:0};f&&("fixed"===b.css("position")&&b.css(a._getPosition(!0)),g=this.getOrigPosition(),c.closeOpacity&&
+(g.opacity=0));b.animate(g,{duration:"none"===d?0:c.closeSpeed,easing:c.closeEasing,step:f?this.step:null,complete:a._afterZoomOut})},changeIn:function(){var b=a.wrap,c=a.current,d=c.nextEffect,f="elastic"===d,g=a._getPosition(f),i={opacity:1};g.opacity=0;f&&(g.top=n(parseInt(g.top,10)-200),i.top="+=200px");b.css(g).show().animate(i,{duration:"none"===d?0:c.nextSpeed,easing:c.nextEasing,complete:a._afterZoomIn})},changeOut:function(){var b=a.wrap,c=a.current,e=c.prevEffect,f={opacity:0};b.removeClass("fancybox-opened");
+"elastic"===e&&(f.top="+=200px");b.animate(f,{duration:"none"===e?0:c.prevSpeed,easing:c.prevEasing,complete:function(){d(this).trigger("onReset").remove()}})}};a.helpers.overlay={overlay:null,update:function(){var a,c;this.overlay.width("100%").height("100%");d.browser.msie||k?(a=Math.max(l.documentElement.scrollWidth,l.body.scrollWidth),c=Math.max(l.documentElement.offsetWidth,l.body.offsetWidth),a=a ').css(b.css).appendTo("body"),b.closeClick&&this.overlay.bind("click.fb",a.close),a.current.fixed&&!k?this.overlay.addClass("overlay-fixed"):(this.update(),this.onUpdate=function(){this.update()}),this.overlay.fadeTo(b.speedIn,b.opacity))},afterClose:function(a){this.overlay&&this.overlay.fadeOut(a.speedOut||0,function(){d(this).remove()});this.overlay=null}};a.helpers.title={beforeShow:function(b){var c;
+if(c=a.current.title)c=d(''+c+"
").appendTo("body"),"float"===b.type&&(c.width(c.width()),c.wrapInner(' '),a.current.margin[2]+=Math.abs(parseInt(c.css("margin-bottom"),10))),c.appendTo("over"===b.type?a.inner:"outside"===b.type?a.wrap:a.skin)}};d.fn.fancybox=function(b){var c=d(this),e=this.selector||"",f,g=function(g){var h=this,j=f,k;!g.ctrlKey&&!g.altKey&&!g.shiftKey&&!g.metaKey&&!d(h).is(".fancybox-wrap")&&
+(g.preventDefault(),g=b.groupAttr||"data-fancybox-group",k=d(h).attr(g),k||(g="rel",k=h[g]),k&&""!==k&&"nofollow"!==k&&(h=e.length?d(e):c,h=h.filter("["+g+'="'+k+'"]'),j=h.index(this)),b.index=j,a.open(h,b))},b=b||{};f=b.index||0;e?q.undelegate(e,"click.fb-start").delegate(e,"click.fb-start",g):c.unbind("click.fb-start").bind("click.fb-start",g);return this};d(l).ready(function(){a.defaults.fixed=d.support.fixedPosition||!(d.browser.msie&&6>=d.browser.version)&&!k})})(window,document,jQuery);
\ No newline at end of file
diff --git a/source/javascripts/libs/jXHR.js b/source/javascripts/libs/jXHR.js
new file mode 100644
index 0000000..6775655
--- /dev/null
+++ b/source/javascripts/libs/jXHR.js
@@ -0,0 +1,85 @@
+// jXHR.js (JSON-P XHR)
+// v0.1 (c) Kyle Simpson
+// MIT License
+
+(function(global){
+ var SETTIMEOUT = global.setTimeout, // for better compression
+ doc = global.document,
+ callback_counter = 0;
+
+ global.jXHR = function() {
+ var script_url,
+ script_loaded,
+ jsonp_callback,
+ scriptElem,
+ publicAPI = null;
+
+ function removeScript() { try { scriptElem.parentNode.removeChild(scriptElem); } catch (err) { } }
+
+ function reset() {
+ script_loaded = false;
+ script_url = "";
+ removeScript();
+ scriptElem = null;
+ fireReadyStateChange(0);
+ }
+
+ function ThrowError(msg) {
+ try { publicAPI.onerror.call(publicAPI,msg,script_url); } catch (err) { throw new Error(msg); }
+ }
+
+ function handleScriptLoad() {
+ if ((this.readyState && this.readyState!=="complete" && this.readyState!=="loaded") || script_loaded) { return; }
+ this.onload = this.onreadystatechange = null; // prevent memory leak
+ script_loaded = true;
+ if (publicAPI.readyState !== 4) ThrowError("Script failed to load ["+script_url+"].");
+ removeScript();
+ }
+
+ function fireReadyStateChange(rs,args) {
+ args = args || [];
+ publicAPI.readyState = rs;
+ if (typeof publicAPI.onreadystatechange === "function") publicAPI.onreadystatechange.apply(publicAPI,args);
+ }
+
+ publicAPI = {
+ onerror:null,
+ onreadystatechange:null,
+ readyState:0,
+ open:function(method,url){
+ reset();
+ internal_callback = "cb"+(callback_counter++);
+ (function(icb){
+ global.jXHR[icb] = function() {
+ try { fireReadyStateChange.call(publicAPI,4,arguments); }
+ catch(err) {
+ publicAPI.readyState = -1;
+ ThrowError("Script failed to run ["+script_url+"].");
+ }
+ global.jXHR[icb] = null;
+ };
+ })(internal_callback);
+ script_url = url.replace(/=\?/,"=jXHR."+internal_callback);
+ fireReadyStateChange(1);
+ },
+ send:function(){
+ SETTIMEOUT(function(){
+ scriptElem = doc.createElement("script");
+ scriptElem.setAttribute("type","text/javascript");
+ scriptElem.onload = scriptElem.onreadystatechange = function(){handleScriptLoad.call(scriptElem);};
+ scriptElem.setAttribute("src",script_url);
+ doc.getElementsByTagName("head")[0].appendChild(scriptElem);
+ },0);
+ fireReadyStateChange(2);
+ },
+ setRequestHeader:function(){}, // noop
+ getResponseHeader:function(){return "";}, // basically noop
+ getAllResponseHeaders:function(){return [];} // ditto
+ };
+
+ reset();
+
+ return publicAPI;
+ };
+})(window);
+
diff --git a/source/javascripts/libs/jquery.min.js b/source/javascripts/libs/jquery.min.js
new file mode 100644
index 0000000..32d50cb
--- /dev/null
+++ b/source/javascripts/libs/jquery.min.js
@@ -0,0 +1,5 @@
+/*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license
+//@ sourceMappingURL=jquery.min.map
+*/(function(e,t){var n,r,i=typeof t,o=e.document,a=e.location,s=e.jQuery,u=e.$,l={},c=[],p="1.9.1",f=c.concat,d=c.push,h=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,b=function(e,t){return new b.fn.init(e,t,r)},x=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s},b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventListener)o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML=" a ",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;
+return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML=" ";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="
",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="
",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML=" ",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML=" ",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML=" ",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&>(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++)b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""," "],legend:[1,""," "],area:[1,""," "],param:[1,""," "],thead:[1,""],tr:[2,""],col:[2,""],td:[3,""],_default:b.support.htmlSerialize?[0,"",""]:[1,"X","
"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l)
+}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write(""),t.close(),n=ln(e,t),Pt.detach()),Gt[e]=n),n}function ln(e,t){var n=b(t.createElement(e)).appendTo(t.body),r=b.css(n[0],"display");return n.remove(),r}b.each(["height","width"],function(e,n){b.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(b.css(e,"display"))?b.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,i),i):0)}}}),b.support.opacity||(b.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=b.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===b.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),b(function(){b.support.reliableMarginRight||(b.cssHooks.marginRight={get:function(e,n){return n?b.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!b.support.pixelPosition&&b.fn.position&&b.each(["top","left"],function(e,n){b.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?b(e).position()[n]+"px":r):t}}})}),b.expr&&b.expr.filters&&(b.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!b.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||b.css(e,"display"))},b.expr.filters.visible=function(e){return!b.expr.filters.hidden(e)}),b.each({margin:"",padding:"",border:"Width"},function(e,t){b.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(b.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Nt.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:b.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),b.param=function(e,n){var r,i=[],o=function(e,t){t=b.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=b.ajaxSettings&&b.ajaxSettings.traditional),b.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(b.isArray(t))b.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==b.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}b.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){b.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),b.fn.hover=function(e,t){return this.mouseenter(e).mouseleave(t||e)};var mn,yn,vn=b.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Nn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Cn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=b.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=a.href}catch(Ln){yn=o.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(b.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(u){var l;return o[u]=!0,b.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||a||o[c]?a?!(l=c):t:(n.dataTypes.unshift(c),s(c),!1)}),l}return s(n.dataTypes[0])||!o["*"]&&s("*")}function Mn(e,n){var r,i,o=b.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&b.extend(!0,e,r),e}b.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),b.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&b.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?b("").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:function(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.done,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("If-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader("Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="error",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"!==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.noop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat(Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.timer(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p()}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.isFunction(e)&&e,duration:e,easing:n&&t||t&&!b.isFunction(t)&&t};return r.duration=b.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in b.fx.speeds?b.fx.speeds[r.duration]:b.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){b.isFunction(r.old)&&r.old.call(this),r.queue&&b.dequeue(this,r.queue)},r},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},b.timers=[],b.fx=rr.prototype.init,b.fx.tick=function(){var e,n=b.timers,r=0;for(Xn=b.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||b.fx.stop(),Xn=t},b.fx.timer=function(e){e()&&b.timers.push(e)&&b.fx.start()},b.fx.interval=13,b.fx.start=function(){Un||(Un=setInterval(b.fx.tick,b.fx.interval))},b.fx.stop=function(){clearInterval(Un),Un=null},b.fx.speeds={slow:600,fast:200,_default:400},b.fx.step={},b.expr&&b.expr.filters&&(b.expr.filters.animated=function(e){return b.grep(b.timers,function(t){return e===t.elem}).length}),b.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){b.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,b.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},b.offset={setOffset:function(e,t,n){var r=b.css(e,"position");"static"===r&&(e.style.position="relative");var i=b(e),o=i.offset(),a=b.css(e,"top"),s=b.css(e,"left"),u=("absolute"===r||"fixed"===r)&&b.inArray("auto",[a,s])>-1,l={},c={},p,f;u?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),b.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(l.top=t.top-o.top+p),null!=t.left&&(l.left=t.left-o.left+f),"using"in t?t.using.call(e,l):i.css(l)}},b.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===b.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),b.nodeName(e[0],"html")||(n=e.offset()),n.top+=b.css(e[0],"borderTopWidth",!0),n.left+=b.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-b.css(r,"marginTop",!0),left:t.left-n.left-b.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||o.documentElement;while(e&&!b.nodeName(e,"html")&&"static"===b.css(e,"position"))e=e.offsetParent;return e||o.documentElement})}}),b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);b.fn[e]=function(i){return b.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?b(a).scrollLeft():o,r?o:b(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return b.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}b.each({Height:"height",Width:"width"},function(e,n){b.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){b.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=b,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return b})})(window);
diff --git a/source/javascripts/libs/swfobject-dynamic.js b/source/javascripts/libs/swfobject-dynamic.js
new file mode 100644
index 0000000..b021614
--- /dev/null
+++ b/source/javascripts/libs/swfobject-dynamic.js
@@ -0,0 +1,298 @@
+/*! SWFObject v2.2
+ is released under the MIT License
+*/
+
+var swfobject = function() {
+
+ var UNDEF = "undefined",
+ OBJECT = "object",
+ SHOCKWAVE_FLASH = "Shockwave Flash",
+ SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
+ FLASH_MIME_TYPE = "application/x-shockwave-flash",
+ EXPRESS_INSTALL_ID = "SWFObjectExprInst",
+
+ win = window,
+ doc = document,
+ nav = navigator,
+
+ plugin = false,
+ regObjArr = [],
+ objIdArr = [],
+ storedAltContent,
+ storedAltContentId,
+ storedCallbackFn,
+ storedCallbackObj,
+ autoHideShow = true,
+
+ /* Centralized function for browser feature detection
+ - User agent string detection is only used when no good alternative is possible
+ - Is executed directly for optimal performance
+ */
+ ua = function() {
+ var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
+ u = nav.userAgent.toLowerCase(),
+ p = nav.platform.toLowerCase(),
+ windows = p ? /win/.test(p) : /win/.test(u),
+ mac = p ? /mac/.test(p) : /mac/.test(u),
+ webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit
+ ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
+ playerVersion = [0,0,0],
+ d = null;
+ if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
+ d = nav.plugins[SHOCKWAVE_FLASH].description;
+ if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+
+ plugin = true;
+ ie = false; // cascaded feature detection for Internet Explorer
+ d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
+ playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
+ playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
+ playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
+ }
+ }
+ else if (typeof win.ActiveXObject != UNDEF) {
+ try {
+ var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
+ if (a) { // a will return null when ActiveX is disabled
+ d = a.GetVariable("$version");
+ if (d) {
+ ie = true; // cascaded feature detection for Internet Explorer
+ d = d.split(" ")[1].split(",");
+ playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
+ }
+ }
+ }
+ catch(e) {}
+ }
+ return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
+ }()
+
+
+ /* Main function
+ - Will preferably execute onDomLoad, otherwise onload (as a fallback)
+ */
+ function main() {
+ if (plugin) { testPlayerVersion(); }
+ else { matchVersions(); }
+ }
+
+ /* Detect the Flash Player version for non-Internet Explorer browsers
+ - Detecting the plug-in version via the object element is more precise than using the plugins collection item's description:
+ a. Both release and build numbers can be detected
+ b. Avoid wrong descriptions by corrupt installers provided by Adobe
+ c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports
+ - Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available
+ */
+ function testPlayerVersion() {
+ var b = doc.getElementsByTagName("body")[0];
+ var o = createElement(OBJECT);
+ o.setAttribute("type", FLASH_MIME_TYPE);
+ var t = b.appendChild(o);
+ if (t) {
+ var counter = 0;
+ (function(){
+ if (typeof t.GetVariable != UNDEF) {
+ var d = t.GetVariable("$version");
+ if (d) {
+ d = d.split(" ")[1].split(",");
+ ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
+ }
+ }
+ else if (counter < 10) {
+ counter++;
+ setTimeout(arguments.callee, 10);
+ return;
+ }
+ b.removeChild(o);
+ t = null;
+ matchVersions();
+ })();
+ }
+ else {
+ matchVersions();
+ }
+ }
+
+
+ /* Cross-browser dynamic SWF creation
+ */
+ function createSWF(attObj, parObj, id) {
+ var r, el = getElementById(id);
+ if (ua.wk && ua.wk < 312) { return r; }
+ if (el) {
+ if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content
+ attObj.id = id;
+ }
+ if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML
+ var att = "";
+ for (var i in attObj) {
+ if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries
+ if (i.toLowerCase() == "data") {
+ parObj.movie = attObj[i];
+ }
+ else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
+ att += ' class="' + attObj[i] + '"';
+ }
+ else if (i.toLowerCase() != "classid") {
+ att += ' ' + i + '="' + attObj[i] + '"';
+ }
+ }
+ }
+ var par = "";
+ for (var j in parObj) {
+ if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries
+ par += ' ';
+ }
+ }
+ el.outerHTML = '' + par + ' ';
+ objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only)
+ r = getElementById(attObj.id);
+ }
+ else { // well-behaving browsers
+ var o = createElement(OBJECT);
+ o.setAttribute("type", FLASH_MIME_TYPE);
+ for (var m in attObj) {
+ if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries
+ if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
+ o.setAttribute("class", attObj[m]);
+ }
+ else if (m.toLowerCase() != "classid") { // filter out IE specific attribute
+ o.setAttribute(m, attObj[m]);
+ }
+ }
+ }
+ for (var n in parObj) {
+ if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element
+ createObjParam(o, n, parObj[n]);
+ }
+ }
+ el.parentNode.replaceChild(o, el);
+ r = o;
+ }
+ }
+ return r;
+ }
+
+ function createObjParam(el, pName, pValue) {
+ var p = createElement("param");
+ p.setAttribute("name", pName);
+ p.setAttribute("value", pValue);
+ el.appendChild(p);
+ }
+
+ /* Cross-browser SWF removal
+ - Especially needed to safely and completely remove a SWF in Internet Explorer
+ */
+ /* Functions to optimize JavaScript compression
+ */
+ function getElementById(id) {
+ var el = null;
+ try {
+ el = doc.getElementById(id);
+ }
+ catch (e) {}
+ return el;
+ }
+
+ function createElement(el) {
+ return doc.createElement(el);
+ }
+
+ /* Flash Player and SWF content version matching
+ */
+ function hasPlayerVersion(rv) {
+ var pv = ua.pv, v = rv.split(".");
+ v[0] = parseInt(v[0], 10);
+ v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0"
+ v[2] = parseInt(v[2], 10) || 0;
+ return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
+ }
+
+
+ /* Filter to avoid XSS attacks
+ */
+ function urlEncodeIfNecessary(s) {
+ var regex = /[\\\"<>\.;]/;
+ var hasBadChars = regex.exec(s) != null;
+ return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
+ }
+
+ return {
+ /* Public API
+ - Reference: http://code.google.com/p/swfobject/wiki/documentation
+ */
+
+ embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, flashvarsObj, parObj, attObj, callbackFn) {
+ var callbackObj = {success:false, id:replaceElemIdStr};
+ if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
+ widthStr += ""; // auto-convert to string
+ heightStr += "";
+ var att = {};
+ if (attObj && typeof attObj === OBJECT) {
+ for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs
+ att[i] = attObj[i];
+ }
+ }
+ att.data = swfUrlStr;
+ att.width = widthStr;
+ att.height = heightStr;
+ var par = {};
+ if (parObj && typeof parObj === OBJECT) {
+ for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs
+ par[j] = parObj[j];
+ }
+ }
+ if (flashvarsObj && typeof flashvarsObj === OBJECT) {
+ for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs
+ if (typeof par.flashvars != UNDEF) {
+ par.flashvars += "&" + k + "=" + flashvarsObj[k];
+ }
+ else {
+ par.flashvars = k + "=" + flashvarsObj[k];
+ }
+ }
+ }
+ if (hasPlayerVersion(swfVersionStr)) { // create SWF
+ var obj = createSWF(att, par, replaceElemIdStr);
+ callbackObj.success = true;
+ callbackObj.ref = obj;
+ }
+ if (callbackFn) { callbackFn(callbackObj); }
+ }
+ else if (callbackFn) { callbackFn(callbackObj); }
+ },
+
+ ua: ua,
+
+ getFlashPlayerVersion: function() {
+ return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
+ },
+
+ hasFlashPlayerVersion: hasPlayerVersion,
+
+ createSWF: function(attObj, parObj, replaceElemIdStr) {
+ if (ua.w3) {
+ return createSWF(attObj, parObj, replaceElemIdStr);
+ }
+ else {
+ return undefined;
+ }
+ },
+
+ getQueryParamValue: function(param) {
+ var q = doc.location.search || doc.location.hash;
+ if (q) {
+ if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark
+ if (param == null) {
+ return urlEncodeIfNecessary(q);
+ }
+ var pairs = q.split("&");
+ for (var i = 0; i < pairs.length; i++) {
+ if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
+ return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
+ }
+ }
+ }
+ return "";
+ }
+ };
+}();
diff --git a/source/javascripts/modernizr-2.0.js b/source/javascripts/modernizr-2.0.js
new file mode 100644
index 0000000..9dca7b0
--- /dev/null
+++ b/source/javascripts/modernizr-2.0.js
@@ -0,0 +1,5 @@
+/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
+ * Build: http://modernizr.com/download/#-video-mq-cssclasses-teststyles-testprop-testallprops-prefixes-domprefixes-load
+ */
+;window.Modernizr=function(a,b,c){function A(a){j.cssText=a}function B(a,b){return A(m.join(a+";")+(b||""))}function C(a,b){return typeof a===b}function D(a,b){return!!~(""+a).indexOf(b)}function E(a,b){for(var d in a){var e=a[d];if(!D(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function F(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:C(f,"function")?f.bind(d||b):f}return!1}function G(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+o.join(d+" ")+d).split(" ");return C(b,"string")||C(b,"undefined")?E(e,b):(e=(a+" "+p.join(d+" ")+d).split(" "),F(e,b,c))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m=" -webkit- -moz- -o- -ms- ".split(" "),n="Webkit Moz O ms",o=n.split(" "),p=n.toLowerCase().split(" "),q={},r={},s={},t=[],u=t.slice,v,w=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["",'"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},x=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return w("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},y={}.hasOwnProperty,z;!C(y,"undefined")&&!C(y.call,"undefined")?z=function(a,b){return y.call(a,b)}:z=function(a,b){return b in a&&C(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=u.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(u.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(u.call(arguments)))};return e}),q.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c};for(var H in q)z(q,H)&&(v=H.toLowerCase(),e[v]=q[H](),t.push((e[v]?"":"no-")+v));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)z(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},A(""),i=k=null,e._version=d,e._prefixes=m,e._domPrefixes=p,e._cssomPrefixes=o,e.mq=x,e.testProp=function(a){return E([a])},e.testAllProps=G,e.testStyles=w,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+t.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f')
+ var mobileNav = $('fieldset.mobile-nav').append('');
+ mobileNav.find('select').append('Navigate… ');
+ var addOption = function(i, option) {
+ mobileNav.find('select').append('» ' + $(this).text() + ' ');
+ }
+ mainNav.find('a').each(addOption);
+ $('ul.subscription a').each(addOption);
+ mobileNav.find('select').bind('change', function(event) {
+ if (event.target.value) { window.location.href = event.target.value; }
+ });
+}
+
+function addSidebarToggler() {
+ if(!$('body').hasClass('sidebar-footer')) {
+ $('#content').append('');
+ $('.toggle-sidebar').bind('click', function(e) {
+ e.preventDefault();
+ $('body').toggleClass('collapse-sidebar');
+ });
+ }
+ var sections = $('aside.sidebar > section');
+ if (sections.length > 1) {
+ sections.each(function(index, section){
+ if ((sections.length >= 3) && index % 3 === 0) {
+ $(section).addClass("first");
+ }
+ var count = ((index +1) % 2) ? "odd" : "even";
+ $(section).addClass(count);
+ });
+ }
+ if (sections.length >= 3){ $('aside.sidebar').addClass('thirds'); }
+}
+
+function testFeatures() {
+ var features = ['maskImage'];
+ $(features).map(function(i, feature) {
+ if (Modernizr.testAllProps(feature)) {
+ $('html').addClass(feature);
+ } else {
+ $('html').addClass('no-'+feature);
+ }
+ });
+ if ("placeholder" in document.createElement("input")) {
+ $('html').addClass('placeholder');
+ } else {
+ $('html').addClass('no-placeholder');
+ }
+}
+
+function addCodeLineNumbers() {
+ if (navigator.appName === 'Microsoft Internet Explorer') { return; }
+ $('div.gist-highlight').each(function(code) {
+ var tableStart = '',
+ lineNumbers = '',
+ tableMiddle = ' ',
+ tableEnd = '
',
+ count = $('.line', code).length;
+ for (var i=1;i<=count; i++) {
+ lineNumbers += ''+i+' \n';
+ }
+ var table = tableStart + lineNumbers + tableMiddle + ''+$('pre', code).html()+' ' + tableEnd;
+ $(code).html(table);
+ });
+}
+
+function flashVideoFallback(){
+ var flashplayerlocation = "/assets/jwplayer/player.swf",
+ flashplayerskin = "/assets/jwplayer/glow/glow.xml";
+ $('video').each(function(i, video){
+ video = $(video);
+ if (!Modernizr.video.h264 && swfobject.getFlashPlayerVersion() || window.location.hash.indexOf("flash-test") !== -1){
+ video.children('source[src$=mp4]').first().map(i, function(source){
+ var src = $(source).attr('src'),
+ id = 'video_'+Math.round(1 + Math.random()*(100000)),
+ width = video.attr('width'),
+ height = parseInt(video.attr('height'), 10) + 30;
+ video.after('');
+ swfobject.embedSWF(flashplayerlocation, id, width, height + 30, "9.0.0",
+ { file : src, image : video.attr('poster'), skin : flashplayerskin } ,
+ { movie : src, wmode : "opaque", allowfullscreen : "true" }
+ );
+ });
+ video.remove();
+ }
+ });
+}
+
+function wrapFlashVideos() {
+ $('object').each(function(i, object) {
+ if( $(object).find('param[name=movie]').length ){
+ $(object).wrap('
')
+ }
+ });
+ $('iframe[src*=vimeo],iframe[src*=youtube]').wrap('
')
+}
+
+$('document').ready(function() {
+ testFeatures();
+ wrapFlashVideos();
+ flashVideoFallback();
+ addCodeLineNumbers();
+ getNav();
+ addSidebarToggler();
+});
+
+// iOS scaling bug fix
+// Rewritten version
+// By @mathias, @cheeaun and @jdalton
+// Source url: https://gist.github.com/901295
+(function(doc) {
+ var addEvent = 'addEventListener',
+ type = 'gesturestart',
+ qsa = 'querySelectorAll',
+ scales = [1, 1],
+ meta = qsa in doc ? doc[qsa]('meta[name=viewport]') : [];
+ function fix() {
+ meta.content = 'width=device-width,minimum-scale=' + scales[0] + ',maximum-scale=' + scales[1];
+ doc.removeEventListener(type, fix, true);
+ }
+ if ((meta = meta[meta.length - 1]) && addEvent in doc) {
+ fix();
+ scales = [0.25, 1.6];
+ doc[addEvent](type, fix, true);
+ }
+}(document));
+
+/*! SWFObject v2.2 modified by Brandon Mathis to contain only what is necessary to dynamically embed flash objects
+ * Uncompressed source in javascripts/libs/swfobject-dynamic.js
+ *
+ released under the MIT License
+*/
+var swfobject=function(){function s(a,b,d){var q,k=n(d);if(g.wk&&g.wk<312)return q;if(k){if(typeof a.id==l)a.id=d;if(g.ie&&g.win){var e="",c;for(c in a)if(a[c]!=Object.prototype[c])c.toLowerCase()=="data"?b.movie=a[c]:c.toLowerCase()=="styleclass"?e+=' class="'+a[c]+'"':c.toLowerCase()!="classid"&&(e+=" "+c+'="'+a[c]+'"');c="";for(var f in b)b[f]!=Object.prototype[f]&&(c+=' ');k.outerHTML='"+c+
+" ";q=n(a.id)}else{f=i.createElement(o);f.setAttribute("type",m);for(var h in a)a[h]!=Object.prototype[h]&&(h.toLowerCase()=="styleclass"?f.setAttribute("class",a[h]):h.toLowerCase()!="classid"&&f.setAttribute(h,a[h]));for(e in b)b[e]!=Object.prototype[e]&&e.toLowerCase()!="movie"&&(a=f,c=e,h=b[e],d=i.createElement("param"),d.setAttribute("name",c),d.setAttribute("value",h),a.appendChild(d));k.parentNode.replaceChild(f,k);q=f}}return q}function n(a){var b=null;try{b=i.getElementById(a)}catch(d){}return b}
+function t(a){var b=g.pv,a=a.split(".");a[0]=parseInt(a[0],10);a[1]=parseInt(a[1],10)||0;a[2]=parseInt(a[2],10)||0;return b[0]>a[0]||b[0]==a[0]&&b[1]>a[1]||b[0]==a[0]&&b[1]==a[1]&&b[2]>=a[2]?!0:!1}function u(a){return/[\\\"<>\.;]/.exec(a)!=null&&typeof encodeURIComponent!=l?encodeURIComponent(a):a}var l="undefined",o="object",m="application/x-shockwave-flash",v=window,i=document,j=navigator,g=function(){var a=typeof i.getElementById!=l&&typeof i.getElementsByTagName!=l&&typeof i.createElement!=l,
+b=j.userAgent.toLowerCase(),d=j.platform.toLowerCase(),g=d?/win/.test(d):/win/.test(b),d=d?/mac/.test(d):/mac/.test(b),b=/webkit/.test(b)?parseFloat(b.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):!1,k=!+"\u000b1",e=[0,0,0],c=null;if(typeof j.plugins!=l&&typeof j.plugins["Shockwave Flash"]==o){if((c=j.plugins["Shockwave Flash"].description)&&!(typeof j.mimeTypes!=l&&j.mimeTypes[m]&&!j.mimeTypes[m].enabledPlugin))k=!1,c=c.replace(/^.*\s+(\S+\s+\S+$)/,"$1"),e[0]=parseInt(c.replace(/^(.*)\..*$/,"$1"),
+10),e[1]=parseInt(c.replace(/^.*\.(.*)\s.*$/,"$1"),10),e[2]=/[a-zA-Z]/.test(c)?parseInt(c.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}else if(typeof v.ActiveXObject!=l)try{var f=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");if(f&&(c=f.GetVariable("$version")))k=!0,c=c.split(" ")[1].split(","),e=[parseInt(c[0],10),parseInt(c[1],10),parseInt(c[2],10)]}catch(h){}return{w3:a,pv:e,wk:b,ie:k,win:g,mac:d}}();return{embedSWF:function(a,b,d,i,k,e,c,f,h){var j={success:!1,id:b};if(g.w3&&!(g.wk&&g.wk<312)&&
+a&&b&&d&&i&&k){d+="";i+="";var p={};if(f&&typeof f===o)for(var m in f)p[m]=f[m];p.data=a;p.width=d;p.height=i;a={};if(c&&typeof c===o)for(var n in c)a[n]=c[n];if(e&&typeof e===o)for(var r in e)typeof a.flashvars!=l?a.flashvars+="&"+r+"="+e[r]:a.flashvars=r+"="+e[r];if(t(k))b=s(p,a,b),j.success=!0,j.ref=b}h&&h(j)},ua:g,getFlashPlayerVersion:function(){return{major:g.pv[0],minor:g.pv[1],release:g.pv[2]}},hasFlashPlayerVersion:t,createSWF:function(a,b,d){if(g.w3)return s(a,b,d)},getQueryParamValue:function(a){var b=
+i.location.search||i.location.hash;if(b){/\?/.test(b)&&(b=b.split("?")[1]);if(a==null)return u(b);for(var b=b.split("&"),d=0;d');
+ (function(){
+ var pinboardLinkroll = document.createElement('script');
+ pinboardLinkroll.type = 'text/javascript';
+ pinboardLinkroll.async = true;
+ pinboardLinkroll.src = url;
+ document.getElementsByTagName('head')[0].appendChild(pinboardLinkroll);
+ })();
+}
+
+function pinboardNS_show_bmarks(r) {
+ var lr = new Pinboard_Linkroll();
+ lr.set_items(r);
+ lr.show_bmarks();
+}
+
+function Pinboard_Linkroll() {
+ var items;
+
+ this.set_items = function(i) {
+ this.items = i;
+ }
+ this.show_bmarks = function() {
+ var lines = [];
+ for (var i = 0; i < this.items.length; i++) {
+ var item = this.items[i];
+ var str = this.format_item(item);
+ lines.push(str);
+ }
+ document.getElementById(linkroll).innerHTML = lines.join("\n");
+ }
+ this.cook = function(v) {
+ return v.replace('<', '<').replace('>', '>>');
+ }
+
+ this.format_item = function(it) {
+ var str = "";
+ if (!it.d) { return; }
+ str += "" + this.cook(it.d) + " ";
+ if (it.n) {
+ str += "" + this.cook(it.n) + " \n";
+ }
+ if (it.t.length > 0) {
+ for (var i = 0; i < it.t.length; i++) {
+ var tag = it.t[i];
+ str += " " + this.cook(tag).replace(/^\s+|\s+$/g, '') + " ";
+ }
+ }
+ str += "
\n";
+ return str;
+ }
+}
+Pinboard_Linkroll.prototype = new Pinboard_Linkroll();
+pinboardNS_fetch_script("https://feeds.pinboard.in/json/v1/u:"+pinboard_user+"/?cb=pinboardNS_show_bmarks\&count="+pinboard_count);
+
diff --git a/source/javascripts/slash.js b/source/javascripts/slash.js
new file mode 100644
index 0000000..5288572
--- /dev/null
+++ b/source/javascripts/slash.js
@@ -0,0 +1,62 @@
+(function($){
+ // Open external links in new window
+ var externalLinks = function(){
+ var host = location.host;
+
+ $('body').on('click', 'a', function(e){
+ var href = this.href,
+ link = href.replace(/https?:\/\/([^\/]+)(.*)/, '$1');
+
+ if (link != '' && link != host && !$(this).hasClass('fancybox')){
+ window.open(href);
+ e.preventDefault();
+ }
+ });
+ };
+
+ // Append caption after pictures
+ var appendCaption = function(){
+ $('.entry-content').each(function(i){
+ var _i = i;
+ $(this).find('img').each(function(){
+ var alt = this.alt;
+
+ if (alt != ''){
+ $(this).after(''+alt+' ');
+ }
+
+ $(this).wrap(' ');
+ });
+ });
+ };
+
+ externalLinks(); // Delete or comment this line to disable opening external links in new window
+ appendCaption(); // Delete or comment this line to disable caption
+
+ var mobilenav = $('#mobile-nav');
+
+ $('html').click(function(){
+ mobilenav.find('.on').each(function(){
+ $(this).removeClass('on').next().hide();
+ });
+ });
+
+ mobilenav.on('click', '.menu .button', function(){
+ if (!$(this).hasClass('on')){
+ var width = $(this).width() + 42;
+ $(this).addClass('on').next().show().css({width: width});
+ } else {
+ $(this).removeClass('on').next().hide();
+ }
+ }).on('click', '.search .button', function(){
+ if (!$(this).hasClass('on')){
+ var width = mobilenav.width() - 51;
+ mobilenav.children('.menu').children().eq(0).removeClass('on').next().hide();
+ $(this).addClass('on').next().show().css({width: width}).children().children().eq(0).focus();
+ } else {
+ $(this).removeClass('on').next().hide().children().children().eq(0).val('');
+ }
+ }).click(function(e){
+ e.stopPropagation();
+ });
+})(jQuery);
\ No newline at end of file
diff --git a/source/javascripts/twitter.js b/source/javascripts/twitter.js
new file mode 100644
index 0000000..3e2dd0d
--- /dev/null
+++ b/source/javascripts/twitter.js
@@ -0,0 +1,78 @@
+// JSON-P Twitter fetcher for Octopress
+// (c) Brandon Mathis // MIT License
+
+/* Sky Slavin, Ludopoli. MIT license. * based on JavaScript Pretty Date * Copyright (c) 2008 John Resig (jquery.com) * Licensed under the MIT license. */
+function prettyDate(time) {
+ if (navigator.appName === 'Microsoft Internet Explorer') {
+ return "∞ "; // because IE date parsing isn't fun.
+ }
+ var say = {
+ just_now: " now",
+ minute_ago: "1m",
+ minutes_ago: "m",
+ hour_ago: "1h",
+ hours_ago: "h",
+ yesterday: "1d",
+ days_ago: "d",
+ last_week: "1w",
+ weeks_ago: "w"
+ };
+
+ var current_date = new Date(),
+ current_date_time = current_date.getTime(),
+ current_date_full = current_date_time + (1 * 60000),
+ date = new Date(time),
+ diff = ((current_date_full - date.getTime()) / 1000),
+ day_diff = Math.floor(diff / 86400);
+
+ if (isNaN(day_diff) || day_diff < 0) { return "∞ "; }
+
+ return day_diff === 0 && (
+ diff < 60 && say.just_now ||
+ diff < 120 && say.minute_ago ||
+ diff < 3600 && Math.floor(diff / 60) + say.minutes_ago ||
+ diff < 7200 && say.hour_ago ||
+ diff < 86400 && Math.floor(diff / 3600) + say.hours_ago) ||
+ day_diff === 1 && say.yesterday ||
+ day_diff < 7 && day_diff + say.days_ago ||
+ day_diff === 7 && say.last_week ||
+ day_diff > 7 && Math.ceil(day_diff / 7) + say.weeks_ago;
+}
+
+function linkifyTweet(text, url) {
+ // Linkify urls, usernames, hashtags
+ text = text.replace(/(https?:\/\/)([\w\-:;?&=+.%#\/]+)/gi, '$2 ')
+ .replace(/(^|\W)@(\w+)/g, '$1@$2 ')
+ .replace(/(^|\W)#(\w+)/g, '$1#$2 ');
+
+ // Use twitter's api to replace t.co shortened urls with expanded ones.
+ for (var u in url) {
+ if(url[u].expanded_url != null){
+ var shortUrl = new RegExp(url[u].url, 'g');
+ text = text.replace(shortUrl, url[u].expanded_url);
+ var shortUrl = new RegExp(">"+(url[u].url.replace(/https?:\/\//, '')), 'g');
+ text = text.replace(shortUrl, ">"+url[u].display_url);
+ }
+ }
+ return text
+}
+
+function showTwitterFeed(tweets, twitter_user) {
+ var timeline = document.getElementById('tweets'),
+ content = '';
+
+ for (var t in tweets) {
+ content += ''+''+''+prettyDate(tweets[t].created_at)+' '+linkifyTweet(tweets[t].text.replace(/\n/g, ' '), tweets[t].entities.urls)+'
'+' ';
+ }
+ timeline.innerHTML = content;
+}
+
+function getTwitterFeed(user, count, replies) {
+ count = parseInt(count, 10);
+ $.ajax({
+ url: "https://api.twitter.com/1/statuses/user_timeline/" + user + ".json?trim_user=true&count=" + (count + 20) + "&include_entities=1&exclude_replies=" + (replies ? "0" : "1") + "&callback=?"
+ , type: 'jsonp'
+ , error: function (err) { $('#tweets li.loading').addClass('error').text("Twitter's busted"); }
+ , success: function(data) { showTwitterFeed(data.slice(0, count), user); }
+ })
+}
diff --git a/source/projects/deep-learn.markdown b/source/projects/deep-learn.markdown
new file mode 100644
index 0000000..6259f09
--- /dev/null
+++ b/source/projects/deep-learn.markdown
@@ -0,0 +1,381 @@
+---
+layout: page
+title: "Deep Learning for Image Classification"
+date: December 15, 2014 22:20:12 -0700
+comments: false
+sharing: true
+footer: true
+---
+
+
+Finding good features is an important yet challenging task in most machine learning applications. For computer vision tasks, deep learning techniques, based on multi-layer neural networks, are effective in extracting good learning representations from image data. Although powerful, deep neural networks are prone to overfitting. In this project, I studied different regularization techniques that mitigate overfitting. Precisely, I present the basic model of feed-forward neural networks. Next, I will present the procedures for fitting the network to the training data. In particular, the backpropagation algorithm, which is used to compute the network weights, is derived for the case of multi-label classification. Next, we will show how different optimization procedures can be built on top of the backpropagation algorithm to minimize the training error. In addition, a prototype neural network library is implemented in the [Julia programming language](http://julialang.org/) and applied to image classification of hand-written digits with the [MNIST datasets](http://yann.lecun.com/exdb/mnist/). Note that classifying hand-written digits can be a difficult task for a machine. As shown below, it can be challenging to distinguish between a digit to another.
+
+{% img ../images/neural/errors.png %}
+
+## Deep Neural Networks
+
+Neural networks are biologically inspired machine learning models that offer lots of flexibility in modeling a target function. It is composed of multiple layers of neurons and was shown to be a universal approximation[1]. It can be used for both regression and classification problems. Although flexible, neural network can easily overfit. Therefore, regularization techniques are needed to train neural networks. The focus of the project is to investigate different regularization techniques.
+
+
+### Feed-forward Neural Network Model
+
+
+Let’s start by describing the architecture of the neural network. As illustrated in the following figure, it consists of \\(L\\) layers of connected neurons or units. The layers are index as \\(l = 1, . . . ,L\\), in which the first \\(L − 1\\) layers are hidden and the last layer \\(l = L\\) is the output layer.
+
+{% img ../images/neural/net.png %}
+
+The input data \\(x = [1, x_1, . . . ,x_p]\\), which has p raw features, enters the network from the leftmost units. It then flows through the network towards the output nodes on the right. Each layer \\(l\\) has \\(d^{(l)}\\) neurons and a bias node. The bias node outputs a constant value 1, which corresponds to an intercept term. On the other hand, a neuron transforms the input, also called activation, to an output using a nonlinear operation \\(\theta\\). The resulting output is called the activity of the neuron.
+
+Except for the bias node, all nodes between two consecutive layers are connected by arrows. In particular, the arrow between node \\(i\\) of layer \\(l\\) and node \\(j\\) of the next layer multiplies the activity \\(x^{(l)}_i\\) of layer \\(l\\) by the weight \\(w(l)_{ij}\\) and passes the result to node \\(j\\). All activities of layer \\(l\\) that goes into node \\(j\\) is combined to obtain the activation \\(s^{(l)}_j\\) as follows:
+
+$$
+s_{j}^{\left(l\right)}=\sum_{i=0}^{d^{\left(l\right)}}w_{ij}x_{i}^{\left(l\right)},\ \forall j=1,\ldots,d^{\left(l\right)}
+$$
+
+This later is then transformed to an activation that is passed to all nodes of the next layer:
+
+$$
+x_{j}^{\left(l+1\right)}=\theta\left(s_{j}^{\left(l\right)}\right),\ \forall j=1,\ldots,d^{\left(l\right)}
+$$
+
+By concatenating all activation inputs and outputs (including the bias nodes’), the above operations can be concisely described in vector notations:
+
+$$
+\begin{align}
+\mathbf{s}^{\left(l\right)} & =\left(\mathbf{W}^{\left(l\right)}\right)^{\top}\mathbf{x}^{\left(l\right)},\ \forall l=1,\ldots,L\label{eq:s_to_x}\\
+\mathbf{x}^{\left(l+1\right)} & =\left[\begin{array}{c}
+1\\
+\theta\left(\mathbf{s}^{\left(l\right)}\right)
+\end{array}\right],\qquad\forall l=1,\ldots,L\label{eq:x_to_s}
+\end{align}
+$$
+
+For classification tasks, the dimension \\(d^{(L)}\\) of the network output vector \\(x^{(L+1)}\\) is equal to the number of class labels \\(C\\). In fact, \\(x^{(L+1)}\\) models the posterior probabilities that a sample belongs to each class given the feature data \\(x^{(1)}\\). To enforce that the outputs sum to one, we use the softmax activation function:
+
+$$
+\begin{equation}
+\mathbf{x}_{j}^{\left(L+1\right)}=\frac{\exp\left(s_{j}^{\left(L\right)}\right)}{\sum_{m=1}^{C}\exp\left(s_{m}^{\left(L\right)}\right)},\ \forall j=1,\ldots,C
+\end{equation}
+$$
+
+For the hidden layers, we instead use the hyperbolic tangent function:
+
+$$
+\mathbf{x}_{j}^{\left(l+1\right)}=\tanh\left(s_{j}^{\left(l\right)}\right),\ \forall j=2,\ldots,d^{\left(l\right)}+1
+$$
+
+Unlike x(L+1), the output vectors x(l) of the hidden layers all include a bias \\(x^{(l)}_1 = 1\\). Thus, \\(x^{(l)}\\) has \\(d^{(l)} + 1\\) elements for all \\(l = 1, . . . ,L\\). These moving parts of a neural network are summarized in the Table 1 and the chain of transformations from input to output is illustrated below:
+
+In summary, a neural network is characterized by:
+
+- the total number of layers
+- the input and output dimensions
+- the number of units at each __hidden layer__ (i.e. layer between input and output)
+- an activation function at each neuron or node
+- a set of weights matrices that relate the input and output between layers.
+
+In Julia, we can define a neural network by the following data type:
+
+```julia
+##----------------------------------------------------------------------
+## Neural Network structure
+type NeuralNet
+ numLayers::Int # Number of layers (excluding input)
+ numInputs::Int # Input dimension (no bias node)
+ numOutputs::Int # Output dimension
+ numHidden::Array{Int} # Number of units at each hidden layer
+ activFunc::String # Activation function of hidden units
+ weights # Weight matrices
+end
+```
+
+#### Predicting the class of test samples
+
+{% img ../images/neural/forward.png %}
+
+Given these parameters, the relationship between the inputs and the outputs of the network is determined by a process called __*forward propagation*__. When predicting the class label of a new test sample \\(\mathbf{x} \\) the corresponding outputs \\(h_k(\mathbf{x}) = x^{(L+1)}_k\\) \\(k = 1, . . . C\\) are calculated using the chain of transformations previously described. Implementing the prediction is very simple. All we need to do is to run the forward propagation algorithm with the new sample `xnew`:
+
+
+```julia
+##----------------------------------------------------------------------
+## predict: predict the labels of new samples using forward propagation
+## Inputs:
+## - Neural network structure
+## - New samples of size N x p
+## Output: a vector of pairs containing:
+## - Maximum posterior probability of predicted class
+## - Label of predicted class ∈ {1,...,C}
+##----------------------------------------------------------------------
+function predict(net::NeuralNet, xnew)
+ x,s = forwardPropagate(net, xnew)
+ prob, class = findmax(x[end])
+end
+```
+
+The implementation of forward propagation follows directly from the above equations as follows:
+
+```julia
+##----------------------------------------------------------------------
+## Forward propagation subroutine
+## Inputs:
+## - Training example: xn
+## - Neural network structure: number of layers, number of units
+## Outputs:
+## - L+1 output vectors x[l] (including input vector x[1] = xn)
+## - L input vectors s[l]
+##----------------------------------------------------------------------
+function forwardPropagate(nn::NeuralNet, xn::Array{Float64})
+ # println("Forward propagation..")
+ # Network topology
+ L = nn.numLayers # number of all layers excluding input
+ C = nn.numOutputs
+
+ # Cells containg L input vectors and L+1 output vectors
+ s = cell(L,1) # inputs of all layers
+ x = cell(L+1,1) # outputs of all layers
+
+ # Compute input s[l] and output x[l+1] at each layer
+ # Input vector x[1] has no bias node
+ x[1] = xn
+ # Hidden layers
+ for l in 1:L-1
+ W = (nn.weights[l])
+ s[l] = W'*x[l]
+ x[l+1] = [1, map(tanh, s[l])] # use tanh
+ end
+ # Output layer
+ s[L] = (nn.weights[L])' * x[L]
+ x[L+1] = if C == 1
+ logit(s[L])
+ else
+ softmax(s[L])
+ end
+
+ # return output and input vectors
+ x, s
+end
+```
+
+
+## Model fitting using backpropagation
+
+Previously, we assumed that the neural network model is already trained, i.e. the set of weight matrices are pre-configured. But how do we set these weight matrices \\(W^{(l)}, l=1,...,L\\)? In the following, we answer that question using another procedure called _**backpropagation**_ in conjunction with forward propagation. A related question is how big and how deep should the network be. Since, it is computationally prohibitive to find the optimal size and depth of the network, a good choice is conventionally found by trial-and-error. However, we will later present an efficient technique called _**dropout**_ to generate and average the predictions of many network configurations. In this section, we will focus on finding the optimal weight parameter \(w given a configuration and training data.
+
+The next thing we need is an error measure for the multi-label classification task. Assuming the class conditional distribution of the training data is multinomial, we employ the negative likelihood as the error function:
+
+$$
+E\left(\mathbf{w}\right)=-\sum_{n=1}^{N}e_{n}\left(h\left(\mathbf{x}_{n};\mathbf{w}\right),\mathbf{y}_{n}\right)=\sum_{n=1}^{N}\sum_{k=1}^{C}y_{nk}\ln\left(h_{k}\left(\mathbf{x}_{n};\mathbf{w}\right)\right)\label{eq:cross-entropy-error}
+$$
+
+where \\(x_n\\) is a feature input vector and \\(y_n\\) is a \\(C\\) by \\(1\\) vector that encodes the class label using _one-of-C rule_. The function \\(h\\) is parameterized by the weights \\(w\\). In (4), we can identify \\(E\\) as a cross-entropy error function that measures the “distance” between the estimated MAP (_Maximum-a-Posteriori_) probabilities \\(h(x_n;w)\\) and the true label vector \\(y_n\\).
+
+The error surface \\(E\\) is not convex w.r.t. the weights \\(w\\). Nonetheless, its derivatives are still useful for finding directions towards a good local optimum. In fact, finding the global optimum is not only computationally prohibitive here, but also it can be harmful. We will discuss more about this issue later and emphasize the importance to stopping our search early to avoid overfitting. In any case, we always need a way to cheaply compute all partial derivatives. Fortunately, there is a clever algorithm, called the _**backpropagation**_ [3] that does it with \\(O(M)\\) runtime complexity. Here, \\(M\\) is the total number of weights in the network.
+
+The implementation of the model training or fitting function is shown below:
+
+```julia
+##----------------------------------------------------------------------
+## Fit: train the neural network model
+## Inputs:
+## - Neural network structure
+## - Matrix of features X with dimension N x p
+## - Class label vector of dimension N x 1 (yn ∈ {1,...,C})
+## - fitting options
+## - maximum number of optimization iterations
+##----------------------------------------------------------------------
+function fit!(nn::NeuralNet, X, y, options::FitOptions, maxIter::Int)
+
+ # assume trainData if preprocessed to make learning faster
+ # e.g. successive examples come from different classes
+ L = nn.numLayers
+ C = nn.numOutputs
+ N = size(X,1)
+ d = [nn.numInputs, reshape(nn.numHidden, length(nn.numHidden),1), nn.numOutputs]
+
+ # Initialize weights
+ initWeights!(nn, X)
+
+ # Iteration of whole batch training
+ for i = 1:maxIter
+ if i % 10 == 0 tic; println("Pass data Iteration: $i") end
+ for n = 1:N
+ if n % 50 == 0 println("Samples: $n") end
+ # Local variables within scope of each iteration
+ xn, yn = X[n,:]', y[n]
+
+ # Compute output vectors x(l), l = 1,...,L+1
+ x, s = forwardPropagate(nn, xn)
+
+ # Compute sensitivity matrices Δ[l], l = 1,...,L
+ local Δ = backPropagate(nn, x)
+
+ # Update the weights
+ updateWeights!(nn, Δ, x, yn)
+ end
+ if i % 10 == 0 toc end
+ end
+
+ # return in-sample error (optionally)
+end
+```
+
+Basically, the training is performed after multiple iterations of both the forward and backward propagations. Through these rounds, the neural network is trained to model the right relationship between the input and the output. The backward propagation computes the sensisitivy matrices \\(\Delta\\) as follows:
+
+```julia
+##----------------------------------------------------------------------
+## Backpropagation subroutine
+## Inputs:
+## - L+1 output vectors x[l] (including input vector x[1] = xn)
+## - L input vectors s[l]
+## Outputs:
+## - Sensitivity matrices Δ[l] for all layer l = 1,...,L
+##----------------------------------------------------------------------
+function backPropagate(nn::NeuralNet, x)
+ # println("Back propagation..")
+ # Network topology
+ L = nn.numLayers # number of all layers excluding input
+ C = nn.numOutputs
+ d = [nn.numInputs, reshape(nn.numHidden, length(nn.numHidden),1), nn.numOutputs]
+ Δ = cell(L,1)
+
+ # Output vector
+ h = x[L+1]
+
+ # Sensitivity matrix for output layer
+ Δ[L] = [ h[i]*(δ(i,j) - h[j]) for i in 1:C, j in 1:C ]
+
+ # Sensitivity matrix for inner layers
+ for l = L-1:-1:1
+ Δ[l] = zeros(Float64, C, d[l+1])
+ W = nn.weights[l+1]
+ for k in 1:C
+ for j in 1:d[l+1]
+ # assuming tanh activation function at hidden units
+ Δ[l][k,j] = (1 - h[k]^2) * (W[j,:] * Δ[l+1][k,:]')[1]
+ end
+ end
+ end
+
+ # return sensitivity matrices for all layers ∀l = L,...,1
+ Δ
+end
+```
+
+## Optimizing the network weights
+
+After the sensitivity matrices are calculated by the weight matrices, the weight matrices are optimized. There are two general strategies for doing this:
+
+1. Batch gradient descent update the weights using the gradient of the error contributed by all training examples. This is done after a single pass through all the examples.
+2. Stochastic gradient descent (SGD) is a more efficient method as it immediately updates the weights after seeing each training example[4]. Another advantage of the stochastic approach is that it takes advantage of randomization to escape poor local optimum. The overall SGD algorithm is presented in Table 2.
+
+{% img right ../images/neural/table2.png %}
+
+Different acceleration techniques have also been proposed to speed up the training procedure of neural networks. These include Nesterov’s method, conjugate gradient descent (which only works for batch mode) as well as Newton-type methods. Due to the computational hurdles with training large neural networks, first-order methods such as SGD are more practical. The implementation of simple SGD method is displayed below:
+
+
+```julia
+##----------------------------------------------------------------------
+## updateWeights: update and return the weight matrices at each iteration
+## Inputs:
+## - Neural network structure
+## - Sensitivity matrices Δ[l], ∀l ∈ {1,..,L}
+## - Output vectors x[l], ∀l ∈ {1,..,L+1}
+## - Class label of example: yn
+## Output:
+## - weights matrices
+##----------------------------------------------------------------------
+function updateWeights!(nn::NeuralNet, Δ, x, yn)
+
+ L = nn.numLayers
+ C = nn.numOutputs
+ d = [nn.numInputs, reshape(nn.numHidden, length(nn.numHidden),1), nn.numOutputs]
+
+ # Softmax output
+ h = x[L+1]
+
+ # Step size
+ μ = 0.1
+
+ # yn is encoded as one-of-C vector
+ yv = mask(ones(C), yn)
+
+ # Gradient of error w.r.t softmax output vector
+ ∇e_h = - vec(yv ./ h)
+
+ # Gradient of error w.r.t weight matrix W[L]
+ # assuming softmax output activation and cross-entropy error
+ ∇e_WL = zeros(Float64, d[L]+1,C)
+ for i in 1:d[L]+1
+ for j in 1:C
+ ∇e_WL[i,j] = x[L][i] * (h[j] - yv[j])
+ end
+ end
+ # SGD update of weight matrix W[L]
+ nn.weights[L] = nn.weights[L] - μ * ∇e_WL
+
+ # Gradient of error w.r.t weight matrix @ input W[1]
+ # Input has no bias node: W1 is d[1] x d[2] matrix
+ ∇e_W1 = zeros(Float64, d[1],d[2])
+ for i in 1:d[1]
+ for j in 1:C
+ ∇e_W1[i,j] = x[1][i] * dot(∇e_h, vec(Δ[1][:,j]))
+ end
+ end
+
+ # SGD update of weight matrix W[1]
+ nn.weights[1] = nn.weights[1] - μ * ∇e_W1
+
+ # Gradient of error w.r.t weight matrices of hidden layers
+ for l = 2:L-1
+ # Gradient of error w.r.t weight matrix Wl
+ # x[l] has bias node: Wl is (d[l]+1) x d[l+1] matrix
+ ∇e_Wl = zeros(Float64, d[l]+1, d[l+1])
+ for i in 1:d[l]+1
+ for j in 1:d[l+1]
+ ∇e_Wl[i,j] = x[l][i] * dot(∇e_h, vec(Δ[l][:,j]))
+ end
+ end
+
+ # SGD update the weight matrices
+ nn.weights[l] = nn.weights[l] - μ * ∇e_Wl
+ end
+ nn.weights
+end
+```
+
+What is most attractive about deep learning models is that they learn the feature automatically. In constrast, classic supervised model such as logistic regression or classification trees require the user to select the features. In neural networks, the features are represented by the states of the neurons in the hidden layers. For the digit classification application, the figure below shows such learned features.
+
+{% img right ../images/neural/featuresminst.png %}
+
+
+## Regularization techniques
+Neural networks offer a considerable flexibility to the extent that they can approximate any function with abritrary complexity. However, they can also easily overfit the data and fail to generalize to give accurate predictions when presented with new data samples. To prevent this, we can use three types of regularization methods: weight decay, early stopping and dropout.
+
+#### Weight decay
+Weight decay is a classic regularization technique [5] that is used in different problems, including linear ridge regression. The basic idea is to penalize models that are too complex by adding a quadratic penalty terms to the error loss function and the weight update becomes:
+Precisely, it seeks to shrink the weights towards zero.
+
+#### Early stopping
+The second regularization method avoids overfitting using a validation set approach. Precisely, we monitor the prediction error of the validation set at each iteration of the weight optimization. Although the optimization seeks to minimize the training error, we stop as early as the validation error increases with the iterations. This is a good indication that the model starts to overfit.
+
+#### Dropout
+Dropout is another regularization technique that was recently proposed in [6]. The key idea is to randomly drop the units during training with a probability p. When a unit is dropped, all its incoming and outgoing connections are also temporarily removed. For each training point, we sample the network by droping units randomly to produce a “thinned” network. This is usually done within a mini-batch and the weight of each arrow becomes average over the points in the mini-batch. If for one point, the unit connecting the arrow was dropped, its weight counts as zero. At test time, the entire network is used but the weights are scaled by the probability p.
+
+{% img right ../images/neural/dropout.png %}
+
+Simulation results show that the use of dropout to regularize the network help against overfitting. The out-of-sample classification can be reduced to 1% with dropout on the MNISTN dataset as shown in the figure below.
+
+{% img left ../images/neural/result.png %}
+
+
+## References
+
+1. R Ramamonjison. Training deep neural networks for multi-label classification, UBC Tech. Report, 2014.
+1. K Murphy. Machine Learning: A Probabilistic Perspective. The MIT Press, 2012.
+2. C Bishop. Neural Networks for Pattern Recognition. Oxford University Press, Inc., New York, NY, USA, 1995.
+3. D Rumelhart, G E Hinton, and R J Williams. Learning representations by back-propagating errors. Nature, 323(6088):533–536, 1986.
+4. L Bottou. Stochastic gradient learning in neural networks. In In Proceedings of Neuro-Nimes. EC2, 1991.
+5. A Tikhonov. Solution of incorrectly formulated problems and the regularization method. Soviet Math. Dokl., 4:1035–1038, 1963.
+6. N Srivastava, Geoffrey Hinton, Alex Krizhevsky, Ilya Sutskever, and Ruslan Salakhutdinov. Dropout: A simple way to prevent neural networks from overfitting. Journal of Machine Learning Research, 15:1929–1958, 2014.
+7. M Schmidt, N Le Roux, and F Bach. Minimizing finite sums with the stochastic average gradient. CoRR, abs/1309.2388, 2013.
+
diff --git a/source/projects/index.markdown b/source/projects/index.markdown
new file mode 100644
index 0000000..f297fb1
--- /dev/null
+++ b/source/projects/index.markdown
@@ -0,0 +1,45 @@
+---
+layout: page
+title: "projects"
+date: 2015-07-15 13:36
+comments: true
+sharing: true
+footer: true
+---
+
+Below is a list of the projects I have been working on recently.
+
+### Anomaly detection (Mitacs research internship)
+
+Anomaly detection is an important analytics problem for business applications. It helps an organization in detecting operation bottlenecks and in reducing risks. However, when the number of metrics to monitor are large, it is crucial to develop efficient machine learning algorithms that are optimized for parallel processing. In this research project, I have been investigating parallel algorithms to enable fast and scalable predictive analytics.
+
+I developed new techniques for detecting data points in time series data that deviate from a normal behavior. In particular, I designed and implemented algorithms using time series decomposition, smoothing methods and robust statistics. The algorithms were prototyped in Matlab and implemented in Haskell. The benefits of these algorithms are that they are computationally efficient and can work on time series data that may exhibit seasonality and trend. In addition, they lead naturally to parallelization. Thus, they can be used for monitoring discrepancies in most time-series data. This project was generously supported by D&B Cloud Innovation center and by the [Mitacs Accelerate](https://www.mitacs.ca/en/programs/accelerate) program.
+
+
+### Apache Spark projects
+
+[Apache Spark](http://spark.apache.org/) is a cluster computing framework originally developed in the AMPLab at UC Berkeley. In contrast to Hadoop's MapReduce paradigm, Spark's in-memory processing provides performance up to 100 times faster for certain applications. By allowing user programs to load data into a cluster's memory and query it repeatedly, Spark is well-suited to various data applications such as machine learning, graph processing and real-time data analysis.
+
+As the most active open-source project in Big Data, Spark has a large and diverse community. I have been involved with Spark since it was in incubation stage. The following list is a sample of my projects and contributions to this exciting project:
+
+- I created and co-organize the local [**Vancouver Spark Meetups**](http://www.meetup.com/Vancouver-Spark/), which now has over 300 members.
+- I also wrote a book on **Spark Graph Processing**. While waiting for its release, you can access a [**chapter preview here**](http://giocode.github.io/projects/spark-graph.html).
+- **CPSC 546 - Optimization course project:** "_Distributed algorithms for training recommendation systems_"
+- Some Spark tutorials that I taught include:
+ - [IEEE Summer School on Signal Processing and Machine Learning for Big Data](https://sites.google.com/site/s3pbigdata2014/lecturers)
+ - [Workshop on Distributed Machine Learning and Computing with Spark](http://www.meetup.com/Vancouver-Spark/events/178126142/) at SAP.
+
+
+### Deep learning for image classification (CPSC 540)
+
+Deep learning and neural networks is a exciting subject not only for researchers but also for A.I. community in general. Google's acquisition of [DeepMind](http://deepmind.com/) is only one of the interesting developments in this field. Traditional approaches to machine learning have been based on having engineers build or select the right features for a learning problem. After extracting the features, the learning model needs to be trained with a large amount of labeled datasets. Feature extraction is a hard topic especially for machine vision problem such as image classification. In contrast, neural networks can learn the features during the training - by themselves. However, care must be taken not overfit the model! In fact, neural networks are known to easily overfit since they can virtually approximate any function.
+
+In my [machine learning course](http://www.cs.ubc.ca/~schmidtm/Courses/540-W16/) project, I investigated regularizations methods to prevent overfitting when training neural networks. Following this project, I wrote a [**compact and accessible tutorial**](http://giocode.github.io/projects/deep-learn.html) on this subject. It includes just the important math and contains illustrative code written in Julia language to explain the main concepts.
+
+
+### Mobile app development
+
+In my free time, I had the chance to learn and build mobile applications on both iOS and Android platform. In particular, I have published the [Hashter mobile app](https://play.google.com/store/apps/details?id=com.highhay.hashtag.free) for creating gorgeous social media posters.
+
+
+
diff --git a/source/projects/spark-graph.markdown b/source/projects/spark-graph.markdown
new file mode 100644
index 0000000..cedc77e
--- /dev/null
+++ b/source/projects/spark-graph.markdown
@@ -0,0 +1,753 @@
+---
+layout: page
+title: "Sabermetrics with Apache Spark"
+date: May 24, 2015
+comments: true
+sharing: true
+footer: true
+---
+
+
+It is no secret analytics have made a big impact in sports. The quest for an objective understanding of the game has even a name: "sabermetrics". Analytics have proven invaluable in many aspects: from [building dream teams under tight cap constraints](http://www.sfgate.com/warriors/article/Golden-State-Warriors-at-the-forefront-of-NBA-5753776.php), to [selecting game-specific strategies](https://en.wikipedia.org/wiki/Moneyball) to actively [engaging with fans](http://www.nhl.com/ice/news.htm?id=754184) and so on. No matter what the goal is, gaining useful insights requires a quick ability to process big data and handle its complexities. In the following, we analyze NCAA Men's college basketball game stats gathered during one season. As sports-data experts, we are going to leverage Spark's graph processing library to answer several questions for retrospection.
+
+[__Apache Spark__](http://spark.apache.org/) is a fast and general-purpose technology, which greatly simplify the parallel processing of large data that is distributed over a computing cluster. While Spark handles different types of processing, here we will focus on its graph processing capability. In particular, our goal is to expose the powerful yet generic graph-aggregation operator of Spark:`aggregateMessages`. We can think of this operator as a version of MapReduce for aggregating the neighborhood information in graphs.
+
+In fact, many graph processing algorithms such as PageRank rely on iteratively accessing the properties of neighbouring vertices and adjacent edges. By applying `aggregateMessages` on the NCAA College Basketball datasets, we will:
+
+- identify the basic mechanisms and undersand the patterns for using `aggregateMessages`
+- apply `aggregateMessages` to create custom graph aggregation operations
+- optimize the performance and efficiency of `aggregateMessages`
+
+## NCAA College Basketball datasets
+
+As an illustrative example, the [NCAA College Basketball](http://www.ncaa.com/sports/basketball-men) datasets consist of two CSV datasets. This first one `teams.csv` contains the list of all college teams that played in NCAA Division I competition. Each team is associated with a 4 digit id number. The second dataset `stats.csv` contains the score and statistics of every game played during the 2014-2015 regular season.
+
+### Loading team data into RDDs
+
+To start, we parse and load these datasets into RDDs (__Resilient Distributed Datasets__), which are the core Spark abstraction for any data that is distributed and stored over a cluster. First, we create a class `GameStats` that records a team's statistics during a game.
+
+```scala
+case class GameStats(
+ val score: Int,
+ val fieldGoalMade: Int,
+ val fieldGoalAttempt: Int,
+ val threePointerMade: Int,
+ val threePointerAttempt: Int,
+ val threeThrowsMade: Int,
+ val threeThrowsAttempt: Int,
+ val offensiveRebound: Int,
+ val defensiveRebound: Int,
+ val assist: Int,
+ val turnOver: Int,
+ val steal: Int,
+ val block: Int,
+ val personalFoul: Int
+)
+```
+
+### Loading game stats into RDDs
+
+We also add the following methods to `GameStats` in order to know how efficient a team's offense was:
+
+```scala
+// Field Goal percentage
+def fgPercent: Double = 100.0 * fieldGoalMade / fieldGoalAttempt
+
+// Three Point percentage
+def tpPercent: Double = 100.0 * threePointerMade / threePointerAttempt
+
+// Free throws percentage
+def ftPercent: Double = 100.0 * threeThrowsMade / threeThrowsAttempt
+override def toString: String = "Score: " + score
+```
+
+Next, we create a couple of classes for the games' result.
+
+```scala
+abstract class GameResult(
+ val season: Int,
+ val day: Int,
+ val loc: String
+)
+
+
+case class FullResult(
+ override val season: Int,
+ override val day: Int,
+ override val loc: String,
+ val winnerStats: GameStats,
+ val loserStats: GameStats
+) extends GameResult(season, day, loc)
+```
+
+`FullResult` has the year and day of the season, the location where the game was played and the game statistics of both the winning and losing teams.
+
+Next, we will create a statistics graph of the regular seasons. In this graph, the nodes are the teams whereas each edge corresponds to a specific game. To create the graph, let us parse the CSV file `teams.csv` into the RDD `teams` :
+
+```scala
+val teams: RDD[(VertexId, String)] =
+ sc.textFile("./data/teams.csv").
+ filter(! _.startsWith("#")).
+ map {line =>
+ val row = line split ','
+ (row(0).toInt, row(1))
+ }
+```
+
+We can check the first few teams in this new RDD:
+
+```scala
+scala> teams.take(3).foreach{println}
+(1101,Abilene Chr)
+(1102,Air Force)
+(1103,Akron)
+```
+
+We do the same thing to obtain an RDD of the game results, which will have a type `RDD[Edge[FullResult]]`. We just parse `stats.csv` and record the fields that we need: (1) the ID of the winning team, (2) the ID of the losing team, and (3) the game statistics of both teams:
+
+```scala
+val detailedStats: RDD[Edge[FullResult]] =
+ sc.textFile("./data/stats.csv").
+ filter(! _.startsWith("#")).
+ map {line =>
+ val row = line split ','
+ Edge(row(2).toInt, row(4).toInt,
+ FullResult(
+ row(0).toInt, row(1).toInt,
+ row(6),
+ GameStats(
+ score = row(3).toInt,
+ fieldGoalMade = row(8).toInt,
+ fieldGoalAttempt = row(9).toInt,
+ threePointerMade = row(10).toInt,
+ threePointerAttempt = row(11).toInt,
+ threeThrowsMade = row(12).toInt,
+ threeThrowsAttempt = row(13).toInt,
+ offensiveRebound = row(14).toInt,
+ defensiveRebound = row(15).toInt,
+ assist = row(16).toInt,
+ turnOver = row(17).toInt,
+ steal = row(18).toInt,
+ block = row(19).toInt,
+ personalFoul = row(20).toInt
+ ),
+ GameStats(
+ score = row(5).toInt,
+ fieldGoalMade = row(21).toInt,
+ fieldGoalAttempt = row(22).toInt,
+ threePointerMade = row(23).toInt,
+ threePointerAttempt = row(24).toInt,
+ threeThrowsMade = row(25).toInt,
+ threeThrowsAttempt = row(26).toInt,
+ offensiveRebound = row(27).toInt,
+ defensiveRebound = row(28).toInt,
+ assist = row(20).toInt,
+ turnOver = row(30).toInt,
+ steal = row(31).toInt,
+ block = row(32).toInt,
+ personalFoul = row(33).toInt
+ )
+ )
+ )
+ }
+```
+
+We could avoid typing all that by using the nice [spark-csv package](http://spark-packages.org/package/databricks/spark-csv) that reads CSV files into `SchemaRDD`. Let's check what we got:
+
+```scala
+scala> detailedStats.take(3).foreach(println)
+Edge(1165,1384,FullResult(2006,8,N,Score: 75-54))
+Edge(1393,1126,FullResult(2006,8,H,Score: 68-37))
+Edge(1107,1324,FullResult(2006,9,N,Score: 90-73))
+```
+
+We then create our score graph using the collection of teams (of type `RDD[(VertexId, String)]`) as vertices and the collection `detailedStats` (of type `RDD[(VertexId, String)]`) as edges:
+
+```scala
+scala> val scoreGraph = Graph(teams, detailedStats)
+```
+
+For curiosity, let's see which team has won against the 2015 NCAA national champ Duke during regular season. It seems Duke has lost only four games during the regular season:
+
+```scala
+scala> scoreGraph.triplets.filter(_.dstAttr == "Duke").foreach(println)
+((1274,Miami FL),(1181,Duke),FullResult(2015,71,A,Score: 90-74))
+((1301,NC State),(1181,Duke),FullResult(2015,69,H,Score: 87-75))
+((1323,Notre Dame),(1181,Duke),FullResult(2015,86,H,Score: 77-73))
+((1323,Notre Dame),(1181,Duke),FullResult(2015,130,N,Score: 74-64))
+```
+
+
+## Aggregating Game Stats
+
+Having our graph ready, let's start aggregating the stats data in `scoreGraph`. In Spark, `aggregateMessages` is the operator for that kind of jobs.
+For example, let's find out the average field goals made per game by the winners. In other words, the games that a team lost will not be counted. To get the average for each team, we first need to have the number of games won by the team and the total field goals that the team made in those games:
+
+```scala
+// Aggregate the total field goals made by winning teams
+type Msg = (Int, Int)
+type Context = EdgeContext[String, FullResult, Msg]
+val winningFieldGoalMade: VertexRDD[Msg] = scoreGraph aggregateMessages(
+ // sendMsg
+ (ec: Context) => ec.sendToSrc(1, ec.attr.winnerStats.fieldGoalMade),
+
+ // mergeMsg
+ (x: Msg, y: Msg) => (x._1 + y._1, x._2+ y._2)
+)
+```
+
+### AggregateMessage operator
+
+There is a lot going on in the above call to `aggregateMessages`. So let's see it working in slow motion. When we called `aggregateMessages` on the `scoreGraph`, we had to pass two functions as arguments.
+
+#### SendMsg
+The first function has a signature `EdgeContext[VD, ED, Msg] => Unit`. It takes an `EdgeContext` as input. Since it does not return anything, its return type is `Unit`. This function is needed for sending message between nodes.
+
+Ok, but what is that `EdgeContext` type? `EdgeContext` represents an edge along with its neighboring nodes. It can access both the edge attribute and the source and destination nodes' attributes. In addition, `EdgeContext` has two methods to send messages along the edge to its source node or to its destination node. These methods are `sendToSrc` and `sendToDst` respectively. Then, the type of messages being sent through the graph is defined by `Msg`. Similar to vertex and edge types, we can defined the concrete type that `Msg` takes as we wish.
+
+#### Merge
+In addition to `sendMsg`, the second function that we need to pass to `aggregateMessages` is a `mergeMsg` function with the following signature `(Msg, Msg) => Msg`. As its name implies, `mergeMsg` is used to merge two messages received at each node into a new one. Its output must also be of type `Msg`. Using these two functions, `aggregateMessages` returns the aggregated messages inside a `VertexRDD[Msg]`.
+
+#### Example
+In our example, we need to aggregate the number of games played and the number of field goals made. Therefore, `Msg` is simply a pair of `Int`. Furthermore, each edge context needs to send a message to only its source node, i.e. the winning team. This is because we want to compute the total field goals made by each team for only the games that it won. The actual message sent to each "winner" node is the pair of integers `(1, ec.attr.winnerStats.fieldGoalMade)`. Here, `1` serves as a counter for the number of games won by the source node. The second integer, which is the number of field goals in one game, is extracted from the edge attribute.
+
+As we set out to compute the average field goals per winning game for all teams, we need to apply the `mapValues` operator to the output of `aggregateMessages` as follows:
+
+```scala
+// Average field goals made per Game by the winning teams
+val avgWinningFieldGoalMade: VertexRDD[Double] =
+ winningFieldGoalMade mapValues (
+ (id: VertexId, x: Msg) => x match {
+ case (count: Int, total: Int) => total.toDouble/count
+})
+
+scala> avgWinningFieldGoalMade.take(5).foreach(println)
+(1260,24.71641791044776)
+(1410,23.56578947368421)
+(1426,26.239436619718308)
+(1166,26.137614678899084)
+(1434,25.34285714285714)
+```
+
+## Abstracting out the aggregation
+
+That was kind of cool! We can surely do the same thing for the average points per game scored by winning teams:
+
+```scala
+// Aggregate the points scored by winning teams
+val winnerTotalPoints: VertexRDD[(Int, Int)] = scoreGraph.aggregateMessages(
+ // sendMsg
+ triplet => triplet.sendToSrc(1, triplet.attr.winnerStats.score),
+ // mergeMsg
+ (x, y) => (x._1 + y._1, x._2+ y._2)
+)
+
+// Average field goals made per Game by winning teams
+var winnersPPG: VertexRDD[Double] =
+ winnerTotalPoints mapValues (
+ (id: VertexId, x: (Int, Int)) => x match {
+ case (count: Int, total: Int) => total.toDouble/count
+ })
+
+scala> winnersPPG.take(5).foreach(println)
+(1260,71.19402985074628)
+(1410,71.11842105263158)
+(1426,76.30281690140845)
+(1166,76.89449541284404)
+(1434,74.28571428571429)
+```
+
+What if the coach wants to know the top 5 teams with the highest average three pointer made per winning game? By the way, he might also ask which teams are the most efficient in three pointers.
+
+### Keeping things DRY
+
+We can copy and modify the previous code but that would be quite repetitive. Instead, let's abstract out the average aggregation operator so that it can work on any statistics that the coach needs. Luckily, Scala's higher-order functions are there to help in this task.
+
+Let's define functions that take a team's `GameStats` as input and returns specific statistic that we are interested in. For now, we will need the number of three pointer made and the average three pointer percentage:
+
+```scala
+// Getting individual stats
+def threePointMade(stats: GameStats) = stats.threePointerMade
+def threePointPercent(stats: GameStats) = stats.tpPercent
+```
+
+Then, we create a generic function that takes as inputs a stats graph and one of the functions defined above, which has a signature `GameStats => Double`.
+
+```scala
+// Generic function for stats averaging
+def averageWinnerStat(graph: Graph[String, FullResult])(getStat: GameStats => Double): VertexRDD[Double] = {
+ type Msg = (Int, Double)
+ val winningScore: VertexRDD[Msg] = graph.aggregateMessages[Msg](
+ // sendMsg
+ triplet => triplet.sendToSrc(1, getStat(triplet.attr.winnerStats)),
+ // mergeMsg
+ (x, y) => (x._1 + y._1, x._2+ y._2)
+ )
+ winningScore mapValues (
+ (id: VertexId, x: Msg) => x match {
+ case (count: Int, total: Double) => total/count
+ })
+}
+```
+
+Now, we can get the average stats by passing the functions `threePointMade` and `threePointPercent` to `averageWinnerStat`:
+
+```scala
+val winnersThreePointMade = averageWinnerStat(scoreGraph)(threePointMade)
+val winnersThreePointPercent = averageWinnerStat(scoreGraph)(threePointPercent)
+```
+
+With little efforts, we can tell coach which five winning teams score the highest number of threes per game:
+
+```scala
+scala> winnersThreePointMade.sortBy(_._2,false).take(5).foreach(println)
+(1440,11.274336283185841)
+(1125,9.521929824561404)
+(1407,9.008849557522124)
+(1172,8.967441860465117)
+(1248,8.915384615384616)
+```
+While we are at it, let's find out the five most efficient teams in three pointers:
+
+```scala
+scala> winnersThreePointPercent.sortBy(_._2,false).take(5).foreach(println)
+(1101,46.90555728464225)
+(1147,44.224282479431224)
+(1294,43.754532434101534)
+(1339,43.52308905887638)
+(1176,43.080814169045105)
+```
+Interestingly, the teams that made the most three pointers per winning game are not always the one who are the most efficient at it. But it is ok because at least, they won those games.
+
+### Coach wants more numbers
+
+Coach seems to argue against that argument. He asks us to get the same statistics but he wants the average over all games that each team has played.
+
+We then have to aggregate the information at all nodes, and not only at the destination nodes. To make our previous abstraction more flexible, let's create the following types:
+
+```scala
+trait Teams
+case class Winners extends Teams
+case class Losers extends Teams
+case class AllTeams extends Teams
+```
+
+We modify the previous higher-order function to have a extra argument `Teams`, which will help us specify at which nodes we want to collect and aggregate the required game stats. The new function becomes:
+
+```scala
+def averageStat(graph: Graph[String, FullResult])(getStat: GameStats => Double, tms: Teams): VertexRDD[Double] = {
+ type Msg = (Int, Double)
+ val aggrStats: VertexRDD[Msg] = graph.aggregateMessages[Msg](
+ // sendMsg
+ tms match {
+ case _ : Winners => t => t.sendToSrc((1, getStat(t.attr.winnerStats)))
+ case _ : Losers => t => t.sendToDst((1, getStat(t.attr.loserStats)))
+ case _ => t => {
+ t.sendToSrc((1, getStat(t.attr.winnerStats)))
+ t.sendToDst((1, getStat(t.attr.loserStats)))
+ }
+ }
+ ,
+ // mergeMsg
+ (x, y) => (x._1 + y._1, x._2+ y._2)
+ )
+
+ aggrStats mapValues (
+ (id: VertexId, x: Msg) => x match {
+ case (count: Int, total: Double) => total/count
+ })
+ }
+```
+
+Now, `aggregateStat` allows us to choose whether we want to aggregate the stats for winners only, for losers only or for all teams. Since coach wants the overall stats averaged over all games played, we aggregate the stats by passing the `AllTeams()` flag in `aggregateStat`. In this case, we define the `sendMsg` argument in `aggregateMessages` to send the required stats to both the source (the winner) and to the destination (the loser) using `EdgeContext`'s `sendToSrc` and `sendToDst` functions respectively. This mechanism is pretty straightforward. We just need make sure we send the right information to the right node. In this case, we send the `winnerStats` to the winner and the `loserStats`to the loser.
+
+Ok, you got the idea now. So, let's apply it to please our coach. Here are the teams with the overall highest three pointers per page:
+
+```scala
+// Average Three Point Made Per Game for All Teams
+val allThreePointMade = averageStat(scoreGraph)(threePointMade, AllTeams())
+scala> allThreePointMade.sortBy(_._2, false).take(5).foreach(println)
+(1440,10.180811808118081)
+(1125,9.098412698412698)
+(1172,8.575657894736842)
+(1184,8.428571428571429)
+(1407,8.411149825783973)
+```
+
+And here are the five most efficient teams overall in three pointers per Game:
+
+```scala
+// Average Three Point Percent for All Teams
+val allThreePointPercent = averageStat(scoreGraph)(threePointPercent, AllTeams())
+
+scala> allThreePointPercent.sortBy(_._2,false).take(5).foreach(println)
+(1429,38.8351815824302)
+(1323,38.522819895594)
+(1181,38.43052051444854)
+(1294,38.41227053353959)
+(1101,38.097896464168954)
+```
+
+Actually, there is only a 2% difference between the most efficient team and the one in 50th position. Most NCAA teams are therefore pretty efficient behind the line. I bet coach knew that already!
+
+### Average Points Per Game
+
+We can also reuse the `averageStat` function to get the average points per game for the winners. In particular, let's take a look at the two teams that won games with the highest and lowest scores:
+
+```
+// Winning teams
+val winnerAvgPPG = averageStat(scoreGraph)(score, Winners())
+
+scala> winnerAvgPPG.max()(Ordering.by(_._2))
+res36: (org.apache.spark.graphx.VertexId, Double) = (1322,90.73333333333333)
+
+scala> winnerAvgPPG.min()(Ordering.by(_._2))
+res39: (org.apache.spark.graphx.VertexId, Double) = (1197,60.5)
+```
+Apparently, the most defensive team can win game by scoring only 60 points whereas the most offensive team can score an average of 90 points.
+
+Next, let us average the points per game for all games played and look at the two teams with the best and worst offense during the 2015 season:
+
+```scala
+// Average Points Per Game of All Teams
+val allAvgPPG = averageStat(scoreGraph)(score, AllTeams())
+
+scala> allAvgPPG.max()(Ordering.by(_._2))
+res42: (org.apache.spark.graphx.VertexId, Double) = (1322,83.81481481481481)
+
+scala> allAvgPPG.min()(Ordering.by(_._2))
+res43: (org.apache.spark.graphx.VertexId, Double) = (1212,51.111111111111114)
+
+```
+
+To no surprise, the best offensive team is the same as the one who scores most in winning games. To win games, 50 points is not enough in average for a team to win games.
+
+## Defense Stats: The D matters as in Direction
+
+Above, we obtained some statistics such as field goals or three point percentage that a team achieves. What if we want to aggregate instead the average points or rebounds that each team concedes to their opponents? To compute that, we define a new higher-order function `averageConcededStat`. Compared to `averageStat`, this function needs to send the `loserStats` to the winning team and the `winnerStats` to the losing team. To make things more interesting, we are going to make the team name as part of the message `Msg`.
+
+```scala
+def averageConcededStat(graph: Graph[String, FullResult])(getStat: GameStats => Double, rxs: Teams): VertexRDD[(String, Double)] = {
+ type Msg = (Int, Double, String)
+ val aggrStats: VertexRDD[Msg] = graph.aggregateMessages[Msg](
+ // sendMsg
+ rxs match {
+ case _ : Winners => t => t.sendToSrc((1, getStat(t.attr.loserStats), t.srcAttr))
+ case _ : Losers => t => t.sendToDst((1, getStat(t.attr.winnerStats), t.dstAttr))
+ case _ => t => {
+ t.sendToSrc((1, getStat(t.attr.loserStats),t.srcAttr))
+ t.sendToDst((1, getStat(t.attr.winnerStats),t.dstAttr))
+ }
+ }
+ ,
+ // mergeMsg
+ (x, y) => (x._1 + y._1, x._2+ y._2, x._3)
+ )
+
+ aggrStats mapValues (
+ (id: VertexId, x: Msg) => x match {
+ case (count: Int, total: Double, name: String) => (name, total/count)
+ })
+}
+
+```
+
+With that, we can calculate the average points conceded by winning and losing teams as follows:
+
+```scala
+val winnersAvgConcededPoints = averageConcededStat(scoreGraph)(score, Winners())
+val losersAvgConcededPoints = averageConcededStat(scoreGraph)(score, Losers())
+
+scala> losersAvgConcededPoints.min()(Ordering.by(_._2))
+res: (VertexId, (String, Double)) = (1101,(Abilene Chr,74.04761904761905))
+
+scala> winnersAvgConcededPoints.min()(Ordering.by(_._2))
+res: (org.apache.spark.graphx.VertexId, (String, Double)) = (1101,(Abilene Chr,74.04761904761905))
+
+scala> losersAvgConcededPoints.max()(Ordering.by(_._2))
+res: (VertexId, (String, Double)) = (1464,(Youngstown St,78.85714285714286))
+
+scala> winnersAvgConcededPoints.max()(Ordering.by(_._2))
+res: (VertexId, (String, Double)) = (1464,(Youngstown St,71.125))
+```
+
+The above tells us that Abilene Christian University is the most defensive team. They concede the least points whether they win a game or not. On the other hand, Youngstown has the worst defense.
+
+
+## Joining Aggregated Stats into Graphs
+
+The previous example shows us how flexible the `aggregateMessages` operator is. We can define the type `Msg` of the messages to be aggregated to fit our needs. Moreover, we can select which nodes receive the messages. Finally, we can also define how we want to merge the messages.
+
+As a final example, let us aggregate many statistics about each team and join this information into the nodes of the graph. To start, we create its own class for the team stats:
+
+```scala
+// Average Stats of All Teams
+case class TeamStat(
+ wins: Int = 0 // Number of wins
+ ,losses: Int = 0 // Number of losses
+ ,ppg: Int = 0 // Points per game
+ ,pcg: Int = 0 // Points conceded per game
+ ,fgp: Double = 0 // Field goal percentage
+ ,tpp: Double = 0 // Three point percentage
+ ,ftp: Double = 0 // Free Throw percentage
+ ){
+ override def toString = wins + "-" + losses
+}
+```
+
+Then, we collect the average stats for all teams using `aggregateMessages` below. For that, we define the type of the message to be an 8-element tuple that holds the counter for games played, wins, losses and other statistics that will be stored in `TeamStat` as listed above.
+
+```scala
+type Msg = (Int, Int, Int, Int, Int, Double, Double, Double)
+
+val aggrStats: VertexRDD[Msg] = scoreGraph.aggregateMessages(
+ // sendMsg
+ t => {
+ t.sendToSrc(( 1,
+ 1, 0,
+ t.attr.winnerStats.score,
+ t.attr.loserStats.score,
+ t.attr.winnerStats.fgPercent,
+ t.attr.winnerStats.tpPercent,
+ t.attr.winnerStats.ftPercent
+ ))
+ t.sendToDst(( 1,
+ 0, 1,
+ t.attr.loserStats.score,
+ t.attr.winnerStats.score,
+ t.attr.loserStats.fgPercent,
+ t.attr.loserStats.tpPercent,
+ t.attr.loserStats.ftPercent
+ ))
+ }
+ ,
+ // mergeMsg
+ (x, y) => ( x._1 + y._1, x._2 + y._2,
+ x._3 + y._3, x._4 + y._4,
+ x._5 + y._5, x._6 + y._6,
+ x._7 + y._7, x._8 + y._8
+ )
+ )
+```
+
+Given the aggregate message `aggrStats`, we map them into a collection of `TeamStat`
+
+```scala
+val teamStats: VertexRDD[TeamStat] = aggrStats mapValues {
+ (id: VertexId, m: Msg) => m match {
+ case ( count: Int,
+ wins: Int,
+ losses: Int,
+ totPts: Int,
+ totConcPts: Int,
+ totFG: Double,
+ totTP: Double,
+ totFT: Double) => TeamStat( wins, losses,
+ totPts/count,
+ totConcPts/count,
+ totFG/count,
+ totTP/count,
+ totFT/count)
+
+ }
+}
+```
+
+Next, let us join the `teamStats` into the graph. For that, we first create a class `Team` as a new type for the vertex attribute. `Team` will have the name and the `TeamStat`:
+
+```scala
+case class Team(name: String, stats: Option[TeamStat]) {
+ override def toString = name + ": " + stats
+}
+```
+
+Next, we use the `joinVertices` operator that we have seen in the previous chapter:
+
+```scala
+// Joining the average stats to vertex attributes
+def addTeamStat(id: VertexId, t: Team, stats: TeamStat) = Team(t.name, Some(stats))
+
+val statsGraph: Graph[Team, FullResult] =
+ scoreGraph.mapVertices((_, name) => Team(name, None)).
+ joinVertices(teamStats)(addTeamStat)
+```
+
+We can see that the join has worked well by printing the first three vertices in the new graph `statsGraph`:
+
+```scala
+scala> statsGraph.vertices.take(3).foreach(println)
+(1260,Loyola-Chicago: Some(17-13))
+(1410,TX Pan American: Some(7-21))
+(1426,UT Arlington: Some(15-15))
+```
+
+To conclude this task, let us find out the top 10 teams in the regular seasons. To do so, we define an `Ordering` for `Option[TeamStat]` as follows:
+
+```scala
+import scala.math.Ordering
+object winsOrdering extends Ordering[Option[TeamStat]] {
+ def compare(x: Option[TeamStat], y: Option[TeamStat]) = (x, y) match {
+ case (None, None) => 0
+ case (Some(a), None) => 1
+ case (None, Some(b)) => -1
+ case (Some(a), Some(b)) => if (a.wins == b.wins) a.losses compare b.losses
+ else a.wins compare b.wins
+ }
+}
+```
+
+Finally!
+
+```scala
+import scala.reflect.classTag
+import scala.reflect.ClassTag
+scala> statsGraph.vertices.sortBy(v => v._2.stats,false)(winsOrdering, classTag[Option[TeamStat]]).
+ | take(10).foreach(println)
+(1246,Kentucky: Some(34-0))
+(1437,Villanova: Some(32-2))
+(1112,Arizona: Some(31-3))
+(1458,Wisconsin: Some(31-3))
+(1211,Gonzaga: Some(31-2))
+(1320,Northern Iowa: Some(30-3))
+(1323,Notre Dame: Some(29-5))
+(1181,Duke: Some(29-4))
+(1438,Virginia: Some(29-3))
+(1268,Maryland: Some(27-6))
+```
+
+Note that the `ClassTag` parameter is required in `sortBy` to make use of Scala's reflection. That is why we had the above imports.
+
+
+## Performance optimization with TripletFields
+
+
+In addition to the `sendMsg` and `mergeMsg`, `aggregateMessages` can also take an optional argument `tripletsFields` which indicates what data is accessed in the EdgeContext. The main reason for explicitly specifying such information is to help optimize the performance of the `aggregateMessages` operation.
+
+In fact, `TripletFields` represents a subset of the fields of an _EdgeTriplet_ and it enables GraphX to populate only those fields when necessary.
+
+The default value is TripletFields.All which means that the `sendMsg` function may access any of the fields in the EdgeContext. Otherwise, the tripletFields argument is used to tell GraphX that only part of the EdgeContext will be required so that an efficient join strategy can be used. All possible options for the tripletsFields are listed below:
+
+- `TripletFields.All`: expose all the fields (source, edge, and destination).
+- `TripletFields.Dst`: expose the destination and edge fields but not the source field.
+- `TripletFields.EdgeOnly`: expose only the edge field.
+- `TripletFields.None`: None of the triplet fields are exposed.
+- `TripletFields.Src`: expose the source and edge fields but not the destination field.
+
+Using our previous example, if we are interested in computing the total number of wins and losses for each team, we will not need to access any field of the `EdgeContext`. In this case, we should use `TripletFields.None` to indicate so:
+
+```scala
+// Number of wins of the teams
+val numWins: VertexRDD[Int] = scoreGraph.aggregateMessages(
+ triplet => {
+ triplet.sendToSrc(1) // No attribute is passed but an integer
+ },
+ (x, y) => x + y,
+ TripletFields.None
+)
+
+// Number of losses of the teams
+val numLosses: VertexRDD[Int] = scoreGraph.aggregateMessages(
+ triplet => {
+ triplet.sendToDst(1) // No attribute is passed but an integer
+ },
+ (x, y) => x + y,
+ TripletFields.None
+)
+```
+
+To see, that this works, let's print the top 5 and bottom 5 teams:
+
+```scala
+scala> numWins.sortBy(_._2,false).take(5).foreach(println)
+(1246,34)
+(1437,32)
+(1112,31)
+(1458,31)
+(1211,31)
+
+scala> numLosses.sortBy(_._2, false).take(5).foreach(println)
+(1363,28)
+(1146,27)
+(1212,27)
+(1197,27)
+(1263,27)
+```
+
+Should you want the name of the top 5 teams, you need to access the `srcAttr` attribute. In this case, we need to set the `tripletFields` to `TripletFields.Src`:
+
+Kentucky as undefeated team in regular season:
+
+```scala
+val numWinsOfTeams: VertexRDD[(String, Int)] = scoreGraph.aggregateMessages(
+ t => {
+ t.sendToSrc(t.srcAttr, 1) // Pass source attribute only
+ },
+ (x, y) => (x._1, x._2 + y._2),
+ TripletFields.Src
+)
+```
+
+Et voila!
+
+```scala
+scala> numWinsOfTeams.sortBy(_._2._2, false).take(5).foreach(println)
+(1246,(Kentucky,34))
+(1437,(Villanova,32))
+(1112,(Arizona,31))
+(1458,(Wisconsin,31))
+(1211,(Gonzaga,31))
+
+scala> numWinsOfTeams.sortBy(_._2._2).take(5).foreach(println)
+(1146,(Cent Arkansas,2))
+(1197,(Florida A&M,2))
+(1398,(Tennessee St,3))
+(1263,(Maine,3))
+(1420,(UMBC,4))
+```
+
+Kentucky has not lost any of its 34 games during the regular season. Too bad that they could not make it into the championship final.
+
+
+## Warning about MapReduceTriplets operator
+
+Prior to Spark 1.2, there was no `aggregateMessages` method in `Graph`. Instead, the now deprecated `mapReduceTriplets` was the primary aggregation operator. The API for `mapReduceTriplets` is:
+
+```scala
+class Graph[VD, ED] {
+ def mapReduceTriplets[Msg](
+ map: EdgeTriplet[VD, ED] => Iterator[(VertexId, Msg)],
+ reduce: (Msg, Msg) => Msg)
+ : VertexRDD[Msg]
+}
+```
+
+Compared to `mapReduceTriplets`, the new operator `aggregateMessages` is more expressive as it employs the message passing mechanism instead of returning an iterator of messages as `mapReduceTriplets` does. In addition, `aggregateMessages` explicitly requires the user to specify the TripletFields object for performance improvement as we explained above. In addition to API improvements, `aggregateMessages` is optimized for performance.
+
+
+Because `mapReduceTriplets` is now deprecated, we will not discuss it further. If you have to use it with earlier versions of Spark, you can refer to the Spark programming guide.
+
+
+## Summary
+
+In brief, AggregateMessages is a useful and generic operator that provides a functional abstraction for aggregating neighbourhood information in Spark graphs. Its definition is summarized below:
+
+```scala
+class Graph[VD, ED] {
+ def aggregateMessages[Msg: ClassTag](
+ sendMsg: EdgeContext[VD, ED, Msg] => Unit,
+ mergeMsg: (Msg, Msg) => Msg,
+ tripletFields: TripletFields = TripletFields.All)
+ : VertexRDD[Msg]
+}
+```
+
+This operator applies a user defined `sendMsg` function to each edge in the graph using an `EdgeContext`. Each `EdgeContext` access the required information about the edge and passes that information to its source node and/or destination node using the `sendToSrc` and/or `sendToDst` respectively. After all messages are received by the nodes, the `mergeMsg` function is used to aggregate those messages at each node.
+
+## Some interesting reads
+
+1. [Six keys to sports analytics.](http://newsoffice.mit.edu/2015/mit-sloan-sports-analytics-conference-0302)
+2. [Moneyball: The Art Of Winning An Unfair Game](https://en.wikipedia.org/wiki/Moneyball)
+3. [Golden State Warriors at the forefront of NBA data analysis](http://www.sfgate.com/warriors/article/Golden-State-Warriors-at-the-forefront-of-NBA-5753776.php)
+4. [How Data and Analytics Have Changed 'The Beautiful Game'](http://www.huffingtonpost.com/travis-korte/soccer-analytics-data_b_5512271.html)
+5. [NHL, SAP partnership to lead statistical revolution](http://www.nhl.com/ice/news.htm?id=754184)
+
diff --git a/source/projects/spark-ml.markdown b/source/projects/spark-ml.markdown
new file mode 100644
index 0000000..54b15a6
--- /dev/null
+++ b/source/projects/spark-ml.markdown
@@ -0,0 +1,8 @@
+---
+layout: page
+title: "spark-ml"
+date: 2015-08-01 13:46
+comments: true
+sharing: true
+footer: true
+---
diff --git a/source/projects/time-series-decomposition.markdown b/source/projects/time-series-decomposition.markdown
new file mode 100644
index 0000000..c2d44e5
--- /dev/null
+++ b/source/projects/time-series-decomposition.markdown
@@ -0,0 +1,287 @@
+---
+layout: page
+title: "Time Series: trend analysis, smoothing and anomaly detection"
+date: 2015-08-10 19:54
+comments: true
+sharing: true
+footer: true
+---
+
+
+## Forecasting
+
+Forecasting is an important tool for making effective decisions, planning efficiently and reducing risks.
+
+Forecasting is useful in many situations when uncertain quantity or event must and can be predicted. In other words, we must have data that allows to forecast the quantity or event accurately. Then, we need to build a model that can tell the difference between a random fluctuation and a existing pattern in the data. A good forecasting model should capture such patterns with a minimum out-of-sample error.
+
+
+### Time series forecasting
+
+Time series forecasting is concerned with only one question. Can we predict future values by looking at past ones? We are not attempting to identify factors that help explain the future. Instead, we want to accurately estimate how the historical data series will continue into the future. Thus, we want to find a functional relationship of the following form:
+
+$$
+Y_{t+1} = f(Y_t, Y_{t-1}, Y_{t-2}, ... , Y_{t-n}, \text{error})
+$$
+
+Such relationship is described by a time series model.
+
+### Basic forecasting steps
+
+There are in general four tasks that must be undertaken in forecasting.
+
+1. **Define the problem.** This is the most difficult task as we need to determine what exactly to forecast, within what time horizon and how frequently.
+2. **Gather data.** It is primordial to find and collect historical data to construct a model with which we can forecast the future. For time series, this can be anything that are observed sequentially over time.
+3. **Building and choosing models.** This step involves choosing and fitting several forecasting models. Each model has parameters that must be fitted based on the known historical data.
+4. **Selecting and using the best model.** We select the model that provides the most accurate predictions on the test data samples, i.e. data that were held out and not used for building the models. With the selected model, we can then predict future values and determine some prediction intervals.
+
+
+### Time series patterns
+
+Before building any forecasting model, it often helps to explore time series data by simply plotting them. This help to understand the behavior of the series data and the patterns that exist in the data. There exist four types of time series data patterns:
+
+1. A **stationary _horizontal_ pattern (H)** exists when the data values clearly fluctuate around a constant mean.
+2. A **_seasonal_ pattern (S)** exists because of the effects of seasonal factors (e.g. beginning of fiscal year, financial reporting quarters, weekends, days of the week, holidays, etc.) Note that such patterns need not to be exactly periodic.
+3. A **_cyclical_ pattern (C)** is present when the data values show a sequence of rises and falls that are not of a fixed period. Typical examples of a cyclical pattern are business cycles that impact the quantity of sales over a longer period of time.
+4. A **_trend_ (T)** is a long-term increase or decrease in the data. For instance, stock prices of high-growth companies usually exhibit a strong upward trend over a long period of time.
+
+A time series can have many of these four components at the same time. Sometimes, it is more convenient to combine H, C and T as a cycle-trend pattern that represents long-term changes in the time series. As a result, we will think of time series as a function of three components: the trend, the seasonality and the random error:
+
+$$
+\text{Time Series} = f(\text{Trend-Cycle}, \text{Seasonality}, \text{error})
+$$
+
+Most forecasting models explicitly assume that the random error is always present and try to minimize this error during model fitting. Depending on the actual time series, the functional relationship above can be additive or multiplicative. For example, we have the following with an additive decomposition model:
+
+$$
+\text{Time Series} = \text{Trend-Cycle} + \text{Seasonality} + \text{error}
+$$
+
+For a multiplicative model, the time series decomposes as follows:
+
+$$
+\text{Time Series} = \text{Trend-Cycle} \times \text{Seasonality} \times \text{error}
+$$
+
+In Haskell, we can for instance define a `TimeSeries` type as follows:
+
+```haskell
+data TimeSeries = TimeSeries [TimeStamp] [Float]
+type TS = TimeSeries
+```
+
+Let's suppose that we can appropriately define addition, substraction and multiplication over `TimeSeries`:
+
+```haskell
+(+) :: TS -> TS -> TS
+(-) :: TS -> TS -> TS
+(*) :: TS -> TS -> TS
+```
+
+Additionally, we need convenience functions for creating lagged version of a time series or for extracting data points that are within a given window of the series:
+
+```haskell
+lag :: TS -> Time -> TS
+window :: TS -> Time -> Time -> TS
+```
+
+
+## Time series decomposition
+
+In principle, if we want to further analyze the time series, we can use decomposition methods that extract these individual patterns. Decomposition methods are useful for forecasting as the trend-cycle can be used to extrapolate future values. This is the idea of **smoothing techniques**, which _smooth_ the series by eliminating the random fluctuations. Decomposition method is also needed when we want to detect anomalies such as outliers in the time series. We will cover about this topic later.
+
+
+### Basic decomposition method:
+
+A simple decomposition method consists of the following steps:
+
+1. The trend-cycle is computed using a Moving Average or LOESS method.
+2. The de-trended series is computed by removing the trend component from the time series.
+3. The seasonality component is extracted by averaging the values of the seasonal points over multiple periods (e.g. the values corresponding to same month for a monthly time series data)
+4. We obtain the residual errors by subtracting the previously estimated components from the time series.
+
+In Haskell, a decomposition method takes an input time series and return its three components:
+
+```haskell
+decompose :: TS -> (TS, TS, TS)
+decompose timeseries = (trendcycle, seasonality, residual)
+```
+
+Next, let's see these specific techniques in more details.
+
+
+### Seasonal effects adjustment
+
+We have seen that a decomposition method fully decomposes the series. Sometimes, we may just need to adjust time series to seasonal effects. In that case, we only need to remove its seasonality component. For example, the seasonal variation may be irrelevant and even lead to false conclusions to our analysis objectives. For an additive model, the _seasonally adjusted series_ is obtained after removing the seasonal pattern:
+
+$$
+\text{Seasonally Adjusted Series} = \text{Time Series} - \text{Seasonality} = \text{Trend-Cycle} + \text{error}
+$$
+
+For that, we can define function that decomposes a time series into its seasonality component and a seasonally adjusted series:
+
+```haskell
+seasonAdjust :: TS -> (TS, TS)
+seasonAdjust ts = (seas, adjusted)
+ where adjusted = ts - seas
+ (_, seas, _) = decompose ts
+```
+
+### Moving averages
+
+The Trend-Cycle component can be estimated by _smoothing_ the seasonally adjusted series. In other words, we reduce the random error fluctuations after removing the seasonality. The easiest way to do this is with a simple _moving average_. In the following, let's consider several moving average methods.
+
+#### Simple moving averages
+
+Moving average is based on the idea that values that are nearby in time are likely to be close. Hence, taking an average of neighboring points of each data point will yield a good estimate of the trend at that point. Local averaging smooths out the randomness in the data. There are two design parameters to consider:
+
+1. How many data points do we include in each average?
+2. How much weight do we put for each neighboring point involved in the average?
+
+The simplest MA smoother averages an odd number of observations around each data point and put equal weights to them. For instance, a MA smoother of order 3 centered at a time `t` is:
+
+$$
+T_t = \frac{1}{3} (Y_{t-1} + Y_{t} + Y_{t+1})
+$$
+
+Then, the estimate at time $$t+1$$ is obtained by dropping the oldest observation $$Y_{t-1}$$ and by including the next observation $$Y_{t-2}$$. Hence, the term _moving average_ describes this procedure.
+
+> The number of points involved in the average, or the order of the MA, affects the smoothness of the estimate. More points lead to a smoother trend. The drawback of MA is that it is impossible to estimate the trend-cycle close to the beginning and end of the series. The higher the order, the more points we miss at the front and back of the series.
+
+In summary, the movies averages takes two parameters: the number of points involved in each average and the weights of each point:
+
+```haskell
+movingAverage :: Int -> [Float] -> TS -> TS
+movingAverage numPoints weights timeSeries = trend
+ where trend = ...
+```
+
+
+### Double moving averages:
+
+Moving averages can be combined by smoothing an already smoothed series. For example, a $$3 \times 3$$ MA is a 3 MA of a 3 MA. When each 3 MA uses equal weights, the result is equivalent to a 5-period weighted moving average with the weigths 0.111, 0.222, 0.333, 0.222 and 0.111.
+
+Thus, the following double moving average
+
+```haskell
+simpleAverage :: TS -> TS
+simpleAverage = movingAverage 3 [0.333, 0.333, 0.333]
+doubleMovingAverage = simpleAverage . simpleAverage
+```
+
+is equivalent to:
+
+```haskell
+doubleMovingAverage :: TS -> TS
+doubleMovingAverage = movingAverage 5 [0.111, 0.222, 0.333, 0.222, 0.111]
+```
+
+### Weighted moving averages:
+
+In general, a weighted MA with order $$k$$ can be written as:
+
+$$
+T_t = \sum_{j=-\frac{k-1}{2}}^{\frac{k-1}{2}} w_j Y_{t+j}
+$$
+
+### LOESS smoothing
+
+Alternatively, we can use a local linear regression technique to determine the trend of a time series. Precisely, we can fit a straight line through the observations near each data point. Then, the estimate of the trend at each point is given by each fitted line. For the data point at time $$t$$, the estimated trend-cycle $$T$$ is given by:
+
+$$
+T_t = a + bt
+$$
+
+where the parameters $a$ and $b$ are determined for each point at time $t$ by minimizing the sum of squared error:
+
+$$
+\sum{j=-\frac{k-1}{2}}^{\frac{k-1}{2}} w_j(Y_{t+j} - a - b(t+j))^2
+$$
+
+
+Another question is how much weight $$w_j$$ we give to each point. Actually, Cleveland and his colleagues at Bell Labs propose a version of LOESS that is robust against outliers or unusual observations in the data. Their algorithm performs three things in each iteration:
+
+1. Run a local weighted regression smoothing (_see above_) for given weights
+2. Compute the error residuals using the fitted curve
+3. Adjust the weights so that large errors receive smaller weights
+
+A loess function is thus defined as follows:
+
+```haskell
+loess :: TS -> [Float] -> TS
+loess series weights = trend
+ where trend = ... -- run recursive of smoothing and weight adjustment
+```
+
+> Note that the LOESS is more computationally intensive than MA methods since a different value of $a$ and $b$ needs to be computed for every observation at a time $t$. For that, a different line is fitted at each data point using least squares. The number of points used in the local regression should not be too large to avoid underfitting and not too small to produce the desired smoothing.
+
+### STL decomposition
+
+The STL decomposition method literally stands for "Seasonal-Trend decomposition procedure based on Loess". It iteratively apply a LOESS smoother to give a decomposition that is robust against outliers. Another benefit of STL is that it has a flexibility to handle seasonality with abritrary length. The seasonality length just needs to be greater than one, which is usually satisfied in most applications. STL is flexible as it can handle trends of varying smoothness, missing values and seasonality of period other than quartlerly and monthly.
+
+
+STL consists of the following two recursive procedures:
+
+1. **Inner loop.** In each iteration of the inner loop, the seasonal and trend-cycle components are updated once.
+2. **Outer loop.** An iteration of outer loop consists of one or two iterations of the inner loop. At the end of each outer loop iteration, outliers are detected. Future iterations of the inner loop puts smaller weights to these outliers in the LOESS regression.
+
+More details about the operations performed in these two loops are described below. Although STL works with arbitrary cycle length, let us simply assume that we have a monthly time series data. This will simplify the explanations.
+
+#### Inner Loop procedure:
+
+We start the procedure by assuming the trend-cycle component is zero. Then, each iteration of the inner loop does the following two things:
+
+1. *Seasonal smoothing*: updates the seasonality component
+2. *Trend-cycle smoothing*: updates the trend-cycle smoothing
+
+**Seasonal smoothing**
+
+To obtain the seasonality component, we perform the following tasks in sequence:
+
+1. De-trend the series by removing the current trend-cycle estimate
+2. Collect the de-trended values for each month. As a result, we will get 12 separate sub-series.
+3. Smooth each of these sub-series with a LOESS smoother.
+4. Glue back the sub-series together to obtain a preliminary seasonality component.
+5. Extrapolate the Loess smoother to estimate the seasonal component for a few months before and after the observed data.
+6. Run a $$3 × 12 × 12$$ moving average on the resulting seasonality component.
+7. Follow with a LOESS smoothing of length 13 (one more than the seasonal period length). The loss of values at the beginning and end due to the moving average was anticipated and overcome by the extrapolation in **Task 5** above. This step also checks any possible trend component in the seasonality.
+8. Compute the seasonality component as difference between the results of step 6 and step 7.
+
+**Trend-cycle smoothing**
+
+Given the seasonality component, get the trend-cycle with two simple steps:
+
+1. Calculate the seasonally adjusted time series by substracting the seasonality from the original series.
+2. Smooth the adjusted time series with LOESS.
+
+#### Outer Loop:
+
+The outer loop consists of the following steps:
+
+1. Run one or two inner loop iterations to get the trend-cycle and seasonality.
+2. Calculate the error residuals by subtracting the trend-cycle and seasonality from the time series.
+3. Identify the observations with unusually large residual values. These could be outliers!
+4. Adjust the weights used for LOESS by downweighting the outliers.
+
+Note that in the STL procedure, all future inner iterations of inner loop begin with the trend component from the previous iteration rather than starter from zero as in the very first iteration of the inner loop.
+
+
+### STL-based Anomaly detection in time series
+
+Proposed by Vallis and his colleagues at Twitter, STL decomposition can be used to detect outliers in long-term time series data with seasonality and trend-cycle. Their proposed method is piece-wise in the sense that a long-term time series is broken down into multiple windows of time series.
+
+For each window, the following **median-based outlier detection** method is performed:
+
+1. Extract the seasonality component $$S$$ using STL decomposition.
+2. Compute the median $$\tilde{Y}$$
+3. Compute the residual $$R = Y - S - \tilde{Y}$$
+4. Run a standard outlier detection on the residuals (e.g. using median absolute deviation)
+
+## Summary
+
+We have presented an overview of time series analysis and forecasting. Time series can be decomposed into three components: a trend-cycle, a seasonality and the error residual. To extract the trend-cycle, we can employe moving average and LOESS techniques. The seasonality component can be obtained from the de-trended series using the STL decomposition procedure, which is flexible and robust against outliers. The STL decomposition method is also a key ingredient for detecting anomalies and outliers in time series data.
+
+## Further reading:
+
+- Makridakis, S., S. Wheelwright, R. Hyndman, and Y. Chang. Forecasting Methods and Applications. 3rd ed. New York: John Wiley & Sons, 1998.
+- Cleveland, R.B, Cleveland, W.S, Mcrae, J.E, and Terpenning, I. STL: A Seasonal-Trend decomposition procedure based on loess. Journal of Official Statistics, 6(1):3–73, 1990.
+- Vallis, O., Hochenbaum, J. and Kejariwal, A., (2014) “A Novel Technique for Long-Term Anomaly Detection in the Cloud”, 6th USENIX Workshop on Hot Topics in Cloud Computing, Philadelphia, PA.
diff --git a/source/robots.txt b/source/robots.txt
new file mode 100644
index 0000000..d47c1f5
--- /dev/null
+++ b/source/robots.txt
@@ -0,0 +1,7 @@
+---
+layout: null
+---
+User-agent: *
+Disallow:
+
+Sitemap: {{ site.url }}/sitemap.xml