<commit_before>$.ajaxSetup({async: false});

var map, points, info, bounds, data, codes = {}, meta, currentDate, loadedData = {};
var dateBegin = new Date('2015-11-16'), dateEnd, firstCsv = true, selectedPoint = false;
var standards = {}, markers = {}, markerClicked = false;

$.getJSON('http://ks-opendata-community.github.io/chimney/data/工廠清單.json', {}, function (p) {
    points = p;
});

$.getJSON('http://ks-opendata-community.github.io/chimney/data/項目代碼.json', {}, function (p) {
    $.each(p, function (k, v) {
        codes[v['ITEM']] = v;
    });
});

$.get('http://ks-opendata-community.github.io/chimney/data/警戒值.csv', {}, function (p) {
    var stack = $.csv.toArrays(p);
    stack.shift();
    /*
     * CNO,POLNO,ITEM,STD
     */
    for (i in stack) {
        if (!standards[stack[i][0]]) {
            standards[stack[i][0]] = {};
        }
        if (!standards[stack[i][0]][stack[i][2]]) {
            standards[stack[i][0]][stack[i][2]] = {};
        }
        standards[stack[i][0]][stack[i][2]][stack[i][1]] = stack[i][3];
        var itemKey = '9' + stack[i][2].slice(-2);
        if (!standards[stack[i][0]][itemKey]) {
            standards[stack[i][0]][itemKey] = {};
        }
        standards[stack[i][0]][itemKey][stack[i][1]] = stack[i][3];
    }
});

loadCsv('http://ks-opendata-community.github.io/chimney/data/daily/latest.csv', 'KHH');

function initialize() {
    var showChart = function (theDay, factoryId) {
        var dirtyDate = new Date(theDay);
        if (!isNaN(dirtyDate.getTime())) {
            currentDate = dirtyDate;
            if (markers[factoryId]) {
                new google.maps.event.trigger(markers[factoryId], 'click');
            }
        }
    };
    var routes = {
        '/:theDay/:factoryId': showChart
    };
    var router = Router(routes);

    /*map setting*/
    $('#map-canvas').height(window.outerHeight / 2.2);

    map = new google.maps.Map(document.getElementById('map-canvas'), {
        zoom: 12,
        center: {lat: 22.672925, lng: 120.309465}
    });
    info = new google.maps.InfoWindow();
    bounds = new google.maps.LatLngBounds();

    var pointSelectOptions = '<option value="">---請選擇---</option>';
    $.each(points, function (k, p) {
        var geoPoint = (new google.maps.LatLng(parseFloat(p.Lat), parseFloat(p.Lng)));
        var marker = new google.maps.Marker({
            position: geoPoint,
            map: map,
            title: p['工廠']
        });
        marker.data = p;
        marker.addListener('click', function () {
            var infoText = '' + this.data['工廠'] + '';
            infoText += '
管制編號: ' + this.data['管制編號'];
            infoText += '
地址: ' + this.data['地址'];
            info.setContent(infoText);
            info.open(map, this);
            map.setZoom(15);
            map.setCenter(this.getPosition());
            currentFactory = this.data;
            selectedPoint = this.data['管制編號'];
            updateData();
        });
        markers[p['管制編號']] = marker;
        bounds.extend(geoPoint);

        pointSelectOptions += '<option value="' + p['管制編號'] + '">' + p['工廠'] + '[' + p['管制編號'] + ']</option>';
    });
    $('#pointSelect').html(pointSelectOptions).select2();
    $('#pointSelect').change(function () {
        if (false === markerClicked) {
            var value = $(this).val();
            if (markers[value]) {
                new google.maps.event.trigger(markers[value], 'click');
            }
        }
    });

    map.fitBounds(bounds);
    router.init();

    $('a.bounds-reset').click(function () {
        map.fitBounds(bounds);
        return false;
    });

    $('a#btnPrevious').click(function () {
        currentDate.setDate(currentDate.getDate() - 1);
        if (currentDate.getTime() < dateBegin.getTime()) {
            currentDate.setDate(currentDate.getDate() + 1);
        }
        updateData();
        return false;
    });

    $('a#btnNext').click(function () {
        currentDate.setDate(currentDate.getDate() + 1);
        if (currentDate.getTime() > dateEnd.getTime()) {
            currentDate.setDate(currentDate.getDate() - 1);
        }
        updateData();
        return false;
    });

    $('input#selectDate').datepicker({
        dateFormat: 'yy-mm-dd',
        onSelect: function (txt) {
            var selectedDate = new Date(txt);
            if (selectedDate.getTime() >= dateBegin.getTime() && selectedDate.getTime() <= dateEnd.getTime()) {
                currentDate = selectedDate;
                updateData();
            } else {
                $('#content').html('選擇的日期沒有資料');
            }

        }
    });

    function updateData() {
        if (false === selectedPoint) {
            return;
        }
        var c = getDateStr(currentDate);
        var city = markers[selectedPoint].data['city'];
        $('input#selectDate').val(c);
        if (!loadedData[city]) {
            loadedData[city] = {};
        }
        if (!loadedData[city][c]) {
            var dateParts = c.split('-');
            var csvUrl = 'http://ks-opendata-community.github.io/chimney/data/daily/';
            switch (city) {
                case 'KHH':
                    csvUrl += 'kaohsiung/'
                    break;
                case 'TXG':
                    csvUrl += 'taichung/'
                    break;
                case 'ILA':
                    csvUrl += 'yilan/'
                    break;
                case 'CYQ':
                    csvUrl += 'chiayi/'
                    break;
                case 'TNN':
                    csvUrl += 'tainan/'
                    break;
                case 'YUN':
                    csvUrl += 'yunlin/'
                    break;
            }
            csvUrl += dateParts[0] + '/' + dateParts[1] + '/' + dateParts[0] + dateParts[1] + dateParts[2] + '.csv';
            loadCsv(csvUrl, city);
        } else {
            data = loadedData[city][c].slice(0);
            meta = data[0];
            currentDate = new Date(meta[0]);
            $('input#selectDate').val(meta[0]);
        }
        if (false !== selectedPoint) {
            showData(selectedPoint);
            window.location.hash = '#' + c + '/' + selectedPoint;
            $('#title').html(markers[selectedPoint].data['工廠']);

            markerClicked = true;
            $('#pointSelect').val(selectedPoint).trigger('change');
            markerClicked = false;
        }
    }

    $('select#chartFilter').select2().change(function () {
        if (false !== selectedPoint) {
            showData(selectedPoint);
        }
    });

    function getDateStr(dateObj) {
        var m = dateObj.getMonth() + 1;
        var d = dateObj.getDate();
        m = m.toString();
        d = d.toString();
        m = m.length > 1 ? m : '0' + m;
        d = d.length > 1 ? d : '0' + d;
        return dateObj.getFullYear() + '-' + m + '-' + d;
    }

    function showData(currentKey) {
        var contentText = '';
        var chartData = {}, defaultChartTypes = ['911', '922', '923', '926'];
        var chartType = $('select#chartFilter').val();
        if (!chartType) {
            chartType = 'default';
        }
        var titleText = markers[currentKey].data['工廠'];
        /*
         * 0: 工廠代號
         * 1: 管制點 [2]
         * 2: 管制項目 [1] - chartKey
         * 3: 時間 [3]
         * 4: 數值 [4]
         */
        $.each(data, function (b, line) {
            if (line[0] === currentKey) {
                var chartCheck = true;
                switch (chartType) {
                    case 'default':
                        if (-1 === defaultChartTypes.indexOf(line[2])) {
                            chartCheck = false;
                        }
                        break;
                    case 'avg':
                        if (line[2].substr(0, 1) !== '2') {
                            chartCheck = false;
                        }
                        break;
                    case 'real':
                        if (line[2].substr(0, 1) !== '9') {
                            chartCheck = false;
                        }
                        break;
                }
                if (chartCheck) {
                    var chartKey = line[2];
                    if (!chartData[chartKey]) {
                        chartData[chartKey] = {};
                        contentText += '
' + chartKey + '
';
                    }
                    if (!chartData[chartKey][line[1]]) {
                        chartData[chartKey][line[1]] = {};
                    }
                    line[3] = '' + line[3];
                    chartData[chartKey][line[1]][line[3]] = parseFloat(line[4]);
                }

            }
        });
        var placeHolderCheck = true;
        if (contentText === '') {
            contentText = '
選擇的管制點沒有圖表可以顯示，可以試著從右邊地圖下方的選單調整圖表過濾規則顯示
';
            placeHolderCheck = false;
        }
        $('#content').html(contentText);

        if (placeHolderCheck) {
            for (k in chartData) {
                var chartLines = [], categories = [];
                var firstPoint = false;
                for (p in chartData[k]) {
                    var tkeys = [];
                    var chartLine = {
                        name: p,
                        data: []
                    };
                    for (t in chartData[k][p]) {
                        tkeys.push(t);
                    }
                    tkeys.sort();
                    for (i in tkeys) {
                        var t = tkeys[i];
                        chartLine.data.push(chartData[k][p][t]);
                    }
                    if (false === firstPoint) {
                        firstPoint = true;
                        for (i in tkeys) {
                            var t = tkeys[i];
                            var ft = t.substr(0, 2) + ':' + t.substr(2, 2);
                            categories.push(ft);
                        }
                    }
                    chartLines.push(chartLine);
                }
                var subtitle = '';
                if (standards[currentKey] && standards[currentKey][k]) {
                    subtitle = ' > 排放標準';
                }
                $('#' + k).highcharts({
                    title: {text: codes[k].DESP + ' (' + codes[k].UNIT + ')'},
                    subtitle: {
                        align: 'right',
                        text: subtitle,
                        useHTML: true
                    },
                    xAxis: {
                        title: {
                            text: titleText + ' @ ' + getDateStr(currentDate)
                        },
                        categories: categories
                    },
                    yAxis: {
                        title: {
                            text: codes[k].UNIT
                        }
                    },
                    series: chartLines
                });
            }

            $('.pop-standard').click(function () {
                var self = $(this), boxid = self.attr('data-id'), boxitem = self.attr('data-item');
                var txt = '
';
                for (k in standards[boxid][boxitem]) {
                    txt += k + ': ' + standards[boxid][boxitem][k] + ' ' + codes[boxitem].UNIT + '
';
                }
                txt += '
';
                $('#dialog').html(txt).dialog({
                    width: 500,
                    title: codes[boxitem].DESP + '排放標準 @ ' + markers[boxid]['data']['工廠']
                });
                return false;
            });
        }

    }
}

function loadCsv(csvUrl, city) {
    $.get(csvUrl, {}, function (p) {
        data = $.csv.toArrays(p);
        meta = data[0];
        if (!loadedData[city]) {
            loadedData[city] = {};
        }
        loadedData[city][meta[0]] = data.slice(0);
        currentDate = new Date(meta[0]);
        if (firstCsv) {
            firstCsv = false;
            dateEnd = new Date(meta[0]);
        }
        $('input#selectDate').val(meta[0]);
    });
}

