├── sounds ├── sample.mp3 ├── bgm │ └── happygit.wav ├── event │ └── cchord.wav └── silence │ ├── silence500.wav │ ├── silence1000.wav │ ├── silence1500.wav │ └── silence5000.wav ├── public ├── fonts │ └── helvnue-th.otf ├── gfx │ └── photos │ │ ├── detail.jpg │ │ ├── inroom.jpg │ │ └── pirsensor.jpg ├── index.html ├── css │ └── main.css └── js │ ├── libs │ ├── curve.js │ ├── skycons.js │ ├── moment.min.js │ └── jquery.min.js │ └── main.js ├── logger.js ├── .gitignore ├── TODO.md ├── package.json ├── config-sample.js ├── musicplayer.js ├── tts.js ├── README.md └── main.js /sounds/sample.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/setpixel/weather-display/HEAD/sounds/sample.mp3 -------------------------------------------------------------------------------- /sounds/bgm/happygit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/setpixel/weather-display/HEAD/sounds/bgm/happygit.wav -------------------------------------------------------------------------------- /sounds/event/cchord.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/setpixel/weather-display/HEAD/sounds/event/cchord.wav -------------------------------------------------------------------------------- /public/fonts/helvnue-th.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/setpixel/weather-display/HEAD/public/fonts/helvnue-th.otf -------------------------------------------------------------------------------- /public/gfx/photos/detail.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/setpixel/weather-display/HEAD/public/gfx/photos/detail.jpg -------------------------------------------------------------------------------- /public/gfx/photos/inroom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/setpixel/weather-display/HEAD/public/gfx/photos/inroom.jpg -------------------------------------------------------------------------------- /sounds/silence/silence500.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/setpixel/weather-display/HEAD/sounds/silence/silence500.wav -------------------------------------------------------------------------------- /public/gfx/photos/pirsensor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/setpixel/weather-display/HEAD/public/gfx/photos/pirsensor.jpg -------------------------------------------------------------------------------- /sounds/silence/silence1000.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/setpixel/weather-display/HEAD/sounds/silence/silence1000.wav -------------------------------------------------------------------------------- /sounds/silence/silence1500.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/setpixel/weather-display/HEAD/sounds/silence/silence1500.wav -------------------------------------------------------------------------------- /sounds/silence/silence5000.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/setpixel/weather-display/HEAD/sounds/silence/silence5000.wav -------------------------------------------------------------------------------- /logger.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var config = require('./config') 4 | var moment = require('moment') 5 | 6 | class Logger { 7 | 8 | static log( message, level ) { 9 | if (!level) { level = 0 } 10 | if (level >= config.logLevel) { 11 | console.log(moment().format('MM/DD/YY h:mm:ssa') + ` || ${message}`) 12 | } 13 | } 14 | 15 | } 16 | 17 | module.exports = Logger -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | 29 | .env 30 | 31 | scratch/ 32 | 33 | config.js -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | 4 | save volume 5 | 6 | its going to rain alert or any precip? snow? 7 | 8 | legit colder than yesterday (currently it just says it is) 9 | 10 | detect if on raspberry pi or computer 11 | change orientation 12 | init the gpio stuff 13 | 14 | Figure out volume issue 15 | 16 | SOUND 17 | make more bgm for different weather conditions 18 | different event sounds for different events? morning, hourly (maybe this is overkill) 19 | 20 | Hook in Calendar? 21 | 22 | Special work days 23 | 24 | RSS feed reader for news 25 | 26 | voice input 27 | 28 | 29 | # TO TEST 30 | 31 | play music if here for a while in 32 | 33 | to add to config: 34 | play npr news in morning 35 | // http://www.npr.org/rss/podcast.php?id=452538242 36 | play npr news when get home 37 | play npr news at sunset 38 | 39 | 40 | add button mute music 41 | // add pin for button 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weather-display", 3 | "version": "0.0.1", 4 | "description": "A weather display system for the home, on the Raspberry Pi platform and various sensors", 5 | "main": "main.js", 6 | "scripts": { 7 | "start": "node main.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/setpixel/weather-display.git" 13 | }, 14 | "keywords": [ 15 | "weather", 16 | "raspberry", 17 | "pi" 18 | ], 19 | "author": "Charles Forman", 20 | "license": "ISC", 21 | "bugs": { 22 | "url": "https://github.com/setpixel/weather-display/issues" 23 | }, 24 | "homepage": "https://github.com/setpixel/weather-display#readme", 25 | "dependencies": { 26 | "express": "^4.13.3", 27 | "forecast.io-bluebird": "0.0.1", 28 | "ivona-node": "^0.2.0", 29 | "moment": "^2.11.1", 30 | "mopidy": "^0.5.0", 31 | "node-localstorage": "^1.1.2", 32 | "rpi-gpio": "^0.7.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Weather Display 6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | 18 |
19 | 20 |
21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /config-sample.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | version: '0.0.1', 3 | forecast: { // Get a Forecast.io account: https://developer.forecast.io/ (Best weather api) 4 | apiKey: 'XXX__INSERTYOURKEYHERE__XXX', 5 | lat: '40.723228', // Look up your lat long: http://www.latlong.net/ 6 | long: '-73.995614', 7 | checkInterval: 5*60*1000, // 5 minutes 8 | }, 9 | ivona: { // Get an Ivona account for text to speech: https://www.ivona.com/ Sign up, get an api key and secret 10 | accessKey: 'XXX__INSERTYOURKEYHERE__XXX', 11 | secretKey: 'XXX__INSERTYOURKEYHERE__XXX' 12 | }, 13 | dayMilestones: [ 14 | ["Sunrise", 6], // You can change the hours, or even add new ones. 15 | ["Wake up", 8], 16 | ["Breakfast", 9], 17 | ["Work", 10], 18 | ["Lunch",12], 19 | ["Sunset", 8+12], 20 | ["Get ready for bed", 12+10.5], 21 | ["Bed time", 12+11] 22 | ], 23 | appearalDegrees: { 24 | hoodie: 64, // Anything belore this number (in F) is that. 25 | jacket: 55, 26 | heavyJacket: 45, 27 | fullWinter: 30 28 | }, 29 | hostname: 'raspberrypi', // If your Raspberry Pi hostname is something else, change it. 30 | port: process.env.PORT || 3000, 31 | logLevel: 0, 32 | presenceTimeout: 2*60*1000, // Light away after 2 minutes 33 | awayTimeout: 35*60*1000, // Definitate away after 35 minutes 34 | goneTimeout: 3*60*60*1000, // Gone after 3 hours 35 | gpioPin: 13, // Pin 13 for the data from the PIR sensor 36 | hourlyNotifications: true, 37 | mopidyAddress: 'ws://10.0.1.37:6680/mopidy/ws/', 38 | newsPodcastUri: 'podcast+http://www.npr.org/rss/podcast.php?id=500005', 39 | musicPlaylistUri: 'spotify:user:setpixel:playlist:0P2T0VBhivKnAjqEwXJkmG', 40 | playMusicAfter: 10*60*1000, // play music after present for 10 minutes 41 | stopMusicAfter: 20*60*1000, // stop playing music after 20 minutes of gone 42 | } 43 | 44 | module.exports = config -------------------------------------------------------------------------------- /public/css/main.css: -------------------------------------------------------------------------------- 1 | @font-face { font-family: 'HelveticaT'; src: url('../fonts/helvnue-th.otf'); } 2 | 3 | body, html { 4 | overflow-x: hidden; 5 | overflow-y: hidden; 6 | cursor: none; 7 | } 8 | 9 | body { 10 | font-family: "HelveticaT"; 11 | font-weight: 100; 12 | margin: 0px; 13 | background-color: rgb(0,0,0); 14 | } 15 | 16 | #bg { 17 | font-family: "HelveticaT"; 18 | background-color: rgb(0,0,0); 19 | width: 1080px; 20 | height: 1920px; 21 | margin: 0px; 22 | padding: 0px; 23 | -webkit-transform: rotate(90deg) translate(0px,-1920px); 24 | -webkit-transform-origin: top left; 25 | color: rgb(255,255,255); 26 | } 27 | 28 | #bg.sunset { 29 | color: rgb(255,200,200); 30 | } 31 | 32 | #bg.night { 33 | color: rgb(40,0,0); 34 | } 35 | 36 | 37 | .alert { 38 | background-color: rgb(0,255,255) !important; 39 | } 40 | 41 | #shade { 42 | display: block; 43 | position: absolute; 44 | width: 1200px; 45 | height: 1920px; 46 | /* background-color: rgba(80,30,0,0.5); 47 | */ background-color: rgba(30,0,0,0.85); 48 | z-index: 99; 49 | mix-blend-mode: multiply; 50 | display: none; 51 | } 52 | 53 | #current_temp { 54 | font-size: 400px; 55 | display: inline-block; 56 | left: 40px; 57 | position: relative; 58 | line-height: 400px; 59 | margin: 0px; 60 | padding: 0px; 61 | top: 80px; 62 | } 63 | 64 | #current_condition_icon { 65 | position: relative; 66 | display: inline-block; 67 | top: -90px; 68 | left: 30px; 69 | } 70 | 71 | 72 | #clock { 73 | font-size: 100px; 74 | line-height: 1em; 75 | position: relative; 76 | display: inline-block; 77 | float: right; 78 | } 79 | 80 | #countdown { 81 | font-size: 50px; 82 | top: -30px; 83 | position: relative; 84 | } 85 | 86 | .contdown-label { 87 | opacity: 0.3; 88 | } 89 | 90 | #date { 91 | font-size: 28px; 92 | right: 20px; 93 | top: 0px; 94 | line-height: 1em; 95 | position: relative; 96 | display: inline-block; 97 | opacity: 0.3; 98 | 99 | 100 | } 101 | 102 | #date_container { 103 | font-size: 100px; 104 | line-height: 1em; 105 | position: absolute; 106 | top: 50px; 107 | right: 50px; 108 | text-align: right; 109 | 110 | } 111 | 112 | #graph_day { 113 | position: relative; 114 | left: 50px; 115 | margin-bottom: 50px; 116 | border-radius: 10px; 117 | } 118 | 119 | 120 | .summary_text { 121 | margin-left: 50px; 122 | margin-right: 50px; 123 | margin-bottom: 50px; 124 | font-size: 50px; 125 | line-height: 60px; 126 | } -------------------------------------------------------------------------------- /public/js/libs/curve.js: -------------------------------------------------------------------------------- 1 | /*! Curve extension for canvas 2.2 2 | * Epistemex (c) 2013-2014 3 | * License: MIT 4 | */ 5 | 6 | /** 7 | * Draws a cardinal spline through given point array. Points must be arranged 8 | * as: [x1, y1, x2, y2, ..., xn, yn]. It adds the points to the current path. 9 | * 10 | * The method continues previous path of the context. If you don't want that 11 | * then you need to use moveTo() with the first point from the input array. 12 | * 13 | * The points for the cardinal spline are returned as a new array. 14 | * 15 | * @param {Array} points - point array 16 | * @param {Number} [tension=0.5] - tension. Typically between [0.0, 1.0] but can be exceeded 17 | * @param {Number} [numOfSeg=20] - number of segments between two points (line resolution) 18 | * @param {Boolean} [close=false] - Close the ends making the line continuous 19 | * @returns {Array} New array with the calculated points that was added to the path 20 | */ 21 | CanvasRenderingContext2D.prototype.curve = function(points, tension, numOfSeg, close) { 22 | 23 | 'use strict'; 24 | 25 | // options or defaults 26 | tension = (typeof tension === 'number') ? tension : 0.5; 27 | numOfSeg = numOfSeg ? numOfSeg : 20; 28 | 29 | var pts, // clone point array 30 | res = [], 31 | l = points.length, i, 32 | cache = new Float32Array((numOfSeg+2)*4), 33 | cachePtr = 4; 34 | 35 | pts = points.slice(0); 36 | 37 | if (close) { 38 | pts.unshift(points[l - 1]); // insert end point as first point 39 | pts.unshift(points[l - 2]); 40 | pts.push(points[0], points[1]); // first point as last point 41 | } 42 | else { 43 | pts.unshift(points[1]); // copy 1. point and insert at beginning 44 | pts.unshift(points[0]); 45 | pts.push(points[l - 2], points[l - 1]); // duplicate end-points 46 | } 47 | 48 | // cache inner-loop calculations as they are based on t alone 49 | cache[0] = 1; 50 | 51 | for (i = 1; i < numOfSeg; i++) { 52 | 53 | var st = i / numOfSeg, 54 | st2 = st * st, 55 | st3 = st2 * st, 56 | st23 = st3 * 2, 57 | st32 = st2 * 3; 58 | 59 | cache[cachePtr++] = st23 - st32 + 1; // c1 60 | cache[cachePtr++] = st32 - st23; // c2 61 | cache[cachePtr++] = st3 - 2 * st2 + st; // c3 62 | cache[cachePtr++] = st3 - st2; // c4 63 | } 64 | 65 | cache[++cachePtr] = 1; 66 | 67 | // calc. points 68 | parse(pts, cache, l); 69 | 70 | if (close) { 71 | //l = points.length; 72 | pts = []; 73 | pts.push(points[l - 4], points[l - 3], points[l - 2], points[l - 1]); // second last and last 74 | pts.push(points[0], points[1], points[2], points[3]); // first and second 75 | parse(pts, cache, 4); 76 | } 77 | 78 | function parse(pts, cache, l) { 79 | 80 | for (var i = 2; i < l; i += 2) { 81 | 82 | var pt1 = pts[i], 83 | pt2 = pts[i+1], 84 | pt3 = pts[i+2], 85 | pt4 = pts[i+3], 86 | 87 | t1x = (pt3 - pts[i-2]) * tension, 88 | t1y = (pt4 - pts[i-1]) * tension, 89 | t2x = (pts[i+4] - pt1) * tension, 90 | t2y = (pts[i+5] - pt2) * tension; 91 | 92 | for (var t = 0; t <= numOfSeg; t++) { 93 | 94 | var c = t * 4; 95 | 96 | res.push(cache[c] * pt1 + cache[c+1] * pt3 + cache[c+2] * t1x + cache[c+3] * t2x, 97 | cache[c] * pt2 + cache[c+1] * pt4 + cache[c+2] * t1y + cache[c+3] * t2y); 98 | } 99 | } 100 | } 101 | 102 | // add lines to path 103 | for(i = 0, l = res.length; i < l; i += 2) 104 | this.lineTo(res[i], res[i+1]); 105 | 106 | return res; 107 | }; 108 | -------------------------------------------------------------------------------- /musicplayer.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var config = require('./config') 4 | var Logger = require('./logger') 5 | var Mopidy = require("mopidy"); 6 | 7 | class MusicPlayer { 8 | 9 | constructor() { 10 | this.mopidy = new Mopidy({ 11 | webSocketUrl: config.mopidyAddress, 12 | callingConvention: "by-position-or-by-name" 13 | }) 14 | 15 | this.playing = false 16 | this.volume = 100 17 | 18 | setInterval(()=>this.getState().then(), 10000) 19 | } 20 | 21 | playPodcast(uri) { 22 | var mopidy = this.mopidy 23 | this.playing = true 24 | 25 | mopidy.mixer.setVolume({volume: 100}) 26 | 27 | mopidy.tracklist.clear().then(()=>{ 28 | mopidy.library.browse({uri: uri }).then((result)=>{ 29 | mopidy.tracklist.add({uri: result[0].uri}).then((e)=>{ 30 | Logger.log(`Playing news podcast`) 31 | mopidy.playback.play() 32 | }) 33 | }) 34 | }) 35 | } 36 | 37 | playPlaylist(uri, volume) { 38 | var mopidy = this.mopidy 39 | this.playing = true 40 | 41 | if (volume) { 42 | this.volume = volume 43 | mopidy.mixer.setVolume({volume: this.volume}) 44 | } else { 45 | mopidy.mixer.setVolume({volume: this.volume}) 46 | } 47 | 48 | mopidy.tracklist.clear().then(()=>{ 49 | mopidy.tracklist.add({uri: uri}).then((result)=>{ 50 | mopidy.tracklist.shuffle().then(()=>{ 51 | Logger.log(`Playing music playlist`) 52 | mopidy.playback.play() 53 | }) 54 | }) 55 | }) 56 | } 57 | 58 | stop() { 59 | var mopidy = this.mopidy 60 | Logger.log(`Stopping music`) 61 | this.playing = false 62 | mopidy.playback.stop() 63 | } 64 | 65 | fadeDown(steps, ms, downTo) { 66 | var mopidy = this.mopidy 67 | if (!steps) steps = 5 68 | if (!ms) ms = 500 69 | if (!downTo) downTo = 72 70 | var thisVolume = this.volume 71 | var promise = new Promise( function (resolve, reject) { 72 | mopidy.mixer.getVolume().then((e)=>{ 73 | thisVolume = e 74 | for (var i = 1; i <= steps; i++) { 75 | var volumeChunks = (thisVolume - downTo) / steps 76 | var volume = Math.round(thisVolume - (volumeChunks * i)) 77 | if (i == steps) { 78 | setTimeout(function(){ 79 | mopidy.mixer.setVolume({volume: Number(this)}).then(()=>{ 80 | resolve(true) 81 | })}.bind(volume), (ms/steps)*i) 82 | } else { 83 | setTimeout(function(){ 84 | mopidy.mixer.setVolume({volume: Number(this)}).then(()=>{ 85 | })}.bind(volume), (ms/steps)*i) 86 | } 87 | } 88 | }) 89 | }) 90 | return promise 91 | } 92 | 93 | fadeUp(steps, ms, to) { 94 | var mopidy = this.mopidy 95 | if (!steps) steps = 10 96 | if (!ms) ms = 500 97 | if (to) this.volume = to 98 | mopidy.mixer.getVolume().then((e)=>{ 99 | for (var i = 1; i <= steps; i++) { 100 | var volumeChunks = Math.abs(this.volume - e) / steps 101 | var volume = Math.round(e + (volumeChunks * i)) 102 | setTimeout(function(){ 103 | mopidy.mixer.setVolume({volume: Number(this)}) 104 | }.bind(volume), (ms/steps)*i) 105 | } 106 | }) 107 | } 108 | 109 | getState() { 110 | var mopidy = this.mopidy 111 | var thisObj = this; 112 | var promise = new Promise( function (resolve, reject) { 113 | mopidy.playback.getState().then((e)=>{ 114 | if (e !== 'playing') { 115 | if (thisObj.playing) { 116 | mopidy.mixer.setVolume({volume: Number(85)}) 117 | thisObj.volume = 85 118 | } 119 | thisObj.playing = false 120 | } else { 121 | thisObj.playing = true 122 | } 123 | mopidy.mixer.getVolume().then((data)=>{ 124 | thisObj.volume = data 125 | }) 126 | }) 127 | }) 128 | return promise 129 | } 130 | 131 | } 132 | 133 | module.exports = MusicPlayer -------------------------------------------------------------------------------- /tts.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs') 4 | var child_process = require('child_process') 5 | var Ivona = require('ivona-node/') 6 | var config = require('./config') 7 | var Logger = require('./logger') 8 | 9 | class TTS { 10 | 11 | constructor(musicPlayer){ 12 | this.ivona = new Ivona({ 13 | accessKey: config.ivona.accessKey, 14 | secretKey: config.ivona.secretKey 15 | }) 16 | 17 | if (musicPlayer) this.musicPlayer = musicPlayer 18 | 19 | this.speaking = false 20 | this.processing = false 21 | 22 | this.voiceOptions = { 23 | body: { 24 | voice: { 25 | gender: 'Female', 26 | language: 'en-GB', 27 | name: 'Amy' 28 | }, 29 | parameters: { 30 | volume: 'x-loud', 31 | rate: 'medium', 32 | sentenceBreak : 600, 33 | paragraphBreak : 1200 34 | }, 35 | input: { 36 | type: 'application/ssml+xml' 37 | } 38 | } 39 | } 40 | 41 | } 42 | 43 | speak(string, options) { 44 | if (!options) { 45 | options = { 46 | alert: true, 47 | bgm: true, 48 | volume: 7, 49 | } 50 | } 51 | if (this.processing || this.speaking) { 52 | Logger.log("Attempted to speak... I'm already speaking or processing. Abandoning.") 53 | } else { 54 | Logger.log("TTS processing: " + string.split("\n").join('')) 55 | this.processing = true 56 | this.ivona.createVoice(`` + string + ``, JSON.parse(JSON.stringify(this.voiceOptions))) 57 | .pipe(fs.createWriteStream('/tmp/text.mp3')) 58 | .on('finish', () => { 59 | var commands = [] 60 | if (options.bgm || options.alert) { 61 | if (options.bgm) { 62 | commands.push('sox sounds/silence/silence1000.wav sounds/silence/silence1000.wav /tmp/text.mp3 sounds/silence/silence1500.wav sounds/silence/silence1500.wav sounds/silence/silence5000.wav /tmp/textdelay.mp3') 63 | } else { 64 | commands.push('sox sounds/silence/silence1000.wav sounds/silence/silence1000.wav /tmp/text.mp3 /tmp/textdelay.mp3') 65 | } 66 | if (options.bgm && options.alert) { 67 | commands.push('sox -m sounds/event/cchord.wav /tmp/textdelay.mp3 sounds/bgm/happygit.wav /tmp/new.mp3 trim 0 `soxi -D /tmp/textdelay.mp3`') 68 | } else if (options.alert) { 69 | commands.push('sox -m sounds/event/cchord.wav /tmp/textdelay.mp3 /tmp/new.mp3 trim 0 `soxi -D /tmp/textdelay.mp3`') 70 | } else { 71 | commands.push('sox -m /tmp/textdelay.mp3 sounds/bgm/happygit.wav /tmp/new.mp3 trim 0 `soxi -D /tmp/textdelay.mp3`') 72 | } 73 | 74 | if (options.bgm) { 75 | commands.push('sox /tmp/new.mp3 /tmp/new2.mp3 fade t 0 `soxi -D /tmp/new.mp3` 0:05') 76 | } else { 77 | commands.push('mv /tmp/new.mp3 /tmp/new2.mp3') 78 | } 79 | 80 | } else { 81 | commands.push('mv /tmp/text.mp3 /tmp/new2.mp3') 82 | } 83 | child_process.exec(commands.join(' && '), () => { 84 | this.processing = false 85 | Logger.log("TTS speaking: " + string.split("\n").join('')) 86 | this.speaking = true 87 | 88 | if (this.musicPlayer.playing) { 89 | this.musicPlayer.fadeDown().then(()=>{ 90 | child_process.exec(`play /tmp/new2.mp3`, () => { 91 | Logger.log("TTS finished playing") 92 | if (this.musicPlayer.playing) this.musicPlayer.fadeUp() 93 | this.speaking = false 94 | if (options.playnews) { 95 | this.musicPlayer.playPodcast(config.newsPodcastUri) 96 | } 97 | }) 98 | }) 99 | } else { 100 | child_process.exec(`play /tmp/new2.mp3`, () => { 101 | Logger.log("TTS finished playing") 102 | if (this.musicPlayer.playing) this.musicPlayer.fadeUp() 103 | this.speaking = false 104 | if (options.playnews) { 105 | this.musicPlayer.playPodcast(config.newsPodcastUri) 106 | } 107 | }) 108 | } 109 | }) 110 | }) 111 | } 112 | } 113 | 114 | } 115 | 116 | module.exports = TTS -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Talking Weather Display (on Raspberry Pi / Node.js) 2 | 3 | The Weather Display shows you the weather at all times. It's a digital display that passively displays the weather. If you put it in an area of your home you can see at most times, you can simply glance in the direction of the display, and you'll see the weather. It runs on a Raspberry Pi Zero, so it's also mad cheap! 4 | 5 | ![Weather Display detail](https://raw.githubusercontent.com/setpixel/weather-display/master/public/gfx/photos/detail.jpg) 6 | 7 | Similar to clock on the wall, it's a single mode display. It just displays the weather. It doesn't cycle through other stuff. If you need to know the temperature, it will always be in the same place. 8 | 9 | ![Weather Display in room](https://raw.githubusercontent.com/setpixel/weather-display/master/public/gfx/photos/inroom.jpg) 10 | 11 | The design is simple and elegant, telling you what you need to know and not much more. It is white text set on a black background, so it will not emit much light, and it will go with any room. 12 | 13 | With the right display, you can hook up all the wires and enclose the unit behind the monitor so that all you have to do is plug in the display, and it works. 14 | 15 | ## But wait, theres more! It speaks to you! 16 | 17 | It does some more smart stuff. After sunset, the display will cut it's blue channel for circadian lighting. After bed time, it will significantly dim, but still be readable. After midnight, the display will go to sleep. 18 | 19 | ![Weather Display pir](https://raw.githubusercontent.com/setpixel/weather-display/master/public/gfx/photos/pirsensor.jpg) 20 | 21 | It talks to you. And not in an annoying way like that Echo. There is a PIR sensor -- a sensor to know if a person is in the room, and a knock sensor -- a sensor for small vibrations. 22 | 23 | ### Wake up knowing the weather 24 | 25 | When you wake up in the morning, and step into the room with the weather display, it will read the weather to you, and play the NPR Hourly News Summary. 26 | 27 | [Click here: Hear a sample of what plays when you enter the room in the morning](https://www.dropbox.com/s/btc129m90bbj6ul/sample.mp3?dl=0) 28 | 29 | #### Minor audio events 30 | 31 | Every hour, between wake and bedtime, if you are in the room, It will tell you the time: '*Ding* 5 p.m.' 32 | 33 | On specific events, it will let you know that it's lunch time, when the sun is setting, get ready for bed, and bedtime. 34 | 35 | ### Welcome home 36 | 37 | After long absense, if the PIR sensor detects you, it will welcome you home and tell you how much time you have before going to bed. 38 | 39 | ## TODO 40 | 41 | [TODO.md](TODO.md) 42 | 43 | ## Quick installation guide 44 | 45 | The Weather Display is a breeze to install with only 21 easy steps. If you're a pro, feel free to skip random steps like I do all the time, and then shit definitely won't work. 46 | 47 | 1. Be on Rasbian Jessie. I built this on Wheezy and I had a horrible time getting GPIO libs to install. I just rebuilt everything on Jessie and it works super well. 48 | 1. Disable WiFi power saving because FUCK YOU WHOEVER THOUGHT THAT WAS A GOOD IDEA: http://www.raspberrypi-spy.co.uk/2015/06/how-to-disable-wifi-power-saving-on-the-raspberry-pi/ 49 | 1. Install Chrome Browser 44. TO THE GUY WHO MADE THIS POSSIBLE, I KISS YOU ON THE MOUTH: https://www.raspberrypi.org/forums/viewtopic.php?t=121195 50 | 1. sudo apt-get update 51 | 1. sudo apt-get upgrade 52 | 1. sudo apt-get remove nodejs (Raspbian auto installs something called node red and it totally sucks) 53 | 1. Download latest node $ wget http://node-arm.herokuapp.com/node_latest_armhf.deb 54 | 1. $ sudo dpkg -i node_latest_armhf.deb 55 | 1. $ node -v (Should be like 5.4.2 or something) 56 | 1. might need to install wiringpi: http://wiringpi.com/download-and-install/ (Don't try to apt-get install or anything like that. It doesn't work) 57 | 1. $ npm install rpi-gpio (Should work, maybe, I had trouble with it) 58 | 1. git clone https://github.com/setpixel/weather-display.git 59 | 1. cd weather-display 60 | 1. npm install 61 | 1. Copy config-sample: $ cp config-sample.js config.js 62 | 1. Get an Ivona account for text to speech: https://www.ivona.com/ Sign up, get an api key and secret 63 | 1. Get a Forecast.io account: https://developer.forecast.io/ (Best weather api) 64 | 1. Look up your lat long: http://www.latlong.net/ 65 | 1. Edit config.js file. Add all that sweet shit in there. 66 | 1. Install sox: $ sudo apt-get install sox (Amazing linux audio command line tool) 67 | 1. $ sudo apt-get install libsox-fmt-mp3 (For MP3 stuffs) 68 | 1. $ sudo npm start (NEED TO BE SUDO FOR GPIO STUFF) 69 | 70 | Optional: 71 | 72 | 1. https://docs.mopidy.com/en/latest/installation/debian/#debian-install 73 | 1. Disable LEDs on Pi 74 | 2. Set up to boot into weather display 75 | 1. $ sudo apt-get install matchbox-window-manager x11-xserver-utils unclutter 76 | 1. $ cp /etc/xdg/lxsession/LXDE-pi/autostart /home/pi/.config/lxsession/LXDE-pi/autostart 77 | 1. $ sudo nano /home/pi/.config/lxsession/LXDE-pi/autostart 78 | 1. Paste in: 79 | ``` 80 | #@lxpanel --profile LXDE-pi 81 | #@pcmanfm --desktop --profile LXDE-pi 82 | #@xscreensaver -no-splash 83 | @xset s off 84 | @xset -dpms 85 | @xset s noblank 86 | @chromium-browser --kiosk --incognito http://localhost:3000 87 | @unclutter -idle 0.1 -root 88 | ``` 89 | 3. Edit crontab to turn display on in the morning and off at late night and start node when it boots! 90 | 1. $ crontab -e 91 | 2. Paste in something like: (7am turn on, 11pm/23:00 turn off) 92 | ``` 93 | # m h dom mon dow command 94 | @reboot sleep 6 && cd ~/git/weather-display && sudo npm start > weatherlog.log 95 | 0 7 * * * tvservice -p && fbset -depth 16 96 | 0 23 * * * tvservice -o 97 | ``` 98 | 99 | sudo -H -u mopidy alsamixer -D equal 100 | -------------------------------------------------------------------------------- /public/js/main.js: -------------------------------------------------------------------------------- 1 | ;(function() { 2 | 'use strict'; 3 | 4 | var weatherData; 5 | var skycons = new Skycons({"color": "white"}); 6 | skycons.play(); 7 | var clockInterval; 8 | var CHECKTIME = 2; 9 | 10 | var whiteColor = [255,255,255]; 11 | 12 | var dayMilestones; 13 | var appearalDegrees; 14 | 15 | var getApparel = function(degrees){ 16 | if (degrees > 64) { 17 | return "t-shirt"; 18 | } else if (degrees <= 64 && degrees > 55) { 19 | return "hoodie"; 20 | } else if (degrees <= 55 && degrees > 45) { 21 | return "jacket"; 22 | } else if (degrees <= 45) { 23 | return "heavy jacket"; 24 | } 25 | }; 26 | 27 | var loadAPICall = function(force) { 28 | console.log("get data") 29 | $.ajax({ 30 | url: "/api/weather", 31 | type: 'GET', 32 | success: function (data) { 33 | weatherData = window.weatherData = data.weather; 34 | dayMilestones = data.dayMilestones; 35 | appearalDegrees = data.appearalDegrees; 36 | //console.log(data); 37 | renderWeatherData(); 38 | return data; 39 | } 40 | }); 41 | setTimeout(function(){loadAPICall(true)}, CHECKTIME * 60 * 1000); 42 | }; 43 | 44 | var renderWeatherData = function() { 45 | console.log("RENDERWEATHERDATA") 46 | renderCurrent(); 47 | renderClock(); 48 | clearInterval(clockInterval); 49 | clockInterval = setInterval(function(){renderClock()}, 1000); 50 | renderDay(); 51 | renderWeek(); 52 | } 53 | 54 | var renderCurrent = function() { 55 | $("#current_temp").html(Math.round(weatherData.currently.apparentTemperature)); 56 | skycons.set("current_condition_icon", weatherData.currently.icon); 57 | 58 | // 59 | 60 | 61 | var lowestTemp = 500; 62 | var highestPrecipProb = 0; 63 | highestPrecipProb = weatherData.currently.precipProbability; 64 | 65 | for (var i = 0; i < 4; i++) { 66 | lowestTemp = Math.min(lowestTemp, weatherData.hourly.data[i].apparentTemperature); 67 | highestPrecipProb = Math.max(highestPrecipProb, weatherData.hourly.data[i].precipProbability); 68 | } 69 | 70 | console.log(highestPrecipProb) 71 | var currentTextString = ""; 72 | currentTextString += "A little colder.
"; 73 | currentTextString += "Wear a " + getApparel(lowestTemp) + ". "; 74 | if (lowestTemp > 32 && highestPrecipProb > 0.65) { 75 | currentTextString += "Maybe bring an umbrella. "; 76 | } 77 | //currentTextString += "
"; 78 | 79 | if (weatherData.currently.time < weatherData.daily.data[0].apparentTemperatureMaxTime) { 80 | currentTextString += "Rising to " + Math.round(weatherData.daily.data[0].apparentTemperatureMax) + "º by " + formatTime(weatherData.daily.data[0].apparentTemperatureMaxTime); 81 | } else if (weatherData.currently.time < weatherData.daily.data[1].apparentTemperatureMinTime) { 82 | currentTextString = currentTextString + "Falling to " + Math.round(weatherData.daily.data[1].apparentTemperatureMin) + "º by " + formatTime(weatherData.daily.data[1].apparentTemperatureMinTime); 83 | } 84 | currentTextString = currentTextString + ".
" + weatherData.hourly.summary 85 | $("#today_text").html(currentTextString); 86 | 87 | 88 | 89 | 90 | }; 91 | 92 | var renderDay = function() { 93 | var ctx = $("#graph_day")[0].getContext("2d"); 94 | 95 | ctx.clearRect ( 0 , 0 , ctx.canvas.width , ctx.canvas.height ); 96 | 97 | 98 | // ctx.fillStyle = "red"; 99 | // ctx.rect(0,0,ctx.canvas.width, ctx.canvas.height); 100 | // ctx.fill(); 101 | 102 | 103 | 104 | // apparentTemperature: 83 *** 105 | // cloudCover: 0.1 *** 106 | // dewPoint: 63.3 107 | // humidity: 0.54 108 | // icon: "clear-day" *** 109 | // ozone: 300.42 110 | // precipIntensity: 0 *** 111 | // precipProbability: 0 *** 112 | // pressure: 1021.13 113 | // summary: "Clear" 114 | // temperature: 81.7 115 | // time: 1409072400 *** 116 | // visibility: 10 117 | // windBearing: 130 118 | // windSpeed: 1.46 119 | 120 | var maxTemp = 0; 121 | var minTemp = 500; 122 | 123 | var currentDay = new Date(weatherData.hourly.data[0].time*1000).getDate(); 124 | var dayOffset = 0; 125 | 126 | var previousSun; 127 | 128 | for(var i = 0; i < weatherData.hourly.data.length; i++) { 129 | maxTemp = Math.max(maxTemp, weatherData.hourly.data[i].apparentTemperature); 130 | minTemp = Math.min(minTemp, weatherData.hourly.data[i].apparentTemperature); 131 | var x = (i/(weatherData.hourly.data.length-1))*ctx.canvas.width; 132 | ctx.fillStyle = "rgba(0,255,255," + (weatherData.hourly.data[i].precipProbability*0.8) + ")"; 133 | ctx.fillRect(x,0,Math.ceil(ctx.canvas.width/weatherData.hourly.data.length), ctx.canvas.height); 134 | ctx.fillStyle = "rgba(0,0,0," + Math.round((Math.pow(weatherData.hourly.data[i].cloudCover,2)*0.3)*20)/20 + ")"; 135 | ctx.fillRect(x,0,Math.ceil(ctx.canvas.width/weatherData.hourly.data.length), ctx.canvas.height); 136 | ctx.fillStyle = "rgba(50,50,100,0.2)"; 137 | if (new Date(weatherData.hourly.data[i].time*1000).getDate() !== currentDay ) { 138 | dayOffset++; 139 | } 140 | currentDay = new Date(weatherData.hourly.data[i].time*1000).getDate(); 141 | if ((weatherData.hourly.data[i].time > weatherData.daily.data[dayOffset].sunriseTime) && (weatherData.hourly.data[i].time < weatherData.daily.data[dayOffset].sunsetTime)) { 142 | var sunUp = true; 143 | } else { 144 | var sunUp = false; 145 | } 146 | if (!sunUp) { 147 | ctx.fillRect(x,0,Math.ceil(ctx.canvas.width/weatherData.hourly.data.length), ctx.canvas.height); 148 | } 149 | 150 | if (sunUp && (sunUp !== previousSun) && (typeof previousSun != 'undefined')) { 151 | var x = (i/(weatherData.hourly.data.length-1))*ctx.canvas.width; 152 | ctx.beginPath(); 153 | ctx.moveTo(x, 0) 154 | ctx.lineTo(x, ctx.canvas.height); 155 | ctx.strokeStyle = 'rgb(' + whiteColor[0] + ',' + whiteColor[1] + ',' + whiteColor[2] + ')'; 156 | 157 | ctx.lineWidth = 1; 158 | ctx.fillStyle = 'rgba(' + whiteColor[0] + ',' + whiteColor[1] + ',' + whiteColor[2] + ',0.1)'; 159 | ctx.stroke(); 160 | 161 | } 162 | previousSun = sunUp; 163 | } 164 | 165 | var scale = (maxTemp - minTemp) 166 | 167 | var pts = []; 168 | 169 | 170 | 171 | 172 | 173 | for(var i = 0; i < weatherData.hourly.data.length; i++) { 174 | var x = (i/(weatherData.hourly.data.length-1))*ctx.canvas.width; 175 | var y = ctx.canvas.height-((weatherData.hourly.data[i].apparentTemperature-minTemp)/scale)*(ctx.canvas.height*0.7)- (ctx.canvas.height*0.15); 176 | pts.push(x); 177 | pts.push(y); 178 | } 179 | 180 | ctx.beginPath(); 181 | ctx.moveTo(pts[0], pts[1]) 182 | ctx.curve(pts, 0.5, 20); 183 | ctx.fillStyle = 'rgba(' + whiteColor[0] + ',' + whiteColor[1] + ',' + whiteColor[2] + ',0.2)'; 184 | ctx.lineTo(ctx.canvas.width, ctx.canvas.height); 185 | ctx.lineTo(0, ctx.canvas.height); 186 | ctx.closePath(); 187 | ctx.fill(); 188 | 189 | ctx.beginPath(); 190 | ctx.moveTo(pts[0], pts[1]) 191 | ctx.curve(pts, 0.5, 20); 192 | ctx.strokeStyle = 'rgba(' + whiteColor[0]*0.8 + ',' + whiteColor[1]*0.8 + ',' + whiteColor[2]*0.8 + ',1)'; 193 | 194 | ctx.lineWidth = 8; 195 | ctx.fillStyle = 'rgba(' + whiteColor[0] + ',' + whiteColor[1] + ',' + whiteColor[2] + ',0.01)'; 196 | ctx.stroke(); 197 | 198 | 199 | ctx.beginPath(); 200 | ctx.moveTo(pts[0], pts[1]) 201 | ctx.lineTo(ctx.canvas.width, pts[1]); 202 | ctx.strokeStyle = 'rgba(' + whiteColor[0] + ',' + whiteColor[1] + ',' + whiteColor[2] + ',0.3)'; 203 | ctx.lineWidth = 1; 204 | //ctx.setLineDash([10, 5]) 205 | ctx.fillStyle = 'rgba(' + whiteColor[0] + ',' + whiteColor[1] + ',' + whiteColor[2] + ',0.1)'; 206 | ctx.stroke(); 207 | 208 | 209 | for(var i = 1; i < weatherData.hourly.data.length-1; i++) { 210 | var x = (i/(weatherData.hourly.data.length-1))*ctx.canvas.width; 211 | var y = ctx.canvas.height-((weatherData.hourly.data[i].apparentTemperature-minTemp)/scale)*(ctx.canvas.height*0.7)- (ctx.canvas.height*0.15); 212 | if (["9am", "12pm", "3pm", "6pm", "9pm", "12am"].indexOf(formatTime(weatherData.hourly.data[i].time)) > -1) { 213 | ctx.fillStyle = 'rgba(' + whiteColor[0] + ',' + whiteColor[1] + ',' + whiteColor[2] + ',0.5)'; 214 | ctx.font = "14px HelveticaT"; 215 | ctx.fillText(formatTime(weatherData.hourly.data[i].time), x-10, ctx.canvas.height-10); 216 | ctx.fillStyle = 'rgba(' + whiteColor[0] + ',' + whiteColor[1] + ',' + whiteColor[2] + ',0.8)'; 217 | ctx.font = "14px HelveticaT"; 218 | ctx.fillText(Math.round(weatherData.hourly.data[i].apparentTemperature) + "º", x-10, y-10); 219 | } 220 | if (["9am"].indexOf(formatTime(weatherData.hourly.data[i].time)) > -1) { 221 | ctx.fillStyle = 'rgba(' + whiteColor[0] + ',' + whiteColor[1] + ',' + whiteColor[2] + ',1)'; 222 | ctx.font = "20px HelveticaT"; 223 | ctx.fillText(("Sunday Monday Tuesday Wednesday Thursday Friday Saturday").split(" ")[new Date(weatherData.hourly.data[i].time*1000).getDay()], x-30, 30); 224 | } 225 | } 226 | } 227 | 228 | var renderWeek = function() { 229 | var string = "This week, "; 230 | 231 | var array = weatherData.daily.summary.split(''); 232 | array[0] = array[0].toLowerCase(); 233 | 234 | $("#thisweek_text").html(string + array.join('')); 235 | } 236 | 237 | var formatTime = function(time) { 238 | var date = new Date(time*1000); 239 | var post = "am"; 240 | var h = date.getHours(); 241 | if (h == 12) { 242 | post = "pm"; 243 | } else if (h == 0) { 244 | post = "am"; 245 | h = 12; 246 | } else if (h > 11) { 247 | post = "pm"; 248 | h = h - 12; 249 | } 250 | var m = date.getMinutes(); 251 | if (m == 0) { 252 | var string = h + post; 253 | } else { 254 | var string = h + ":" + pad(m, 2) + post; 255 | } 256 | return string; 257 | }; 258 | 259 | var previousNextThing; 260 | var dimMode = 0; 261 | var previousDimMode = 0; 262 | 263 | var renderClock = function() { 264 | var today = new Date(); 265 | var h = today.getHours(); 266 | if (h == 0) { 267 | h = 12; 268 | } else if (h > 12) { 269 | h = h - 12; 270 | } 271 | var m = today.getMinutes(); 272 | var string = h + ":" + pad(m, 2); 273 | 274 | $("#date").html(("SUN MON TUE WED THU FRI SAT").split(" ")[today.getDay()] + " " + (today.getMonth()+1) + "/" + today.getDate()) 275 | $("#clock").html(string); 276 | 277 | var nextThing = 0; 278 | for (var i = 0; i < dayMilestones.length; i++) { 279 | if (dayMilestones[i][0] == "Sunrise") { 280 | if ((today.getTime()/1000) > weatherData.daily.data[0].sunriseTime) { 281 | dayMilestones[i][1] = 24 + (new Date(weatherData.daily.data[1].sunriseTime*1000).getHours())+(new Date(weatherData.daily.data[1].sunriseTime*1000).getMinutes()/60) 282 | } else { 283 | dayMilestones[i][1] = (new Date(weatherData.daily.data[0].sunriseTime*1000).getHours())+(new Date(weatherData.daily.data[0].sunriseTime*1000).getMinutes()/60) 284 | } 285 | } 286 | if (dayMilestones[i][0] == "Sunset") { 287 | dayMilestones[i][1] = (new Date(weatherData.daily.data[0].sunsetTime*1000).getHours())+(new Date(weatherData.daily.data[0].sunsetTime*1000).getMinutes()/60) 288 | } 289 | } 290 | dayMilestones.sort(function(a, b){return a[1]-b[1]}); 291 | for (var i = 0; i < dayMilestones.length; i++) { 292 | if ((today.getHours() + (today.getMinutes()/60) + (today.getSeconds()/60/60)) < dayMilestones[i][1]) { 293 | 294 | nextThing = i; 295 | break; 296 | } else { 297 | switch (dayMilestones[i][0]) { 298 | case "Sunrise": 299 | dimMode = 0; 300 | break; 301 | case "Sunset": 302 | dimMode = 1; 303 | break; 304 | case "Bed time": 305 | dimMode = 2; 306 | break; 307 | } 308 | } 309 | } 310 | 311 | if (previousDimMode !== dimMode) { 312 | switch (dimMode) { 313 | case 0: 314 | $("#shade").hide(); 315 | $("#bg").toggleClass("sunset", false); 316 | $("#bg").toggleClass("night", false); 317 | whiteColor = [255,255,255]; 318 | break; 319 | case 1: 320 | $("#bg").toggleClass("sunset", true); 321 | $("#bg").toggleClass("night", false); 322 | whiteColor = [255,200,200]; 323 | // $("#shade").css("backgroundColor", "rgba(80,30,0,0.5)"); 324 | // $("#shade").show(); 325 | break; 326 | case 2: 327 | $("#bg").toggleClass("sunset", false); 328 | $("#bg").toggleClass("night", true); 329 | whiteColor = [40,0,0]; 330 | // $("#shade").css("backgroundColor", "rgba(30,0,0,0.85)"); 331 | // $("#shade").show(); 332 | break; 333 | } 334 | skycons.color = 'rgb(' + whiteColor[0] + ',' + whiteColor[1] + ',' + whiteColor[2] + ')' 335 | previousDimMode = dimMode; 336 | } 337 | 338 | if (previousNextThing !== nextThing) { 339 | alert(10); 340 | previousNextThing = nextThing; 341 | } 342 | 343 | var targetDate = new Date(today.getFullYear(), today.getMonth(), today.getDate()) 344 | targetDate = (new Date(targetDate.getTime() + (dayMilestones[nextThing][1] * 60 * 1000 * 60) )) 345 | var string = "" + dayMilestones[nextThing][0] + " in " + formatDuration(targetDate - today); 346 | $("#countdown").html(string); 347 | }; 348 | 349 | var formatDuration = function(duration) { 350 | var h = Math.floor(duration/1000/60/60); 351 | var m = Math.floor((duration/1000/60)- (h*60)); 352 | var s = Math.floor((duration/1000)-((h*60*60)+(m*60))); 353 | 354 | if (duration < (10*1000*60)) { 355 | return m + ":" + pad(s, 2); 356 | } else if (duration < (60*1000*60)){ 357 | return pad(m, 2); 358 | } else { 359 | return h + ":" + pad(m, 2); 360 | } 361 | }; 362 | 363 | var pad = function(n, width, z) { 364 | z = z || '0'; 365 | n = n + ''; 366 | return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; 367 | }; 368 | 369 | $(document).ready(function() { 370 | setTimeout(function() { 371 | console.log("sup") 372 | loadAPICall(true); 373 | }, 1400); 374 | }); 375 | 376 | var alert = function(times) { 377 | if (!times) { times = 5 }; 378 | flashScreen(times); 379 | } 380 | 381 | var flashScreen = function(times) { 382 | 383 | $("#bg").addClass("alert" ); 384 | 385 | setTimeout(function() { 386 | $("#bg").removeClass("alert" ); 387 | }, times*1000); 388 | } 389 | 390 | window.weather = { 391 | alert: alert, 392 | } 393 | 394 | }).call(this); -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | process.chdir(__dirname) 4 | 5 | var express = require('express') 6 | var app = express() 7 | var server = require('http').Server(app) 8 | var LocalStorage = require('node-localstorage').LocalStorage 9 | var localStorage = new LocalStorage('./scratch') 10 | var moment = require('moment') 11 | var Forecast = require('forecast.io-bluebird') 12 | var os = require('os') 13 | var path = require('path') 14 | var config = require('./config') 15 | if (os.hostname() == config.hostname) { 16 | var gpio = require('rpi-gpio') 17 | } 18 | 19 | var Logger = require('./logger') 20 | var TTS = require('./tts') 21 | var MusicPlayer = require('./musicplayer') 22 | 23 | var weatherData 24 | var tts 25 | var musicPlayer 26 | var dayMilestones = config.dayMilestones 27 | var quiet = true 28 | var present = 0 29 | var lastPresentTime = Date.now() 30 | var presentSince = Date.now() 31 | var wakeGreeting = true 32 | var dontPlayMusicUntil = 0 33 | var buttonTime = Date.now() 34 | var buttonPressCount = 0 35 | 36 | function init() { 37 | 38 | Logger.log('=============================================', 100) 39 | Logger.log(`STARTING UP...`, 100) 40 | Logger.log(`Version: ${config.version}`, 100) 41 | Logger.log(`Time: ${moment().format('MM/DD/YY h:mm:ssa')}`, 100) 42 | Logger.log(`Port: ${config.port}`, 100) 43 | Logger.log(`♪♫♪ GUITAR RIFF ♪♫♪`, 100) 44 | Logger.log('=============================================', 100) 45 | 46 | // Set up Mopidy Music player. 47 | musicPlayer = new MusicPlayer() 48 | 49 | tts = new TTS(musicPlayer) 50 | tts.speak(`Weather display... is online.`, {alert: false, bgm: true, volume: 0}) 51 | 52 | // Web stuff 53 | app.get('/', (req, res) => res.sendFile(__dirname + '/public/index.html')) 54 | app.use(express.static(path.join(__dirname, 'public'))); 55 | var router = express.Router() 56 | router.route('/weather') 57 | .get(function(req, res) { 58 | res.json({ appearalDegrees: config.appearalDegrees, dayMilestones: dayMilestones, weather: weatherData }) 59 | }) 60 | router.route('/status') 61 | .get(function(req, res) { 62 | res.json({ status: getStatus() }) 63 | }) 64 | router.route('/present') 65 | .get(function(req, res) { 66 | setPresent() 67 | present = 3 68 | res.json({ present: present }) 69 | }) 70 | router.route('/music/playnews') 71 | .get(function(req, res) { 72 | musicPlayer.playPodcast(config.newsPodcastUri) 73 | res.json({ play: 'news' }) 74 | }) 75 | router.route('/music/play') 76 | .get(function(req, res) { 77 | musicPlayer.playPlaylist(config.musicPlaylistUri, 85) 78 | res.json({ play: musicPlayer.playing }) 79 | }) 80 | router.route('/music/stop') 81 | .get(function(req, res) { 82 | musicPlayer.stop() 83 | presentSince = Date.now() 84 | res.json({ play: musicPlayer.playing }) 85 | }) 86 | router.route('/music/delay') 87 | .get(function(req, res) { 88 | musicPlayer.stop() 89 | presentSince = Date.now() 90 | dontPlayMusicUntil = Math.max(dontPlayMusicUntil, Date.now()) + (30*60*1000) 91 | res.json({ play: musicPlayer.playing }) 92 | }) 93 | router.route('/music/getstatus') 94 | .get(function(req, res) { 95 | res.json({ playing: musicPlayer.playing }) 96 | }) 97 | router.route('/morninggreeting') 98 | .get(function(req, res) { 99 | var textArray = [] 100 | textArray.push('Good morning.') 101 | textArray.push('') 102 | textArray.push(`It's ` + moment().format('h:mm') + `, on ` + moment().format('dddd, MMMM Do')) 103 | textArray.push('') 104 | // It's a freezing 5 degrees 105 | textArray.push(`It's ` + Math.round(weatherData.currently.apparentTemperature) + ` degrees.`) 106 | textArray.push('') 107 | textArray.push(`It's a lot colder than yesterday.`) 108 | textArray.push(`Make sure to wear a ` + getApperel(weatherData.currently.apparentTemperature)) 109 | textArray.push('') 110 | // but, it will rise to 10 degrees in the day 111 | textArray.push(`It will be ` + weatherData.hourly.summary) 112 | textArray.push('') 113 | textArray.push(`This week, ` + weatherData.daily.summary) 114 | textArray.push('') 115 | textArray.push('') 116 | textArray.push('') 117 | textArray.push(`Have a great day!`) 118 | 119 | tts.speak(textArray.join('\n\n'), {alert: true, bgm: true, volume: 7, playnews: true}) 120 | res.json({ play: present }) 121 | }) 122 | router.route('/speak/:string') 123 | .get(function(req, res) { 124 | tts.speak(req.params.string, { 125 | alert: true, 126 | bgm: false, 127 | volume: 7, 128 | }) 129 | res.json({ string: req.params.string }) 130 | }) 131 | app.use('/api', router) 132 | app.listen(config.port) 133 | 134 | // load internet information 135 | getForecast() 136 | setInterval(()=>{getForecast(true)}, config.forecast.checkInterval) 137 | 138 | // log status information 139 | setTimeout(getStatus, 5000) 140 | setInterval(getStatus, 15*60*1000) 141 | 142 | // check every second for new events 143 | setInterval(checkTime, 1000) 144 | 145 | // get information from sensors 146 | if (gpio) { 147 | gpio.setup(config.pirGpioPin, gpio.DIR_IN, gpio.EDGE_BOTH) 148 | gpio.setup(config.buttonGpioPin, gpio.DIR_IN, gpio.EDGE_BOTH) 149 | 150 | gpio.on('change', function(channel, value) { 151 | Logger.log('Channel ' + channel + ' value is now ' + value) 152 | if (channel == config.pirGpioPin) { 153 | if (value) { 154 | Logger.log('+++ PIR ACTIVATED: present: 4') 155 | setPresent() 156 | } else { 157 | Logger.log('--- PIR deactivated: present: 3') 158 | present = 3 159 | } 160 | } 161 | 162 | if (channel == config.buttonGpioPin) { 163 | if (!value) { 164 | if ((Date.now() - buttonTime) > 500) { 165 | buttonPress() 166 | buttonTime = Date.now() 167 | } 168 | } 169 | } 170 | 171 | 172 | }) 173 | } 174 | 175 | } 176 | 177 | function buttonPress() { 178 | if (buttonPressCount == 0) { 179 | musicPlayer.fadeDown(null, null, 73).then(()=> musicPlayer.volume = 73) 180 | } else { 181 | musicPlayer.stop() 182 | presentSince = Date.now() 183 | dontPlayMusicUntil = Math.max(dontPlayMusicUntil, Date.now()) + (30*60*1000) 184 | Logger.log('Not playing playing music for: ' + moment(dontPlayMusicUntil).toNow(true)) 185 | } 186 | buttonPressCount++ 187 | } 188 | 189 | function getStatus() { 190 | var statusString = []; 191 | statusString.push('present: ' + present) 192 | statusString.push('present since: ' + moment.duration(Date.now()-presentSince).asMinutes().toFixed(2)) 193 | statusString.push('away since: ' + moment.duration(Date.now()-lastPresentTime).asMinutes().toFixed(2)) 194 | statusString.push('music playing: ' + musicPlayer.playing) 195 | statusString.push('dont play music for: ' + moment.duration(Date.now()-dontPlayMusicUntil).asMinutes().toFixed(2)) 196 | statusString.push('quiet: ' + quiet) 197 | statusString.push('wakeGreeting: ' + wakeGreeting) 198 | statusString.push('nextEvent: ' + dayMilestones[previousNextThing][0]) 199 | statusString = 'STATUS: ' + statusString.join(' | ') 200 | Logger.log(statusString) 201 | return statusString 202 | } 203 | 204 | function getForecast(force) { 205 | if (!localStorage.getItem("weatherData") || force) { 206 | var forecast = new Forecast({ 207 | key: config.forecast.apiKey, 208 | timeout: 2500 209 | }) 210 | forecast.fetch(config.forecast.lat, config.forecast.long) 211 | .then(function(data) { 212 | weatherData = data 213 | localStorage.setItem("weatherData", JSON.stringify(weatherData)) 214 | Logger.log('Forecast.io: Got weather data from internet.') 215 | checkForPrecipitation() 216 | }) 217 | .catch(function(error) { 218 | Logger.log("Forecast.io Error: " + error) 219 | }) 220 | } else { 221 | weatherData = JSON.parse(localStorage.getItem("weatherData")) 222 | Logger.log('Forecast.io: Got weather data from localstorage.') 223 | } 224 | checkForPrecipitation() 225 | } 226 | 227 | function checkForPrecipitation() { 228 | // console.log(weatherData.minutely.data) 229 | 230 | // var totalaccumulation = 0; 231 | 232 | // for (var i = 0; i < weatherData.hourly.data.length; i++) { 233 | // var node = weatherData.hourly.data[i] 234 | // totalaccumulation+= node.precipAccumulation 235 | // console.log(moment(node.time*1000).format('h:mma') + " " + node.summary + ", total: " + totalaccumulation) 236 | // //console.log(node.summary, moment(node.time*1000).format('h:mma')) 237 | // //console.log(node.precipProbability, node.precipType, moment(node.time*1000).format('h:mma')) 238 | // } 239 | } 240 | 241 | var previousNextThing 242 | var previousHour 243 | var previousMinute 244 | 245 | function checkTime() { 246 | var today = new Date() 247 | var h = today.getHours() 248 | var m = today.getMinutes() 249 | 250 | var nextThing = 0 251 | 252 | for (var i = 0; i < dayMilestones.length; i++) { 253 | if (dayMilestones[i][0] == "Sunrise") { 254 | if ((today.getTime()/1000) > weatherData.daily.data[0].sunriseTime) { 255 | dayMilestones[i][1] = 24 + (new Date(weatherData.daily.data[1].sunriseTime*1000).getHours())+(new Date(weatherData.daily.data[1].sunriseTime*1000).getMinutes()/60) 256 | } else { 257 | dayMilestones[i][1] = (new Date(weatherData.daily.data[0].sunriseTime*1000).getHours())+(new Date(weatherData.daily.data[0].sunriseTime*1000).getMinutes()/60) 258 | } 259 | } 260 | if (dayMilestones[i][0] == "Sunset") { 261 | dayMilestones[i][1] = (new Date(weatherData.daily.data[0].sunsetTime*1000).getHours())+(new Date(weatherData.daily.data[0].sunsetTime*1000).getMinutes()/60) 262 | } 263 | } 264 | dayMilestones.sort(function(a, b){return a[1]-b[1]}) 265 | for (var i = 0; i < dayMilestones.length; i++) { 266 | if ((today.getHours() + (today.getMinutes()/60) + (today.getSeconds()/60/60)) < dayMilestones[i][1]) { 267 | nextThing = i 268 | break 269 | } else { 270 | switch (dayMilestones[i][0]) { 271 | case "Breakfast": 272 | quiet = false 273 | break 274 | case "Sunset": 275 | break 276 | case "Bed time": 277 | quiet = true 278 | break 279 | } 280 | } 281 | } 282 | 283 | if (previousNextThing !== nextThing) { 284 | if (typeof previousNextThing !== 'undefined') { 285 | Logger.log("NEW EVENT: " + dayMilestones[previousNextThing][0] + ' quiet: ' + quiet + ' present: ' + present) 286 | switch (dayMilestones[previousNextThing][0]) { 287 | case "Wake up": 288 | quiet = false 289 | wakeGreeting = false 290 | tts.speak("It's " + moment().format('h:mma') + ".\n\nTime to wake up.", {alert: true, bgm: false, volume: 0}) 291 | break 292 | case "Lunch": 293 | if (present > 1) tts.speak("It's " + moment().format('h:mma') + ". It's time to eat lunch.", {alert: true, bgm: false, volume: 7}) 294 | break 295 | case "Sunset": 296 | if (present > 1) tts.speak("It's " + moment().format('h:mma') + ". It will be dark soon.\n\nTurn on a light.", {alert: true, bgm: false, volume: 7, playnews: true}) 297 | break 298 | case "Dinner": 299 | if (present > 1) tts.speak("It's dinner time! It's " + moment().format('h:mma'), {alert: true, bgm: false, volume: 7, playnews: true}) 300 | break 301 | case "Time to bone": 302 | if (present > 1) tts.speak("It's " + moment().format('h:mma') + "It's time to bone!", {alert: true, bgm: false, volume: 7}) 303 | break 304 | case "Get ready for bed": 305 | if (present > 1) tts.speak("Time to get ready for bed. It's " + moment().format('h:mma'), {alert: true, bgm: false, volume: 7}) 306 | if (musicPlayer.playing) { 307 | musicPlayer.fadeDown(null, null, 73).then(()=> musicPlayer.volume = 73) 308 | } 309 | break 310 | case "Bed time": 311 | if (present > 1) tts.speak("Alright. It's time to go to bed. It's " + moment().format('h:mma'), {alert: true, bgm: false, volume: 5}) 312 | quiet = true 313 | if (musicPlayer.playing) { 314 | musicPlayer.stop() 315 | } 316 | break 317 | } 318 | } 319 | previousNextThing = nextThing 320 | } 321 | 322 | if (previousHour !== h) { 323 | previousHour = h 324 | if ((present > 1) && !quiet && config.hourlyNotifications) { 325 | tts.speak(moment(today).format('h:mma'), {alert: true, bgm: false, volume: 0}) 326 | } 327 | } 328 | 329 | if (present > 2 && !musicPlayer.playing && !quiet) { 330 | if (((Date.now() - presentSince)> config.playMusicAfter) && (Date.now() > dontPlayMusicUntil)) { 331 | buttonPressCount = 0 332 | musicPlayer.playPlaylist(config.musicPlaylistUri, 85) 333 | } 334 | } 335 | 336 | if (present < 4) { 337 | var timeSince = Date.now() - lastPresentTime 338 | 339 | if (timeSince > config.goneTimeout) { 340 | if (present !==0) Logger.log("PRESENT: 0. I am gone.") 341 | present = 0 342 | } else if (timeSince > config.awayTimeout) { 343 | if (present !==1) Logger.log("PRESENT: 1. I am away.") 344 | present = 1 345 | } else if (timeSince > config.presenceTimeout) { 346 | if (present !==2) Logger.log("PRESENT: 2. I am a little away.") 347 | present = 2 348 | } 349 | } 350 | 351 | if (present < 3) { 352 | var timeSince = Date.now() - lastPresentTime 353 | if (timeSince > config.stopMusicAfter) { 354 | if (musicPlayer.playing) { 355 | musicPlayer.stop() 356 | presentSince = Date.now() 357 | } 358 | } 359 | } 360 | 361 | } 362 | 363 | function getApperel(degrees) { 364 | if (degrees > config.appearalDegrees.hoodie) { 365 | return "t-shirt" 366 | } else if (degrees <= config.appearalDegrees.hoodie && degrees > config.appearalDegrees.jacket) { 367 | return "hoodie" 368 | } else if (degrees <= config.appearalDegrees.jacket && degrees > config.appearalDegrees.heavyJacket) { 369 | return "jacket" 370 | } else if (degrees <= config.appearalDegrees.heavyJacket && degrees > config.appearalDegrees.fullWinter) { 371 | return "heavy jacket" 372 | } else if (degrees <= config.appearalDegrees.fullWinter) { 373 | return "heavy jacket with a hat and gloves" 374 | } 375 | } 376 | 377 | function setPresent() { 378 | // console.log("quiet: " + quiet) 379 | // console.log("previousNextThing: " + previousNextThing) 380 | // console.log("dayMilestones: " + dayMilestones) 381 | 382 | if (present < 2) { 383 | presentSince = Date.now() 384 | } 385 | 386 | if (!wakeGreeting) { 387 | var textArray = [] 388 | textArray.push('Good morning.') 389 | textArray.push('') 390 | textArray.push(`It's ` + moment().format('h:mm') + `, on ` + moment().format('dddd, MMMM Do')) 391 | textArray.push('') 392 | // It's a freezing 5 degrees 393 | textArray.push(`It's ` + Math.round(weatherData.currently.apparentTemperature) + ` degrees.`) 394 | textArray.push('') 395 | textArray.push(`It's a lot colder than yesterday.`) 396 | textArray.push(`Make sure to wear a ` + getApperel(weatherData.currently.apparentTemperature)) 397 | textArray.push('') 398 | // but, it will rise to 10 degrees in the day 399 | textArray.push(`It will be ` + weatherData.hourly.summary) 400 | textArray.push('') 401 | textArray.push(`This week, ` + weatherData.daily.summary) 402 | textArray.push('') 403 | textArray.push('') 404 | textArray.push('') 405 | textArray.push(`Have a great day!`) 406 | 407 | tts.speak(textArray.join('\n\n'), {alert: true, bgm: true, volume: 7, playnews: true}, musicPlayer) 408 | wakeGreeting = true 409 | } 410 | 411 | // 3 = totally present 412 | // 2 = away for more than 2 minutes 413 | // 1 = firmly away for more than 1 hour 414 | // 0 = gone for more than 3 hours 415 | if (present !== 3) { 416 | Logger.log("I AM PRESENT!!!!") 417 | switch (present) { 418 | case 2: 419 | // just a little away. 420 | // do nothing. 421 | break 422 | case 1: 423 | // away. 424 | // say the time 425 | if (!quiet) tts.speak("Welcome back.\n\nIt's " + moment().format('h:mma'), {alert: true, bgm: false, volume: 0}) 426 | break 427 | case 0: 428 | // was gone 429 | // say full welcome back 430 | if (!quiet) { 431 | var bedTimeHour 432 | dayMilestones.forEach(function(v){if (v[0] == 'Bed time') {bedTimeHour = (v[1])}}) 433 | var timeUntil = moment.duration(moment().hour(bedTimeHour).minute(0).diff(moment(), 'minutes', true), 'minutes').humanize() 434 | var text = `Welcome home.\n\n\n\n\n\n\n\nIt's ` + moment().format('h:mma') + `.\n ` + timeUntil + ` until bedtime!\n\nThere are a couple new shows on Hulu. The Daily Show and Adventure Time.\n\nLet's have a great night!` 435 | tts.speak(text, {alert: true, bgm: true, volume: 7, playnews: true}) 436 | } 437 | break 438 | } 439 | } else { 440 | // Still present. 441 | // Logger.log("I AM STILL PRESENT. Boring.") 442 | } 443 | present = 4 444 | lastPresentTime = Date.now() 445 | } 446 | 447 | init() -------------------------------------------------------------------------------- /public/js/libs/skycons.js: -------------------------------------------------------------------------------- 1 | (function(global) { 2 | "use strict"; 3 | 4 | /* Set up a RequestAnimationFrame shim so we can animate efficiently FOR 5 | * GREAT JUSTICE. */ 6 | var requestInterval, cancelInterval; 7 | 8 | (function() { 9 | var raf = global.requestAnimationFrame || 10 | global.webkitRequestAnimationFrame || 11 | global.mozRequestAnimationFrame || 12 | global.oRequestAnimationFrame || 13 | global.msRequestAnimationFrame , 14 | caf = global.cancelAnimationFrame || 15 | global.webkitCancelAnimationFrame || 16 | global.mozCancelAnimationFrame || 17 | global.oCancelAnimationFrame || 18 | global.msCancelAnimationFrame ; 19 | 20 | if(raf && caf) { 21 | requestInterval = function(fn, delay) { 22 | var handle = {value: null}; 23 | 24 | function loop() { 25 | handle.value = raf(loop); 26 | fn(); 27 | } 28 | 29 | loop(); 30 | return handle; 31 | }; 32 | 33 | cancelInterval = function(handle) { 34 | caf(handle.value); 35 | }; 36 | } 37 | 38 | else { 39 | requestInterval = setInterval; 40 | cancelInterval = clearInterval; 41 | } 42 | }()); 43 | 44 | /* Catmull-rom spline stuffs. */ 45 | /* 46 | function upsample(n, spline) { 47 | var polyline = [], 48 | len = spline.length, 49 | bx = spline[0], 50 | by = spline[1], 51 | cx = spline[2], 52 | cy = spline[3], 53 | dx = spline[4], 54 | dy = spline[5], 55 | i, j, ax, ay, px, qx, rx, sx, py, qy, ry, sy, t; 56 | 57 | for(i = 6; i !== spline.length; i += 2) { 58 | ax = bx; 59 | bx = cx; 60 | cx = dx; 61 | dx = spline[i ]; 62 | px = -0.5 * ax + 1.5 * bx - 1.5 * cx + 0.5 * dx; 63 | qx = ax - 2.5 * bx + 2.0 * cx - 0.5 * dx; 64 | rx = -0.5 * ax + 0.5 * cx ; 65 | sx = bx ; 66 | 67 | ay = by; 68 | by = cy; 69 | cy = dy; 70 | dy = spline[i + 1]; 71 | py = -0.5 * ay + 1.5 * by - 1.5 * cy + 0.5 * dy; 72 | qy = ay - 2.5 * by + 2.0 * cy - 0.5 * dy; 73 | ry = -0.5 * ay + 0.5 * cy ; 74 | sy = by ; 75 | 76 | for(j = 0; j !== n; ++j) { 77 | t = j / n; 78 | 79 | polyline.push( 80 | ((px * t + qx) * t + rx) * t + sx, 81 | ((py * t + qy) * t + ry) * t + sy 82 | ); 83 | } 84 | } 85 | 86 | polyline.push( 87 | px + qx + rx + sx, 88 | py + qy + ry + sy 89 | ); 90 | 91 | return polyline; 92 | } 93 | 94 | function downsample(n, polyline) { 95 | var len = 0, 96 | i, dx, dy; 97 | 98 | for(i = 2; i !== polyline.length; i += 2) { 99 | dx = polyline[i ] - polyline[i - 2]; 100 | dy = polyline[i + 1] - polyline[i - 1]; 101 | len += Math.sqrt(dx * dx + dy * dy); 102 | } 103 | 104 | len /= n; 105 | 106 | var small = [], 107 | target = len, 108 | min = 0, 109 | max, t; 110 | 111 | small.push(polyline[0], polyline[1]); 112 | 113 | for(i = 2; i !== polyline.length; i += 2) { 114 | dx = polyline[i ] - polyline[i - 2]; 115 | dy = polyline[i + 1] - polyline[i - 1]; 116 | max = min + Math.sqrt(dx * dx + dy * dy); 117 | 118 | if(max > target) { 119 | t = (target - min) / (max - min); 120 | 121 | small.push( 122 | polyline[i - 2] + dx * t, 123 | polyline[i - 1] + dy * t 124 | ); 125 | 126 | target += len; 127 | } 128 | 129 | min = max; 130 | } 131 | 132 | small.push(polyline[polyline.length - 2], polyline[polyline.length - 1]); 133 | 134 | return small; 135 | } 136 | */ 137 | 138 | /* Define skycon things. */ 139 | /* FIXME: I'm *really really* sorry that this code is so gross. Really, I am. 140 | * I'll try to clean it up eventually! Promise! */ 141 | var KEYFRAME = 500, 142 | STROKE = 0.08, 143 | TAU = 2.0 * Math.PI, 144 | TWO_OVER_SQRT_2 = 2.0 / Math.sqrt(2); 145 | 146 | function circle(ctx, x, y, r) { 147 | ctx.beginPath(); 148 | ctx.arc(x, y, r, 0, TAU, false); 149 | ctx.fill(); 150 | } 151 | 152 | function line(ctx, ax, ay, bx, by) { 153 | ctx.beginPath(); 154 | ctx.moveTo(ax, ay); 155 | ctx.lineTo(bx, by); 156 | ctx.stroke(); 157 | } 158 | 159 | function puff(ctx, t, cx, cy, rx, ry, rmin, rmax) { 160 | var c = Math.cos(t * TAU), 161 | s = Math.sin(t * TAU); 162 | 163 | rmax -= rmin; 164 | 165 | circle( 166 | ctx, 167 | cx - s * rx, 168 | cy + c * ry + rmax * 0.5, 169 | rmin + (1 - c * 0.5) * rmax 170 | ); 171 | } 172 | 173 | function puffs(ctx, t, cx, cy, rx, ry, rmin, rmax) { 174 | var i; 175 | 176 | for(i = 5; i--; ) 177 | puff(ctx, t + i / 5, cx, cy, rx, ry, rmin, rmax); 178 | } 179 | 180 | function cloud(ctx, t, cx, cy, cw, s, color) { 181 | t /= 30000; 182 | 183 | var a = cw * 0.21, 184 | b = cw * 0.12, 185 | c = cw * 0.24, 186 | d = cw * 0.28; 187 | 188 | ctx.fillStyle = color; 189 | puffs(ctx, t, cx, cy, a, b, c, d); 190 | 191 | ctx.globalCompositeOperation = 'destination-out'; 192 | puffs(ctx, t, cx, cy, a, b, c - s, d - s); 193 | ctx.globalCompositeOperation = 'source-over'; 194 | } 195 | 196 | function sun(ctx, t, cx, cy, cw, s, color) { 197 | t /= 120000; 198 | 199 | var a = cw * 0.25 - s * 0.5, 200 | b = cw * 0.32 + s * 0.5, 201 | c = cw * 0.50 - s * 0.5, 202 | i, p, cos, sin; 203 | 204 | ctx.strokeStyle = color; 205 | ctx.lineWidth = s; 206 | ctx.lineCap = "round"; 207 | ctx.lineJoin = "round"; 208 | 209 | ctx.beginPath(); 210 | ctx.arc(cx, cy, a, 0, TAU, false); 211 | ctx.stroke(); 212 | 213 | for(i = 8; i--; ) { 214 | p = (t + i / 8) * TAU; 215 | cos = Math.cos(p); 216 | sin = Math.sin(p); 217 | line(ctx, cx + cos * b, cy + sin * b, cx + cos * c, cy + sin * c); 218 | } 219 | } 220 | 221 | function moon(ctx, t, cx, cy, cw, s, color) { 222 | t /= 15000; 223 | 224 | var a = cw * 0.29 - s * 0.5, 225 | b = cw * 0.05, 226 | c = Math.cos(t * TAU), 227 | p = c * TAU / -16; 228 | 229 | ctx.strokeStyle = color; 230 | ctx.lineWidth = s; 231 | ctx.lineCap = "round"; 232 | ctx.lineJoin = "round"; 233 | 234 | cx += c * b; 235 | 236 | ctx.beginPath(); 237 | ctx.arc(cx, cy, a, p + TAU / 8, p + TAU * 7 / 8, false); 238 | ctx.arc(cx + Math.cos(p) * a * TWO_OVER_SQRT_2, cy + Math.sin(p) * a * TWO_OVER_SQRT_2, a, p + TAU * 5 / 8, p + TAU * 3 / 8, true); 239 | ctx.closePath(); 240 | ctx.stroke(); 241 | } 242 | 243 | function rain(ctx, t, cx, cy, cw, s, color) { 244 | t /= 1350; 245 | 246 | var a = cw * 0.16, 247 | b = TAU * 11 / 12, 248 | c = TAU * 7 / 12, 249 | i, p, x, y; 250 | 251 | ctx.fillStyle = color; 252 | 253 | for(i = 4; i--; ) { 254 | p = (t + i / 4) % 1; 255 | x = cx + ((i - 1.5) / 1.5) * (i === 1 || i === 2 ? -1 : 1) * a; 256 | y = cy + p * p * cw; 257 | ctx.beginPath(); 258 | ctx.moveTo(x, y - s * 1.5); 259 | ctx.arc(x, y, s * 0.75, b, c, false); 260 | ctx.fill(); 261 | } 262 | } 263 | 264 | function sleet(ctx, t, cx, cy, cw, s, color) { 265 | t /= 750; 266 | 267 | var a = cw * 0.1875, 268 | b = TAU * 11 / 12, 269 | c = TAU * 7 / 12, 270 | i, p, x, y; 271 | 272 | ctx.strokeStyle = color; 273 | ctx.lineWidth = s * 0.5; 274 | ctx.lineCap = "round"; 275 | ctx.lineJoin = "round"; 276 | 277 | for(i = 4; i--; ) { 278 | p = (t + i / 4) % 1; 279 | x = Math.floor(cx + ((i - 1.5) / 1.5) * (i === 1 || i === 2 ? -1 : 1) * a) + 0.5; 280 | y = cy + p * cw; 281 | line(ctx, x, y - s * 1.5, x, y + s * 1.5); 282 | } 283 | } 284 | 285 | function snow(ctx, t, cx, cy, cw, s, color) { 286 | t /= 3000; 287 | 288 | var a = cw * 0.16, 289 | b = s * 0.75, 290 | u = t * TAU * 0.7, 291 | ux = Math.cos(u) * b, 292 | uy = Math.sin(u) * b, 293 | v = u + TAU / 3, 294 | vx = Math.cos(v) * b, 295 | vy = Math.sin(v) * b, 296 | w = u + TAU * 2 / 3, 297 | wx = Math.cos(w) * b, 298 | wy = Math.sin(w) * b, 299 | i, p, x, y; 300 | 301 | ctx.strokeStyle = color; 302 | ctx.lineWidth = s * 0.5; 303 | ctx.lineCap = "round"; 304 | ctx.lineJoin = "round"; 305 | 306 | for(i = 4; i--; ) { 307 | p = (t + i / 4) % 1; 308 | x = cx + Math.sin((p + i / 4) * TAU) * a; 309 | y = cy + p * cw; 310 | 311 | line(ctx, x - ux, y - uy, x + ux, y + uy); 312 | line(ctx, x - vx, y - vy, x + vx, y + vy); 313 | line(ctx, x - wx, y - wy, x + wx, y + wy); 314 | } 315 | } 316 | 317 | function fogbank(ctx, t, cx, cy, cw, s, color) { 318 | t /= 30000; 319 | 320 | var a = cw * 0.21, 321 | b = cw * 0.06, 322 | c = cw * 0.21, 323 | d = cw * 0.28; 324 | 325 | ctx.fillStyle = color; 326 | puffs(ctx, t, cx, cy, a, b, c, d); 327 | 328 | ctx.globalCompositeOperation = 'destination-out'; 329 | puffs(ctx, t, cx, cy, a, b, c - s, d - s); 330 | ctx.globalCompositeOperation = 'source-over'; 331 | } 332 | 333 | /* 334 | var WIND_PATHS = [ 335 | downsample(63, upsample(8, [ 336 | -1.00, -0.28, 337 | -0.75, -0.18, 338 | -0.50, 0.12, 339 | -0.20, 0.12, 340 | -0.04, -0.04, 341 | -0.07, -0.18, 342 | -0.19, -0.18, 343 | -0.23, -0.05, 344 | -0.12, 0.11, 345 | 0.02, 0.16, 346 | 0.20, 0.15, 347 | 0.50, 0.07, 348 | 0.75, 0.18, 349 | 1.00, 0.28 350 | ])), 351 | downsample(31, upsample(16, [ 352 | -1.00, -0.10, 353 | -0.75, 0.00, 354 | -0.50, 0.10, 355 | -0.25, 0.14, 356 | 0.00, 0.10, 357 | 0.25, 0.00, 358 | 0.50, -0.10, 359 | 0.75, -0.14, 360 | 1.00, -0.10 361 | ])) 362 | ]; 363 | */ 364 | 365 | var WIND_PATHS = [ 366 | [ 367 | -0.7500, -0.1800, -0.7219, -0.1527, -0.6971, -0.1225, 368 | -0.6739, -0.0910, -0.6516, -0.0588, -0.6298, -0.0262, 369 | -0.6083, 0.0065, -0.5868, 0.0396, -0.5643, 0.0731, 370 | -0.5372, 0.1041, -0.5033, 0.1259, -0.4662, 0.1406, 371 | -0.4275, 0.1493, -0.3881, 0.1530, -0.3487, 0.1526, 372 | -0.3095, 0.1488, -0.2708, 0.1421, -0.2319, 0.1342, 373 | -0.1943, 0.1217, -0.1600, 0.1025, -0.1290, 0.0785, 374 | -0.1012, 0.0509, -0.0764, 0.0206, -0.0547, -0.0120, 375 | -0.0378, -0.0472, -0.0324, -0.0857, -0.0389, -0.1241, 376 | -0.0546, -0.1599, -0.0814, -0.1876, -0.1193, -0.1964, 377 | -0.1582, -0.1935, -0.1931, -0.1769, -0.2157, -0.1453, 378 | -0.2290, -0.1085, -0.2327, -0.0697, -0.2240, -0.0317, 379 | -0.2064, 0.0033, -0.1853, 0.0362, -0.1613, 0.0672, 380 | -0.1350, 0.0961, -0.1051, 0.1213, -0.0706, 0.1397, 381 | -0.0332, 0.1512, 0.0053, 0.1580, 0.0442, 0.1624, 382 | 0.0833, 0.1636, 0.1224, 0.1615, 0.1613, 0.1565, 383 | 0.1999, 0.1500, 0.2378, 0.1402, 0.2749, 0.1279, 384 | 0.3118, 0.1147, 0.3487, 0.1015, 0.3858, 0.0892, 385 | 0.4236, 0.0787, 0.4621, 0.0715, 0.5012, 0.0702, 386 | 0.5398, 0.0766, 0.5768, 0.0890, 0.6123, 0.1055, 387 | 0.6466, 0.1244, 0.6805, 0.1440, 0.7147, 0.1630, 388 | 0.7500, 0.1800 389 | ], 390 | [ 391 | -0.7500, 0.0000, -0.7033, 0.0195, -0.6569, 0.0399, 392 | -0.6104, 0.0600, -0.5634, 0.0789, -0.5155, 0.0954, 393 | -0.4667, 0.1089, -0.4174, 0.1206, -0.3676, 0.1299, 394 | -0.3174, 0.1365, -0.2669, 0.1398, -0.2162, 0.1391, 395 | -0.1658, 0.1347, -0.1157, 0.1271, -0.0661, 0.1169, 396 | -0.0170, 0.1046, 0.0316, 0.0903, 0.0791, 0.0728, 397 | 0.1259, 0.0534, 0.1723, 0.0331, 0.2188, 0.0129, 398 | 0.2656, -0.0064, 0.3122, -0.0263, 0.3586, -0.0466, 399 | 0.4052, -0.0665, 0.4525, -0.0847, 0.5007, -0.1002, 400 | 0.5497, -0.1130, 0.5991, -0.1240, 0.6491, -0.1325, 401 | 0.6994, -0.1380, 0.7500, -0.1400 402 | ] 403 | ], 404 | WIND_OFFSETS = [ 405 | {start: 0.36, end: 0.11}, 406 | {start: 0.56, end: 0.16} 407 | ]; 408 | 409 | function leaf(ctx, t, x, y, cw, s, color) { 410 | var a = cw / 8, 411 | b = a / 3, 412 | c = 2 * b, 413 | d = (t % 1) * TAU, 414 | e = Math.cos(d), 415 | f = Math.sin(d); 416 | 417 | ctx.fillStyle = color; 418 | ctx.strokeStyle = color; 419 | ctx.lineWidth = s; 420 | ctx.lineCap = "round"; 421 | ctx.lineJoin = "round"; 422 | 423 | ctx.beginPath(); 424 | ctx.arc(x , y , a, d , d + Math.PI, false); 425 | ctx.arc(x - b * e, y - b * f, c, d + Math.PI, d , false); 426 | ctx.arc(x + c * e, y + c * f, b, d + Math.PI, d , true ); 427 | ctx.globalCompositeOperation = 'destination-out'; 428 | ctx.fill(); 429 | ctx.globalCompositeOperation = 'source-over'; 430 | ctx.stroke(); 431 | } 432 | 433 | function swoosh(ctx, t, cx, cy, cw, s, index, total, color) { 434 | t /= 2500; 435 | 436 | var path = WIND_PATHS[index], 437 | a = (t + index - WIND_OFFSETS[index].start) % total, 438 | c = (t + index - WIND_OFFSETS[index].end ) % total, 439 | e = (t + index ) % total, 440 | b, d, f, i; 441 | 442 | ctx.strokeStyle = color; 443 | ctx.lineWidth = s; 444 | ctx.lineCap = "round"; 445 | ctx.lineJoin = "round"; 446 | 447 | if(a < 1) { 448 | ctx.beginPath(); 449 | 450 | a *= path.length / 2 - 1; 451 | b = Math.floor(a); 452 | a -= b; 453 | b *= 2; 454 | b += 2; 455 | 456 | ctx.moveTo( 457 | cx + (path[b - 2] * (1 - a) + path[b ] * a) * cw, 458 | cy + (path[b - 1] * (1 - a) + path[b + 1] * a) * cw 459 | ); 460 | 461 | if(c < 1) { 462 | c *= path.length / 2 - 1; 463 | d = Math.floor(c); 464 | c -= d; 465 | d *= 2; 466 | d += 2; 467 | 468 | for(i = b; i !== d; i += 2) 469 | ctx.lineTo(cx + path[i] * cw, cy + path[i + 1] * cw); 470 | 471 | ctx.lineTo( 472 | cx + (path[d - 2] * (1 - c) + path[d ] * c) * cw, 473 | cy + (path[d - 1] * (1 - c) + path[d + 1] * c) * cw 474 | ); 475 | } 476 | 477 | else 478 | for(i = b; i !== path.length; i += 2) 479 | ctx.lineTo(cx + path[i] * cw, cy + path[i + 1] * cw); 480 | 481 | ctx.stroke(); 482 | } 483 | 484 | else if(c < 1) { 485 | ctx.beginPath(); 486 | 487 | c *= path.length / 2 - 1; 488 | d = Math.floor(c); 489 | c -= d; 490 | d *= 2; 491 | d += 2; 492 | 493 | ctx.moveTo(cx + path[0] * cw, cy + path[1] * cw); 494 | 495 | for(i = 2; i !== d; i += 2) 496 | ctx.lineTo(cx + path[i] * cw, cy + path[i + 1] * cw); 497 | 498 | ctx.lineTo( 499 | cx + (path[d - 2] * (1 - c) + path[d ] * c) * cw, 500 | cy + (path[d - 1] * (1 - c) + path[d + 1] * c) * cw 501 | ); 502 | 503 | ctx.stroke(); 504 | } 505 | 506 | if(e < 1) { 507 | e *= path.length / 2 - 1; 508 | f = Math.floor(e); 509 | e -= f; 510 | f *= 2; 511 | f += 2; 512 | 513 | leaf( 514 | ctx, 515 | t, 516 | cx + (path[f - 2] * (1 - e) + path[f ] * e) * cw, 517 | cy + (path[f - 1] * (1 - e) + path[f + 1] * e) * cw, 518 | cw, 519 | s, 520 | color 521 | ); 522 | } 523 | } 524 | 525 | var Skycons = function(opts) { 526 | this.list = []; 527 | this.interval = null; 528 | this.color = opts && opts.color ? opts.color : "black"; 529 | this.resizeClear = !!(opts && opts.resizeClear); 530 | }; 531 | 532 | Skycons.CLEAR_DAY = function(ctx, t, color) { 533 | var w = ctx.canvas.width, 534 | h = ctx.canvas.height, 535 | s = Math.min(w, h); 536 | 537 | sun(ctx, t, w * 0.5, h * 0.5, s, s * STROKE, color); 538 | }; 539 | 540 | Skycons.CLEAR_NIGHT = function(ctx, t, color) { 541 | var w = ctx.canvas.width, 542 | h = ctx.canvas.height, 543 | s = Math.min(w, h); 544 | 545 | moon(ctx, t, w * 0.5, h * 0.5, s, s * STROKE, color); 546 | }; 547 | 548 | Skycons.PARTLY_CLOUDY_DAY = function(ctx, t, color) { 549 | var w = ctx.canvas.width, 550 | h = ctx.canvas.height, 551 | s = Math.min(w, h); 552 | 553 | sun(ctx, t, w * 0.625, h * 0.375, s * 0.75, s * STROKE, color); 554 | cloud(ctx, t, w * 0.375, h * 0.625, s * 0.75, s * STROKE, color); 555 | }; 556 | 557 | Skycons.PARTLY_CLOUDY_NIGHT = function(ctx, t, color) { 558 | var w = ctx.canvas.width, 559 | h = ctx.canvas.height, 560 | s = Math.min(w, h); 561 | 562 | moon(ctx, t, w * 0.667, h * 0.375, s * 0.75, s * STROKE, color); 563 | cloud(ctx, t, w * 0.375, h * 0.625, s * 0.75, s * STROKE, color); 564 | }; 565 | 566 | Skycons.CLOUDY = function(ctx, t, color) { 567 | var w = ctx.canvas.width, 568 | h = ctx.canvas.height, 569 | s = Math.min(w, h); 570 | 571 | cloud(ctx, t, w * 0.5, h * 0.5, s, s * STROKE, color); 572 | }; 573 | 574 | Skycons.RAIN = function(ctx, t, color) { 575 | var w = ctx.canvas.width, 576 | h = ctx.canvas.height, 577 | s = Math.min(w, h); 578 | 579 | rain(ctx, t, w * 0.5, h * 0.37, s * 0.9, s * STROKE, color); 580 | cloud(ctx, t, w * 0.5, h * 0.37, s * 0.9, s * STROKE, color); 581 | }; 582 | 583 | Skycons.SLEET = function(ctx, t, color) { 584 | var w = ctx.canvas.width, 585 | h = ctx.canvas.height, 586 | s = Math.min(w, h); 587 | 588 | sleet(ctx, t, w * 0.5, h * 0.37, s * 0.9, s * STROKE, color); 589 | cloud(ctx, t, w * 0.5, h * 0.37, s * 0.9, s * STROKE, color); 590 | }; 591 | 592 | Skycons.SNOW = function(ctx, t, color) { 593 | var w = ctx.canvas.width, 594 | h = ctx.canvas.height, 595 | s = Math.min(w, h); 596 | 597 | snow(ctx, t, w * 0.5, h * 0.37, s * 0.9, s * STROKE, color); 598 | cloud(ctx, t, w * 0.5, h * 0.37, s * 0.9, s * STROKE, color); 599 | }; 600 | 601 | Skycons.WIND = function(ctx, t, color) { 602 | var w = ctx.canvas.width, 603 | h = ctx.canvas.height, 604 | s = Math.min(w, h); 605 | 606 | swoosh(ctx, t, w * 0.5, h * 0.5, s, s * STROKE, 0, 2, color); 607 | swoosh(ctx, t, w * 0.5, h * 0.5, s, s * STROKE, 1, 2, color); 608 | }; 609 | 610 | Skycons.FOG = function(ctx, t, color) { 611 | var w = ctx.canvas.width, 612 | h = ctx.canvas.height, 613 | s = Math.min(w, h), 614 | k = s * STROKE; 615 | 616 | fogbank(ctx, t, w * 0.5, h * 0.32, s * 0.75, k, color); 617 | 618 | t /= 5000; 619 | 620 | var a = Math.cos((t ) * TAU) * s * 0.02, 621 | b = Math.cos((t + 0.25) * TAU) * s * 0.02, 622 | c = Math.cos((t + 0.50) * TAU) * s * 0.02, 623 | d = Math.cos((t + 0.75) * TAU) * s * 0.02, 624 | n = h * 0.936, 625 | e = Math.floor(n - k * 0.5) + 0.5, 626 | f = Math.floor(n - k * 2.5) + 0.5; 627 | 628 | ctx.strokeStyle = color; 629 | ctx.lineWidth = k; 630 | ctx.lineCap = "round"; 631 | ctx.lineJoin = "round"; 632 | 633 | line(ctx, a + w * 0.2 + k * 0.5, e, b + w * 0.8 - k * 0.5, e); 634 | line(ctx, c + w * 0.2 + k * 0.5, f, d + w * 0.8 - k * 0.5, f); 635 | }; 636 | 637 | Skycons.prototype = { 638 | _determineDrawingFunction: function(draw) { 639 | if(typeof draw === "string") 640 | draw = Skycons[draw.toUpperCase().replace(/-/g, "_")] || null; 641 | 642 | return draw; 643 | }, 644 | add: function(el, draw) { 645 | var obj; 646 | 647 | if(typeof el === "string") 648 | el = document.getElementById(el); 649 | 650 | // Does nothing if canvas name doesn't exists 651 | if(el === null) 652 | return; 653 | 654 | draw = this._determineDrawingFunction(draw); 655 | 656 | // Does nothing if the draw function isn't actually a function 657 | if(typeof draw !== "function") 658 | return; 659 | 660 | obj = { 661 | element: el, 662 | context: el.getContext("2d"), 663 | drawing: draw 664 | }; 665 | 666 | this.list.push(obj); 667 | this.draw(obj, KEYFRAME); 668 | }, 669 | set: function(el, draw) { 670 | var i; 671 | 672 | if(typeof el === "string") 673 | el = document.getElementById(el); 674 | 675 | for(i = this.list.length; i--; ) 676 | if(this.list[i].element === el) { 677 | this.list[i].drawing = this._determineDrawingFunction(draw); 678 | this.draw(this.list[i], KEYFRAME); 679 | return; 680 | } 681 | 682 | this.add(el, draw); 683 | }, 684 | remove: function(el) { 685 | var i; 686 | 687 | if(typeof el === "string") 688 | el = document.getElementById(el); 689 | 690 | for(i = this.list.length; i--; ) 691 | if(this.list[i].element === el) { 692 | this.list.splice(i, 1); 693 | return; 694 | } 695 | }, 696 | draw: function(obj, time) { 697 | var canvas = obj.context.canvas; 698 | 699 | if(this.resizeClear) 700 | canvas.width = canvas.width; 701 | 702 | else 703 | obj.context.clearRect(0, 0, canvas.width, canvas.height); 704 | 705 | obj.drawing(obj.context, time, this.color); 706 | }, 707 | play: function() { 708 | var self = this; 709 | 710 | this.pause(); 711 | this.interval = requestInterval(function() { 712 | var now = Date.now(), 713 | i; 714 | 715 | for(i = self.list.length; i--; ) 716 | self.draw(self.list[i], now); 717 | }, 1000 / 60); 718 | }, 719 | pause: function() { 720 | var i; 721 | 722 | if(this.interval) { 723 | cancelInterval(this.interval); 724 | this.interval = null; 725 | } 726 | } 727 | }; 728 | 729 | global.Skycons = Skycons; 730 | }(this)); 731 | -------------------------------------------------------------------------------- /public/js/libs/moment.min.js: -------------------------------------------------------------------------------- 1 | //! moment.js 2 | //! version : 2.10.6 3 | //! authors : Tim Wood, Iskren Chernev, Moment.js contributors 4 | //! license : MIT 5 | //! momentjs.com 6 | !function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return Hc.apply(null,arguments)}function b(a){Hc=a}function c(a){return"[object Array]"===Object.prototype.toString.call(a)}function d(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function e(a,b){var c,d=[];for(c=0;c0)for(c in Jc)d=Jc[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function n(b){m(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),Kc===!1&&(Kc=!0,a.updateOffset(this),Kc=!1)}function o(a){return a instanceof n||null!=a&&null!=a._isAMomentObject}function p(a){return 0>a?Math.ceil(a):Math.floor(a)}function q(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=p(b)),c}function r(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&q(a[d])!==q(b[d]))&&g++;return g+f}function s(){}function t(a){return a?a.toLowerCase().replace("_","-"):a}function u(a){for(var b,c,d,e,f=0;f0;){if(d=v(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&r(e,c,!0)>=b-1)break;b--}f++}return null}function v(a){var b=null;if(!Lc[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=Ic._abbr,require("./locale/"+a),w(b)}catch(c){}return Lc[a]}function w(a,b){var c;return a&&(c="undefined"==typeof b?y(a):x(a,b),c&&(Ic=c)),Ic._abbr}function x(a,b){return null!==b?(b.abbr=a,Lc[a]=Lc[a]||new s,Lc[a].set(b),w(a),Lc[a]):(delete Lc[a],null)}function y(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return Ic;if(!c(a)){if(b=v(a))return b;a=[a]}return u(a)}function z(a,b){var c=a.toLowerCase();Mc[c]=Mc[c+"s"]=Mc[b]=a}function A(a){return"string"==typeof a?Mc[a]||Mc[a.toLowerCase()]:void 0}function B(a){var b,c,d={};for(c in a)f(a,c)&&(b=A(c),b&&(d[b]=a[c]));return d}function C(b,c){return function(d){return null!=d?(E(this,b,d),a.updateOffset(this,c),this):D(this,b)}}function D(a,b){return a._d["get"+(a._isUTC?"UTC":"")+b]()}function E(a,b,c){return a._d["set"+(a._isUTC?"UTC":"")+b](c)}function F(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else if(a=A(a),"function"==typeof this[a])return this[a](b);return this}function G(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d}function H(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(Qc[a]=e),b&&(Qc[b[0]]=function(){return G(e.apply(this,arguments),b[1],b[2])}),c&&(Qc[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function I(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function J(a){var b,c,d=a.match(Nc);for(b=0,c=d.length;c>b;b++)Qc[d[b]]?d[b]=Qc[d[b]]:d[b]=I(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function K(a,b){return a.isValid()?(b=L(b,a.localeData()),Pc[b]=Pc[b]||J(b),Pc[b](a)):a.localeData().invalidDate()}function L(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Oc.lastIndex=0;d>=0&&Oc.test(a);)a=a.replace(Oc,c),Oc.lastIndex=0,d-=1;return a}function M(a){return"function"==typeof a&&"[object Function]"===Object.prototype.toString.call(a)}function N(a,b,c){dd[a]=M(b)?b:function(a){return a&&c?c:b}}function O(a,b){return f(dd,a)?dd[a](b._strict,b._locale):new RegExp(P(a))}function P(a){return a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function Q(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=q(a)}),c=0;cd;d++){if(e=h([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function X(a,b){var c;return"string"==typeof b&&(b=a.localeData().monthsParse(b),"number"!=typeof b)?a:(c=Math.min(a.date(),T(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a)}function Y(b){return null!=b?(X(this,b),a.updateOffset(this,!0),this):D(this,"Month")}function Z(){return T(this.year(),this.month())}function $(a){var b,c=a._a;return c&&-2===j(a).overflow&&(b=c[gd]<0||c[gd]>11?gd:c[hd]<1||c[hd]>T(c[fd],c[gd])?hd:c[id]<0||c[id]>24||24===c[id]&&(0!==c[jd]||0!==c[kd]||0!==c[ld])?id:c[jd]<0||c[jd]>59?jd:c[kd]<0||c[kd]>59?kd:c[ld]<0||c[ld]>999?ld:-1,j(a)._overflowDayOfYear&&(fd>b||b>hd)&&(b=hd),j(a).overflow=b),a}function _(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function aa(a,b){var c=!0;return g(function(){return c&&(_(a+"\n"+(new Error).stack),c=!1),b.apply(this,arguments)},b)}function ba(a,b){od[a]||(_(b),od[a]=!0)}function ca(a){var b,c,d=a._i,e=pd.exec(d);if(e){for(j(a).iso=!0,b=0,c=qd.length;c>b;b++)if(qd[b][1].exec(d)){a._f=qd[b][0];break}for(b=0,c=rd.length;c>b;b++)if(rd[b][1].exec(d)){a._f+=(e[6]||" ")+rd[b][0];break}d.match(ad)&&(a._f+="Z"),va(a)}else a._isValid=!1}function da(b){var c=sd.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(ca(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}function ea(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function fa(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function ga(a){return ha(a)?366:365}function ha(a){return a%4===0&&a%100!==0||a%400===0}function ia(){return ha(this.year())}function ja(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=Da(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function ka(a){return ja(a,this._week.dow,this._week.doy).week}function la(){return this._week.dow}function ma(){return this._week.doy}function na(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function oa(a){var b=ja(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function pa(a,b,c,d,e){var f,g=6+e-d,h=fa(a,0,1+g),i=h.getUTCDay();return e>i&&(i+=7),c=null!=c?1*c:e,f=1+g+7*(b-1)-i+c,{year:f>0?a:a-1,dayOfYear:f>0?f:ga(a-1)+f}}function qa(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function ra(a,b,c){return null!=a?a:null!=b?b:c}function sa(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function ta(a){var b,c,d,e,f=[];if(!a._d){for(d=sa(a),a._w&&null==a._a[hd]&&null==a._a[gd]&&ua(a),a._dayOfYear&&(e=ra(a._a[fd],d[fd]),a._dayOfYear>ga(e)&&(j(a)._overflowDayOfYear=!0),c=fa(e,0,a._dayOfYear),a._a[gd]=c.getUTCMonth(),a._a[hd]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[id]&&0===a._a[jd]&&0===a._a[kd]&&0===a._a[ld]&&(a._nextDay=!0,a._a[id]=0),a._d=(a._useUTC?fa:ea).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[id]=24)}}function ua(a){var b,c,d,e,f,g,h;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=ra(b.GG,a._a[fd],ja(Da(),1,4).year),d=ra(b.W,1),e=ra(b.E,1)):(f=a._locale._week.dow,g=a._locale._week.doy,c=ra(b.gg,a._a[fd],ja(Da(),f,g).year),d=ra(b.w,1),null!=b.d?(e=b.d,f>e&&++d):e=null!=b.e?b.e+f:f),h=pa(c,d,e,g,f),a._a[fd]=h.year,a._dayOfYear=h.dayOfYear}function va(b){if(b._f===a.ISO_8601)return void ca(b);b._a=[],j(b).empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,k=0;for(e=L(b._f,b._locale).match(Nc)||[],c=0;c0&&j(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),k+=d.length),Qc[f]?(d?j(b).empty=!1:j(b).unusedTokens.push(f),S(f,d,b)):b._strict&&!d&&j(b).unusedTokens.push(f);j(b).charsLeftOver=i-k,h.length>0&&j(b).unusedInput.push(h),j(b).bigHour===!0&&b._a[id]<=12&&b._a[id]>0&&(j(b).bigHour=void 0),b._a[id]=wa(b._locale,b._a[id],b._meridiem),ta(b),$(b)}function wa(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function xa(a){var b,c,d,e,f;if(0===a._f.length)return j(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;ef)&&(d=f,c=b));g(a,c||b)}function ya(a){if(!a._d){var b=B(a._i);a._a=[b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],ta(a)}}function za(a){var b=new n($(Aa(a)));return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function Aa(a){var b=a._i,e=a._f;return a._locale=a._locale||y(a._l),null===b||void 0===e&&""===b?l({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),o(b)?new n($(b)):(c(e)?xa(a):e?va(a):d(b)?a._d=b:Ba(a),a))}function Ba(b){var f=b._i;void 0===f?b._d=new Date:d(f)?b._d=new Date(+f):"string"==typeof f?da(b):c(f)?(b._a=e(f.slice(0),function(a){return parseInt(a,10)}),ta(b)):"object"==typeof f?ya(b):"number"==typeof f?b._d=new Date(f):a.createFromInputFallback(b)}function Ca(a,b,c,d,e){var f={};return"boolean"==typeof c&&(d=c,c=void 0),f._isAMomentObject=!0,f._useUTC=f._isUTC=e,f._l=c,f._i=a,f._f=b,f._strict=d,za(f)}function Da(a,b,c,d){return Ca(a,b,c,d,!1)}function Ea(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return Da();for(d=b[0],e=1;ea&&(a=-a,c="-"),c+G(~~(a/60),2)+b+G(~~a%60,2)})}function Ka(a){var b=(a||"").match(ad)||[],c=b[b.length-1]||[],d=(c+"").match(xd)||["-",0,0],e=+(60*d[1])+q(d[2]);return"+"===d[0]?e:-e}function La(b,c){var e,f;return c._isUTC?(e=c.clone(),f=(o(b)||d(b)?+b:+Da(b))-+e,e._d.setTime(+e._d+f),a.updateOffset(e,!1),e):Da(b).local()}function Ma(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Na(b,c){var d,e=this._offset||0;return null!=b?("string"==typeof b&&(b=Ka(b)),Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ma(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?bb(this,Ya(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ma(this)}function Oa(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Pa(a){return this.utcOffset(0,a)}function Qa(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ma(this),"m")),this}function Ra(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Ka(this._i)),this}function Sa(a){return a=a?Da(a).utcOffset():0,(this.utcOffset()-a)%60===0}function Ta(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ua(){if("undefined"!=typeof this._isDSTShifted)return this._isDSTShifted;var a={};if(m(a,this),a=Aa(a),a._a){var b=a._isUTC?h(a._a):Da(a._a);this._isDSTShifted=this.isValid()&&r(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Va(){return!this._isUTC}function Wa(){return this._isUTC}function Xa(){return this._isUTC&&0===this._offset}function Ya(a,b){var c,d,e,g=a,h=null;return Ia(a)?g={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(g={},b?g[b]=a:g.milliseconds=a):(h=yd.exec(a))?(c="-"===h[1]?-1:1,g={y:0,d:q(h[hd])*c,h:q(h[id])*c,m:q(h[jd])*c,s:q(h[kd])*c,ms:q(h[ld])*c}):(h=zd.exec(a))?(c="-"===h[1]?-1:1,g={y:Za(h[2],c),M:Za(h[3],c),d:Za(h[4],c),h:Za(h[5],c),m:Za(h[6],c),s:Za(h[7],c),w:Za(h[8],c)}):null==g?g={}:"object"==typeof g&&("from"in g||"to"in g)&&(e=_a(Da(g.from),Da(g.to)),g={},g.ms=e.milliseconds,g.M=e.months),d=new Ha(g),Ia(a)&&f(a,"_locale")&&(d._locale=a._locale),d}function Za(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function $a(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function _a(a,b){var c;return b=La(b,a),a.isBefore(b)?c=$a(a,b):(c=$a(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c}function ab(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||(ba(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Ya(c,d),bb(this,e,a),this}}function bb(b,c,d,e){var f=c._milliseconds,g=c._days,h=c._months;e=null==e?!0:e,f&&b._d.setTime(+b._d+f*d),g&&E(b,"Date",D(b,"Date")+g*d),h&&X(b,D(b,"Month")+h*d),e&&a.updateOffset(b,g||h)}function cb(a,b){var c=a||Da(),d=La(c,this).startOf("day"),e=this.diff(d,"days",!0),f=-6>e?"sameElse":-1>e?"lastWeek":0>e?"lastDay":1>e?"sameDay":2>e?"nextDay":7>e?"nextWeek":"sameElse";return this.format(b&&b[f]||this.localeData().calendar(f,this,Da(c)))}function db(){return new n(this)}function eb(a,b){var c;return b=A("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Da(a),+this>+a):(c=o(a)?+a:+Da(a),c<+this.clone().startOf(b))}function fb(a,b){var c;return b=A("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Da(a),+a>+this):(c=o(a)?+a:+Da(a),+this.clone().endOf(b)b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)}function kb(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function lb(){var a=this.clone().utc();return 0b;b++)if(this._weekdaysParse[b]||(c=Da([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b}function Pb(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Kb(a,this.localeData()),this.add(a-b,"d")):b}function Qb(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function Rb(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)}function Sb(a,b){H(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function Tb(a,b){return b._meridiemParse}function Ub(a){return"p"===(a+"").toLowerCase().charAt(0)}function Vb(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Wb(a,b){b[ld]=q(1e3*("0."+a))}function Xb(){return this._isUTC?"UTC":""}function Yb(){return this._isUTC?"Coordinated Universal Time":""}function Zb(a){return Da(1e3*a)}function $b(){return Da.apply(null,arguments).parseZone()}function _b(a,b,c){var d=this._calendar[a];return"function"==typeof d?d.call(b,c):d}function ac(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function bc(){return this._invalidDate}function cc(a){return this._ordinal.replace("%d",a)}function dc(a){return a}function ec(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)}function fc(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)}function gc(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function hc(a,b,c,d){var e=y(),f=h().set(d,b);return e[c](f,a)}function ic(a,b,c,d,e){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return hc(a,b,c,e);var f,g=[];for(f=0;d>f;f++)g[f]=hc(a,f,c,e);return g}function jc(a,b){return ic(a,b,"months",12,"month")}function kc(a,b){return ic(a,b,"monthsShort",12,"month")}function lc(a,b){return ic(a,b,"weekdays",7,"day")}function mc(a,b){return ic(a,b,"weekdaysShort",7,"day")}function nc(a,b){return ic(a,b,"weekdaysMin",7,"day")}function oc(){var a=this._data;return this._milliseconds=Wd(this._milliseconds),this._days=Wd(this._days),this._months=Wd(this._months),a.milliseconds=Wd(a.milliseconds),a.seconds=Wd(a.seconds),a.minutes=Wd(a.minutes),a.hours=Wd(a.hours),a.months=Wd(a.months),a.years=Wd(a.years),this}function pc(a,b,c,d){var e=Ya(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function qc(a,b){return pc(this,a,b,1)}function rc(a,b){return pc(this,a,b,-1)}function sc(a){return 0>a?Math.floor(a):Math.ceil(a)}function tc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data;return f>=0&&g>=0&&h>=0||0>=f&&0>=g&&0>=h||(f+=864e5*sc(vc(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=p(f/1e3),i.seconds=a%60,b=p(a/60),i.minutes=b%60,c=p(b/60),i.hours=c%24,g+=p(c/24),e=p(uc(g)),h+=e,g-=sc(vc(e)),d=p(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function uc(a){return 4800*a/146097}function vc(a){return 146097*a/4800}function wc(a){var b,c,d=this._milliseconds;if(a=A(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+uc(b),"month"===a?c:c/12;switch(b=this._days+Math.round(vc(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}function xc(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*q(this._months/12)}function yc(a){return function(){return this.as(a)}}function zc(a){return a=A(a),this[a+"s"]()}function Ac(a){return function(){return this._data[a]}}function Bc(){return p(this.days()/7)}function Cc(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function Dc(a,b,c){var d=Ya(a).abs(),e=ke(d.as("s")),f=ke(d.as("m")),g=ke(d.as("h")),h=ke(d.as("d")),i=ke(d.as("M")),j=ke(d.as("y")),k=e0,k[4]=c,Cc.apply(null,k)}function Ec(a,b){return void 0===le[a]?!1:void 0===b?le[a]:(le[a]=b,!0)}function Fc(a){var b=this.localeData(),c=Dc(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function Gc(){var a,b,c,d=me(this._milliseconds)/1e3,e=me(this._days),f=me(this._months);a=p(d/60),b=p(a/60),d%=60,a%=60,c=p(f/12),f%=12;var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(0>m?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var Hc,Ic,Jc=a.momentProperties=[],Kc=!1,Lc={},Mc={},Nc=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,Oc=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Pc={},Qc={},Rc=/\d/,Sc=/\d\d/,Tc=/\d{3}/,Uc=/\d{4}/,Vc=/[+-]?\d{6}/,Wc=/\d\d?/,Xc=/\d{1,3}/,Yc=/\d{1,4}/,Zc=/[+-]?\d{1,6}/,$c=/\d+/,_c=/[+-]?\d+/,ad=/Z|[+-]\d\d:?\d\d/gi,bd=/[+-]?\d+(\.\d{1,3})?/,cd=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,dd={},ed={},fd=0,gd=1,hd=2,id=3,jd=4,kd=5,ld=6;H("M",["MM",2],"Mo",function(){return this.month()+1}),H("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),H("MMMM",0,0,function(a){return this.localeData().months(this,a)}),z("month","M"),N("M",Wc),N("MM",Wc,Sc),N("MMM",cd),N("MMMM",cd),Q(["M","MM"],function(a,b){b[gd]=q(a)-1}),Q(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[gd]=e:j(c).invalidMonth=a});var md="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),nd="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),od={};a.suppressDeprecationWarnings=!1;var pd=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,qd=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],rd=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],sd=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=aa("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),H(0,["YY",2],0,function(){return this.year()%100}),H(0,["YYYY",4],0,"year"),H(0,["YYYYY",5],0,"year"),H(0,["YYYYYY",6,!0],0,"year"),z("year","y"),N("Y",_c),N("YY",Wc,Sc),N("YYYY",Yc,Uc),N("YYYYY",Zc,Vc),N("YYYYYY",Zc,Vc),Q(["YYYYY","YYYYYY"],fd),Q("YYYY",function(b,c){c[fd]=2===b.length?a.parseTwoDigitYear(b):q(b)}),Q("YY",function(b,c){c[fd]=a.parseTwoDigitYear(b)}),a.parseTwoDigitYear=function(a){return q(a)+(q(a)>68?1900:2e3)};var td=C("FullYear",!1);H("w",["ww",2],"wo","week"),H("W",["WW",2],"Wo","isoWeek"),z("week","w"),z("isoWeek","W"),N("w",Wc),N("ww",Wc,Sc),N("W",Wc),N("WW",Wc,Sc),R(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=q(a)});var ud={dow:0,doy:6};H("DDD",["DDDD",3],"DDDo","dayOfYear"),z("dayOfYear","DDD"),N("DDD",Xc),N("DDDD",Tc),Q(["DDD","DDDD"],function(a,b,c){c._dayOfYear=q(a)}),a.ISO_8601=function(){};var vd=aa("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var a=Da.apply(null,arguments);return this>a?this:a}),wd=aa("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var a=Da.apply(null,arguments);return a>this?this:a});Ja("Z",":"),Ja("ZZ",""),N("Z",ad),N("ZZ",ad),Q(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Ka(a)});var xd=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var yd=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,zd=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;Ya.fn=Ha.prototype;var Ad=ab(1,"add"),Bd=ab(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ";var Cd=aa("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});H(0,["gg",2],0,function(){return this.weekYear()%100}),H(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Db("gggg","weekYear"),Db("ggggg","weekYear"),Db("GGGG","isoWeekYear"),Db("GGGGG","isoWeekYear"),z("weekYear","gg"),z("isoWeekYear","GG"),N("G",_c),N("g",_c),N("GG",Wc,Sc),N("gg",Wc,Sc),N("GGGG",Yc,Uc),N("gggg",Yc,Uc),N("GGGGG",Zc,Vc),N("ggggg",Zc,Vc),R(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=q(a)}),R(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),H("Q",0,0,"quarter"),z("quarter","Q"),N("Q",Rc),Q("Q",function(a,b){b[gd]=3*(q(a)-1)}),H("D",["DD",2],"Do","date"),z("date","D"),N("D",Wc),N("DD",Wc,Sc),N("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),Q(["D","DD"],hd),Q("Do",function(a,b){b[hd]=q(a.match(Wc)[0],10)});var Dd=C("Date",!0);H("d",0,"do","day"),H("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),H("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),H("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),H("e",0,0,"weekday"),H("E",0,0,"isoWeekday"),z("day","d"),z("weekday","e"),z("isoWeekday","E"),N("d",Wc),N("e",Wc),N("E",Wc),N("dd",cd),N("ddd",cd),N("dddd",cd),R(["dd","ddd","dddd"],function(a,b,c){var d=c._locale.weekdaysParse(a);null!=d?b.d=d:j(c).invalidWeekday=a}),R(["d","e","E"],function(a,b,c,d){b[d]=q(a)});var Ed="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Fd="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Gd="Su_Mo_Tu_We_Th_Fr_Sa".split("_");H("H",["HH",2],0,"hour"),H("h",["hh",2],0,function(){return this.hours()%12||12}),Sb("a",!0),Sb("A",!1),z("hour","h"),N("a",Tb),N("A",Tb),N("H",Wc),N("h",Wc),N("HH",Wc,Sc),N("hh",Wc,Sc),Q(["H","HH"],id),Q(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),Q(["h","hh"],function(a,b,c){b[id]=q(a),j(c).bigHour=!0});var Hd=/[ap]\.?m?\.?/i,Id=C("Hours",!0);H("m",["mm",2],0,"minute"),z("minute","m"),N("m",Wc),N("mm",Wc,Sc),Q(["m","mm"],jd);var Jd=C("Minutes",!1);H("s",["ss",2],0,"second"),z("second","s"),N("s",Wc),N("ss",Wc,Sc),Q(["s","ss"],kd);var Kd=C("Seconds",!1);H("S",0,0,function(){return~~(this.millisecond()/100)}),H(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),H(0,["SSS",3],0,"millisecond"),H(0,["SSSS",4],0,function(){return 10*this.millisecond()}),H(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),H(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),H(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),H(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),H(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),z("millisecond","ms"),N("S",Xc,Rc),N("SS",Xc,Sc),N("SSS",Xc,Tc);var Ld;for(Ld="SSSS";Ld.length<=9;Ld+="S")N(Ld,$c);for(Ld="S";Ld.length<=9;Ld+="S")Q(Ld,Wb);var Md=C("Milliseconds",!1);H("z",0,0,"zoneAbbr"),H("zz",0,0,"zoneName");var Nd=n.prototype;Nd.add=Ad,Nd.calendar=cb,Nd.clone=db,Nd.diff=ib,Nd.endOf=ub,Nd.format=mb,Nd.from=nb,Nd.fromNow=ob,Nd.to=pb,Nd.toNow=qb,Nd.get=F,Nd.invalidAt=Cb,Nd.isAfter=eb,Nd.isBefore=fb,Nd.isBetween=gb,Nd.isSame=hb,Nd.isValid=Ab,Nd.lang=Cd,Nd.locale=rb,Nd.localeData=sb,Nd.max=wd,Nd.min=vd,Nd.parsingFlags=Bb,Nd.set=F,Nd.startOf=tb,Nd.subtract=Bd,Nd.toArray=yb,Nd.toObject=zb,Nd.toDate=xb,Nd.toISOString=lb,Nd.toJSON=lb,Nd.toString=kb,Nd.unix=wb,Nd.valueOf=vb,Nd.year=td,Nd.isLeapYear=ia,Nd.weekYear=Fb,Nd.isoWeekYear=Gb,Nd.quarter=Nd.quarters=Jb,Nd.month=Y,Nd.daysInMonth=Z,Nd.week=Nd.weeks=na,Nd.isoWeek=Nd.isoWeeks=oa,Nd.weeksInYear=Ib,Nd.isoWeeksInYear=Hb,Nd.date=Dd,Nd.day=Nd.days=Pb,Nd.weekday=Qb,Nd.isoWeekday=Rb,Nd.dayOfYear=qa,Nd.hour=Nd.hours=Id,Nd.minute=Nd.minutes=Jd,Nd.second=Nd.seconds=Kd, 7 | Nd.millisecond=Nd.milliseconds=Md,Nd.utcOffset=Na,Nd.utc=Pa,Nd.local=Qa,Nd.parseZone=Ra,Nd.hasAlignedHourOffset=Sa,Nd.isDST=Ta,Nd.isDSTShifted=Ua,Nd.isLocal=Va,Nd.isUtcOffset=Wa,Nd.isUtc=Xa,Nd.isUTC=Xa,Nd.zoneAbbr=Xb,Nd.zoneName=Yb,Nd.dates=aa("dates accessor is deprecated. Use date instead.",Dd),Nd.months=aa("months accessor is deprecated. Use month instead",Y),Nd.years=aa("years accessor is deprecated. Use year instead",td),Nd.zone=aa("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",Oa);var Od=Nd,Pd={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Qd={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Rd="Invalid date",Sd="%d",Td=/\d{1,2}/,Ud={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Vd=s.prototype;Vd._calendar=Pd,Vd.calendar=_b,Vd._longDateFormat=Qd,Vd.longDateFormat=ac,Vd._invalidDate=Rd,Vd.invalidDate=bc,Vd._ordinal=Sd,Vd.ordinal=cc,Vd._ordinalParse=Td,Vd.preparse=dc,Vd.postformat=dc,Vd._relativeTime=Ud,Vd.relativeTime=ec,Vd.pastFuture=fc,Vd.set=gc,Vd.months=U,Vd._months=md,Vd.monthsShort=V,Vd._monthsShort=nd,Vd.monthsParse=W,Vd.week=ka,Vd._week=ud,Vd.firstDayOfYear=ma,Vd.firstDayOfWeek=la,Vd.weekdays=Lb,Vd._weekdays=Ed,Vd.weekdaysMin=Nb,Vd._weekdaysMin=Gd,Vd.weekdaysShort=Mb,Vd._weekdaysShort=Fd,Vd.weekdaysParse=Ob,Vd.isPM=Ub,Vd._meridiemParse=Hd,Vd.meridiem=Vb,w("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===q(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=aa("moment.lang is deprecated. Use moment.locale instead.",w),a.langData=aa("moment.langData is deprecated. Use moment.localeData instead.",y);var Wd=Math.abs,Xd=yc("ms"),Yd=yc("s"),Zd=yc("m"),$d=yc("h"),_d=yc("d"),ae=yc("w"),be=yc("M"),ce=yc("y"),de=Ac("milliseconds"),ee=Ac("seconds"),fe=Ac("minutes"),ge=Ac("hours"),he=Ac("days"),ie=Ac("months"),je=Ac("years"),ke=Math.round,le={s:45,m:45,h:22,d:26,M:11},me=Math.abs,ne=Ha.prototype;ne.abs=oc,ne.add=qc,ne.subtract=rc,ne.as=wc,ne.asMilliseconds=Xd,ne.asSeconds=Yd,ne.asMinutes=Zd,ne.asHours=$d,ne.asDays=_d,ne.asWeeks=ae,ne.asMonths=be,ne.asYears=ce,ne.valueOf=xc,ne._bubble=tc,ne.get=zc,ne.milliseconds=de,ne.seconds=ee,ne.minutes=fe,ne.hours=ge,ne.days=he,ne.weeks=Bc,ne.months=ie,ne.years=je,ne.humanize=Fc,ne.toISOString=Gc,ne.toString=Gc,ne.toJSON=Gc,ne.locale=rb,ne.localeData=sb,ne.toIsoString=aa("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Gc),ne.lang=Cd,H("X",0,0,"unix"),H("x",0,0,"valueOf"),N("x",_c),N("X",bd),Q("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),Q("x",function(a,b,c){c._d=new Date(q(a))}),a.version="2.10.6",b(Da),a.fn=Od,a.min=Fa,a.max=Ga,a.utc=h,a.unix=Zb,a.months=jc,a.isDate=d,a.locale=w,a.invalid=l,a.duration=Ya,a.isMoment=o,a.weekdays=lc,a.parseZone=$b,a.localeData=y,a.isDuration=Ia,a.monthsShort=kc,a.weekdaysMin=nc,a.defineLocale=x,a.weekdaysShort=mc,a.normalizeUnits=A,a.relativeTimeThreshold=Ec;var oe=a;return oe}); -------------------------------------------------------------------------------- /public/js/libs/jquery.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v2.1.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ 2 | !function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k="".trim,l={},m=a.document,n="2.1.0",o=function(a,b){return new o.fn.init(a,b)},p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};o.fn=o.prototype={jquery:n,constructor:o,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=o.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return o.each(this,a,b)},map:function(a){return this.pushStack(o.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},o.extend=o.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||o.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(o.isPlainObject(d)||(e=o.isArray(d)))?(e?(e=!1,f=c&&o.isArray(c)?c:[]):f=c&&o.isPlainObject(c)?c:{},g[b]=o.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},o.extend({expando:"jQuery"+(n+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===o.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return a-parseFloat(a)>=0},isPlainObject:function(a){if("object"!==o.type(a)||a.nodeType||o.isWindow(a))return!1;try{if(a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(b){return!1}return!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=o.trim(a),a&&(1===a.indexOf("use strict")?(b=m.createElement("script"),b.text=a,m.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":k.call(a)},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?o.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),o.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||o.guid++,f):void 0},now:Date.now,support:l}),o.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=o.type(a);return"function"===c||o.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s="sizzle"+-new Date,t=a.document,u=0,v=0,w=eb(),x=eb(),y=eb(),z=function(a,b){return a===b&&(j=!0),0},A="undefined",B=1<<31,C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=D.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",M=L.replace("w","w#"),N="\\["+K+"*("+L+")"+K+"*(?:([*^$|!~]?=)"+K+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+M+")|)|)"+K+"*\\]",O=":("+L+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+N.replace(3,8)+")*)|.*)\\)|)",P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(O),U=new RegExp("^"+M+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L.replace("w","w*")+")"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=/'|\\/g,ab=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),bb=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{G.apply(D=H.call(t.childNodes),t.childNodes),D[t.childNodes.length].nodeType}catch(cb){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function db(a,b,d,e){var f,g,h,i,j,m,p,q,u,v;if((b?b.ownerDocument||b:t)!==l&&k(b),b=b||l,d=d||[],!a||"string"!=typeof a)return d;if(1!==(i=b.nodeType)&&9!==i)return[];if(n&&!e){if(f=Z.exec(a))if(h=f[1]){if(9===i){if(g=b.getElementById(h),!g||!g.parentNode)return d;if(g.id===h)return d.push(g),d}else if(b.ownerDocument&&(g=b.ownerDocument.getElementById(h))&&r(b,g)&&g.id===h)return d.push(g),d}else{if(f[2])return G.apply(d,b.getElementsByTagName(a)),d;if((h=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(h)),d}if(c.qsa&&(!o||!o.test(a))){if(q=p=s,u=b,v=9===i&&a,1===i&&"object"!==b.nodeName.toLowerCase()){m=ob(a),(p=b.getAttribute("id"))?q=p.replace(_,"\\$&"):b.setAttribute("id",q),q="[id='"+q+"'] ",j=m.length;while(j--)m[j]=q+pb(m[j]);u=$.test(a)&&mb(b.parentNode)||b,v=m.join(",")}if(v)try{return G.apply(d,u.querySelectorAll(v)),d}catch(w){}finally{p||b.removeAttribute("id")}}}return xb(a.replace(P,"$1"),b,d,e)}function eb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function fb(a){return a[s]=!0,a}function gb(a){var b=l.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function hb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function ib(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||B)-(~a.sourceIndex||B);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function jb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function kb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function lb(a){return fb(function(b){return b=+b,fb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function mb(a){return a&&typeof a.getElementsByTagName!==A&&a}c=db.support={},f=db.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},k=db.setDocument=function(a){var b,e=a?a.ownerDocument||a:t,g=e.defaultView;return e!==l&&9===e.nodeType&&e.documentElement?(l=e,m=e.documentElement,n=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){k()},!1):g.attachEvent&&g.attachEvent("onunload",function(){k()})),c.attributes=gb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=gb(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(e.getElementsByClassName)&&gb(function(a){return a.innerHTML="
",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=gb(function(a){return m.appendChild(a).id=s,!e.getElementsByName||!e.getElementsByName(s).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==A&&n){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){var c=typeof a.getAttributeNode!==A&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==A?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==A&&n?b.getElementsByClassName(a):void 0},p=[],o=[],(c.qsa=Y.test(e.querySelectorAll))&&(gb(function(a){a.innerHTML="",a.querySelectorAll("[t^='']").length&&o.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||o.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll(":checked").length||o.push(":checked")}),gb(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&o.push("name"+K+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||o.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),o.push(",.*:")})),(c.matchesSelector=Y.test(q=m.webkitMatchesSelector||m.mozMatchesSelector||m.oMatchesSelector||m.msMatchesSelector))&&gb(function(a){c.disconnectedMatch=q.call(a,"div"),q.call(a,"[s!='']:x"),p.push("!=",O)}),o=o.length&&new RegExp(o.join("|")),p=p.length&&new RegExp(p.join("|")),b=Y.test(m.compareDocumentPosition),r=b||Y.test(m.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},z=b?function(a,b){if(a===b)return j=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===t&&r(t,a)?-1:b===e||b.ownerDocument===t&&r(t,b)?1:i?I.call(i,a)-I.call(i,b):0:4&d?-1:1)}:function(a,b){if(a===b)return j=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],k=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:i?I.call(i,a)-I.call(i,b):0;if(f===g)return ib(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)k.unshift(c);while(h[d]===k[d])d++;return d?ib(h[d],k[d]):h[d]===t?-1:k[d]===t?1:0},e):l},db.matches=function(a,b){return db(a,null,null,b)},db.matchesSelector=function(a,b){if((a.ownerDocument||a)!==l&&k(a),b=b.replace(S,"='$1']"),!(!c.matchesSelector||!n||p&&p.test(b)||o&&o.test(b)))try{var d=q.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return db(b,l,null,[a]).length>0},db.contains=function(a,b){return(a.ownerDocument||a)!==l&&k(a),r(a,b)},db.attr=function(a,b){(a.ownerDocument||a)!==l&&k(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!n):void 0;return void 0!==f?f:c.attributes||!n?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},db.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},db.uniqueSort=function(a){var b,d=[],e=0,f=0;if(j=!c.detectDuplicates,i=!c.sortStable&&a.slice(0),a.sort(z),j){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return i=null,a},e=db.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=db.selectors={cacheLength:50,createPseudo:fb,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ab,bb),a[3]=(a[4]||a[5]||"").replace(ab,bb),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||db.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&db.error(a[0]),a},PSEUDO:function(a){var b,c=!a[5]&&a[2];return V.CHILD.test(a[0])?null:(a[3]&&void 0!==a[4]?a[2]=a[4]:c&&T.test(c)&&(b=ob(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ab,bb).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=w[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&w(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==A&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=db.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),t=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&t){k=q[s]||(q[s]={}),j=k[a]||[],n=j[0]===u&&j[1],m=j[0]===u&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[u,n,m];break}}else if(t&&(j=(b[s]||(b[s]={}))[a])&&j[0]===u)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(t&&((l[s]||(l[s]={}))[a]=[u,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||db.error("unsupported pseudo: "+a);return e[s]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?fb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:fb(function(a){var b=[],c=[],d=g(a.replace(P,"$1"));return d[s]?fb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:fb(function(a){return function(b){return db(a,b).length>0}}),contains:fb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:fb(function(a){return U.test(a||"")||db.error("unsupported lang: "+a),a=a.replace(ab,bb).toLowerCase(),function(b){var c;do if(c=n?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===m},focus:function(a){return a===l.activeElement&&(!l.hasFocus||l.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:lb(function(){return[0]}),last:lb(function(a,b){return[b-1]}),eq:lb(function(a,b,c){return[0>c?c+b:c]}),even:lb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:lb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:lb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:lb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function qb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=v++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[u,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[s]||(b[s]={}),(h=i[d])&&h[0]===u&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function rb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function sb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function tb(a,b,c,d,e,f){return d&&!d[s]&&(d=tb(d)),e&&!e[s]&&(e=tb(e,f)),fb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||wb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:sb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=sb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=sb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ub(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],i=g||d.relative[" "],j=g?1:0,k=qb(function(a){return a===b},i,!0),l=qb(function(a){return I.call(b,a)>-1},i,!0),m=[function(a,c,d){return!g&&(d||c!==h)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>j;j++)if(c=d.relative[a[j].type])m=[qb(rb(m),c)];else{if(c=d.filter[a[j].type].apply(null,a[j].matches),c[s]){for(e=++j;f>e;e++)if(d.relative[a[e].type])break;return tb(j>1&&rb(m),j>1&&pb(a.slice(0,j-1).concat({value:" "===a[j-2].type?"*":""})).replace(P,"$1"),c,e>j&&ub(a.slice(j,e)),f>e&&ub(a=a.slice(e)),f>e&&pb(a))}m.push(c)}return rb(m)}function vb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,i,j,k){var m,n,o,p=0,q="0",r=f&&[],s=[],t=h,v=f||e&&d.find.TAG("*",k),w=u+=null==t?1:Math.random()||.1,x=v.length;for(k&&(h=g!==l&&g);q!==x&&null!=(m=v[q]);q++){if(e&&m){n=0;while(o=a[n++])if(o(m,g,i)){j.push(m);break}k&&(u=w)}c&&((m=!o&&m)&&p--,f&&r.push(m))}if(p+=q,c&&q!==p){n=0;while(o=b[n++])o(r,s,g,i);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=E.call(j));s=sb(s)}G.apply(j,s),k&&!f&&s.length>0&&p+b.length>1&&db.uniqueSort(j)}return k&&(u=w,h=t),r};return c?fb(f):f}g=db.compile=function(a,b){var c,d=[],e=[],f=y[a+" "];if(!f){b||(b=ob(a)),c=b.length;while(c--)f=ub(b[c]),f[s]?d.push(f):e.push(f);f=y(a,vb(e,d))}return f};function wb(a,b,c){for(var d=0,e=b.length;e>d;d++)db(a,b[d],c);return c}function xb(a,b,e,f){var h,i,j,k,l,m=ob(a);if(!f&&1===m.length){if(i=m[0]=m[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&c.getById&&9===b.nodeType&&n&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(ab,bb),b)||[])[0],!b)return e;a=a.slice(i.shift().value.length)}h=V.needsContext.test(a)?0:i.length;while(h--){if(j=i[h],d.relative[k=j.type])break;if((l=d.find[k])&&(f=l(j.matches[0].replace(ab,bb),$.test(i[0].type)&&mb(b.parentNode)||b))){if(i.splice(h,1),a=f.length&&pb(i),!a)return G.apply(e,f),e;break}}}return g(a,m)(f,b,!n,e,$.test(a)&&mb(b.parentNode)||b),e}return c.sortStable=s.split("").sort(z).join("")===s,c.detectDuplicates=!!j,k(),c.sortDetached=gb(function(a){return 1&a.compareDocumentPosition(l.createElement("div"))}),gb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||hb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&gb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||hb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),gb(function(a){return null==a.getAttribute("disabled")})||hb(J,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),db}(a);o.find=t,o.expr=t.selectors,o.expr[":"]=o.expr.pseudos,o.unique=t.uniqueSort,o.text=t.getText,o.isXMLDoc=t.isXML,o.contains=t.contains;var u=o.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(o.isFunction(b))return o.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return o.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return o.filter(b,a,c);b=o.filter(b,a)}return o.grep(a,function(a){return g.call(b,a)>=0!==c})}o.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?o.find.matchesSelector(d,a)?[d]:[]:o.find.matches(a,o.grep(b,function(a){return 1===a.nodeType}))},o.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(o(a).filter(function(){for(b=0;c>b;b++)if(o.contains(e[b],this))return!0}));for(b=0;c>b;b++)o.find(a,e[b],d);return d=this.pushStack(c>1?o.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?o(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=o.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof o?b[0]:b,o.merge(this,o.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:m,!0)),v.test(c[1])&&o.isPlainObject(b))for(c in b)o.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=m.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=m,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):o.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(o):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),o.makeArray(a,this))};A.prototype=o.fn,y=o(m);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};o.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&o(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),o.fn.extend({has:function(a){var b=o(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(o.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?o(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&o.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?o.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(o(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(o.unique(o.merge(this.get(),o(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}o.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return o.dir(a,"parentNode")},parentsUntil:function(a,b,c){return o.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return o.dir(a,"nextSibling")},prevAll:function(a){return o.dir(a,"previousSibling")},nextUntil:function(a,b,c){return o.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return o.dir(a,"previousSibling",c)},siblings:function(a){return o.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return o.sibling(a.firstChild)},contents:function(a){return a.contentDocument||o.merge([],a.childNodes)}},function(a,b){o.fn[a]=function(c,d){var e=o.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=o.filter(d,e)),this.length>1&&(C[a]||o.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return o.each(a.match(E)||[],function(a,c){b[c]=!0}),b}o.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):o.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){o.each(b,function(b,c){var d=o.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&o.each(arguments,function(a,b){var c;while((c=o.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?o.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},o.extend({Deferred:function(a){var b=[["resolve","done",o.Callbacks("once memory"),"resolved"],["reject","fail",o.Callbacks("once memory"),"rejected"],["notify","progress",o.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return o.Deferred(function(c){o.each(b,function(b,f){var g=o.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&o.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?o.extend(a,d):d}},e={};return d.pipe=d.then,o.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&o.isFunction(a.promise)?e:0,g=1===f?a:o.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&o.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;o.fn.ready=function(a){return o.ready.promise().done(a),this},o.extend({isReady:!1,readyWait:1,holdReady:function(a){a?o.readyWait++:o.ready(!0)},ready:function(a){(a===!0?--o.readyWait:o.isReady)||(o.isReady=!0,a!==!0&&--o.readyWait>0||(H.resolveWith(m,[o]),o.fn.trigger&&o(m).trigger("ready").off("ready")))}});function I(){m.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),o.ready()}o.ready.promise=function(b){return H||(H=o.Deferred(),"complete"===m.readyState?setTimeout(o.ready):(m.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},o.ready.promise();var J=o.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===o.type(c)){e=!0;for(h in c)o.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,o.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(o(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};o.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=o.expando+Math.random()}K.uid=1,K.accepts=o.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,o.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(o.isEmptyObject(f))o.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,o.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{o.isArray(b)?d=b.concat(b.map(o.camelCase)):(e=o.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!o.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?o.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}o.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),o.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length; 3 | while(c--)d=g[c].name,0===d.indexOf("data-")&&(d=o.camelCase(d.slice(5)),P(f,d,e[d]));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=o.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),o.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||o.isArray(c)?d=L.access(a,b,o.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=o.queue(a,b),d=c.length,e=c.shift(),f=o._queueHooks(a,b),g=function(){o.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:o.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),o.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length",l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";l.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return m.activeElement}catch(a){}}o.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=o.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof o!==U&&o.event.triggered!==b.type?o.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],n=q=h[1],p=(h[2]||"").split(".").sort(),n&&(l=o.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=o.event.special[n]||{},k=o.extend({type:n,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&o.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(n,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),o.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],n=q=h[1],p=(h[2]||"").split(".").sort(),n){l=o.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||o.removeEvent(a,n,r.handle),delete i[n])}else for(n in i)o.event.remove(a,n+b[j],c,d,!0);o.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,p=[d||m],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||m,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+o.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[o.expando]?b:new o.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:o.makeArray(c,[b]),n=o.event.special[q]||{},e||!n.trigger||n.trigger.apply(d,c)!==!1)){if(!e&&!n.noBubble&&!o.isWindow(d)){for(i=n.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||m)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:n.bindType||q,l=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),l&&l.apply(g,c),l=k&&g[k],l&&l.apply&&o.acceptData(g)&&(b.result=l.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||n._default&&n._default.apply(p.pop(),c)!==!1||!o.acceptData(d)||k&&o.isFunction(d[q])&&!o.isWindow(d)&&(h=d[k],h&&(d[k]=null),o.event.triggered=q,d[q](),o.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=o.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=o.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=o.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((o.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?o(e,this).index(i)>=0:o.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return o.nodeName(a,"table")&&o.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)o.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=o.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&o.nodeName(a,b)?o.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}o.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=o.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||o.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,n=a.length;n>m;m++)if(e=a[m],e||0===e)if("object"===o.type(e))o.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;o.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===o.inArray(e,d))&&(i=o.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f,g,h=o.event.special,i=0;void 0!==(c=a[i]);i++){if(o.acceptData(c)&&(f=c[L.expando],f&&(b=L.cache[f]))){if(d=Object.keys(b.events||{}),d.length)for(g=0;void 0!==(e=d[g]);g++)h[e]?o.event.remove(c,e):o.removeEvent(c,e,b.handle);L.cache[f]&&delete L.cache[f]}delete M.cache[c[M.expando]]}}}),o.fn.extend({text:function(a){return J(this,function(a){return void 0===a?o.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?o.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||o.cleanData(ob(c)),c.parentNode&&(b&&o.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(o.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return o.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(o.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,o.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,k=this.length,m=this,n=k-1,p=a[0],q=o.isFunction(p);if(q||k>1&&"string"==typeof p&&!l.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(k&&(c=o.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=o.map(ob(c,"script"),kb),g=f.length;k>j;j++)h=c,j!==n&&(h=o.clone(h,!0,!0),g&&o.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,o.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&o.contains(i,h)&&(h.src?o._evalUrl&&o._evalUrl(h.src):o.globalEval(h.textContent.replace(hb,"")))}return this}}),o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){o.fn[a]=function(a){for(var c,d=[],e=o(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),o(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d=o(c.createElement(b)).appendTo(c.body),e=a.getDefaultComputedStyle?a.getDefaultComputedStyle(d[0]).display:o.css(d[0],"display");return d.detach(),e}function tb(a){var b=m,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||o("