google.maps.event.addDomListener(window, 'load', initialize);<commit_msg>add changhua option<commit_after>$.ajaxSetup({async: false});

var map, points, info, bounds, data, codes = {}, meta, currentDate, loadedData = {};
var dateBegin = new Date('2015-11-16'), dateEnd, firstCsv = true, selectedPoint = false;
var standards = {}, markers = {}, markerClicked = false;

$.getJSON('http://ks-opendata-community.github.io/chimney/data/工廠清單.json', {}, function (p) {
    points = p;
});

$.getJSON('http://ks-opendata-community.github.io/chimney/data/項目代碼.json', {}, function (p) {
    $.each(p, function (k, v) {
        codes[v['ITEM']] = v;
    });
});

$.get('http://ks-opendata-community.github.io/chimney/data/警戒值.csv', {}, function (p) {
    var stack = $.csv.toArrays(p);
    stack.shift();
    /*
     * CNO,POLNO,ITEM,STD
     */
    for (i in stack) {
        if (!standards[stack[i][0]]) {
            standards[stack[i][0]] = {};
        }
        if (!standards[stack[i][0]][stack[i][2]]) {
            standards[stack[i][0]][stack[i][2]] = {};
        }
        standards[stack[i][0]][stack[i][2]][stack[i][1]] = stack[i][3];
        var itemKey = '9' + stack[i][2].slice(-2);
        if (!standards[stack[i][0]][itemKey]) {
            standards[stack[i][0]][itemKey] = {};
        }
        standards[stack[i][0]][itemKey][stack[i][1]] = stack[i][3];
    }
});

loadCsv('http://ks-opendata-community.github.io/chimney/data/daily/latest.csv', 'KHH');

function initialize() {
    var showChart = function (theDay, factoryId) {
        var dirtyDate = new Date(theDay);
        if (!isNaN(dirtyDate.getTime())) {
            currentDate = dirtyDate;
            if (markers[factoryId]) {
                new google.maps.event.trigger(markers[factoryId], 'click');
            }
        }
    };
    var routes = {
        '/:theDay/:factoryId': showChart
    };
    var router = Router(routes);

    /*map setting*/
    $('#map-canvas').height(window.outerHeight / 2.2);

    map = new google.maps.Map(document.getElementById('map-canvas'), {
        zoom: 12,
        center: {lat: 22.672925, lng: 120.309465}
    });
    info = new google.maps.InfoWindow();
    bounds = new google.maps.LatLngBounds();

    var pointSelectOptions = '<option value="">---請選擇---</option>';
    $.each(points, function (k, p) {
        var geoPoint = (new google.maps.LatLng(parseFloat(p.Lat), parseFloat(p.Lng)));
        var marker = new google.maps.Marker({
            position: geoPoint,
            map: map,
            title: p['工廠']
        });
        marker.data = p;
        marker.addListener('click', function () {
            var infoText = '' + this.data['工廠'] + '';
            infoText += '
管制編號: ' + this.data['管制編號'];
            infoText += '
地址: ' + this.data['地址'];
            info.setContent(infoText);
            info.open(map, this);
            map.setZoom(15);
            map.setCenter(this.getPosition());
            currentFactory = this.data;
            selectedPoint = this.data['管制編號'];
            updateData();
        });
        markers[p['管制編號']] = marker;
        bounds.extend(geoPoint);

        pointSelectOptions += '<option value="' + p['管制編號'] + '">' + p['工廠'] + '[' + p['管制編號'] + ']</option>';
    });
    $('#pointSelect').html(pointSelectOptions).select2();
    $('#pointSelect').change(function () {
        if (false === markerClicked) {
            var value = $(this).val();
            if (markers[value]) {
                new google.maps.event.trigger(markers[value], 'click');
            }
        }
    });

    map.fitBounds(bounds);
    router.init();

    $('a.bounds-reset').click(function () {
        map.fitBounds(bounds);
        return false;
    });

    $('a#btnPrevious').click(function () {
        currentDate.setDate(currentDate.getDate() - 1);
        if (currentDate.getTime() < dateBegin.getTime()) {
            currentDate.setDate(currentDate.getDate() + 1);
        }
        updateData();
        return false;
    });

    $('a#btnNext').click(function () {
        currentDate.setDate(currentDate.getDate() + 1);
        if (currentDate.getTime() > dateEnd.getTime()) {
            currentDate.setDate(currentDate.getDate() - 1);
        }
        updateData();
        return false;
    });

    $('input#selectDate').datepicker({
        dateFormat: 'yy-mm-dd',
        onSelect: function (txt) {
            var selectedDate = new Date(txt);
            if (selectedDate.getTime() >= dateBegin.getTime() && selectedDate.getTime() <= dateEnd.getTime()) {
                currentDate = selectedDate;
                updateData();
            } else {
                $('#content').html('選擇的日期沒有資料');
            }

        }
    });

    function updateData() {
        if (false === selectedPoint) {
            return;
        }
        var c = getDateStr(currentDate);
        var city = markers[selectedPoint].data['city'];
        $('input#selectDate').val(c);
        if (!loadedData[city]) {
            loadedData[city] = {};
        }
        if (!loadedData[city][c]) {
            var dateParts = c.split('-');
            var csvUrl = 'http://ks-opendata-community.github.io/chimney/data/daily/';
            switch (city) {
                case 'KHH':
                    csvUrl += 'kaohsiung/'
                    break;
                case 'TXG':
                    csvUrl += 'taichung/'
                    break;
                case 'ILA':
                    csvUrl += 'yilan/'
                    break;
                case 'CYQ':
                    csvUrl += 'chiayi/'
                    break;
                case 'TNN':
                    csvUrl += 'tainan/'
                    break;
                case 'YUN':
                    csvUrl += 'yunlin/'
                    break;
                case 'CHA':
                    csvUrl += 'changhua/'
                    break;
            }
            csvUrl += dateParts[0] + '/' + dateParts[1] + '/' + dateParts[0] + dateParts[1] + dateParts[2] + '.csv';
            loadCsv(csvUrl, city);
        } else {
            data = loadedData[city][c].slice(0);
            meta = data[0];
            currentDate = new Date(meta[0]);
            $('input#selectDate').val(meta[0]);
        }
        if (false !== selectedPoint) {
            showData(selectedPoint);
            window.location.hash = '#' + c + '/' + selectedPoint;
            $('#title').html(markers[selectedPoint].data['工廠']);

            markerClicked = true;
            $('#pointSelect').val(selectedPoint).trigger('change');
            markerClicked = false;
        }
    }

    $('select#chartFilter').select2().change(function () {
        if (false !== selectedPoint) {
            showData(selectedPoint);
        }
    });

    function getDateStr(dateObj) {
        var m = dateObj.getMonth() + 1;
        var d = dateObj.getDate();
        m = m.toString();
        d = d.toString();
        m = m.length > 1 ? m : '0' + m;
        d = d.length > 1 ? d : '0' + d;
        return dateObj.getFullYear() + '-' + m + '-' + d;
    }

    function showData(currentKey) {
        var contentText = '';
        var chartData = {}, defaultChartTypes = ['911', '922', '923', '926'];
        var chartType = $('select#chartFilter').val();
        if (!chartType) {
            chartType = 'default';
        }
        var titleText = markers[currentKey].data['工廠'];
        /*
         * 0: 工廠代號
         * 1: 管制點 [2]
         * 2: 管制項目 [1] - chartKey
         * 3: 時間 [3]
         * 4: 數值 [4]
         */
        $.each(data, function (b, line) {
            if (line[0] === currentKey) {
                var chartCheck = true;
                switch (chartType) {
                    case 'default':
                        if (-1 === defaultChartTypes.indexOf(line[2])) {
                            chartCheck = false;
                        }
                        break;
                    case 'avg':
                        if (line[2].substr(0, 1) !== '2') {
                            chartCheck = false;
                        }
                        break;
                    case 'real':
                        if (line[2].substr(0, 1) !== '9') {
                            chartCheck = false;
                        }
                        break;
                }
                if (chartCheck) {
                    var chartKey = line[2];
                    if (!chartData[chartKey]) {
                        chartData[chartKey] = {};
                        contentText += '
' + chartKey + '
';
                    }
                    if (!chartData[chartKey][line[1]]) {
                        chartData[chartKey][line[1]] = {};
                    }
                    line[3] = '' + line[3];
                    chartData[chartKey][line[1]][line[3]] = parseFloat(line[4]);
                }

            }
        });
        var placeHolderCheck = true;
        if (contentText === '') {
            contentText = '
選擇的管制點沒有圖表可以顯示，可以試著從右邊地圖下方的選單調整圖表過濾規則顯示
';
            placeHolderCheck = false;
        }
        $('#content').html(contentText);

        if (placeHolderCheck) {
            for (k in chartData) {
                var chartLines = [], categories = [];
                var firstPoint = false;
                for (p in chartData[k]) {
                    var tkeys = [];
                    var chartLine = {
                        name: p,
                        data: []
                    };
                    for (t in chartData[k][p]) {
                        tkeys.push(t);
                    }
                    tkeys.sort();
                    for (i in tkeys) {
                        var t = tkeys[i];
                        chartLine.data.push(chartData[k][p][t]);
                    }
                    if (false === firstPoint) {
                        firstPoint = true;
                        for (i in tkeys) {
                            var t = tkeys[i];
                            var ft = t.substr(0, 2) + ':' + t.substr(2, 2);
                            categories.push(ft);
                        }
                    }
                    chartLines.push(chartLine);
                }
                var subtitle = '';
                if (standards[currentKey] && standards[currentKey][k]) {
                    subtitle = ' > 排放標準';
                }
                $('#' + k).highcharts({
                    title: {text: codes[k].DESP + ' (' + codes[k].UNIT + ')'},
                    subtitle: {
                        align: 'right',
                        text: subtitle,
                        useHTML: true
                    },
                    xAxis: {
                        title: {
                            text: titleText + ' @ ' + getDateStr(currentDate)
                        },
                        categories: categories
                    },
                    yAxis: {
                        title: {
                            text: codes[k].UNIT
                        }
                    },
                    series: chartLines
                });
            }

            $('.pop-standard').click(function () {
                var self = $(this), boxid = self.attr('data-id'), boxitem = self.attr('data-item');
                var txt = '
';
                for (k in standards[boxid][boxitem]) {
                    txt += k + ': ' + standards[boxid][boxitem][k] + ' ' + codes[boxitem].UNIT + '
';
                }
                txt += '
';
                $('#dialog').html(txt).dialog({
                    width: 500,
                    title: codes[boxitem].DESP + '排放標準 @ ' + markers[boxid]['data']['工廠']
                });
                return false;
            });
        }

    }
}

function loadCsv(csvUrl, city) {
    $.get(csvUrl, {}, function (p) {
        data = $.csv.toArrays(p);
        meta = data[0];
        if (!loadedData[city]) {
            loadedData[city] = {};
        }
        loadedData[city][meta[0]] = data.slice(0);
        currentDate = new Date(meta[0]);
        if (firstCsv) {
            firstCsv = false;
            dateEnd = new Date(meta[0]);
        }
        $('input#selectDate').val(meta[0]);
    });
}

google.maps.event.addDomListener(window, 'load', initialize);<|endoftext|>


<commit_before>(function() {
  var Ruban,
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

  Ruban = (function() {
    function Ruban(options) {
      this.options = options != null ? options : {};
      this.next = __bind(this.next, this);
      this.prev = __bind(this.prev, this);
      this.first = __bind(this.first, this);
      this.last = __bind(this.last, this);
      this.checkHash = __bind(this.checkHash, this);
      this.initOptions();
      this.$sections = $('section').wrapAll('

');
      this.$ruban = $('.ruban');
      this.toc();
      this.current(this.$sections.first());
      this.pagination();
      this.checkHash();
      this.highlight();
      this.resize();
      this.bind();
      this.$ruban.css('transition-property', 'transform');
      this.$ruban.css('-webkit-transition-property', '-webkit-transform');
      this.$ruban.css('transition-duration', this.options.transitionDuration);
    }

    Ruban.prototype.initOptions = function() {
      var _base, _base1, _base2, _base3, _base4, _base5, _base6;
      if ((_base = this.options).ratio == null) {
        _base.ratio = 4 / 3;
      }
      if ((_base1 = this.options).minPadding == null) {
        _base1.minPadding = '0.4em';
      }
      if ((_base2 = this.options).transitionDuration == null) {
        _base2.transitionDuration = '1s';
      }
      if ((_base3 = this.options).pagination == null) {
        _base3.pagination = false;
      }
      if ((_base4 = this.options).stripHtmlInToc == null) {
        _base4.stripHtmlInToc = false;
      }
      if ((_base5 = this.options).bindClicks == null) {
        _base5.bindClicks = false;
      }
      return (_base6 = this.options).bindMouseWheel != null ? (_base6 = this.options).bindMouseWheel : _base6.bindMouseWheel = false;
    };

    Ruban.prototype.bind = function() {
      this.bindKeys();
      this.bindGestures();
      if (this.options.bindClicks) {
        this.bindClicks();
      }
      if (this.options.bindMouseWheel) {
        this.bindMouseWheel();
      }
      this.bindResize();
      return this.bindHashChange();
    };

    Ruban.prototype.bindKeys = function() {
      key('right, down, space, return, j, l, pagedown', this.next);
      key('home', this.first);
      key('end', this.last);
      return key('left, up, backspace, k, h, pageup', this.prev);
    };

    Ruban.prototype.bindGestures = function() {
      return Hammer(document, {
        drag_block_vertical: true,
        drag_block_horizontal: true
      }).on('swipeleft swipeup', this.next).on('swiperight swipedown', this.prev);
    };

    Ruban.prototype.bindClicks = function() {
      var _this = this;
      this.$ruban.contextmenu(function() {
        return false;
      });
      return this.$ruban.mousedown(function(e) {
        switch (e.which) {
          case 1:
            return _this.next();
          case 3:
            return _this.prev();
        }
      });
    };

    Ruban.prototype.bindMouseWheel = function() {
      var _this = this;
      return this.$ruban.on('wheel', function(e) {
        if (e.originalEvent.deltaY > 0) {
          return _this.next();
        } else if (e.originalEvent.deltaY < 0) {
          return _this.prev();
        }
      });
    };

    Ruban.prototype.bindResize = function() {
      var _this = this;
      return $(window).resize(function() {
        _this.resize();
        return _this.go(_this.$current, {
          force: true
        });
      });
    };

    Ruban.prototype.bindHashChange = function() {
      return $(window).on('hashchange', this.checkHash);
    };

    Ruban.prototype.resize = function() {
      var height, min, outerHeight, outerWidth, paddingH, paddingV, width, _ref;
      _ref = [$(window).width(), $(window).height()], outerWidth = _ref[0], outerHeight = _ref[1];
      if (outerWidth > this.options.ratio * outerHeight) {
        min = outerHeight;
        paddingV = this.options.minPadding;
        this.$ruban.parent().css('font-size', "" + (min * 0.4) + "%");
        this.$sections.css({
          'padding-top': paddingV,
          'padding-bottom': paddingV
        });
        height = this.$current.height();
        width = this.options.ratio * height;
        paddingH = "" + ((outerWidth - width) / 2) + "px";
        return this.$sections.css({
          'padding-left': paddingH,
          'padding-right': paddingH
        });
      } else {
        min = outerWidth / this.options.ratio;
        paddingH = this.options.minPadding;
        this.$ruban.parent().css('font-size', "" + (min * 0.4) + "%");
        this.$sections.css({
          'padding-left': paddingH,
          'padding-right': paddingH
        });
        width = this.$current.width();
        height = width / this.options.ratio;
        paddingV = "" + ((outerHeight - height) / 2) + "px";
        return this.$sections.css({
          'padding-top': paddingV,
          'padding-bottom': paddingV
        });
      }
    };

    Ruban.prototype.checkHash = function() {
      var hash, slide;
      hash = window.location.hash;
      if (slide = hash.substr(2)) {
        return this.go(slide);
      }
    };

    Ruban.prototype.highlight = function() {
      return hljs.initHighlightingOnLoad();
    };

    Ruban.prototype.prev = function() {
      if (this.hasSteps()) {
        return this.prevStep();
      } else {
        return this.prevSlide();
      }
    };

    Ruban.prototype.prevSlide = function() {
      var $prev;
      $prev = this.$current.prev('section');
      return this.go($prev, {
        direction: 'backward'
      });
    };

    Ruban.prototype.prevStep = function() {
      var $prev;
      this.$steps.eq(this.index).removeClass('step').fadeOut();
      $prev = this.$steps.eq(--this.index);
      if (!(this.index < -1)) {
        if ($prev.is(':visible')) {
          return $prev.addClass('step').trigger('step');
        } else if (this.index > -1) {
          return this.prevStep();
        }
      } else {
        return this.prevSlide();
      }
    };

    Ruban.prototype.first = function() {
      return this.firstSlide();
    };

    Ruban.prototype.firstSlide = function() {
      var $first = this.$current.prevAll('section:first-child');
      return this.go($first, {
        direction: 'backward'
      });
    };

    Ruban.prototype.last = function() {
      return this.lastSlide();
    };

    Ruban.prototype.lastSlide = function() {
      var $last = this.$current.nextAll('section:last-child');
      return this.go($last, {
        direction: 'forward'
      });
    };

    Ruban.prototype.next = function() {
      if (this.hasSteps()) {
        return this.nextStep();
      } else {
        return this.nextSlide();
      }
    };

    Ruban.prototype.nextSlide = function() {
      var $next;
      $next = this.$current.next('section');
      return this.go($next, {
        direction: 'forward'
      });
    };

    Ruban.prototype.nextStep = function() {
      var $next;
      this.$steps.eq(this.index).removeClass('step');
      $next = this.$steps.eq(++this.index);
      if ($next.length) {
        return $next.fadeIn().addClass('step').trigger('step');
      } else {
        return this.nextSlide();
      }
    };

    Ruban.prototype.checkSteps = function($section, direction) {
      this.$steps = $section.find('.steps').children();
      if (!this.$steps.length) {
        this.$steps = $section.find('.step');
      }
      if (direction === 'backward') {
        return this.index = this.$steps.length - 1;
      } else {
        this.index = -1;
        return this.$steps.hide();
      }
    };

    Ruban.prototype.hasSteps = function() {
      return (this.$steps != null) && this.$steps.length !== 0;
    };

    Ruban.prototype.find = function(slide) {
      var $section;
      if (slide instanceof $) {
        return slide;
      } else {
        $section = $("#" + slide);
        if ($section.length === 0) {
          $section = this.$sections.eq(parseInt(slide) - 1);
        }
        return $section;
      }
    };

    Ruban.prototype.go = function(slide, options) {
      var $section;
      if (slide == null) {
        slide = 1;
      }
      if (options == null) {
        options = {};
      }
      $section = this.find(slide);
      if ($section.length && (options.force || !$section.is(this.$current))) {
        this.checkSteps($section, options.direction);
        this.navigate($section);
        this.translate($section);
        this.current($section);
        return this.pagination();
      }
    };

    Ruban.prototype.navigate = function($section) {
      return window.location.hash = "/" + ($section.attr('id') || $section.index() + 1);
    };

    Ruban.prototype.translate = function($section) {
      var y;
      y = $section.prevAll().map(function() {
        return $(this).outerHeight();
      }).get().reduce(function(memo, height) {
        return memo + height;
      }, 0);
      return this.$ruban.css('transform', "translateY(-" + y + "px)");
    };

    Ruban.prototype.current = function($section) {
      if (this.$current != null) {
        this.$current.removeClass('active').trigger('inactive');
      }
      $section.addClass('active').trigger('active');
      return this.$current = $section;
    };

    Ruban.prototype.pagination = function() {
      if (this.options.pagination) {
        if (!this.$pagination) {
          this.$ruban.parent().append('');
          this.$pagination = $('.pagination');
          this.total = this.$sections.length;
        }
        return this.$pagination.html("" + (this.$current.index() + 1) + "/" + this.total);
      }
    };

    Ruban.prototype.toc = function() {
      var $toc, $ul, stripHtmlInToc;
      $toc = $('.toc').first();
      if ($toc.length) {
        stripHtmlInToc = this.options.stripHtmlInToc;
        $ul = $('
');
        $('section:not(.no-toc,.toc) > h1:only-child').each(function() {
          var $h1, $section, html, title;
          $section = $(this).parent();
          if (stripHtmlInToc) {
            title = html = $(this).text();
          } else {
            $h1 = $(this).clone().find('a').replaceWith(function() {
              return $(this).text();
            }).end();
            title = $h1.text();
            html = $h1.html();
          }
          return $('
').append($('', {
            href: "#/" + ($section.attr('id') || $section.index() + 1),
            title: title,
            html: html
          })).appendTo($ul);
        });
        return $toc.append($ul);
      }
    };

    return Ruban;

  })();

  window.Ruban = Ruban;

}).call(this);
<commit_msg>Add first and last functions<commit_after>(function() {
  var Ruban,
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

  Ruban = (function() {
    function Ruban(options) {
      this.options = options != null ? options : {};
      this.next = __bind(this.next, this);
      this.last = __bind(this.last, this);
      this.prev = __bind(this.prev, this);
      this.first = __bind(this.first, this);
      this.checkHash = __bind(this.checkHash, this);
      this.initOptions();
      this.$sections = $('section').wrapAll('

');
      this.$ruban = $('.ruban');
      this.toc();
      this.current(this.$sections.first());
      this.pagination();
      this.checkHash();
      this.highlight();
      this.resize();
      this.bind();
      this.$ruban.css('transition-property', 'transform');
      this.$ruban.css('-webkit-transition-property', '-webkit-transform');
      this.$ruban.css('transition-duration', this.options.transitionDuration);
    }

    Ruban.prototype.initOptions = function() {
      var _base, _base1, _base2, _base3, _base4, _base5, _base6;
      if ((_base = this.options).ratio == null) {
        _base.ratio = 4 / 3;
      }
      if ((_base1 = this.options).minPadding == null) {
        _base1.minPadding = '0.4em';
      }
      if ((_base2 = this.options).transitionDuration == null) {
        _base2.transitionDuration = '1s';
      }
      if ((_base3 = this.options).pagination == null) {
        _base3.pagination = false;
      }
      if ((_base4 = this.options).stripHtmlInToc == null) {
        _base4.stripHtmlInToc = false;
      }
      if ((_base5 = this.options).bindClicks == null) {
        _base5.bindClicks = false;
      }
      return (_base6 = this.options).bindMouseWheel != null ? (_base6 = this.options).bindMouseWheel : _base6.bindMouseWheel = false;
    };

    Ruban.prototype.bind = function() {
      this.bindKeys();
      this.bindGestures();
      if (this.options.bindClicks) {
        this.bindClicks();
      }
      if (this.options.bindMouseWheel) {
        this.bindMouseWheel();
      }
      this.bindResize();
      return this.bindHashChange();
    };

    Ruban.prototype.bindKeys = function() {
      key('right, down, space, return, j, l, pagedown', this.next);
      key('left, up, backspace, k, h, pageup', this.prev);
      key('home', this.first);
      return key('last', this.last);
    };

    Ruban.prototype.bindGestures = function() {
      return Hammer(document, {
        drag_block_vertical: true,
        drag_block_horizontal: true
      }).on('swipeleft swipeup', this.next).on('swiperight swipedown', this.prev);
    };

    Ruban.prototype.bindClicks = function() {
      var _this = this;
      this.$ruban.contextmenu(function() {
        return false;
      });
      return this.$ruban.mousedown(function(e) {
        switch (e.which) {
          case 1:
            return _this.next();
          case 3:
            return _this.prev();
        }
      });
    };

    Ruban.prototype.bindMouseWheel = function() {
      var _this = this;
      return this.$ruban.on('wheel', function(e) {
        if (e.originalEvent.deltaY > 0) {
          return _this.next();
        } else if (e.originalEvent.deltaY < 0) {
          return _this.prev();
        }
      });
    };

    Ruban.prototype.bindResize = function() {
      var _this = this;
      return $(window).resize(function() {
        _this.resize();
        return _this.go(_this.$current, {
          force: true
        });
      });
    };

    Ruban.prototype.bindHashChange = function() {
      return $(window).on('hashchange', this.checkHash);
    };

    Ruban.prototype.resize = function() {
      var height, min, outerHeight, outerWidth, paddingH, paddingV, width, _ref;
      _ref = [$(window).width(), $(window).height()], outerWidth = _ref[0], outerHeight = _ref[1];
      if (outerWidth > this.options.ratio * outerHeight) {
        min = outerHeight;
        paddingV = this.options.minPadding;
        this.$ruban.parent().css('font-size', "" + (min * 0.4) + "%");
        this.$sections.css({
          'padding-top': paddingV,
          'padding-bottom': paddingV
        });
        height = this.$current.height();
        width = this.options.ratio * height;
        paddingH = "" + ((outerWidth - width) / 2) + "px";
        return this.$sections.css({
          'padding-left': paddingH,
          'padding-right': paddingH
        });
      } else {
        min = outerWidth / this.options.ratio;
        paddingH = this.options.minPadding;
        this.$ruban.parent().css('font-size', "" + (min * 0.4) + "%");
        this.$sections.css({
          'padding-left': paddingH,
          'padding-right': paddingH
        });
        width = this.$current.width();
        height = width / this.options.ratio;
        paddingV = "" + ((outerHeight - height) / 2) + "px";
        return this.$sections.css({
          'padding-top': paddingV,
          'padding-bottom': paddingV
        });
      }
    };

    Ruban.prototype.checkHash = function() {
      var hash, slide;
      hash = window.location.hash;
      if (slide = hash.substr(2)) {
        return this.go(slide);
      }
    };

    Ruban.prototype.highlight = function() {
      return hljs.initHighlightingOnLoad();
    };

    Ruban.prototype.first = function() {
      return this.firstSlide();
    };

    Ruban.prototype.firstSlide = function() {
      var $first;
      $first = this.$current.prevAll('section:first-child');
      return this.go($first, {
        direction: 'backward'
      });
    };

    Ruban.prototype.prev = function() {
      if (this.hasSteps()) {
        return this.prevStep();
      } else {
        return this.prevSlide();
      }
    };

    Ruban.prototype.prevSlide = function() {
      var $prev;
      $prev = this.$current.prev('section');
      return this.go($prev, {
        direction: 'backward'
      });
    };

    Ruban.prototype.prevStep = function() {
      var $prev;
      this.$steps.eq(this.index).removeClass('step').fadeOut();
      $prev = this.$steps.eq(--this.index);
      if (!(this.index < -1)) {
        if ($prev.is(':visible')) {
          return $prev.addClass('step').trigger('step');
        } else if (this.index > -1) {
          return this.prevStep();
        }
      } else {
        return this.prevSlide();
      }
    };

    Ruban.prototype.last = function() {
      return this.lastSlide();
    };

    Ruban.prototype.lastSlide = function() {
      var $last;
      $last = this.$current.nextAll('section:last-child');
      return this.go($last, {
        direction: 'forward'
      });
    };

    Ruban.prototype.next = function() {
      if (this.hasSteps()) {
        return this.nextStep();
      } else {
        return this.nextSlide();
      }
    };

    Ruban.prototype.nextSlide = function() {
      var $next;
      $next = this.$current.next('section');
      return this.go($next, {
        direction: 'forward'
      });
    };

    Ruban.prototype.nextStep = function() {
      var $next;
      this.$steps.eq(this.index).removeClass('step');
      $next = this.$steps.eq(++this.index);
      if ($next.length) {
        return $next.fadeIn().addClass('step').trigger('step');
      } else {
        return this.nextSlide();
      }
    };

    Ruban.prototype.checkSteps = function($section, direction) {
      this.$steps = $section.find('.steps').children();
      if (!this.$steps.length) {
        this.$steps = $section.find('.step');
      }
      if (direction === 'backward') {
        return this.index = this.$steps.length - 1;
      } else {
        this.index = -1;
        return this.$steps.hide();
      }
    };

    Ruban.prototype.hasSteps = function() {
      return (this.$steps != null) && this.$steps.length !== 0;
    };

    Ruban.prototype.find = function(slide) {
      var $section;
      if (slide instanceof $) {
        return slide;
      } else {
        $section = $("#" + slide);
        if ($section.length === 0) {
          $section = this.$sections.eq(parseInt(slide) - 1);
        }
        return $section;
      }
    };

    Ruban.prototype.go = function(slide, options) {
      var $section;
      if (slide == null) {
        slide = 1;
      }
      if (options == null) {
        options = {};
      }
      $section = this.find(slide);
      if ($section.length && (options.force || !$section.is(this.$current))) {
        this.checkSteps($section, options.direction);
        this.navigate($section);
        this.translate($section);
        this.current($section);
        return this.pagination();
      }
    };

    Ruban.prototype.navigate = function($section) {
      return window.location.hash = "/" + ($section.attr('id') || $section.index() + 1);
    };

    Ruban.prototype.translate = function($section) {
      var y;
      y = $section.prevAll().map(function() {
        return $(this).outerHeight();
      }).get().reduce(function(memo, height) {
        return memo + height;
      }, 0);
      return this.$ruban.css('transform', "translateY(-" + y + "px)");
    };

    Ruban.prototype.current = function($section) {
      if (this.$current != null) {
        this.$current.removeClass('active').trigger('inactive');
      }
      $section.addClass('active').trigger('active');
      return this.$current = $section;
    };

    Ruban.prototype.pagination = function() {
      if (this.options.pagination) {
        if (!this.$pagination) {
          this.$ruban.parent().append('');
          this.$pagination = $('.pagination');
          this.total = this.$sections.length;
        }
        return this.$pagination.html("" + (this.$current.index() + 1) + "/" + this.total);
      }
    };

    Ruban.prototype.toc = function() {
      var $toc, $ul, stripHtmlInToc;
      $toc = $('.toc').first();
      if ($toc.length) {
        stripHtmlInToc = this.options.stripHtmlInToc;
        $ul = $('
');
        $('section:not(.no-toc,.toc) > h1:only-child').each(function() {
          var $h1, $section, html, title;
          $section = $(this).parent();
          if (stripHtmlInToc) {
            title = html = $(this).text();
          } else {
            $h1 = $(this).clone().find('a').replaceWith(function() {
              return $(this).text();
            }).end();
            title = $h1.text();
            html = $h1.html();
          }
          return $('
').append($('', {
            href: "#/" + ($section.attr('id') || $section.index() + 1),
            title: title,
            html: html
          })).appendTo($ul);
        });
        return $toc.append($ul);
      }
    };

    return Ruban;

  })();

  window.Ruban = Ruban;

}).call(this);
<|endoftext|>


<commit_before>/*
 * Javascript Terminal Emulator by the venerable Gerhuyy.
 * Use at your own risk.
 */

//Object for storing possible commands
window.process = {
};
//stores environment variables
window.environment = {
    PATH: "scripts/"
};
//Promise that gives either a command, or an error if it can't find the command
get_script = function(name){
    return new Promise(function(resolve, reject){
        if(!window.process[name]){
            var path = window.environment.PATH.split(":"),
                i = 0; //begin convoluted async for loop
            function load(location){
                var script = document.createElement("script");
                script.src = location + name + ".js"
                script.onload = function(){
                    resolve(window.process[name])
                }
                script.onerror = function(){
                    i ++;
                    if(i<path.length){
                        load(path[i])
                    }
                    else{
                        reject(Error("File didn't exist anywhere along the PATH"))
                    }
                }
                document.getElementsByTagName("head")[0].appendChild(script);
            }
            if(i<path.length){
                load(path[i])
            }
            else{
                reject(Error("There's nothing in the PATH variable"))
            }
        }
        else{
            resolve(window.process[name])
        }
});
}
File = function(name){
    this.name = name
}
File.prototype = {
    write: function(text){
        localStorage.setItem(this.name, text);
    },
    read: function(){
        return localStorage.getItem(this.name);
    },
    append: function(text){
        this.write(this.read() + text);
    }
};
window.process.export = function(args, stdin, stdout, stderr, communicate){
    var sides = args[1].split("="),
        name = sides[0],
        value = sides[1];
    window.environment[name] = value;
    communicate.finish(0);
}
window.process.reload = function(args, stdin, stdout, stderr, comm){
    for(var i = 1; i < args.length; i++){
        window.process[args[i]] = null;
        get_script(args[i]);
    }
    comm.finish(0);
}
window.man = {
    man: "Usage: man command\n\nDisplays information such as usage and output for 'command'.\nOnly available as provided by 'command'.",
    export: "Usage export VARIABLE=VALUE\n\nSets the environment variable named 'VARIABLE' to the string of 'VALUE'",
};
window.process.man = function(args, stdin, stdout, stderr, communicate){
    var process = args[1];
    if(window.man[process]){
        stdout.writeln(window.man[process]);
        communicate.finish(0);
    }else{
        get_script(process).then(
            function(){
                if(window.man[process]){
                    stdout.writeln(window.man[process]);
                    communicate.finish(0);
                }else{
                    stderr.writeln("'" + process + "' does not have a man page");
                    communicate.finish(-1);
                }
            },
            function(err){
                console.log(err, "what?")
                stderr.writeln("'" + process + "' does not exist");
                communicate.finish(-1);
            }
        );
    }
}
function Communicate(finish){
    this.finish = finish;
};
Communicate.prototype = {
    dead: false,
};
function In(stream){
    this.stream = stream;
    this.index = 0;
    this.depth = 0;
}
In.prototype = {
    readln: function(callback){
        if(this.index < this.stream.lines.length){
            this.index ++;
            callback(this.stream.lines[this.index-1]);
        }
        else{
            this.index ++;
            this.stream.line_listener.push(callback);
        }
    },
    read: function(callback){
        if(this.index < this.stream.lines.length || this.depth < this.stream.line.length ){
            prevind = this.index;
            prevdepth = this.depth;
            this.index = this.stream.lines.length;
            this.depth = this.stream.line.length;
            callback(this.stream.lines.slice(prevind).join("\n") + "\n" + this.stream.line.slice(prevdepth))
        }
        else{
            this.index = this.stream.lines.length;
            this.depth = this.stream.line.length;
            this.stream.listener.push(callback);
        }
    },
};
function Stream(){
    this.lines = [];
    this.line = "";
    this.line_listener = [];
    this.listener = [];

};
Stream.prototype = {
    write: function(text){
        var lines = text.split("\n")
        for(var i = 0; i < lines.length-1; i++){
            this.line += lines[i]
            this.endln()
        }
        this.line += lines[lines.length-1]
        var callbacks = this.listener;
        this.listener = [];
        for(var i = 0; i < callbacks.length; i++){
            callbacks[i](text)
        }
    },
    writeln: function(text){
        this.write(text+"\n")
    },
    endln: function(){
        var line_listener = this.line_listener;
        this.line_listener = [];
        for(var i = 0; i < line_listener.length; i++){
            line_listener[i](this.line);
        }
        this.lines.push(this.line)
        this.line = ""
    },
    reader: function(){
        return new In(this);
    },
};

function Controller(backColor, mainColor, errColor, id){
    this.backColor = backColor;
    this.mainColor = mainColor;
    this.errColor = errColor;
    this.id = id;
    term = document.getElementById(id);
    term.focus()
    term.style = "font-family:courier; color:"+mainColor+"; background-color:"+backColor+";display:inline-block;overflow:scroll;"
    term.innerHTML = '
|
'
    this.userin = new UserIn(backColor, mainColor, "current");
    this.prompt = new Stream().reader();
    this.err = new Stream().reader()
    self = this;
    document.addEventListener("keypress", function(e){
        e = e || window.event;
        if(self.press(e) || self.userin.press(e)){
            e.preventDefault()
        }
    });
    /*$(document).on('paste','[contenteditable]',function(e) {
        e.preventDefault();
        var text = (e.originalEvent || e).clipboardData.getData('text/plain') || prompt('Paste something..');
        window.document.execCommand('insertText', false, text);
        console.log(text);
    });*/
    this.errorReport()
    this.get_job()
};
Controller.prototype = {
    errorReport: function(){
        function err(line){
            self.println(""+line+"");
            self.err.readln(err);
        }
        this.err.readln(err);
    },
    press: function(e){
        if(e.ctrlKey && e.charCode == 99){
            self.kill_job();
            return true;
        }
        return false
    },
    kill_job: function(){
        this.pipeline.kill();
    },
    get_job: function(){
        this.print("$")
        var self = this
        this.userin.stream = this.prompt.stream
        this.prompt.readln(function(line){
            self.println(line);
            self.start_job(line)
        })
    },
    start_job: function(line){
        var processes = line.split("|");
        var args = [];
        for(var i = 0; i < processes.length; i++){
            var process = processes[i]
            process = process.replace(/[\n 	]+/g, " ")
            process = process.replace(/^ | $/g, "")
            args.push(process.split(" "));
        }
        var self = this;
        this.pipeline = new Pipeline(function(){self.get_job()});
        var instream = this.userin.reset_input(),
            outstream = new Stream();
        this.instream = instream.reader()
        this.displayin();
        for(var i = 0; i < args.length; i++){
            //this.new_process(args[i], instream.reader(), outstream);
            this.pipeline.add(args[i], instream.reader(), outstream, this.err.stream);
            if(i < args.length - 1){
                instream = outstream;
                outstream = new Stream();
            }
        }
        this.outstream = outstream.reader();
        this.displayout()
    },
    new_process: function(args, instream, outstream){
        self = this;
        var communicate = new Communicate(function(){
            self.kill_job();
        })
        if(!window.process[args[0]]){
            path = window.environment.PATH.split(":");
            var i = 0;
            function load(location){
                script = document.createElement("script");
                script.src = location + args[0] + ".js"
                script.onload = function(){
                    window.process[args[0]](args, instream, outstream, self.err.stream, communicate);
                }
                script.onerror = function(){
                    i ++;
                    if(i<path.lenght){
                        load(path[i])
                    }
                    else{
                        self.println(args[0] + ": command not found")
                        communicate.finish();
                    }
                }
                document.getElementsByTagName("head")[0].appendChild(script);
            }
            if(i<path.length){
                load(path[i])
            }
       }
        else{
            window.process[args[0]](args, instream, outstream, communicate);
        }

    },
    displayin: function(){
        var self = this
        function print(text){
            self.println(text)
            self.instream.readln(print)
        }
        this.instream.readln(print)
    },
    displayout: function(){
        var self = this
        function print(text){
            self.println(text)
            self.outstream.readln(print)
        }
        this.outstream.readln(print)
    },
    print: function(text){
        document.getElementById("finished").innerHTML += text.replace("\n", "
");
    },
    println: function(line){
        this.print(line + "\n");
    }
};

function UserIn(back, fore, id){
    this.background = back;
    this.foreground = fore;
    this.stream = new Stream()
    this.id = id;
    this.back = 0;
}
UserIn.prototype = {
    reset_input: function(){
        this.stream = new Stream()
        return this.stream;
    },
    special: {
        13: function(userin){
            userin.finish()
        },
        8: function(userin){
            userin.text = userin.text.slice(0, userin.pointer-1) +
                         userin.text.slice(userin.pointer, userin.text.length);
            if(userin.pointer > 0)userin.pointer --;
        },
        39: function(userin){
            if(userin.pointer < userin.text.length){
                userin.pointer ++;
            }
        },
        37: function(userin){
            if(userin.pointer > 0){
                userin.pointer --;
            }
        },
        38: function(userin){
            if(userin.back < userin.stream.lines.length-1){
                if(userin.back === -1){
                    userin.store = userin.text
                }
                userin.back ++;
                userin.text = userin.stream.lines[userin.stream.lines.length - userin.back - 1]
                userin.pointer = userin.text.length;
            }
        },
        40: function(userin){
            if(userin.back > -1){
                userin.back --;
                if(userin.back === -1){
                    userin.text = userin.store;
                }
                else{
                    text = userin.stream.lines[userin.stream.lines.length - userin.back - 1];
                    if(text)userin.text = text;
                }
                userin.pointer = userin.text.length;
            }
        },
    },
    ctrl: {
        97: function(userin){
            userin.pointer = 0;
        },
        101: function(userin){
            userin.pointer = userin.text.length;
        },
        117: function(userin){
            userin.text = userin.text.slice(userin.pointer);
            userin.pointer = 0;
        },
        118: function(userin){
            paste = prompt("Paste Here");
            userin.pointer = userin.pointer + paste.length;
            userin.text = userin.text.slice(0, userin.pointer) + paste + userin.text.slice(userin.pointer);
        }
        },
    text: "",
    pointer: 0,
    finish: function(){
        var text = this.text
        this.text = "";
        this.pointer = 0;
        this.back = -1
        this.stream.writeln(text);

    },
    add: function(char){
        this.text = this.text.slice(0, this.pointer) +
                        char + this.text.slice(this.pointer, this.text.length);
        this.pointer++;
    },
    press: function(e){
        if(this.special[e.keyCode]){
            this.special[e.keyCode](this);
        }
        else if(e.ctrlKey){
            if(this.ctrl[e.charCode]){
                this.ctrl[e.charCode](this);
            }
            else{
                return false;
            }
        }
        else if(e.metaKey){
            return false;
        }
        else{
            this.add(String.fromCharCode(e.charCode));
        }
        this.html = textify(this.text.slice(0, this.pointer));
        if(this.text[this.pointer] === "\n"){
            this.html += "|
"
        }
        else if(this.text[this.pointer]){
            this.html += ""+textify(this.text[this.pointer])+""
        }
        else{
            this.html += "|"
        }
        this.html += textify (this.text.slice(this.pointer+1));
        document.getElementById(this.id).innerHTML = this.html
        return true
    }
}
function textify(text){
    return text.replace("&", "&").replace("<", "<").replace(">", ">").replace("\n","
");
}
var FORE = "black",
    BACK = "white";
setInterval(function(){
    pointer = document.getElementById("pointer");
    pointer.style.backgroundColor = pointer.style.backgroundColor === BACK? FORE: BACK
    pointer.style.color = pointer.style.color === BACK? FORE: BACK

}, 700);
new Controller(BACK, FORE, "red", "term")<commit_msg>shortcuts don't work in chrome/ie<commit_after>/*
 * Javascript Terminal Emulator by the venerable Gerhuyy.
 * Use at your own risk.
 */

//Object for storing possible commands
window.process = {
};
//stores environment variables
window.environment = {
    PATH: "scripts/"
};
//Promise that gives either a command, or an error if it can't find the command
get_script = function(name){
    return new Promise(function(resolve, reject){
        if(!window.process[name]){
            var path = window.environment.PATH.split(":"),
                i = 0; //begin convoluted async for loop
            function load(location){
                var script = document.createElement("script");
                script.src = location + name + ".js"
                script.onload = function(){
                    resolve(window.process[name])
                }
                script.onerror = function(){
                    i ++;
                    if(i<path.length){
                        load(path[i])
                    }
                    else{
                        reject(Error("File didn't exist anywhere along the PATH"))
                    }
                }
                document.getElementsByTagName("head")[0].appendChild(script);
            }
            if(i<path.length){
                load(path[i])
            }
            else{
                reject(Error("There's nothing in the PATH variable"))
            }
        }
        else{
            resolve(window.process[name])
        }
});
}
File = function(name){
    this.name = name
}
File.prototype = {
    write: function(text){
        localStorage.setItem(this.name, text);
    },
    read: function(){
        return localStorage.getItem(this.name);
    },
    append: function(text){
        this.write(this.read() + text);
    }
};
window.process.export = function(args, stdin, stdout, stderr, communicate){
    var sides = args[1].split("="),
        name = sides[0],
        value = sides[1];
    window.environment[name] = value;
    communicate.finish(0);
}
window.process.reload = function(args, stdin, stdout, stderr, comm){
    for(var i = 1; i < args.length; i++){
        window.process[args[i]] = null;
        get_script(args[i]);
    }
    comm.finish(0);
}
window.man = {
    man: "Usage: man command\n\nDisplays information such as usage and output for 'command'.\nOnly available as provided by 'command'.",
    export: "Usage export VARIABLE=VALUE\n\nSets the environment variable named 'VARIABLE' to the string of 'VALUE'",
};
window.process.man = function(args, stdin, stdout, stderr, communicate){
    var process = args[1];
    if(window.man[process]){
        stdout.writeln(window.man[process]);
        communicate.finish(0);
    }else{
        get_script(process).then(
            function(){
                if(window.man[process]){
                    stdout.writeln(window.man[process]);
                    communicate.finish(0);
                }else{
                    stderr.writeln("'" + process + "' does not have a man page");
                    communicate.finish(-1);
                }
            },
            function(err){
                console.log(err, "what?")
                stderr.writeln("'" + process + "' does not exist");
                communicate.finish(-1);
            }
        );
    }
}
function Communicate(finish){
    this.finish = finish;
};
Communicate.prototype = {
    dead: false,
};
function In(stream){
    this.stream = stream;
    this.index = 0;
    this.depth = 0;
}
In.prototype = {
    readln: function(callback){
        if(this.index < this.stream.lines.length){
            this.index ++;
            callback(this.stream.lines[this.index-1]);
        }
        else{
            this.index ++;
            this.stream.line_listener.push(callback);
        }
    },
    read: function(callback){
        if(this.index < this.stream.lines.length || this.depth < this.stream.line.length ){
            prevind = this.index;
            prevdepth = this.depth;
            this.index = this.stream.lines.length;
            this.depth = this.stream.line.length;
            callback(this.stream.lines.slice(prevind).join("\n") + "\n" + this.stream.line.slice(prevdepth))
        }
        else{
            this.index = this.stream.lines.length;
            this.depth = this.stream.line.length;
            this.stream.listener.push(callback);
        }
    },
};
function Stream(){
    this.lines = [];
    this.line = "";
    this.line_listener = [];
    this.listener = [];

};
Stream.prototype = {
    write: function(text){
        var lines = text.split("\n")
        for(var i = 0; i < lines.length-1; i++){
            this.line += lines[i]
            this.endln()
        }
        this.line += lines[lines.length-1]
        var callbacks = this.listener;
        this.listener = [];
        for(var i = 0; i < callbacks.length; i++){
            callbacks[i](text)
        }
    },
    writeln: function(text){
        this.write(text+"\n")
    },
    endln: function(){
        var line_listener = this.line_listener;
        this.line_listener = [];
        for(var i = 0; i < line_listener.length; i++){
            line_listener[i](this.line);
        }
        this.lines.push(this.line)
        this.line = ""
    },
    reader: function(){
        return new In(this);
    },
};

function Controller(backColor, mainColor, errColor, id){
    this.backColor = backColor;
    this.mainColor = mainColor;
    this.errColor = errColor;
    this.id = id;
    term = document.getElementById(id);
    term.focus()
    term.style = "font-family:courier; color:"+mainColor+"; background-color:"+backColor+";display:inline-block;overflow:scroll;"
    term.innerHTML = '
|
'
    this.userin = new UserIn(backColor, mainColor, "current");
    this.prompt = new Stream().reader();
    this.err = new Stream().reader()
    self = this;
    document.addEventListener("keypress", function(e){
        e = e || window.event;
        console.log(e)
        if(self.press(e) || self.userin.press(e)){
            e.preventDefault()
        }
    });
    /*$(document).on('paste','[contenteditable]',function(e) {
        e.preventDefault();
        var text = (e.originalEvent || e).clipboardData.getData('text/plain') || prompt('Paste something..');
        window.document.execCommand('insertText', false, text);
        console.log(text);
    });*/
    this.errorReport()
    this.get_job()
};
Controller.prototype = {
    errorReport: function(){
        function err(line){
            self.println(""+line+"");
            self.err.readln(err);
        }
        this.err.readln(err);
    },
    press: function(e){
        if(e.ctrlKey && e.charCode == 99){
            self.kill_job();
            return true;
        }
        return false
    },
    kill_job: function(){
        this.pipeline.kill();
    },
    get_job: function(){
        this.print("$")
        var self = this
        this.userin.stream = this.prompt.stream
        this.prompt.readln(function(line){
            self.println(line);
            self.start_job(line)
        })
    },
    start_job: function(line){
        var processes = line.split("|");
        var args = [];
        for(var i = 0; i < processes.length; i++){
            var process = processes[i]
            process = process.replace(/[\n 	]+/g, " ")
            process = process.replace(/^ | $/g, "")
            args.push(process.split(" "));
        }
        var self = this;
        this.pipeline = new Pipeline(function(){self.get_job()});
        var instream = this.userin.reset_input(),
            outstream = new Stream();
        this.instream = instream.reader()
        this.displayin();
        for(var i = 0; i < args.length; i++){
            //this.new_process(args[i], instream.reader(), outstream);
            this.pipeline.add(args[i], instream.reader(), outstream, this.err.stream);
            if(i < args.length - 1){
                instream = outstream;
                outstream = new Stream();
            }
        }
        this.outstream = outstream.reader();
        this.displayout()
    },
    new_process: function(args, instream, outstream){
        self = this;
        var communicate = new Communicate(function(){
            self.kill_job();
        })
        if(!window.process[args[0]]){
            path = window.environment.PATH.split(":");
            var i = 0;
            function load(location){
                script = document.createElement("script");
                script.src = location + args[0] + ".js"
                script.onload = function(){
                    window.process[args[0]](args, instream, outstream, self.err.stream, communicate);
                }
                script.onerror = function(){
                    i ++;
                    if(i<path.lenght){
                        load(path[i])
                    }
                    else{
                        self.println(args[0] + ": command not found")
                        communicate.finish();
                    }
                }
                document.getElementsByTagName("head")[0].appendChild(script);
            }
            if(i<path.length){
                load(path[i])
            }
       }
        else{
            window.process[args[0]](args, instream, outstream, communicate);
        }

    },
    displayin: function(){
        var self = this
        function print(text){
            self.println(text)
            self.instream.readln(print)
        }
        this.instream.readln(print)
    },
    displayout: function(){
        var self = this
        function print(text){
            self.println(text)
            self.outstream.readln(print)
        }
        this.outstream.readln(print)
    },
    print: function(text){
        document.getElementById("finished").innerHTML += text.replace("\n", "
");
    },
    println: function(line){
        this.print(line + "\n");
    }
};

function UserIn(back, fore, id){
    this.background = back;
    this.foreground = fore;
    this.stream = new Stream()
    this.id = id;
    this.back = 0;
}
UserIn.prototype = {
    reset_input: function(){
        this.stream = new Stream()
        return this.stream;
    },
    special: {
        13: function(userin){
            userin.finish()
        },
        8: function(userin){
            userin.text = userin.text.slice(0, userin.pointer-1) +
                         userin.text.slice(userin.pointer, userin.text.length);
            if(userin.pointer > 0)userin.pointer --;
        },
        39: function(userin){
            if(userin.pointer < userin.text.length){
                userin.pointer ++;
            }
        },
        37: function(userin){
            if(userin.pointer > 0){
                userin.pointer --;
            }
        },
        38: function(userin){
            if(userin.back < userin.stream.lines.length-1){
                if(userin.back === -1){
                    userin.store = userin.text
                }
                userin.back ++;
                userin.text = userin.stream.lines[userin.stream.lines.length - userin.back - 1]
                userin.pointer = userin.text.length;
            }
        },
        40: function(userin){
            if(userin.back > -1){
                userin.back --;
                if(userin.back === -1){
                    userin.text = userin.store;
                }
                else{
                    text = userin.stream.lines[userin.stream.lines.length - userin.back - 1];
                    if(text)userin.text = text;
                }
                userin.pointer = userin.text.length;
            }
        },
    },
    ctrl: {
        97: function(userin){
            userin.pointer = 0;
        },
        101: function(userin){
            userin.pointer = userin.text.length;
        },
        117: function(userin){
            userin.text = userin.text.slice(userin.pointer);
            userin.pointer = 0;
        },
        118: function(userin){
            paste = prompt("Paste Here");
            userin.pointer = userin.pointer + paste.length;
            userin.text = userin.text.slice(0, userin.pointer) + paste + userin.text.slice(userin.pointer);
        }
        },
    text: "",
    pointer: 0,
    finish: function(){
        var text = this.text
        this.text = "";
        this.pointer = 0;
        this.back = -1
        this.stream.writeln(text);

    },
    add: function(char){
        this.text = this.text.slice(0, this.pointer) +
                        char + this.text.slice(this.pointer, this.text.length);
        this.pointer++;
    },
    press: function(e){
        if(this.special[e.keyCode]){
            this.special[e.keyCode](this);
        }
        else if(e.ctrlKey){
            if(this.ctrl[e.charCode]){
                this.ctrl[e.charCode](this);
            }
            else{
                return false;
            }
        }
        else if(e.metaKey){
            return false;
        }
        else{
            this.add(String.fromCharCode(e.charCode));
        }
        this.html = textify(this.text.slice(0, this.pointer));
        if(this.text[this.pointer] === "\n"){
            this.html += "|
"
        }
        else if(this.text[this.pointer]){
            this.html += ""+textify(this.text[this.pointer])+""
        }
        else{
            this.html += "|"
        }
        this.html += textify (this.text.slice(this.pointer+1));
        document.getElementById(this.id).innerHTML = this.html
        return true
    }
}
function textify(text){
    return text.replace("&", "&").replace("<", "<").replace(">", ">").replace("\n","
");
}
var FORE = "black",
    BACK = "white";
setInterval(function(){
    pointer = document.getElementById("pointer");
    pointer.style.backgroundColor = pointer.style.backgroundColor === BACK? FORE: BACK
    pointer.style.color = pointer.style.color === BACK? FORE: BACK

}, 700);
new Controller(BACK, FORE, "red", "term")
<|endoftext|>


<commit_before>var hours = ['6am','7am','8am','9am','10am','11am','12pm','1pm','2pm','3pm','4pm','5pm','6pm','7pm','8pm','9pm'];
var allStores = [];
function LocationSales (storeName, minCustomer, maxCustomer, avgSales) {
  this.storeName = storeName;
  this.minCustomer = minCustomer;
  this.maxCustomer = maxCustomer;
  this.avgSales = avgSales;
  this.randomNumber = function(min,max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  };
  this.hourlyCustomer = function(){
    this.hCustomer = [];
    for (var i = 0; i < hours.length; i++) {
      this.hCustomer.push(Math.floor(this.randomNumber(this.minCustomer,this.maxCustomer)));
    }
    return this.hCustomer;
  };
  this.hourlySales = function() {
    this.hSales = [];
    for (var i = 0; i < this.hCustomer.length; i++) {
      this.hSales.push(Math.floor(this.hCustomer[i] * this.avgSales));
    };
    return this.hSales;
  };
  this.salesDailyTotals = function() {
    this.dSalesTotal = 0;
    for (var i = 0; i < this.hSales.length; i++) {
      this.dSalesTotal = this.dSalesTotal + this.hSales[i];
    }
    return this.dSalesTotal;
  };
};

function putSalesInTable(location) {
//table header gets hours from hours[]
  var appendHeader = document.getElementById('hours');
  var th = document.createElement('th');
  th.textContent = ('Location');
  appendHeader.appendChild(th);
  for (var i = 0; i < hours.length; i++){
    var td = document.createElement('td');
    var tr = document.createElement('tr');
    td.textContent = hours[i];
    appendHeader.appendChild(td);
  }
  th = document.createElement('th');
  th.textContent = ('Total');
  appendHeader.appendChild(th);
// table body gets location sales
  var appendRow = document.getElementById('store-info');
  //var tr = document.createElement('tr');
  var th = document.createElement('th');
  th.textContent = location.storeName;
  appendRow.appendChild(th);
  for (var i = 0; i < location.hourlySales().length; i++){
    var td = document.createElement ('td');
    var tr = document.createElement('tr');
    td.textContent = location.hourlySales()[i];
    //tr.appendChild(td);
    appendRow.appendChild(td);
  }
  td = document.createElement('td');
  td.textContent = location.salesDailyTotals();
  //tr.appendChild(td);
  appendRow.appendChild(td);
};

var pikePlace = new LocationSales ('Pike Place', 17, 88, 5.2);
var seaTacAirport = new LocationSales ('Sea Tac Airport', 6, 24, 1.2);
var southcenter = new LocationSales ('Southcenter', 11, 38, 1.9);
var bellevue = new LocationSales ('Bellevue', 20, 48, 3.3);
var alki = new LocationSales ('Alki', 3, 24, 2.6);

//AllStores.push(pikePlace, seaTacAirport, southcenter, bellevue, alki);
allStores.push(this);
for(i = 0; i < allStores.length; i++){
  putSalesInTable(allStores[i]);
}
<commit_msg>hours are added to the header, sales added to each hour for each store, all stores are in array, for-loop calls function for the table display for the array<commit_after>var hours = ['6am','7am','8am','9am','10am','11am','12pm','1pm','2pm','3pm','4pm','5pm','6pm','7pm','8pm','9pm'];
var allStores = [];
function LocationSales (storeName, minCustomer, maxCustomer, avgSales) {
  this.storeName = storeName;
  this.minCustomer = minCustomer;
  this.maxCustomer = maxCustomer;
  this.avgSales = avgSales;
  this.randomNumber = function(min,max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  };
  this.hourlyCustomer = function(){
    this.hCustomer = [];
    for (var i = 0; i < hours.length; i++) {
      this.hCustomer.push(Math.floor(this.randomNumber(this.minCustomer,this.maxCustomer)));
    }
    return this.hCustomer;
  };
  this.hourlySales = function() {
    this.hSales = [];
    for (var i = 0; i < this.hourlyCustomer().length; i++) {
      this.hSales.push(Math.floor(this.hCustomer[i] * this.avgSales));
    };
    return this.hSales;
  };
  this.salesDailyTotals = function() {
    this.dSalesTotal = 0;
    for (var i = 0; i < this.hSales.length; i++) {
      this.dSalesTotal = this.dSalesTotal + this.hSales[i];
    }
    return this.dSalesTotal;
  };
};

//table header gets 'Location', hours from hours[], and 'Total'
function putHoursInTable() {
  var appendHeader = document.getElementById('hours');
  var tr = document.createElement('tr');
  var th = document.createElement('th');
  th.textContent = ('Location');
  tr.appendChild(th);
  appendHeader.appendChild(tr);
//adding hours to the header
  for (var i = 0; i < hours.length; i++){
    var th = document.createElement('th');
    th.textContent = hours[i];
    tr.appendChild(th);
  }

  th = document.createElement('th');
  th.textContent = ('Total');
  tr.appendChild(th);
}

// table body gets location sales
function putSalesInTable(location) {
  var appendRow = document.getElementById('store-info');
  var tr = document.createElement('tr');
  var th = document.createElement('th');
  th.textContent = location.storeName; //addidng location name to the first column
  tr.appendChild(th);
  appendRow.appendChild(tr);//only appending to <tbody> here in this function

  for (var i = 0; i < location.hourlySales().length; i++){
    td = document.createElement ('td');
    td.textContent = location.hourlySales()[i]; //addidng hourly sales to the row
    tr.appendChild(td);
  }

  td = document.createElement('td');
  td.textContent = location.salesDailyTotals(); //adding total sales for each location to the last column
  tr.appendChild(td);
};

allStores.push(new LocationSales ('Pike Place', 17, 88, 5.2));
allStores.push(new LocationSales ('Sea Tac Airport', 6, 24, 1.2));
allStores.push(new LocationSales ('Southcenter', 11, 38, 1.9));
allStores.push(new LocationSales ('Bellevue', 20, 48, 3.3));
allStores.push(new LocationSales ('Alki', 3, 24, 2.6));

putHoursInTable();
for(i = 0; i < allStores.length; i++){
  putSalesInTable(allStores[i]);
}
<|endoftext|>


<commit_before>var camera, controls, scene, renderer;

var tick = 0;

init();
render();
animate();

function init() {

    scene = new THREE.Scene();
    // scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
    scene.fog = new THREE.Fog(0xece9ca, 500, 2000);

    camera = new THREE.PerspectiveCamera( 45,
                                          window.innerWidth / window.innerHeight,
                                          1,
                                          1000 );

    camera.position.set( 0, -40, 40 );
    camera.lookAt( scene.position );

    renderer = new THREE.WebGLRenderer( { alpha: true,
                                          antialias: false } );
 	renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setClearColor( scene.fog.color, 1 );
    renderer.setSize( window.innerWidth, window.innerHeight );
	renderer.sortObjects = false;

    controls = new THREE.OrbitControls( camera );
    controls.addEventListener( 'change', render );

    document.body.appendChild( renderer.domElement );

    window.addEventListener( 'resize', onWindowResize, false );

    initializeLights();
    createEnvironment( 30, 30, 2 );
}

function onWindowResize() {

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize( window.innerWidth, window.innerHeight );

    render();

}

function animate() {

    render();
    tick++;

    updateLanterns( tick );

    controls.update();
    requestAnimationFrame( animate );

}

function render() {

    renderer.render( scene, camera );

}

function initializeLights() {

    var sceneLight = new THREE.HemisphereLight( 0xdddddd, 0x202020, .1 );

    var lamp = new THREE.DirectionalLight( 0xdddddd, 0.5 );
    lamp.position.set( 0, 10, 30 );
    lamp.castShadow = true;

    scene.add( sceneLight );
    scene.add( lamp );

}

function createEnvironment( width, height, depth ) {

    createSand( width, height );
    createBase( width, height, depth );

    var rock = basicRockFactory( 3, 3, Math.random() * 3 + 1 );
    rock.position.x = peturb( rock.position.x, width - 3 );
    rock.position.y = peturb( rock.position.y, height - 3 );
    rippleSand( 3, rock );
    scene.add( rock );

    rock = basicRockFactory( 2, 2, Math.random() * 3 + 1 );
    rock.position.x = peturb( rock.position.x, width - 2 );
    rock.position.y = peturb( rock.position.y, height - 2 );
    rippleSand( 3, rock );
    scene.add( rock );

    var lantern = lanternFactory( 3, 3, 3 );
    lantern.position.x = peturb( lantern.position.x, width - 1 );
    lantern.position.y = peturb( lantern.position.y, height - 1 );
    lantern.position.z += 4;

    scene.add( lantern );

}
<commit_msg>Fixed rocks sticking out the back<commit_after>var camera, controls, scene, renderer;

var tick = 0;

init();
render();
animate();

function init() {

    scene = new THREE.Scene();
    // scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
    scene.fog = new THREE.Fog(0xece9ca, 500, 2000);

    camera = new THREE.PerspectiveCamera( 45,
                                          window.innerWidth / window.innerHeight,
                                          1,
                                          1000 );

    camera.position.set( 0, -40, 40 );
    camera.lookAt( scene.position );

    renderer = new THREE.WebGLRenderer( { alpha: true,
                                          antialias: false } );
 	renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setClearColor( scene.fog.color, 1 );
    renderer.setSize( window.innerWidth, window.innerHeight );
	renderer.sortObjects = false;

    controls = new THREE.OrbitControls( camera );
    controls.addEventListener( 'change', render );

    document.body.appendChild( renderer.domElement );

    window.addEventListener( 'resize', onWindowResize, false );

    initializeLights();
    createEnvironment( 30, 30, 2 );
}

function onWindowResize() {

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize( window.innerWidth, window.innerHeight );

    render();

}

function animate() {

    render();
    tick++;

    updateLanterns( tick );

    controls.update();
    requestAnimationFrame( animate );

}

function render() {

    renderer.render( scene, camera );

}

function initializeLights() {

    var sceneLight = new THREE.HemisphereLight( 0xdddddd, 0x202020, .1 );

    var lamp = new THREE.DirectionalLight( 0xdddddd, 0.5 );
    lamp.position.set( 0, 10, 30 );
    lamp.castShadow = true;

    scene.add( sceneLight );
    scene.add( lamp );

}

function createEnvironment( width, height, depth ) {

    createSand( width, height );
    createBase( width, height, depth );

    var z = Math.random() * 2 + 1;
    var rock = basicRockFactory( 3, 3, z );
    rock.position.x = peturb( rock.position.x, width - 3 );
    rock.position.y = peturb( rock.position.y, height - 3 );
    rock.position.z += z / 2;
    rippleSand( 3, rock );
    scene.add( rock );

    z = Math.random() * 2 + 1;
    rock = basicRockFactory( 2, 2, z );
    rock.position.x = peturb( rock.position.x, width - 2 );
    rock.position.y = peturb( rock.position.y, height - 2 );
    rock.position.z += z / 2;
    rippleSand( 3, rock );
    scene.add( rock );

    var lantern = lanternFactory( 5, 5, 3 );
    lantern.position.x = peturb( lantern.position.x, width - 1 );
    lantern.position.y = peturb( lantern.position.y, height - 1 );
    lantern.position.z += 4;

    scene.add( lantern );

}
<|endoftext|>


<commit_before>//*** GLOBALS ***//
this.display = '3D Globe';
this.binsize = 3.0;
this.speed = 0.0;
this.run = 1;

var deltarealt = 1.778; //set zero to realtime (1 delta = 1 second)
var stellarday = 86164.1 / 86400; //seconds in a stellar day / solar day
var tropicalyear = 31556926.08; //seconds in one revolution around the Earth
var earthaxistilt = 23.4; //in degrees, difference from true north and celestial north
var earthradius = 6378.1; //in kilometers
var PI_HALF = Math.PI / 2; //tau

//GRACE Orbital Parameters
var g_a = 6871.0; //Semi-major axis in kilometers, also radius since e is about zero
var g_e = 0.000; //eccentricity
var g_i = 89.000; //inclination in degrees, 89deg is prograde

//*** DATGUI ***//
var gui = new dat.GUI({ autoPlace: false });
var customContainer = document.getElementById('gui-container');
customContainer.appendChild(gui.domElement);

var displayupdate = gui.add(this, 'display', [ '3D Globe', '2D Map'  ] ).name("Display");
displayupdate.onChange(function(value){
  //change displaymodes

});
var sizeupdate = gui.add(this, 'binsize', 1.0, 5.0).name("Binsize (degrees)");
sizeupdate.onChange(function(value){
  binsize = Math.floor(binsize * 2) / 2;
});
var speedupdate = gui.add(this, 'speed', 0.0, 6.0).name("Simulation Speed");

//*** INITIALIZE THREE.JS ***//
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
//Maximize renderer to window
renderer.setSize(window.innerWidth, window.innerHeight);
//Activate the three.js DOM render element
renderer.setClearColor(0x000000, 1.0);
document.body.appendChild(renderer.domElement);
//Allow shadow mapping
renderer.shadowMapEnabled = true;

//*** CREATE SCENE AND CAMERA ***//
var onRenderFcts=[]; //rendering stack
var scene = new THREE.Scene(); //initilize scene
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 800); //add new camera definition (FOV deg, aspect ratio, near, far)
camera.position.z = 2.5; //set z axis camera position

//*** TIMER ***//
onRenderFcts.push(function(delta, now){
  //one Earth minute per delta
  this.time += delta * 60 * Math.pow(10,(this.speed - deltarealt)) * run;
  var rotsun = this.time / tropicalyear * 2 * Math.PI; //revolution of Earth
  light.position.set(10*Math.cos(-rotsun),0,10*Math.sin(-rotsun)); //rotsun = counterclockwise revolution
  updateTime();
});

//*** AMBIENT LIGHT ***//
var light = new THREE.AmbientLight(0x222222);
scene.add(light);

//*** DIRECTIONAL LIGHT ***//
var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(10,0,10);
scene.add(light);

light.castShadow = true;
light.shadowCameraNear = 0.01;
light.shadowCameraFar = 15;
light.shadowCameraFov = 45;

light.shadowCameraLeft = -1;
light.shadowCameraRight = 1;
light.shadowCameraTop = 1;
light.shadowCameraBottom = -1;

light.shadowBias = 0.001;
light.shadowDarkness = 0.2;

light.shadowMapWidth = 1024;
light.shadowMapHeight = 1024;

//*** ADD STARFIELD ***//
var starSphere = createStarfield();
scene.add(starSphere);

//*** EARTH ***//
//Render Container
var containerEarth = new THREE.Object3D();
containerEarth.rotateZ(-earthaxistilt * Math.PI/180);
containerEarth.position.z = 0;
scene.add(containerEarth);

//Mesh
var earthMesh = createEarth();
earthMesh.receiveShadow = true;
earthMesh.castShadow = true;
containerEarth.add(earthMesh);
//Animate Mesh
onRenderFcts.push(function(delta, now){
  //one Earth minute per delta
  containerEarth.rotation.y += 1/1440 * 2 * Math.PI * delta * Math.pow(10,(this.speed - deltarealt)) * run * stellarday;
});

//Clouds
/*var earthCloud = createEarthCloud();
earthCloud.recieveShadow = true;
earthCloud.castShadow = true;
containerEarth.add(earthCloud);
//Cloud Animation
onRenderFcts.push(function(delta, now){
  earthCloud.rotation.y += 1/8 * delta * Math.pow(10,(this.speed - 1)) * run;
});*/

//*** GRACE ORBIT ***//
var radius   = g_a / earthradius;
var segments = 64;
var material = new THREE.LineBasicMaterial( { color: 0x0044ff } ),
geometry = new THREE.CircleGeometry( radius, segments );

geometry.vertices.shift(); // Remove center vertex
scene.add( new THREE.Line( geometry, material ) );

//*** CAMERA CONTROLS ***//
//Trackball Controller
var controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.rotateSpeed = 0.4;
controls.noZoom = false;
controls.noPan = true;
controls.staticMoving = false;
controls.minDistance = 1.75;
controls.maxDistance = 8.5;
controls.dynamicDampingFactor = 0.2;

//*** RENDER SCENE ***//
onRenderFcts.push(function(){
  controls.update();
  renderer.render(scene, camera);
});

//*** LOOP ***//
var lastTimeMsec = null;
requestAnimationFrame(function animate(nowMsec){
  //keep looping
  requestAnimationFrame(animate);

  //measure time delta (wait 200 msec)
  lastTimeMsec = lastTimeMsec || nowMsec-1000/60;
  var deltaMsec = Math.min(200, nowMsec - lastTimeMsec);
  lastTimeMsec = nowMsec;

  //call each update function
  onRenderFcts.forEach(function(onRenderFct){
    onRenderFct(deltaMsec/1000, nowMsec/1000);
  });
});<commit_msg>Incline Orbit<commit_after>//*** GLOBALS ***//
this.display = '3D Globe';
this.binsize = 3.0;
this.speed = 0.0;
this.run = 1;

var deltarealt = 1.778; //set zero to realtime (1 delta = 1 second)
var stellarday = 86164.1 / 86400; //seconds in a stellar day / solar day
var tropicalyear = 31556926.08; //seconds in one revolution around the Earth
var earthaxistilt = 23.4; //in degrees, difference from true north and celestial north
var earthradius = 6378.1; //in kilometers
var PI_HALF = Math.PI / 2; //tau

//GRACE Orbital Parameters
var g_a = 6871.0; //Semi-major axis in kilometers, also radius since e is about zero
var g_e = 0.000; //eccentricity
var g_i = 89.000; //inclination in degrees, 89deg is prograde

//*** DATGUI ***//
var gui = new dat.GUI({ autoPlace: false });
var customContainer = document.getElementById('gui-container');
customContainer.appendChild(gui.domElement);

var displayupdate = gui.add(this, 'display', [ '3D Globe', '2D Map'  ] ).name("Display");
displayupdate.onChange(function(value){
  //change displaymodes

});
var sizeupdate = gui.add(this, 'binsize', 1.0, 5.0).name("Binsize (degrees)");
sizeupdate.onChange(function(value){
  binsize = Math.floor(binsize * 2) / 2;
});
var speedupdate = gui.add(this, 'speed', 0.0, 6.0).name("Simulation Speed");

//*** INITIALIZE THREE.JS ***//
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
//Maximize renderer to window
renderer.setSize(window.innerWidth, window.innerHeight);
//Activate the three.js DOM render element
renderer.setClearColor(0x000000, 1.0);
document.body.appendChild(renderer.domElement);
//Allow shadow mapping
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;

//*** CREATE SCENE AND CAMERA ***//
var onRenderFcts=[]; //rendering stack
var scene = new THREE.Scene(); //initilize scene
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 800); //add new camera definition (FOV deg, aspect ratio, near, far)
camera.position.z = 2.5; //set z axis camera position

//*** TIMER ***//
onRenderFcts.push(function(delta, now){
  //one Earth minute per delta
  this.time += delta * 60 * Math.pow(10,(this.speed - deltarealt)) * run;
  var rotsun = this.time / tropicalyear * 2 * Math.PI; //revolution of Earth
  light.position.set(10*Math.cos(-rotsun),0,10*Math.sin(-rotsun)); //rotsun = counterclockwise revolution
  updateTime();
});

//*** AMBIENT LIGHT ***//
var light = new THREE.AmbientLight(0x222222);
scene.add(light);

//*** DIRECTIONAL LIGHT ***//
var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(10,0,10);
scene.add(light);

light.castShadow = true;
light.shadowCameraNear = 0.01;
light.shadowCameraFar = 15;
light.shadowCameraFov = 45;

light.shadowCameraLeft = -1;
light.shadowCameraRight = 1;
light.shadowCameraTop = 1;
light.shadowCameraBottom = -1;

light.shadowBias = 0.001;
light.shadowDarkness = 0.2;

light.shadowMapWidth = 1024;
light.shadowMapHeight = 1024;

//*** ADD STARFIELD ***//
var starSphere = createStarfield();
scene.add(starSphere);

//*** EARTH ***//
//Render Container
var containerEarth = new THREE.Object3D();
containerEarth.rotateZ(-earthaxistilt * Math.PI/180);
containerEarth.position.z = 0;
scene.add(containerEarth);

//Mesh
var earthMesh = createEarth();
earthMesh.receiveShadow = true;
earthMesh.castShadow = true;
containerEarth.add(earthMesh);
//Animate Mesh
onRenderFcts.push(function(delta, now){
  //one Earth minute per delta
  containerEarth.rotation.y += 1/1440 * 2 * Math.PI * delta * Math.pow(10,(this.speed - deltarealt)) * run * stellarday;
});

//Clouds
/*var earthCloud = createEarthCloud();
earthCloud.recieveShadow = true;
earthCloud.castShadow = true;
containerEarth.add(earthCloud);
//Cloud Animation
onRenderFcts.push(function(delta, now){
  earthCloud.rotation.y += 1/8 * delta * Math.pow(10,(this.speed - 1)) * run;
});*/

//*** GRACE ORBIT ***//
var radius   = g_a / earthradius;
var segments = 64;
var ccolor = 0x0044ff;
var material = new THREE.LineBasicMaterial( { color: ccolor } ),

geometry = new THREE.CircleGeometry( radius, segments );
geometry.vertices.shift(); // Remove center vertex
var circle = new THREE.Line(geometry, material);
circle.rotation.x = -1 * Math.PI / 180;
circle.castShadow = circle.receiveShadow = false;
scene.add(circle);

/*geometry = new THREE.CircleGeometry( radius, segments );
geometry.vertices.shift(); // Remove center vertex
geometry.rotation.z = 1.0 * Math.PI/180;

scene.add( new THREE.Line( geometry, material ) );*/

//*** CAMERA CONTROLS ***//
//Trackball Controller
var controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.rotateSpeed = 0.4;
controls.noZoom = false;
controls.noPan = true;
controls.staticMoving = false;
controls.minDistance = 1.75;
controls.maxDistance = 8.5;
controls.dynamicDampingFactor = 0.25;

//*** RENDER SCENE ***//
onRenderFcts.push(function(){
  controls.update();
  renderer.render(scene, camera);
});

//*** LOOP ***//
var lastTimeMsec = null;
requestAnimationFrame(function animate(nowMsec){
  //keep looping
  requestAnimationFrame(animate);

  //measure time delta (wait 200 msec)
  lastTimeMsec = lastTimeMsec || nowMsec-1000/60;
  var deltaMsec = Math.min(200, nowMsec - lastTimeMsec);
  lastTimeMsec = nowMsec;

  //call each update function
  onRenderFcts.forEach(function(onRenderFct){
    onRenderFct(deltaMsec/1000, nowMsec/1000);
  });
});<|endoftext|>