<commit_before>/**
    Listing Editor activity

    Visualizes a listing of a user, or current user
**/
'use strict';

var ko = require('knockout');
var $ = require('jquery');
var Activity = require('../components/Activity');
var PublicUser = require('../models/PublicUser');
var user = require('../data/userProfile').data;
var users = require('../data/users');
var MessageBar = require('../components/MessageBar');
var PublicUserJobTitle = require('../models/PublicUserJobTitle');

var A = Activity.extend(function ListingEditorActivity() {

    Activity.apply(this, arguments);

    this.accessLevel = null;
    this.viewModel = new ViewModel(this.app);
    // null for logo
    this.navBar = Activity.createSectionNavBar(null);

    this.registerHandler({
        event: 'layoutUpdate',
        target: $(window),
        handler: function() {
            this.viewModel.refreshTs(new Date());
        }.bind(this)
    });
});

exports.init = A.init;

A.prototype.loadData = function(userID, jobTitleID) {
    this.viewModel.reset();
    if (userID) {
        this.viewModel.isLoading(true);
        users.getUser(userID, { includeFullJobTitleID: -1 })
        .then(function(data) {
            var pu = new PublicUser(data);
            this.viewModel.user(pu);
            if (!jobTitleID)
                return pu.jobProfile() && pu.jobProfile()[0] && pu.jobProfile()[0].jobTitleID();
            else
                return jobTitleID;
        }.bind(this))
        .then(function(jobTitleID) {
            // For service professionals:
            if (jobTitleID) {
                this.viewModel.user().selectedJobTitleID(jobTitleID);
                // Load extra job data (reviews)
                this.viewModel.reviews.load({ limit: 2 });
            }
        }.bind(this))
        .catch(function(err) {
            this.app.modals.showError({ error: err, title: 'The user profile could not be loaded.' });
        }.bind(this))
        .then(function() {
            // always
            this.viewModel.isLoading(false);
        }.bind(this));
    }
};

/**
    Parameters: /{userID:int}/{jobTitleID:int}
    Both are optional.
    If no userID, the current user profile is showed
    If not jobTitleID, the first one is returned
**/
A.prototype.show = function show(options) {
    Activity.prototype.show.call(this, options);

    var params = options.route && options.route.segments;
    // Get requested userID or the current user profile
    var userID = (params[0] |0) || user.userID();
    var jobTitleID = params[1] |0;
    this.loadData(userID, jobTitleID);
    this.viewModel.reviews.reset(userID, jobTitleID);
    this.viewModel.refreshTs(new Date());
    this.viewModel.userID(userID);
    this.viewModel.showMessageBar(true);
};

A.prototype.hide = function() {
    Activity.prototype.hide.call(this);

    this.viewModel.showMessageBar(false);
};

function ViewModel(app) {
    //jshint maxstatements:40
    this.isLoading = ko.observable(false);
    this.user = ko.observable(null);
    this.userID = ko.observable(null);
    this.reviews = new ReviewsVM();
    this.showMessageBar = ko.observable(false);

    // Just a timestamp to notice that a request to refresh UI happens
    // Is updated on 'show' and layoutUpdate (when inside this UI) currently
    // just to notify app-address-map elements
    this.refreshTs = ko.observable(new Date());

    this.reset = function() {
        this.user(null);
        this.userID(null);
        this.showMessageBar(false);
    };

    /// Work Photos utils
    var DEFAULT_WORKPHOTOS_LIMIT = 2;
    this.isShowingAllPhotos = ko.observable(false);
    this.workPhotos = ko.pureComputed(function() {
        var u = this.user();
        var ph = u && u.selectedJobTitle() && u.selectedJobTitle().workPhotos();
        if (!ph) {
            return [];
        }
        else if (this.isShowingAllPhotos()) {
            return ph;
        }
        else {
            // Filter by 2 first photos:
            var firsts = [];
            ph.some(function(p, i) {
                if (i > DEFAULT_WORKPHOTOS_LIMIT - 1)
                    return true;
                firsts.push(p);
            });
            return firsts;
        }
    }, this);
    this.viewMoreWorkPhotosLabel = ko.pureComputed(function() {
        var imgCount = this.user() && this.user().selectedJobTitle() && this.user().selectedJobTitle().workPhotos();
        imgCount = imgCount && imgCount.length || 0;
        if (this.isShowingAllPhotos() || imgCount === 0 || imgCount <= DEFAULT_WORKPHOTOS_LIMIT)
            return '';
        else
            return 'View all ' + imgCount + ' images';
    }, this);
    this.viewAllPhotos = function() {
        this.isShowingAllPhotos(true);
    }.bind(this);

    /// Addresses
    this.serviceAddresses = ko.pureComputed(function() {
        var u = this.user();
        var adds = u && u.selectedJobTitle() && u.selectedJobTitle().serviceAddresses();
        return adds || [];
    }, this);

    this.changeJobTitle = function(jobTitle, event) {
        this.user().selectedJobTitleID(jobTitle.jobTitleID());
        this.reviews.reset(undefined, jobTitle.jobTitleID());
        this.reviews.load({ limit: 2 });
        if (event) {
            event.preventDefault();
            event.stopImmediatePropagation();
        }
        var url = event.target.getAttribute('href');
        app.shell.pushState(null, null, url);
    }.bind(this);

    /// Social links
    this.getEmailLink = ko.pureComputed(function() {
        var u = this.user();
        if (!u) return '';
        var url = encodeURIComponent(u.profile().serviceProfessionalProfileUrl());
        return 'mailto:?body=' + encodeURIComponent(u.profile().fullName() + ': ') + url;
    }, this);
    this.getFacebookLink = ko.pureComputed(function() {
        var u = this.user();
        if (!u) return '';
        var url = encodeURIComponent(u.profile().serviceProfessionalProfileUrl());
        return 'http://www.facebook.com/share.php?u=' + url + '&t=' + encodeURIComponent(u.profile().fullName());
    }, this);
    this.getTwitterLink = ko.pureComputed(function() {
        var u = this.user();
        if (!u) return '';
        var url = encodeURIComponent(u.profile().serviceProfessionalProfileUrl());
        return 'http://twitter.com/intent/tweet?text=' + encodeURIComponent(u.profile().fullName() + ': ' + url);
    }, this);
    this.getGooglePlusLink = ko.pureComputed(function() {
        var u = this.user();
        if (!u) return '';
        var url = encodeURIComponent(u.profile().serviceProfessionalProfileUrl());
        return 'https://plus.google.com/share?url=' + url;
    }, this);
    this.getPinterestLink = ko.pureComputed(function() {
        var u = this.user();
        if (!u) return '';
        var url = encodeURIComponent(u.profile().serviceProfessionalProfileUrl());
        var photo = encodeURIComponent(u.profile().photoUrl());
        return 'http://pinterest.com/pin/create/button/?url=' + url + '&media=' + photo + '&description=' + encodeURIComponent(u.profile().fullName() + ': ' + url);
    }, this);

    this.getBookLink = ko.pureComputed(function() {
        var u = this.user();
        if (!u) return '';
        return '#!booking/' + u.profile().userID() + '/' + u.selectedJobTitleID();
    }, this);
    this.getSendMessageLink = ko.pureComputed(function() {
        var u = this.user();
        if (!u) return '';
        return '#!inbox/new/' + u.profile().userID();
    }, this);

    this.hasServicesOverview = ko.pureComputed(function() {
        var jobTitle = this.user() && this.user().selectedJobTitle(),
            hasIntro = jobTitle && jobTitle.hasIntro(),
            hasAttributes = jobTitle && jobTitle.serviceAttributes().hasAttributes();

        return hasIntro || hasAttributes;
    }, this);

    this.jobTitleSingularName = ko.pureComputed(function() {
        return this.selectedJobTitle().jobTitleSingularName();
    }, this);

    this.selectedJobTitle = ko.pureComputed(function() {
        return (this.user() && this.user().selectedJobTitle()) || new PublicUserJobTitle();
    }, this);

    this.editListing = function() {
        app.shell.go('/marketplaceJobtitles/' + this.selectedJobTitle().jobTitleID());
    }.bind(this);

    this.listingIsActive = ko.pureComputed(function() {
        return this.selectedJobTitle().isActive();
    }, this);

    this.isOwnProfile = ko.pureComputed(function() {
        var profileOwnerUserID = this.userID();

        if(user.isAnonymous() || profileOwnerUserID === null) {
            return false;
        }
        else {
            return profileOwnerUserID == user.userID();
        }
    }, this);

    this.isMessageBarVisible = ko.pureComputed(function() {
        return this.isOwnProfile() && this.showMessageBar();
    }, this);

    this.messageBarTone = ko.pureComputed(function() {
        return this.listingIsActive() ? MessageBar.tones.success : MessageBar.tones.warning;
    }, this);
}

var PublicUserReview = require('../models/PublicUserReview');
function ReviewsVM() {
    this.userID = ko.observable(null);
    this.jobTitleID = ko.observable(null);
    this.list = ko.observableArray([]);
    this.isLoading = ko.observable(false);
    this.endReached = ko.observable(false);
    var currentXhr = null;

    this.reset = function reset(userID, jobTitleID) {
        this.list([]);
        if (userID)
            this.userID(userID);
        this.jobTitleID(jobTitleID);
        this.endReached(false);
        if (currentXhr && currentXhr.abort) {
            currentXhr.abort();
        }
    };

    this.load = function loadReviews(options) {
        options = options || {};
        if (this.isLoading() || this.endReached() || !this.userID()) return;
        this.isLoading(true);
        var task = users.getReviews(this.userID(), this.jobTitleID(), options)
        .then(function(newData) {
            //jshint maxcomplexity:8
            if (newData && newData.length) {
                if (newData.length < (options.limit || 20)) {
                    this.endReached(true);
                }
                // convert the newData to Model instances
                newData = newData.map(function(d) { return new PublicUserReview(d); });
                var list = this.list();
                if (options.since && options.until) {
                    // Insert in the middle
                    // TODO Unused situation right now, not supported in the UI
                    throw new Error('UNSUPPORTED SET-UP: since and until parameters at the same time');
                }
                else if (options.since) {
                    // We 'suppose' that a 'since' request from the previous first item (descending order) was performed
                    // so we add the newData to the beggining of the list
                    list = newData.concat.apply(newData, list);
                }
                else if (options.until) {
                    // We 'suppose' that an 'until' request from the previous last item  (descending order) was performed
                    // so we add the newData to the ending of the list
                    list.push.apply(list, newData);
                }
                else {
                    // Just new, to replace, data
                    list = newData;
                }
                this.list(list);
            }
            else {
                this.endReached(true);
            }
            this.isLoading(false);
            currentXhr = null;
        }.bind(this))
        .catch(function(err) {
            this.isLoading(false);
            currentXhr = null;
            if (err && err.statusText !== 'abort') {
                console.error('Error loading user reviews', err);
                throw err;
            }
        }.bind(this));
        currentXhr = task.xhr;
        return task;
    }.bind(this);

    this.loadOlder = function loadOlderReviews() {
        var l = this.list();
        var last = l[l.length - 1];
        return this.load({ limit: 10, until: last && last.updatedDate() });
    }.bind(this);

    this.loadNewer = function loadOlderReviews() {
        var first = this.list()[0];
        return this.load({ limit: 10, since: first && first.updatedDate() });
    }.bind(this);
}
<commit_msg>Added page title to listingEditor<commit_after>/**
    Listing Editor activity
    TO-DO: create components and combine with listing activity
    Visualizes a listing of a user, or current user
**/
'use strict';

var ko = require('knockout');
var $ = require('jquery');
var Activity = require('../components/Activity');
var PublicUser = require('../models/PublicUser');
var user = require('../data/userProfile').data;
var users = require('../data/users');
var MessageBar = require('../components/MessageBar');
var PublicUserJobTitle = require('../models/PublicUserJobTitle');

var A = Activity.extend(function ListingEditorActivity() {

    Activity.apply(this, arguments);

    this.accessLevel = null;
    this.viewModel = new ViewModel(this.app);
    // null for logo
    this.navBar = Activity.createSectionNavBar(null);
    this.title = ko.pureComputed(function() {
        var user = this.user();
        if (user) {
            return user.profile().firstNameLastInitial() + ', ' + (user.selectedJobTitle() && user.selectedJobTitle().jobTitleSingularName());
        }
    }, this.viewModel);

    this.registerHandler({
        event: 'layoutUpdate',
        target: $(window),
        handler: function() {
            this.viewModel.refreshTs(new Date());
        }.bind(this)
    });
});

exports.init = A.init;

A.prototype.loadData = function(userID, jobTitleID) {
    this.viewModel.reset();
    if (userID) {
        this.viewModel.isLoading(true);
        users.getUser(userID, { includeFullJobTitleID: -1 })
        .then(function(data) {
            var pu = new PublicUser(data);
            this.viewModel.user(pu);
            if (!jobTitleID)
                return pu.jobProfile() && pu.jobProfile()[0] && pu.jobProfile()[0].jobTitleID();
            else
                return jobTitleID;
        }.bind(this))
        .then(function(jobTitleID) {
            // For service professionals:
            if (jobTitleID) {
                this.viewModel.user().selectedJobTitleID(jobTitleID);
                // Load extra job data (reviews)
                this.viewModel.reviews.load({ limit: 2 });
            }
        }.bind(this))
        .catch(function(err) {
            this.app.modals.showError({ error: err, title: 'The user profile could not be loaded.' });
        }.bind(this))
        .then(function() {
            // always
            this.viewModel.isLoading(false);
        }.bind(this));
    }
};

/**
    Parameters: /{userID:int}/{jobTitleID:int}
    Both are optional.
    If no userID, the current user profile is showed
    If not jobTitleID, the first one is returned
**/
A.prototype.show = function show(options) {
    Activity.prototype.show.call(this, options);

    var params = options.route && options.route.segments;
    // Get requested userID or the current user profile
    var userID = (params[0] |0) || user.userID();
    var jobTitleID = params[1] |0;
    this.loadData(userID, jobTitleID);
    this.viewModel.reviews.reset(userID, jobTitleID);
    this.viewModel.refreshTs(new Date());
    this.viewModel.userID(userID);
    this.viewModel.showMessageBar(true);
};

A.prototype.hide = function() {
    Activity.prototype.hide.call(this);

    this.viewModel.showMessageBar(false);
};

function ViewModel(app) {
    //jshint maxstatements:40
    this.isLoading = ko.observable(false);
    this.user = ko.observable(null);
    this.userID = ko.observable(null);
    this.reviews = new ReviewsVM();
    this.showMessageBar = ko.observable(false);

    // Just a timestamp to notice that a request to refresh UI happens
    // Is updated on 'show' and layoutUpdate (when inside this UI) currently
    // just to notify app-address-map elements
    this.refreshTs = ko.observable(new Date());

    this.reset = function() {
        this.user(null);
        this.userID(null);
        this.showMessageBar(false);
    };

    /// Work Photos utils
    var DEFAULT_WORKPHOTOS_LIMIT = 2;
    this.isShowingAllPhotos = ko.observable(false);
    this.workPhotos = ko.pureComputed(function() {
        var u = this.user();
        var ph = u && u.selectedJobTitle() && u.selectedJobTitle().workPhotos();
        if (!ph) {
            return [];
        }
        else if (this.isShowingAllPhotos()) {
            return ph;
        }
        else {
            // Filter by 2 first photos:
            var firsts = [];
            ph.some(function(p, i) {
                if (i > DEFAULT_WORKPHOTOS_LIMIT - 1)
                    return true;
                firsts.push(p);
            });
            return firsts;
        }
    }, this);
    this.viewMoreWorkPhotosLabel = ko.pureComputed(function() {
        var imgCount = this.user() && this.user().selectedJobTitle() && this.user().selectedJobTitle().workPhotos();
        imgCount = imgCount && imgCount.length || 0;
        if (this.isShowingAllPhotos() || imgCount === 0 || imgCount <= DEFAULT_WORKPHOTOS_LIMIT)
            return '';
        else
            return 'View all ' + imgCount + ' images';
    }, this);
    this.viewAllPhotos = function() {
        this.isShowingAllPhotos(true);
    }.bind(this);

    /// Addresses
    this.serviceAddresses = ko.pureComputed(function() {
        var u = this.user();
        var adds = u && u.selectedJobTitle() && u.selectedJobTitle().serviceAddresses();
        return adds || [];
    }, this);

    this.changeJobTitle = function(jobTitle, event) {
        this.user().selectedJobTitleID(jobTitle.jobTitleID());
        this.reviews.reset(undefined, jobTitle.jobTitleID());
        this.reviews.load({ limit: 2 });
        if (event) {
            event.preventDefault();
            event.stopImmediatePropagation();
        }
        var url = event.target.getAttribute('href');
        app.shell.pushState(null, null, url);
    }.bind(this);

    /// Social links
    this.getEmailLink = ko.pureComputed(function() {
        var u = this.user();
        if (!u) return '';
        var url = encodeURIComponent(u.profile().serviceProfessionalProfileUrl());
        return 'mailto:?body=' + encodeURIComponent(u.profile().fullName() + ': ') + url;
    }, this);
    this.getFacebookLink = ko.pureComputed(function() {
        var u = this.user();
        if (!u) return '';
        var url = encodeURIComponent(u.profile().serviceProfessionalProfileUrl());
        return 'http://www.facebook.com/share.php?u=' + url + '&t=' + encodeURIComponent(u.profile().fullName());
    }, this);
    this.getTwitterLink = ko.pureComputed(function() {
        var u = this.user();
        if (!u) return '';
        var url = encodeURIComponent(u.profile().serviceProfessionalProfileUrl());
        return 'http://twitter.com/intent/tweet?text=' + encodeURIComponent(u.profile().fullName() + ': ' + url);
    }, this);
    this.getGooglePlusLink = ko.pureComputed(function() {
        var u = this.user();
        if (!u) return '';
        var url = encodeURIComponent(u.profile().serviceProfessionalProfileUrl());
        return 'https://plus.google.com/share?url=' + url;
    }, this);
    this.getPinterestLink = ko.pureComputed(function() {
        var u = this.user();
        if (!u) return '';
        var url = encodeURIComponent(u.profile().serviceProfessionalProfileUrl());
        var photo = encodeURIComponent(u.profile().photoUrl());
        return 'http://pinterest.com/pin/create/button/?url=' + url + '&media=' + photo + '&description=' + encodeURIComponent(u.profile().fullName() + ': ' + url);
    }, this);

    this.getBookLink = ko.pureComputed(function() {
        var u = this.user();
        if (!u) return '';
        return '#!booking/' + u.profile().userID() + '/' + u.selectedJobTitleID();
    }, this);
    this.getSendMessageLink = ko.pureComputed(function() {
        var u = this.user();
        if (!u) return '';
        return '#!inbox/new/' + u.profile().userID();
    }, this);

    this.hasServicesOverview = ko.pureComputed(function() {
        var jobTitle = this.user() && this.user().selectedJobTitle(),
            hasIntro = jobTitle && jobTitle.hasIntro(),
            hasAttributes = jobTitle && jobTitle.serviceAttributes().hasAttributes();

        return hasIntro || hasAttributes;
    }, this);

    this.jobTitleSingularName = ko.pureComputed(function() {
        return this.selectedJobTitle().jobTitleSingularName();
    }, this);

    this.selectedJobTitle = ko.pureComputed(function() {
        return (this.user() && this.user().selectedJobTitle()) || new PublicUserJobTitle();
    }, this);

    this.editListing = function() {
        app.shell.go('/marketplaceJobtitles/' + this.selectedJobTitle().jobTitleID());
    }.bind(this);

    this.listingIsActive = ko.pureComputed(function() {
        return this.selectedJobTitle().isActive();
    }, this);

    this.isOwnProfile = ko.pureComputed(function() {
        var profileOwnerUserID = this.userID();

        if(user.isAnonymous() || profileOwnerUserID === null) {
            return false;
        }
        else {
            return profileOwnerUserID == user.userID();
        }
    }, this);

    this.isMessageBarVisible = ko.pureComputed(function() {
        return this.isOwnProfile() && this.showMessageBar();
    }, this);

    this.messageBarTone = ko.pureComputed(function() {
        return this.listingIsActive() ? MessageBar.tones.success : MessageBar.tones.warning;
    }, this);
}

var PublicUserReview = require('../models/PublicUserReview');
function ReviewsVM() {
    this.userID = ko.observable(null);
    this.jobTitleID = ko.observable(null);
    this.list = ko.observableArray([]);
    this.isLoading = ko.observable(false);
    this.endReached = ko.observable(false);
    var currentXhr = null;

    this.reset = function reset(userID, jobTitleID) {
        this.list([]);
        if (userID)
            this.userID(userID);
        this.jobTitleID(jobTitleID);
        this.endReached(false);
        if (currentXhr && currentXhr.abort) {
            currentXhr.abort();
        }
    };

    this.load = function loadReviews(options) {
        options = options || {};
        if (this.isLoading() || this.endReached() || !this.userID()) return;
        this.isLoading(true);
        var task = users.getReviews(this.userID(), this.jobTitleID(), options)
        .then(function(newData) {
            //jshint maxcomplexity:8
            if (newData && newData.length) {
                if (newData.length < (options.limit || 20)) {
                    this.endReached(true);
                }
                // convert the newData to Model instances
                newData = newData.map(function(d) { return new PublicUserReview(d); });
                var list = this.list();
                if (options.since && options.until) {
                    // Insert in the middle
                    // TODO Unused situation right now, not supported in the UI
                    throw new Error('UNSUPPORTED SET-UP: since and until parameters at the same time');
                }
                else if (options.since) {
                    // We 'suppose' that a 'since' request from the previous first item (descending order) was performed
                    // so we add the newData to the beggining of the list
                    list = newData.concat.apply(newData, list);
                }
                else if (options.until) {
                    // We 'suppose' that an 'until' request from the previous last item  (descending order) was performed
                    // so we add the newData to the ending of the list
                    list.push.apply(list, newData);
                }
                else {
                    // Just new, to replace, data
                    list = newData;
                }
                this.list(list);
            }
            else {
                this.endReached(true);
            }
            this.isLoading(false);
            currentXhr = null;
        }.bind(this))
        .catch(function(err) {
            this.isLoading(false);
            currentXhr = null;
            if (err && err.statusText !== 'abort') {
                console.error('Error loading user reviews', err);
                throw err;
            }
        }.bind(this));
        currentXhr = task.xhr;
        return task;
    }.bind(this);

    this.loadOlder = function loadOlderReviews() {
        var l = this.list();
        var last = l[l.length - 1];
        return this.load({ limit: 10, until: last && last.updatedDate() });
    }.bind(this);

    this.loadNewer = function loadOlderReviews() {
        var first = this.list()[0];
        return this.load({ limit: 10, since: first && first.updatedDate() });
    }.bind(this);
}
<|endoftext|>


<commit_before>//config
WebVRConfig = {
  CARDBOARD_UI_DISABLED: false,
  BUFFER_SCALE: 0.6,
  FORCE_ENABLE_VR: true
}

curScene = "first";

var isMusicLoaded = false;
var areShadersLoaded = false;
var currentTrack = 0;

var container, camera, scene, renderer, stats, effect;
var vrDisplay = null;
var camX = 0, camY = 0, camZ = 0;
var gravity = 0.005;
var negGravity = -0.005;

var gem, gui;

var tv1 = new THREE.Vector3();
var tv2 = new THREE.Vector3();
var repelerMeshes = [];
var repelersHidden = true;

var REPELERS = [];

var loaded = 0;
var neededToLoad = 1;

var loader = new Loader();
setTimeout(function () {
  loader.liftCurtain();
}, 3000);

var clock = new THREE.Clock();
var audioController = new AudioController();

initMusic(function () {
  stream = new Stream(musicArray[0], audioController)

  var playUntilItDies = function () {
    setTimeout(function () {
      currentTrack++;
      if (currentTrack >= musicArray.length) {
        currentTrack = 0;
      }
      stream.next(musicArray[currentTrack])

      playUntilItDies();

    }, (musicArray[currentTrack].duration - 2) * 1000);
  }
  playUntilItDies();

  checkLoad(true, false)
});

var shaders = new ShaderLoader('shaders');

shaders.load('ss-fire', 'fire', 'simulation');
shaders.load('ss-weird1', 'weird1', 'simulation');
shaders.load('vs-fire', 'fire', 'vertex');
shaders.load('fs-weird1', 'weird1', 'fragment');
shaders.load('fs-fire', 'fire', 'fragment');

shaders.shaderSetLoaded = function () {
  checkLoad(false, true);
}

var G_UNIFORMS = {
  dT: { type: "f", value: 0 },
  time: { type: "f", value: 0 },
  t_audio: { type: "t", value: audioController.texture },
}

function checkLoad(isMusic, areShaders) {
  isMusicLoaded = isMusicLoaded || isMusic;
  areShadersLoaded = areShadersLoaded || areShaders;

  console.log(isMusicLoaded, areShadersLoaded);

  if (isMusicLoaded && areShadersLoaded) {
    onLoad();
  }
}

function init() {
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 7000);
  camera.position.z = 0;

  // Getting the container in the right location
  container = document.createElement('div');
  container.id = 'container';
  document.body.appendChild(container);

  // Getting the stats in the right position
  stats = new Stats();
  stats.domElement.id = 'stats';
  document.body.appendChild(stats.domElement);

  // Setting up our Renderer
  renderer = new THREE.WebGLRenderer({ alpha: false, antialias: false });
  renderer.setClearColor(0x505050);
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.sortObjects = false;
  renderer.setSize(window.innerWidth, window.innerHeight);
  container.appendChild(renderer.domElement);
  renderer.domElement.style.background = "#000";

  controls = new THREE.DeviceOrientationControls(camera);

  effect = new THREE.VREffect(renderer);
  window.addEventListener('resize', onWindowResize, false);

  var g = new THREE.Mesh(new THREE.SphereGeometry(1200, 90, 90));
  gem = new CurlMesh('Space Puppy', g, {
    soul: {
      noiseSize: { type: "f", value: .001, constraints: [.0001, .01] },
      noiseVariation: { type: "f", value: .8, constraints: [.01, 1.] },
      dampening: { type: "f", value: .85, constraints: [.8, .999] },
      noisePower: { type: "f", value: 60, constraints: [0, 200.] },
      returnPower: { type: "f", value: 1.2, constraints: [.0, 2.] },
      audioVelMultiplier: { type: "f", value: .7, constraints: [0, 1] },
    },
    body: {
      audioDisplacement: { type: "f", value: 30.0, constraints: [0, 100] },
      tmp_color1: { type: "color", value: 0xff0000 },
      tmp_color2: { type: "color", value: 0x00ffe1 },
      tmp_color3: { type: "color", value: 0x5500ff },
      color1: { type: "c", value: new THREE.Color(0xff0000) },
      color2: { type: "c", value: new THREE.Color(0x00ffe1) },
      color3: { type: "c", value: new THREE.Color(0x5500ff) },
    }
  });

  gem.toggle();

  if (navigator.getVRDisplays) {
    navigator.getVRDisplays().then(function (displays) {
      vrDisplay = displays[0];
      vrDisplay.requestPresent([{ source: renderer.domElement }]);
      vrDisplay.requestAnimationFrame(animate);
    }).catch(function () {
      console.log('NO DISPLAYS!');
    });
  }
}

function clearScene() {
  for (var i = scene.children.length - 1; i >= 0; i--) {
    scene.remove(i);
  }
}

var spheres, lineGeom;
function setSecondScene() {
  curScene = "second";
  gem.removeFromScene();
  clearScene();

  renderer.setClearColor(0x000);
  spheres = [];
  var curPos = {};
  for (var i = 0; i < 300; i++) {
    var geometry = new THREE.SphereGeometry(Math.random() + 0.5, 12, 12);
    var material = new THREE.MeshBasicMaterial({
      color: getRandomColor()
    });
    var sphere = new THREE.Mesh(geometry, material);
    sphere.position.x = getRandomInt(-100, 100);
    sphere.position.y = getRandomInt(-100, 100);
    sphere.position.z = getRandomInt(-100, 100);
    sphere.vx = 0.5;
    sphere.vy = 0.5;
    sphere.vz = 0.5;
    spheres.push(sphere);
    scene.add(sphere);
  }

  lineGeom = new THREE.Geometry();

  for (var i = 0; i < spheres.length; i++) {
    lineGeom.vertices.push(new THREE.Vector3(spheres[i].position.x, spheres[i].position.y, spheres[i].position.z));
  }

  var lineMat = new THREE.LineBasicMaterial({
    color: 0xfff,
    transparent: true,
    opacity: 0.2,
    linewidth: 0.5
  });
  line = new THREE.Line(lineGeom, lineMat);
  scene.add(line);

  animate();
}

updateLines = function () {

  //lineGeom.vertices = [];
  for (var i = 0; i < spheres.length; i++) {
    lineGeom.vertices[i].x = spheres[i].position.x;
    lineGeom.vertices[i].y = spheres[i].position.y;
    lineGeom.vertices[i].z = spheres[i].position.z;
  }

  lineGeom.verticesNeedUpdate = true;
  lineGeom.elementsNeedUpdate = true;
  lineGeom.morphTargetsNeedUpdate = true;
  lineGeom.uvsNeedUpdate = true;
  lineGeom.normalsNeedUpdate = true;
  lineGeom.colorsNeedUpdate = true;
  lineGeom.tangentsNeedUpdate = true;
}

function setFirstScene() {
  curScene = "first";
  clearScene();
  gem.addToScene();
}

var nextScene = "first";
function animate() {
  //console.log(gem.uniforms.dT.value);
  audioController.update();

  G_UNIFORMS.dT.value = clock.getDelta();
  G_UNIFORMS.time.value += G_UNIFORMS.dT.value;

  if (curScene == "first") {
    gem.update();
    console.log('updating gem!');
  } else if (curScene == "second") {
    updateState();
    console.log('should do 2nd scene');
  } else if (curScene == "third") {

  }

  stats.update();
  controls.update();

  if (nextScene != curScene) {
    if (nextScene == "first")
      setFirstScene();
    else if (nextScene == "second") {
      setSecondScene();
    }
  } else {
    vrDisplay.requestAnimationFrame(animate);
    effect.render(scene, camera);
  }
}

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

  renderer.setSize(window.innerWidth, window.innerHeight);
  var dpr = devicePixelRatio || 1;
}

function onLoad() {
  loaded++;
  if (loaded === neededToLoad) {

    if (stream) {
      stream.play();
    }

    init();
  }
}

$(document).ready(function () {
  $('#vrbutton').click(function () {
    //nextScene = "second";
    vrDisplay.requestPresent([{ source: renderer.domElement }]);
  });

  $('#menubutton').click(function () {
    toggleMenu();
  });

  $('#scbutton1').click(function () {
    nextScene = "first";
    toggleMenu();
  });

  $('#scbutton2').click(function () {
    nextScene = "second";
    toggleMenu();
  });

  $('#scbutton3').click(function () {
    console.log("call scene three");
    toggleMenu();
  });
});

function toggleMenu() {
  $("#menu").toggle(300);

}
function toCart(r, t, p) {

  var x = r * (Math.sin(t)) * (Math.cos(p));
  var y = r * (Math.sin(t)) * (Math.sin(p));
  var z = r * (Math.cos(t));

  return new THREE.Vector3(x, y, z);

}

function getSign(num) {
  if (num > 0) {
    return 1;
  } else {
    return -1;
  }
}

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function updateState() {
  var curdT = gem.uniforms.dT.value;
  var dTint = Math.round(curdT * 1000);
  dTint = dTint - 12;
  if(dTint < 0){
    dTint = 0;
  }
  //console.log(dTint);

  //remove time interval, handle it on animate
  for (var i = 0; i < spheres.length; i++) {
    spheres[i].position.x = add(spheres[i].position.x, spheres[i].vx);
    spheres[i].position.y = add(spheres[i].position.y, spheres[i].vy);
    spheres[i].position.z = add(spheres[i].position.z, spheres[i].vz);
    if (spheres[i].vx > 0) {
      spheres[i].vx = add(spheres[i].vx, negGravity);
    } else if (spheres[i].vx < 0) {
      spheres[i].vx = add(spheres[i].vx, gravity);
    } else if (spheres[i].vx.toPrecision(5) == 0.00000) {
      spheres[i].vx = strip(getRandomInt(-2, 2) / 10 * dTint);
      console.log(spheres[i].vx);
    }

    if (spheres[i].vy > 0) {
      spheres[i].vy = add(spheres[i].vy, negGravity);
    } else if (spheres[i].vy < 0) {
      spheres[i].vy = add(spheres[i].vy, gravity);
    } else if (spheres[i].vy == 0.000000000000) {
      spheres[i].vy = strip(getRandomInt(-3, 3) / 10 * dTint);
      console.log(spheres[i].vy);
    }
    if (spheres[i].vz > 0) {
      spheres[i].vz = add(spheres[i].vz, negGravity);
    } else if (spheres[i].vz < 0) {
      spheres[i].vz = add(spheres[i].vz, gravity);
    } else if (spheres[i].vy == 0.000000000000) {
      spheres[i].vz = strip(getRandomInt(-3, 3) / 10 * dTint);
      console.log(spheres[i].vz);
    }
  }
  updateLines();
}

function add(num1, num2) {
  num1 *= 1000;
  num2 *= 1000;
  return (num1 + num2) / 1000;
}

function getRandomColor() {
  var letters = '0123456789ABCDEF';
  var color = '#';
  for (var i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}

function strip(number) {
    return (parseFloat(number).toPrecision(12));
}<commit_msg>fixed balls<commit_after>//config
WebVRConfig = {
  CARDBOARD_UI_DISABLED: false,
  BUFFER_SCALE: 0.6,
  FORCE_ENABLE_VR: true
}

curScene = "first";

var isMusicLoaded = false;
var areShadersLoaded = false;
var currentTrack = 0;

var container, camera, scene, renderer, stats, effect;
var vrDisplay = null;
var camX = 0, camY = 0, camZ = 0;
var gravity = 0.005;
var negGravity = -0.005;

var gem, gui;

var tv1 = new THREE.Vector3();
var tv2 = new THREE.Vector3();
var repelerMeshes = [];
var repelersHidden = true;

var REPELERS = [];

var loaded = 0;
var neededToLoad = 1;

var loader = new Loader();
setTimeout(function () {
  loader.liftCurtain();
}, 3000);

var clock = new THREE.Clock();
var audioController = new AudioController();

initMusic(function () {
  stream = new Stream(musicArray[0], audioController)

  var playUntilItDies = function () {
    setTimeout(function () {
      currentTrack++;
      if (currentTrack >= musicArray.length) {
        currentTrack = 0;
      }
      stream.next(musicArray[currentTrack])

      playUntilItDies();

    }, (musicArray[currentTrack].duration - 2) * 1000);
  }
  playUntilItDies();

  checkLoad(true, false)
});

var shaders = new ShaderLoader('shaders');

shaders.load('ss-fire', 'fire', 'simulation');
shaders.load('ss-weird1', 'weird1', 'simulation');
shaders.load('vs-fire', 'fire', 'vertex');
shaders.load('fs-weird1', 'weird1', 'fragment');
shaders.load('fs-fire', 'fire', 'fragment');

shaders.shaderSetLoaded = function () {
  checkLoad(false, true);
}

var G_UNIFORMS = {
  dT: { type: "f", value: 0 },
  time: { type: "f", value: 0 },
  t_audio: { type: "t", value: audioController.texture },
}

function checkLoad(isMusic, areShaders) {
  isMusicLoaded = isMusicLoaded || isMusic;
  areShadersLoaded = areShadersLoaded || areShaders;

  console.log(isMusicLoaded, areShadersLoaded);

  if (isMusicLoaded && areShadersLoaded) {
    onLoad();
  }
}

function init() {
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 7000);
  camera.position.z = 0;

  // Getting the container in the right location
  container = document.createElement('div');
  container.id = 'container';
  document.body.appendChild(container);

  // Getting the stats in the right position
  stats = new Stats();
  stats.domElement.id = 'stats';
  document.body.appendChild(stats.domElement);

  // Setting up our Renderer
  renderer = new THREE.WebGLRenderer({ alpha: false, antialias: false });
  renderer.setClearColor(0x505050);
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.sortObjects = false;
  renderer.setSize(window.innerWidth, window.innerHeight);
  container.appendChild(renderer.domElement);
  renderer.domElement.style.background = "#000";

  controls = new THREE.DeviceOrientationControls(camera);

  effect = new THREE.VREffect(renderer);
  window.addEventListener('resize', onWindowResize, false);

  var g = new THREE.Mesh(new THREE.SphereGeometry(1200, 90, 90));
  gem = new CurlMesh('Space Puppy', g, {
    soul: {
      noiseSize: { type: "f", value: .001, constraints: [.0001, .01] },
      noiseVariation: { type: "f", value: .8, constraints: [.01, 1.] },
      dampening: { type: "f", value: .85, constraints: [.8, .999] },
      noisePower: { type: "f", value: 60, constraints: [0, 200.] },
      returnPower: { type: "f", value: 1.2, constraints: [.0, 2.] },
      audioVelMultiplier: { type: "f", value: .7, constraints: [0, 1] },
    },
    body: {
      audioDisplacement: { type: "f", value: 30.0, constraints: [0, 100] },
      tmp_color1: { type: "color", value: 0xff0000 },
      tmp_color2: { type: "color", value: 0x00ffe1 },
      tmp_color3: { type: "color", value: 0x5500ff },
      color1: { type: "c", value: new THREE.Color(0xff0000) },
      color2: { type: "c", value: new THREE.Color(0x00ffe1) },
      color3: { type: "c", value: new THREE.Color(0x5500ff) },
    }
  });

  gem.toggle();

  if (navigator.getVRDisplays) {
    navigator.getVRDisplays().then(function (displays) {
      vrDisplay = displays[0];
      vrDisplay.requestPresent([{ source: renderer.domElement }]);
      vrDisplay.requestAnimationFrame(animate);
    }).catch(function () {
      console.log('NO DISPLAYS!');
    });
  }
}

function clearScene() {
  for (var i = scene.children.length - 1; i >= 0; i--) {
    scene.remove(i);
  }
}

var spheres, lineGeom;
function setSecondScene() {
  curScene = "second";
  gem.removeFromScene();
  clearScene();

  renderer.setClearColor(0x000);
  spheres = [];
  var curPos = {};
  for (var i = 0; i < 300; i++) {
    var geometry = new THREE.SphereGeometry(Math.random() + 0.5, 12, 12);
    var material = new THREE.MeshBasicMaterial({
      color: getRandomColor()
    });
    var sphere = new THREE.Mesh(geometry, material);
    sphere.position.x = getRandomInt(-100, 100);
    sphere.position.y = getRandomInt(-100, 100);
    sphere.position.z = getRandomInt(-100, 100);
    sphere.vx = 0.05;
    sphere.vy = 0.05;
    sphere.vz = 0.05;
    spheres.push(sphere);
    scene.add(sphere);
  }

  lineGeom = new THREE.Geometry();

  for (var i = 0; i < spheres.length; i++) {
    lineGeom.vertices.push(new THREE.Vector3(spheres[i].position.x, spheres[i].position.y, spheres[i].position.z));
  }

  var lineMat = new THREE.LineBasicMaterial({
    color: 0xfff,
    transparent: true,
    opacity: 0.2,
    linewidth: 0.5
  });
  line = new THREE.Line(lineGeom, lineMat);
  scene.add(line);

  animate();
}

updateLines = function () {

  //lineGeom.vertices = [];
  for (var i = 0; i < spheres.length; i++) {
    lineGeom.vertices[i].x = spheres[i].position.x;
    lineGeom.vertices[i].y = spheres[i].position.y;
    lineGeom.vertices[i].z = spheres[i].position.z;
  }

  lineGeom.verticesNeedUpdate = true;
  lineGeom.elementsNeedUpdate = true;
  lineGeom.morphTargetsNeedUpdate = true;
  lineGeom.uvsNeedUpdate = true;
  lineGeom.normalsNeedUpdate = true;
  lineGeom.colorsNeedUpdate = true;
  lineGeom.tangentsNeedUpdate = true;
}

function setFirstScene() {
  curScene = "first";
  clearScene();
  gem.addToScene();
}

var nextScene = "first";
function animate() {
  //console.log(gem.uniforms.dT.value);
  audioController.update();

  G_UNIFORMS.dT.value = clock.getDelta();
  G_UNIFORMS.time.value += G_UNIFORMS.dT.value;

  if (curScene == "first") {
    gem.update();
    console.log('updating gem!');
  } else if (curScene == "second") {
    updateState();
  } else if (curScene == "third") {

  }

  stats.update();
  controls.update();

  if (nextScene != curScene) {
    if (nextScene == "first")
      setFirstScene();
    else if (nextScene == "second") {
      setSecondScene();
    }
  } else {
    vrDisplay.requestAnimationFrame(animate);
    effect.render(scene, camera);
  }
}

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

  renderer.setSize(window.innerWidth, window.innerHeight);
  var dpr = devicePixelRatio || 1;
}

function onLoad() {
  loaded++;
  if (loaded === neededToLoad) {

    if (stream) {
      stream.play();
    }

    init();
  }
}

$(document).ready(function () {
  $('#vrbutton').click(function () {
    //nextScene = "second";
    vrDisplay.requestPresent([{ source: renderer.domElement }]);
  });

  $('#menubutton').click(function () {
    toggleMenu();
  });

  $('#scbutton1').click(function () {
    nextScene = "first";
    toggleMenu();
  });

  $('#scbutton2').click(function () {
    nextScene = "second";
    toggleMenu();
  });

  $('#scbutton3').click(function () {
    console.log("call scene three");
    toggleMenu();
  });
});

function toggleMenu() {
  $("#menu").toggle(300);

}
function toCart(r, t, p) {

  var x = r * (Math.sin(t)) * (Math.cos(p));
  var y = r * (Math.sin(t)) * (Math.sin(p));
  var z = r * (Math.cos(t));

  return new THREE.Vector3(x, y, z);

}

function getSign(num) {
  if (num > 0) {
    return 1;
  } else {
    return -1;
  }
}

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function updateState() {
  var curdT = gem.uniforms.dT.value;
  var dTint = Math.round(curdT * 1000);
  dTint = dTint - 10;
  if(dTint < 0){
    dTint = 0;
  }
  //console.log(dTint);
  //remove time interval, handle it on animate
  for (var i = 0; i < spheres.length; i++) {
    //console.log("1: "+spheres[i].vx +"  2: "+spheres[i].vy + "  3."+spheres[i].vz);
    spheres[i].position.x = add(spheres[i].position.x, spheres[i].vx);
    spheres[i].position.y = add(spheres[i].position.y, spheres[i].vy);
    spheres[i].position.z = add(spheres[i].position.z, spheres[i].vz);
    if (spheres[i].vx > 0) {
      spheres[i].vx = add(spheres[i].vx, negGravity);
    } else if (spheres[i].vx < 0) {
      spheres[i].vx = add(spheres[i].vx, gravity);
    } else if (parseFloat(spheres[i].vx).toPrecision(5) == 0.00000) {
      spheres[i].vx = strip(getRandomInt(-2, 2) / 100 * dTint);
      console.log(spheres[i].vx);
    }

    if (spheres[i].vy > 0) {
      spheres[i].vy = add(spheres[i].vy, negGravity);
    } else if (spheres[i].vy < 0) {
      spheres[i].vy = add(spheres[i].vy, gravity);
    } else if (parseFloat(spheres[i].vy).toPrecision(5) == 0.00000) {
      spheres[i].vy = strip(getRandomInt(-2, 2) / 100 * dTint);
      console.log(spheres[i].vy);
    }
    if (spheres[i].vz > 0) {
      spheres[i].vz = add(spheres[i].vz, negGravity);
    } else if (spheres[i].vz < 0) {
      spheres[i].vz = add(spheres[i].vz, gravity);
    } else if (parseFloat(spheres[i].vy).toPrecision(5) == 0.00000) {
      spheres[i].vz = strip(getRandomInt(-2, 2) / 100 * dTint);
      console.log(spheres[i].vz);
    }
  }
  updateLines();
}

function add(num1, num2) {
  num1 *= 1000;
  num2 *= 1000;
  return (num1 + num2) / 1000;
}

function getRandomColor() {
  var letters = '0123456789ABCDEF';
  var color = '#';
  for (var i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}

function strip(number) {
    return (parseFloat(number).toPrecision(6));
}<|endoftext|>


<commit_before>/**
 * @fileoverview Sumorobot blocks for Blockly.
 * @author info@robokoding.com (RoboKoding)
 */
'use strict';

goog.provide('Blockly.Blocks.sumorobot');

goog.require('Blockly.Blocks');

Blockly.Blocks['sumorobot_delay'] = {
  init: function() {
    this.setHelpUrl(Blockly.Msg.SUMOROBOT_DELAY_HELPURL);
    this.setColour("#E64C00");
    this.appendDummyInput()
      .appendField(Blockly.Msg.SUMOROBOT_DELAY_TITLE)
        .appendField(new Blockly.FieldTextInput('0',
          Blockly.FieldTextInput.numberValidator), 'DELAY');
    this.setPreviousStatement(true);
    this.setNextStatement(true);
    this.setTooltip(Blockly.Msg.SUMOROBOT_DELAY_TOOLTIP);
  }
};

Blockly.Blocks['sumorobot_move'] = {
  init: function() {
    var OPERATORS =
      [[Blockly.Msg.SUMOROBOT_MOVE_MSG_STOP, 'STOP'],
       [Blockly.Msg.SUMOROBOT_MOVE_MSG_LEFT, 'LEFT'],
       [Blockly.Msg.SUMOROBOT_MOVE_MSG_RIGHT, 'RIGHT'],
       [Blockly.Msg.SUMOROBOT_MOVE_MSG_FORWARD, 'FORWARD'],
       [Blockly.Msg.SUMOROBOT_MOVE_MSG_BACKWARD, 'BACKWARD']];
    this.setHelpUrl(Blockly.Msg.SUMOROBOT_MOVE_HELPURL);
    this.setColour("#E60000");
    var dropdown = new Blockly.FieldDropdown(OPERATORS);
    this.appendDummyInput().appendField(dropdown, 'MOVE');
    this.setPreviousStatement(true);
    this.setNextStatement(true);
    this.setTooltip(Blockly.Msg.SUMOROBOT_MOVE_TOOLTIP);
  }
};

Blockly.Blocks['sumorobot_enemy'] = {
  init: function() {
    this.setHelpUrl(Blockly.Msg.SUMOROBOT_ENEMY_HELPURL);
    this.setColour("#0099E6");
    var dropdown = new Blockly.FieldDropdown(OPERATORS);
    this.appendDummyInput().appendField('ENEMY');
    this.setOutput(true, 'Boolean');
    this.setTooltip(Blockly.Msg.SUMOROBOT_ENEMY_TOOLTIP);
  }
};

Blockly.Blocks['sumorobot_line'] = {
  init: function() {
    var OPERATORS =
      [[Blockly.Msg.SUMOROBOT_LINE_MSG_LEFT, 'LEFT'],
       [Blockly.Msg.SUMOROBOT_LINE_MSG_FRONT, 'FRONT'],
       [Blockly.Msg.SUMOROBOT_LINE_MSG_RIGHT, 'RIGHT']];
    this.setHelpUrl(Blockly.Msg.SUMOROBOT_LINE_HELPURL);
    this.setColour("#E6BF00");
    var dropdown = new Blockly.FieldDropdown(OPERATORS);
    this.appendDummyInput().appendField(dropdown, 'LINE');
    this.setOutput(true, 'Boolean');
    this.setTooltip(Blockly.Msg.SUMOROBOT_LINE_TOOLTIP);
  }
};
<commit_msg>Update sumorobot.js<commit_after>/**
 * @fileoverview Sumorobot blocks for Blockly.
 * @author info@robokoding.com (RoboKoding)
 */
'use strict';

goog.provide('Blockly.Blocks.sumorobot');

goog.require('Blockly.Blocks');

Blockly.Blocks['sumorobot_delay'] = {
  init: function() {
    this.setHelpUrl(Blockly.Msg.SUMOROBOT_DELAY_HELPURL);
    this.setColour("#E64C00");
    this.appendDummyInput()
      .appendField(Blockly.Msg.SUMOROBOT_DELAY_TITLE)
        .appendField(new Blockly.FieldTextInput('0',
          Blockly.FieldTextInput.numberValidator), 'DELAY');
    this.setPreviousStatement(true);
    this.setNextStatement(true);
    this.setTooltip(Blockly.Msg.SUMOROBOT_DELAY_TOOLTIP);
  }
};

Blockly.Blocks['sumorobot_move'] = {
  init: function() {
    var OPERATORS =
      [[Blockly.Msg.SUMOROBOT_MOVE_MSG_STOP, 'STOP'],
       [Blockly.Msg.SUMOROBOT_MOVE_MSG_LEFT, 'LEFT'],
       [Blockly.Msg.SUMOROBOT_MOVE_MSG_RIGHT, 'RIGHT'],
       [Blockly.Msg.SUMOROBOT_MOVE_MSG_FORWARD, 'FORWARD'],
       [Blockly.Msg.SUMOROBOT_MOVE_MSG_BACKWARD, 'BACKWARD']];
    this.setHelpUrl(Blockly.Msg.SUMOROBOT_MOVE_HELPURL);
    this.setColour("#E60000");
    var dropdown = new Blockly.FieldDropdown(OPERATORS);
    this.appendDummyInput().appendField(dropdown, 'MOVE');
    this.setPreviousStatement(true);
    this.setNextStatement(true);
    this.setTooltip(Blockly.Msg.SUMOROBOT_MOVE_TOOLTIP);
  }
};

Blockly.Blocks['sumorobot_enemy'] = {
  init: function() {
    this.setHelpUrl(Blockly.Msg.SUMOROBOT_ENEMY_HELPURL);
    this.setColour("#0099E6");
    var dropdown = new Blockly.FieldDropdown(OPERATORS);
    this.appendDummyInput().appendField('enemy');
    this.setOutput(true, 'Boolean');
    this.setTooltip(Blockly.Msg.SUMOROBOT_ENEMY_TOOLTIP);
  }
};

Blockly.Blocks['sumorobot_line'] = {
  init: function() {
    var OPERATORS =
      [[Blockly.Msg.SUMOROBOT_LINE_MSG_LEFT, 'LEFT'],
       [Blockly.Msg.SUMOROBOT_LINE_MSG_FRONT, 'FRONT'],
       [Blockly.Msg.SUMOROBOT_LINE_MSG_RIGHT, 'RIGHT']];
    this.setHelpUrl(Blockly.Msg.SUMOROBOT_LINE_HELPURL);
    this.setColour("#E6BF00");
    var dropdown = new Blockly.FieldDropdown(OPERATORS);
    this.appendDummyInput().appendField(dropdown, 'LINE');
    this.setOutput(true, 'Boolean');
    this.setTooltip(Blockly.Msg.SUMOROBOT_LINE_TOOLTIP);
  }
};
<|endoftext|>


<commit_before>var self,
    clickHandlers = [], // bindet click handlers (for removing them)
    shadow = [],        // shadow copy of children
    visibleButtons,
    _first,             // holds first index
    _last,              // holds last index
    _direction,
    exclusive;

/**
 * prepares the group behavior for that component
 */

var create = function(that, options) {
    self = that;
    _direction = options.direction || Qt.Horizontal;
    exclusive = self.exclusive|| options.exclusive;
    self.childrenChanged.connect(childrenChanged);
    self.widthChanged.connect(resizeChildren);
    build();
}

// fun is taken from qt-components
// "duck-typing" to identify the Buttons, find a better way to do it :-P
function isButton(item) {
    if (item && item["__position"] !== undefined)
        return true;
    return false;
}

function hasChecked(item) {
    if (item && item["checked"] !== undefined)
        return true;
    return false;
}

/**
 * Destroy behavior for that component
 */
var destroy = function() {
    self.childrenChanged.disconnect(childrenChanged);
    self.widthChanged.disconnect(resizeChildren);
    cleanup();
}

/**
 * prepare the buttongroup
 */
function build() {
    // copy of children because its not an array. also we need a copy
    shadow = [];
    shadow.length = self.children.length;
    visibleButtons = 0;
    _first = undefined;
    _last = 0;
    var isCheckedPresent = false;
    for (var i = 0, item; (item = self.children[i]); i++) {
        if (hasChecked(item)) {
            shadow[i] = item;
            if (item.visible) {
                if (_first === undefined)
                    _first = i;
                _last = i;
                visibleButtons = visibleButtons + 1;
            }
            if (item === self.checkedButton) {
                isCheckedPresent = true;
            }
        }
    }
    if (!isCheckedPresent) {
        self.checkedButton = undefined;
    }

    shadow.forEach(function(item, i) {
        if (isButton(item) ) {
            item.__position = _first===_last ?
                                        "only":
                             _first === i ?
                                        (_direction == Qt.Horizontal ? "leftmost" : "top")  :
                             _last === i ?
                                        (_direction == Qt.Horizontal ? "rightmost" : "bottom") :
                                        (_direction == Qt.Horizontal ? "h_middle": "v_middle"); // middle

            if (self.width > 0) { // fixed: ASGARD-18
                if (_direction == Qt.Vertical) {
                    item.anchors.left = self.left
                    item.anchors.right = self.right
                }
            }
            item.visibleChanged.connect(childrenChanged);
        }
        if (exclusive && hasChecked(item)) {
            if (item["checkable"]!==undefined) {
                item.checkable = true;
            }
            clickHandlers[i] = function() { checkExclusive(item); }
            item.clicked.connect(clickHandlers[i]);
        }

    });
}

/**
 * cleanup the buttongroup
 */
function cleanup() {
    for (var i = 0, l = shadow.length; i < l; i++) {
        try {
            if (clickHandlers[i]) { shadow[i].clicked.disconnect(clickHandlers[i]); }
            if (isButton(shadow[i]))
                shadow[i].visibleChanged.disconnect(childrenChanged);
        } catch (e) {}
    }
    clickHandlers = [];
}

/**
 * rebuild if buttongroup has changed
 */
function childrenChanged() {
    cleanup();
    build();
}

var resizeChildren = function() {
    if (_direction != Qt.Horizontal) {
        return;
    }

    var extraPixels = self.width % visibleButtons;
    var buttonSize = (self.width - extraPixels) / visibleButtons;
    shadow.forEach(function(item, i) {
        if (!item.visible)
            return;
        item.width = buttonSize + (extraPixels > 0 ? 1 : 0);
        if (extraPixels > 0) {
            extraPixels--;
        }
    });
}

function checkExclusive(item) {
    for (var i = 0, ref; (ref = shadow[i]); i++) {
        ref.checked = item === ref;
    }
    self.checkedButton = item;
}
<commit_msg>Cleaning ButtonGroup.js<commit_after>var self,
    clickHandlers = [], // bindet click handlers (for removing them)
    shadow = [],        // shadow copy of children
    visibleButtons,
    _first,             // holds first index
    _last,              // holds last index
    _direction,
    exclusive;

/**
 * prepares the group behavior for that component
 */

function create(that, options) {
    self = that;
    _direction = options.direction || Qt.Horizontal;
    exclusive = self.exclusive|| options.exclusive;
    self.childrenChanged.connect(childrenChanged);
    self.widthChanged.connect(resizeChildren);
    build();
}

// fun is taken from qt-components
// "duck-typing" to identify the Buttons, find a better way to do it :-P
function isButton(item) {
    if (item && item["__position"] !== undefined)
        return true;
    return false;
}

function hasChecked(item) {
    if (item && item["checked"] !== undefined)
        return true;
    return false;
}

/**
 * Destroy behavior for that component
 */
function destroy() {
    self.childrenChanged.disconnect(childrenChanged);
    self.widthChanged.disconnect(resizeChildren);
    cleanup();
}

/**
 * prepare the buttongroup
 */
function build() {
    // copy of children because its not an array. also we need a copy
    shadow = [];
    shadow.length = self.children.length;
    visibleButtons = 0;
    _first = undefined;
    _last = 0;
    var isCheckedPresent = false;
    for (var i = 0, item; (item = self.children[i]); i++) {
        if (hasChecked(item)) {
            shadow[i] = item;
            if (item.visible) {
                if (_first === undefined)
                    _first = i;
                _last = i;
                visibleButtons = visibleButtons + 1;
            }
            if (item === self.checkedButton) {
                isCheckedPresent = true;
            }
        }
    }
    if (!isCheckedPresent) {
        self.checkedButton = undefined;
    }

    shadow.forEach(function(item, i) {
        if (isButton(item) ) {
            item.__position = _first===_last ?
                                        "only":
                             _first === i ?
                                        (_direction == Qt.Horizontal ? "leftmost" : "top")  :
                             _last === i ?
                                        (_direction == Qt.Horizontal ? "rightmost" : "bottom") :
                                        (_direction == Qt.Horizontal ? "h_middle": "v_middle"); // middle

            if (self.width > 0) { // fixed: ASGARD-18
                if (_direction == Qt.Vertical) {
                    item.anchors.left = self.left
                    item.anchors.right = self.right
                }
            }
            item.visibleChanged.connect(childrenChanged);
        }
        if (exclusive && hasChecked(item)) {
            if (item["checkable"]!==undefined) {
                item.checkable = true;
            }
            clickHandlers[i] = function() { checkExclusive(item); }
            item.clicked.connect(clickHandlers[i]);
        }

    });
}

/**
 * cleanup the buttongroup
 */
function cleanup() {
    shadow.forEach(function(item, i) {
        if (item) {
            if (clickHandlers[i])
                item.clicked.disconnect(clickHandlers[i]);
            if (isButton(shadow[i]))
                item.visibleChanged.disconnect(childrenChanged);
        }
    });
    clickHandlers = [];
}

/**
 * rebuild if buttongroup has changed
 */
function childrenChanged() {
    cleanup();
    build();
}

function resizeChildren() {
    if (_direction != Qt.Horizontal)
        return;

    console.log("resizeChildren");
    var extraPixels = self.width % visibleButtons;
    var buttonSize = (self.width - extraPixels) / visibleButtons;
    shadow.forEach(function(item, i) {
        if (!item || !item.visible)
            return;
        item.width = buttonSize + (extraPixels > 0 ? 1 : 0);
        if (extraPixels > 0)
            extraPixels--;
    });
}

function checkExclusive(item) {
    for (var i = 0, ref; (ref = shadow[i]); i++) {
        ref.checked = item === ref;
    }
    self.checkedButton = item;
}
<|endoftext|>


<commit_before>// Global vars
var pymChild = null;
var isMobile = false;

/*
 * Initialize graphic
 */
var onWindowLoaded = function () {
    if (Modernizr.svg) {
        formatData();

        pymChild = new pym.Child({
            renderCallback: render,
        });
    } else {
        pymChild = new pym.Child({});
    }
};

/*
 * Format graphic data for processing by D3.
 */
var formatData = function () {
    DATA.forEach(function (d) {
        d.start = +d.start;
        d.end = +d.end;
    });
};

/*
 * Render the graphic(s). Called by pym with the container width.
 */
var render = function (containerWidth) {
    containerWidth = containerWidth || DEFAULT_WIDTH;
    isMobile = (containerWidth <= MOBILE_THRESHOLD);

    // Render the chart!
    renderSlopegraph();

    // Update iframe
    if (pymChild) {
        pymChild.sendHeight();
    }
};

/*
 * Render a line chart.
 */
var renderSlopegraph = function () {
    /*
     * Setup
     */
    var startLabel = LABELS.start_label;
    var endLabel = LABELS.end_label;

    var aspectRatio = getAspectRatio(LABELS.ratio, {
        base: 3 / 2,
        mobile: 2 / 3,
    });

    var margins = {
        top: parseInt(LABELS.marginTop || 20, 10),
        right: parseInt(LABELS.marginRight || 30, 10),
        bottom: parseInt(LABELS.marginBottom || 20, 10),
        left: parseInt(LABELS.marginLeft || 30, 10),
    };

    var labelWidth = parseInt(LABELS.labelWidth || 80, 10);
    var valueGap = parseInt(LABELS.valueGap || 6, 10);

    // Clear existing graphic (for redraw)
    var containerElement = d3.select('#slopegraph');
    containerElement.html('');

    /*
     * Create the root SVG element.
     */
    var chartWrapper = containerElement.append('div')
        .attr('class', 'graphic-wrapper');

    // Calculate actual chart dimensions
    var innerWidth = chartWrapper.node().getBoundingClientRect().width;
    var horizMargins = margins.left + margins.right;
    var vertMargins = margins.top + margins.bottom;
    var labelAndGapWidth = labelWidth + valueGap;
    var noOfLabelCols = isMobile ? 1 : 2;
    var chartWidth = innerWidth - horizMargins - (labelAndGapWidth * noOfLabelCols);
    var chartHeight = Math.ceil(innerWidth / aspectRatio) - vertMargins;

    /*
     * Create D3 scale objects.
     */

    var xLabels = [startLabel, endLabel];

    var xScale = d3.scale.ordinal()
        .domain(xLabels)
        .range([0, chartWidth]);

    var minY = d3.min(DATA, function (d) {
        return Math.min(d.start, d.end);
    });

    var maxY = d3.max(DATA, function (d) {
        return Math.max(d.start, d.end);
    });

    var yScale = d3.scale.linear()
        .domain([minY, maxY])
        .range([chartHeight, 0]);

    var labelScale = d3.scale.ordinal()
        .domain(DATA.map(function (d) {
            return d.label;
        }));

    var colorList = colorArray(LABELS, MONOCHROMECOLORS);
    var colorScale = labelScale.copy()
        .range(colorList);

    var accessibleColorScale = labelScale.copy()
        .range(colorList.map(function (color) {
            return getAccessibleColor(color);
        }));

    var leftOffset = isMobile ? margins.left : margins.left + labelAndGapWidth;

    var chartElement = chartWrapper.append('svg')
        .attr({
            width: chartWidth + horizMargins + (labelAndGapWidth * noOfLabelCols),
            height: chartHeight + vertMargins,
        })
        .append('g')
            .attr('transform', makeTranslate(leftOffset, margins.top));

    /*
     * Render axes to chart.
     */
    chartWrapper.selectAll('svg').append('g')
        .attr('class', 'x axis')
        .selectAll('text')
        .data(xLabels)
        .enter()
        .append('text')
            .style('text-anchor', function (d, i) {
                if (i) {
                    return 'end';
                }
            })
            .attr('x', function (d, i) {
                if (i) {
                    return innerWidth;
                }
            })
            .text(function (d) {
                return d;
            });

    /*
     * Render lines to chart.
     */
    chartElement.append('g')
        .attr('class', 'lines')
        .selectAll('line')
        .data(DATA)
        .enter()
        .append('line')
            .attr('class', function (d, i) {
                return 'line ' + classify(d.label);
            })
            .attr({
                x1: xScale(startLabel),
                y1: function (d) {
                    return yScale(d.start);
                },

                x2: xScale(endLabel),
                y2: function (d) {
                    return yScale(d.end);
                },
            })
            .style('stroke', function (d) {
                return colorScale(d.label);
            });

    /*
     * Uncomment if needed:
     * Move a particular line to the front of the stack
     */

    // svg.select('line.unaffiliated').moveToFront();

    /*
     * Render values.
     */
    var valuesStart = chartElement.append('g')
        .attr('class', 'value start')
        .selectAll('text')
        .data(DATA)
        .enter()
        .append('text')
            .attr('class', function (d) {
                return classify(d.label);
            })
            .attr({
                x: xScale(startLabel),
                y: function (d) {
                    return yScale(d.start);
                },

                dx: -valueGap,
                dy: 4,
                fill: function (d) {
                    return accessibleColorScale(d.label);
                },
            })
            .text(function (d) {
                return formattedNumber(
                    d.start,
                    LABELS.valuePrefix,
                    LABELS.valueSuffix,
                    LABELS.maxDecimalPlaces
                );
            });

    var valuesEnd = chartElement.append('g')
        .attr('class', 'value end')
        .selectAll('text')
        .data(DATA)
        .enter()
        .append('text')
            .attr('class', function (d) {
                return classify(d.label);
            })
            .attr({
                x: xScale(endLabel),
                y: function (d) {
                    return yScale(d.end);
                },

                dx: valueGap,
                dy: 4,
                fill: function (d) {
                    return accessibleColorScale(d.label);
                },
            })
            .text(function (d) {
                return formattedNumber(
                    d.end,
                    LABELS.valuePrefix,
                    LABELS.valueSuffix,
                    LABELS.maxDecimalPlaces
                );
            });

    /*
     * Render labels.
     */
    if (!isMobile) {
        var valuesStartMaxWidth = getMaxElemWidth(valuesStart);

        chartElement.append('g')
            .attr('class', 'label start')
            .selectAll('text')
            .data(DATA)
            .enter()
            .append('text')
                .attr('class', function (d, i) {
                    return classify(d.label);
                })
                .attr({
                    x: xScale(startLabel),
                    y: function (d) {
                        return yScale(d.start);
                    },

                    dx: -(valuesStartMaxWidth + (valueGap * 2)),
                    dy: 4,
                    fill: function (d) {
                        return accessibleColorScale(d.label);
                    },
                })
                .text(function (d) {
                    return d.label;
                })
                .call(wrapText, labelWidth, 12);
    }

    var valuesEndMaxWidth = getMaxElemWidth(valuesEnd);

    chartElement.append('g')
        .attr('class', 'label end')
        .selectAll('text')
        .data(DATA)
        .enter()
        .append('text')
            .attr('class', function (d, i) {
                return classify(d.label);
            })
            .attr({
                x: xScale(endLabel),
                y: function (d) {
                    return yScale(d.end);
                },

                dx: valuesEndMaxWidth + (valueGap * 2),
                dy: 4,
                fill: function (d) {
                    return accessibleColorScale(d.label);
                },
            })
            .text(function (d) {
                return d.label;
            })
            .call(wrapText, labelWidth, 12);

    chartElement.selectAll('.value, .label, .lines')
        .attr('transform', 'translate(0,15)');

};

var getMaxElemWidth = function (elems) {
    var maxWidth = 0;
    elems.each(function () {
        var width = d3.select(this).node().getComputedTextLength();
        if (width > maxWidth) {
            maxWidth = width;
        }
    });

    return maxWidth;
};

/*
 * Wrap a block of text to a given width
 * via http://bl.ocks.org/mbostock/7555321
 */
var wrapText = function (texts, width, lineHeight) {
    texts.each(function () {
        var text = d3.select(this);
        var words = text.text().split(/\s+/).reverse();

        var word = null;
        var line = [];
        var lineNumber = 0;

        var x = text.attr('x');
        var y = text.attr('y');

        var dx = parseFloat(text.attr('dx') || 0);
        var dy = parseFloat(text.attr('dy') || 0);

        var tspan = text.text(null)
            .append('tspan')
            .attr({
                x: x,
                dx: dx,
                dy: dy,
            });

        while (word = words.pop()) {
            line.push(word);
            tspan.text(line.join(' '));

            if (tspan.node().getComputedTextLength() > width) {
                line.pop();
                tspan.text(line.join(' '));
                line = [word];

                lineNumber += 1;

                tspan = text.append('tspan')
                    .attr({
                        x: x,
                        dx: dx,
                        dy: (dy + (lineNumber * lineHeight)),
                    })
                    .text(word);
            }
        }
    });
};

/*
 * Select an element and move it to the front of the stack
 */
d3.selection.prototype.moveToFront = function () {
    return this.each(function () {
        this.parentNode.appendChild(this);
    });
};

/*
 * Initially load the graphic
 * (NB: Use window.load to ensure all images have loaded)
 */
window.onload = onWindowLoaded;
<commit_msg>Group labels with the same values<commit_after>// Global vars
var pymChild = null;
var isMobile = false;

/*
 * Initialize graphic
 */
var onWindowLoaded = function () {
    if (Modernizr.svg) {
        formatData();

        pymChild = new pym.Child({
            renderCallback: render,
        });
    } else {
        pymChild = new pym.Child({});
    }
};

/*
 * Format graphic data for processing by D3.
 */
var formatData = function () {
    DATA.forEach(function (d) {
        d.start = +d.start;
        d.end = +d.end;
    });
};

/*
 * Render the graphic(s). Called by pym with the container width.
 */
var render = function (containerWidth) {
    containerWidth = containerWidth || DEFAULT_WIDTH;
    isMobile = (containerWidth <= MOBILE_THRESHOLD);

    // Render the chart!
    renderSlopegraph();

    // Update iframe
    if (pymChild) {
        pymChild.sendHeight();
    }
};

/*
 * Render a line chart.
 */
var renderSlopegraph = function () {
    /*
     * Setup
     */
    var startLabel = LABELS.start_label;
    var endLabel = LABELS.end_label;

    var aspectRatio = getAspectRatio(LABELS.ratio, {
        base: 3 / 2,
        mobile: 2 / 3,
    });

    var margins = {
        top: parseInt(LABELS.marginTop || 20, 10),
        right: parseInt(LABELS.marginRight || 30, 10),
        bottom: parseInt(LABELS.marginBottom || 20, 10),
        left: parseInt(LABELS.marginLeft || 30, 10),
    };

    var labelWidth = parseInt(LABELS.labelWidth || 80, 10);
    var valueGap = parseInt(LABELS.valueGap || 6, 10);

    // Clear existing graphic (for redraw)
    var containerElement = d3.select('#slopegraph');
    containerElement.html('');

    /*
     * Create the root SVG element.
     */
    var chartWrapper = containerElement.append('div')
        .attr('class', 'graphic-wrapper');

    // Calculate actual chart dimensions
    var innerWidth = chartWrapper.node().getBoundingClientRect().width;
    var horizMargins = margins.left + margins.right;
    var vertMargins = margins.top + margins.bottom;
    var labelAndGapWidth = labelWidth + valueGap;
    var noOfLabelCols = isMobile ? 1 : 2;
    var chartWidth = innerWidth - horizMargins - (labelAndGapWidth * noOfLabelCols);
    var chartHeight = Math.ceil(innerWidth / aspectRatio) - vertMargins;

    /*
     * Create D3 scale objects.
     */

    var xLabels = [startLabel, endLabel];

    var xScale = d3.scale.ordinal()
        .domain(xLabels)
        .range([0, chartWidth]);

    var minY = d3.min(DATA, function (d) {
        return Math.min(d.start, d.end);
    });

    var maxY = d3.max(DATA, function (d) {
        return Math.max(d.start, d.end);
    });

    var yScale = d3.scale.linear()
        .domain([minY, maxY])
        .range([chartHeight, 0]);

    var labelScale = d3.scale.ordinal()
        .domain(DATA.map(function (d) {
            return d.label;
        }));

    var colorList = colorArray(LABELS, MONOCHROMECOLORS);
    var colorScale = labelScale.copy()
        .range(colorList);

    var accessibleColorScale = labelScale.copy()
        .range(colorList.map(function (color) {
            return getAccessibleColor(color);
        }));

    var leftOffset = isMobile ? margins.left : margins.left + labelAndGapWidth;

    var chartElement = chartWrapper.append('svg')
        .attr({
            width: chartWidth + horizMargins + (labelAndGapWidth * noOfLabelCols),
            height: chartHeight + vertMargins,
        })
        .append('g')
            .attr('transform', makeTranslate(leftOffset, margins.top));

    /*
     * Render axes to chart.
     */
    chartWrapper.selectAll('svg').append('g')
        .attr('class', 'x axis')
        .selectAll('text')
        .data(xLabels)
        .enter()
        .append('text')
            .style('text-anchor', function (d, i) {
                if (i) {
                    return 'end';
                }
            })
            .attr('x', function (d, i) {
                if (i) {
                    return innerWidth;
                }
            })
            .text(function (d) {
                return d;
            });

    /*
     * Render lines to chart.
     */
    chartElement.append('g')
        .attr('class', 'lines')
        .selectAll('line')
        .data(DATA)
        .enter()
        .append('line')
            .attr('class', function (d, i) {
                return 'line ' + classify(d.label);
            })
            .attr({
                x1: xScale(startLabel),
                y1: function (d) {
                    return yScale(d.start);
                },

                x2: xScale(endLabel),
                y2: function (d) {
                    return yScale(d.end);
                },
            })
            .style('stroke', function (d) {
                return colorScale(d.label);
            });

    /*
     * Uncomment if needed:
     * Move a particular line to the front of the stack
     */

    // svg.select('line.unaffiliated').moveToFront();

    var DATA_GROUPED_START = d3.nest()
        .key(function (d) { return d.start; })
        .entries(DATA.sort(function (a, b) { // sort by start value descending
            return b.start - a.start;
        }));

    var DATA_GROUPED_END = d3.nest()
        .key(function (d) { return d.end; })
        .entries(DATA.sort(function (a, b) { // sort by end value descending
            return b.end - a.end;
        }));

    /*
     * Render values.
     */
    var valuesStart = chartElement.append('g')
        .attr('class', 'value start')
        .selectAll('text')
        .data(DATA_GROUPED_START)
        .enter()
        .append('text')
            .attr('class', function (d) {
                return d.values.map(function (v) {
                    return classify(v.label);
                }).join(' ');
            })
            .attr({
                x: xScale(startLabel),
                y: function (d) {
                    return yScale(d.values[0].start);
                },

                dx: -valueGap,
                dy: 4,
                fill: function (d) {
                    return accessibleColorScale(d.values[0].label);
                },
            })
            .text(function (d) {
                return formattedNumber(
                    d.values[0].start,
                    LABELS.valuePrefix,
                    LABELS.valueSuffix,
                    LABELS.maxDecimalPlaces
                );
            });

    var valuesEnd = chartElement.append('g')
        .attr('class', 'value end')
        .selectAll('text')
        .data(DATA_GROUPED_END)
        .enter()
        .append('text')
            .attr('class', function (d) {
                return d.values.map(function (v) {
                    return classify(v.label);
                }).join(' ');
            })
            .attr({
                x: xScale(endLabel),
                y: function (d) {
                    return yScale(d.values[0].end);
                },

                dx: valueGap,
                dy: 4,
                fill: function (d) {
                    return accessibleColorScale(d.values[0].label);
                },
            })
            .text(function (d) {
                return formattedNumber(
                    d.values[0].end,
                    LABELS.valuePrefix,
                    LABELS.valueSuffix,
                    LABELS.maxDecimalPlaces
                );
            });

    /*
     * Render labels.
     */
    if (!isMobile) {
        // get the width of the widest start value
        var valuesStartMaxWidth = getMaxElemWidth(valuesStart);

        chartElement.append('g')
            .attr('class', 'label start')
            .selectAll('text')
            .data(DATA_GROUPED_START)
            .enter()
            .append('g')
                .attr('transform', function (d) {
                    var x = xScale(startLabel) - (valuesStartMaxWidth + (valueGap * 2));
                    var y = yScale(d.values[0].start) + 4;
                    return 'translate(' + x + ', ' + y + ')';
                })
                .each(function (d) {
                    var g = d3.select(this);
                    d.values.forEach(function (v, i) {
                        g.append('text')
                            .attr('class', classify(v.label))
                            .attr({
                                x: 0,
                                fill: accessibleColorScale(v.label),
                            })
                            .text(v.label)
                            .call(wrapText, labelWidth, '1.1em')
                            .attr({
                                y: function () {
                                    if (i === 0) {
                                        return 0;
                                    }

                                    var yOffset = 0;
                                    g.selectAll('text').each(function (t, j) {
                                        if (j < i) {
                                            yOffset = yOffset + this.clientHeight;
                                        }
                                    });

                                    return yOffset;
                                },
                            });

                    });
                });
    }

    // get the width of the widest end value
    var valuesEndMaxWidth = getMaxElemWidth(valuesEnd);

    chartElement.append('g')
        .attr('class', 'label end')
        .selectAll('text')
        .data(DATA_GROUPED_END)
        .enter()
        .append('g')
            .attr('transform', function (d) {
                var x = xScale(endLabel) + valuesEndMaxWidth + (valueGap * 2);
                var y = yScale(d.values[0].end) + 4;
                return 'translate(' + x + ', ' + y + ')';
            })
            .each(function (d) {
                var g = d3.select(this);
                d.values.forEach(function (v, i) {
                    g.append('text')
                        .attr('class', classify(v.label))
                        .attr({
                            x: 0,
                            fill: accessibleColorScale(v.label),
                        })
                        .text(v.label)
                        .call(wrapText, labelWidth, '1.1em')
                        .attr({
                            y: function () {
                                if (i === 0) {
                                    return 0;
                                }

                                var yOffset = 0;
                                g.selectAll('text').each(function (t, j) {
                                    if (j < i) {
                                        yOffset = yOffset + this.clientHeight;
                                    }
                                });

                                return yOffset;
                            },
                        });
                });
            });

    chartElement.selectAll('.value, .label, .lines')
        .attr('transform', 'translate(0,15)');

};

var getMaxElemWidth = function (elems) {
    var maxWidth = 0;
    elems.each(function () {
        var width = d3.select(this).node().getComputedTextLength();
        if (width > maxWidth) {
            maxWidth = width;
        }
    });

    return maxWidth;
};

/*
 * Wrap a block of text to a given width
 * via http://bl.ocks.org/mbostock/7555321
 */
var wrapText = function (texts, width, lineHeight) {
    texts.each(function () {
        var text = d3.select(this);
        var words = text.text().split(/\s+/).reverse();

        var word = null;
        var line = [];
        var lineNumber = 0;

        var x = text.attr('x');
        var y = text.attr('y');

        var dx = parseFloat(text.attr('dx') || 0);
        var dy = parseFloat(text.attr('dy') || 0);

        var tspan = text.text(null)
            .append('tspan')
            .attr({
                x: x,
                dx: dx,
                dy: dy,
            });

        while (word = words.pop()) {
            line.push(word);
            tspan.text(line.join(' '));

            if (tspan.node().getComputedTextLength() > width) {
                line.pop();
                tspan.text(line.join(' '));
                line = [word];

                lineNumber += 1;

                tspan = text.append('tspan')
                    .attr({
                        x: x,
                        dx: dx,
                        dy: lineNumber ? lineHeight : 0,
                    })
                    .text(word);
            }
        }
    });
};

/*
 * Select an element and move it to the front of the stack
 */
d3.selection.prototype.moveToFront = function () {
    return this.each(function () {
        this.parentNode.appendChild(this);
    });
};

/*
 * Initially load the graphic
 * (NB: Use window.load to ensure all images have loaded)
 */
window.onload = onWindowLoaded;
<|endoftext|>


<commit_before>import CartoNode from 'carto-node';
import toObject from 'new-dashboard/utils/to-object';
import Filters, { defaultParams as filtersDefaultParams } from 'new-dashboard/core/filters';

const client = new CartoNode.AuthenticatedClient();

const datasets = {
  namespaced: true,
  state: {
    isFetching: false,
    isFiltered: false,
    isErrored: false,
    error: {},
    filterType: 'mine',
    order: 'updated_at',
    list: {},
    metadata: {},
    page: 1,
    numPages: 1
  },
  mutations: {
    setRequestError (state, error) {
      state.isFetching = false;
      state.isErrored = true;
      state.error = error;
    },

    setDatasets (state, datasets) {
      state.list = toObject(datasets.visualizations, 'id');
      state.metadata = {
        total_entries: datasets.total_entries,
        total_likes: datasets.total_likes,
        total_shared: datasets.total_shared,
        total_user_entries: datasets.total_user_entries
      };

      state.isFetching = false;
    },

    setFetchingState (state) {
      state.isFetching = true;
      state.isErrored = false;
      state.error = {};
    },

    setURLOptions (state, options) {
      state.page = options.page ? parseInt(options.page) : 1;
      state.filterType = options.filter || 'mine';
    },

    setPagination (state, page) {
      state.page = page;
      state.numPages = Math.ceil(state.metadata.total_entries / filtersDefaultParams.per_page) || 1;
    },

    updateLike (state, {datasetId, liked}) {
      state.list[datasetId].liked = liked;
    },
    updateNumberLikes (state, {datasetId, likes}) {
      state.list[datasetId].likes = likes;
    }
  },
  actions: {
    fetchDatasets (context) {
      context.commit('setFetchingState');

      const params = {
        ...Filters[context.state.filterType],
        types: 'table',
        page: context.state.page,
        order: context.state.order
      };

      client.getVisualization('',
        params,
        function (err, _, data) {
          if (err) {
            context.commit('setRequestError', err);
            return;
          }
          context.commit('setDatasets', data);
          context.commit('setPagination', context.state.page);
        });
    },

    like (context, dataset) {
      const currentLikeStatus = dataset.liked;
      context.commit('updateLike', { datasetId: dataset.id, liked: true });
      client.like(dataset.id,
        function (err, _, data) {
          if (err) {
            context.commit('updateLike', { datasetId: dataset.id, liked: currentLikeStatus });
            return;
          }
          context.commit('updateNumberLikes', { datasetId: dataset.id, likes: data.likes });
        }
      );
    },
    deleteLike (context, dataset) {
      const currentLikeStatus = dataset.liked;
      context.commit('updateLike', { datasetId: dataset.id, liked: false });
      client.deleteLike(dataset.id,
        function (err, _, data) {
          if (err) {
            context.commit('updateLike', { datasetId: dataset.id, liked: currentLikeStatus });
            return;
          }
          context.commit('updateNumberLikes', { datasetId: dataset.id, likes: data.likes });
        }
      );
    },

    setURLOptions (context, options) {
      context.commit('setURLOptions', options);
      context.dispatch('fetchDatasets');
    }
  }
};

export default datasets;
<commit_msg>Fix trailing space<commit_after>import CartoNode from 'carto-node';
import toObject from 'new-dashboard/utils/to-object';
import Filters, { defaultParams as filtersDefaultParams } from 'new-dashboard/core/filters';

const client = new CartoNode.AuthenticatedClient();

const datasets = {
  namespaced: true,
  state: {
    isFetching: false,
    isFiltered: false,
    isErrored: false,
    error: {},
    filterType: 'mine',
    order: 'updated_at',
    list: {},
    metadata: {},
    page: 1,
    numPages: 1
  },
  mutations: {
    setRequestError (state, error) {
      state.isFetching = false;
      state.isErrored = true;
      state.error = error;
    },

    setDatasets (state, datasets) {
      state.list = toObject(datasets.visualizations, 'id');
      state.metadata = {
        total_entries: datasets.total_entries,
        total_likes: datasets.total_likes,
        total_shared: datasets.total_shared,
        total_user_entries: datasets.total_user_entries
      };

      state.isFetching = false;
    },

    setFetchingState (state) {
      state.isFetching = true;
      state.isErrored = false;
      state.error = {};
    },

    setURLOptions (state, options) {
      state.page = options.page ? parseInt(options.page) : 1;
      state.filterType = options.filter || 'mine';
    },

    setPagination (state, page) {
      state.page = page;
      state.numPages = Math.ceil(state.metadata.total_entries / filtersDefaultParams.per_page) || 1;
    },

    updateLike (state, {datasetId, liked}) {
      state.list[datasetId].liked = liked;
    },

    updateNumberLikes (state, {datasetId, likes}) {
      state.list[datasetId].likes = likes;
    }
  },
  actions: {
    fetchDatasets (context) {
      context.commit('setFetchingState');

      const params = {
        ...Filters[context.state.filterType],
        types: 'table',
        page: context.state.page,
        order: context.state.order
      };

      client.getVisualization('',
        params,
        function (err, _, data) {
          if (err) {
            context.commit('setRequestError', err);
            return;
          }
          context.commit('setDatasets', data);
          context.commit('setPagination', context.state.page);
        });
    },

    like (context, dataset) {
      const currentLikeStatus = dataset.liked;
      context.commit('updateLike', { datasetId: dataset.id, liked: true });
      client.like(dataset.id,
        function (err, _, data) {
          if (err) {
            context.commit('updateLike', { datasetId: dataset.id, liked: currentLikeStatus });
            return;
          }
          context.commit('updateNumberLikes', { datasetId: dataset.id, likes: data.likes });
        }
      );
    },
    deleteLike (context, dataset) {
      const currentLikeStatus = dataset.liked;
      context.commit('updateLike', { datasetId: dataset.id, liked: false });
      client.deleteLike(dataset.id,
        function (err, _, data) {
          if (err) {
            context.commit('updateLike', { datasetId: dataset.id, liked: currentLikeStatus });
            return;
          }
          context.commit('updateNumberLikes', { datasetId: dataset.id, likes: data.likes });
        }
      );
    },

    setURLOptions (context, options) {
      context.commit('setURLOptions', options);
      context.dispatch('fetchDatasets');
    }
  }
};

export default datasets;
<|endoftext|>


<commit_before>var APIEndPoint = "http://api.sunrise-sunset.org/json?"
var date;

$(document).ready(function() {
	// Put your code in here!
    updateTime();
    getLocation();
    window.setInterval(updateTime, 1000);
    window.setInterval(getLocation, 1000*60);
});

function updateTime() {
    date = new moment();
    date.local();

	$("#date_section #day_of_week").text(moment(date).format("ddd. h:mm:ss A"));
	$("#date_section #date").text(moment(date).format("MMMM DD, YYYY"));
}

function getLocation() {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(getSunPosFromAPI);
    } else {
    	displayError({ "errorTitle": "Sorry", "errorText": "Geolocation is not supported by this browser."});
    }
}

function showPosition(position) {

    var innerHTML = "Latitude: " + position.coords.latitude +
    "
Longitude: " + position.coords.longitude;

    $("#content").html("
"+innerHTML+"
");
}

function getSunPosFromAPI(position) {
    $.getJSON(APIEndPoint + "lat=" + position.coords.latitude + "&lng=" + position.coords.longitude + "&date=today" + "&callback=?")
    .done(parseData)
    .fail(getAPIError);
}

function getAPIError() {
    displayError({ "errorTitle": "Sorry", "errorText": "Refresh Me! - Service Temporarily Unavailable"});
}

function parseData(data) {
    var sunriseDate = getLocalDateFromUTCDate(data["results"]["sunrise"]);
    var noonDate = getLocalDateFromUTCDate(data["results"]["solar_noon"]);
    var sunsetDate = getLocalDateFromUTCDate(data["results"]["sunset"]);

    $("#sun-rise .time").text(moment(sunriseDate).format("h:mm:ss A"));
    $("#noon .time").text(moment(noonDate).format("h:mm:ss A"));
    $("#sun-set .time").text(moment(sunsetDate).format("h:mm:ss A"));

    loadSunPos(sunriseDate, sunsetDate);

    $("#content").css("display","inline");
    $("#loading").css("display","none");
}

function loadSunPos(sunriseDate, sunsetDate) {
    var timeNow = moment();
    timeNow.local();
    nowMinute = timeNow.hours() * 60 + timeNow.minutes();
    sunriseMinute = sunriseDate.hours() * 60 + sunriseDate.minutes();
    sunsetMinute = sunsetDate.hours() * 60 + sunsetDate.minutes();

    var progress = (((nowMinute - sunriseMinute) / (sunsetMinute - sunriseMinute)) * 87) + 3;

    if (progress < 3) {
        progress = 3;
    } else if (progress > 87) {
        position = 87;
    }

    $("#sun-img").css("margin-left", progress+"%");

    $
}

//helper functions
function displayError(errorInfo) {
    var item_html = $("#error-prototype").html();
    var innerHTML = Mustache.render(item_html, errorInfo);
    $("#content").html(innerHTML);
    $("#content").css("display","inline");
    $("#loading").css("display","none");
}

function getLocalDateFromUTCDate(utcDateString) {
    var offsetHours = date.utcOffset() / 60;
    var localDate = new moment(utcDateString, "h:mm:ss A");

    localDate = localDate.add(-offsetHours, 'hours');

    return localDate;
}
<commit_msg>Fix moment call<commit_after>var APIEndPoint = "http://api.sunrise-sunset.org/json?"
var date;

$(document).ready(function() {
	// Put your code in here!
    updateTime();
    getLocation();
    window.setInterval(updateTime, 1000);
    window.setInterval(getLocation, 1000*60);
});

function updateTime() {
    date = new moment();
    date.local();

	$("#date_section #day_of_week").text(moment(date).format("ddd. h:mm:ss A"));
	$("#date_section #date").text(moment(date).format("MMMM DD, YYYY"));
}

function getLocation() {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(getSunPosFromAPI);
    } else {
    	displayError({ "errorTitle": "Sorry", "errorText": "Geolocation is not supported by this browser."});
    }
}

function showPosition(position) {

    var innerHTML = "Latitude: " + position.coords.latitude +
    "
Longitude: " + position.coords.longitude;

    $("#content").html("
"+innerHTML+"
");
}

function getSunPosFromAPI(position) {
    $.getJSON(APIEndPoint + "lat=" + position.coords.latitude + "&lng=" + position.coords.longitude + "&date=today" + "&callback=?")
    .done(parseData)
    .fail(getAPIError);
}

function getAPIError() {
    displayError({ "errorTitle": "Sorry", "errorText": "Refresh Me! - Service Temporarily Unavailable"});
}

function parseData(data) {
    var sunriseDate = getLocalDateFromUTCDate(data["results"]["sunrise"]);
    var noonDate = getLocalDateFromUTCDate(data["results"]["solar_noon"]);
    var sunsetDate = getLocalDateFromUTCDate(data["results"]["sunset"]);

    $("#sun-rise .time").text(moment(sunriseDate).format("h:mm:ss A"));
    $("#noon .time").text(moment(noonDate).format("h:mm:ss A"));
    $("#sun-set .time").text(moment(sunsetDate).format("h:mm:ss A"));

    loadSunPos(sunriseDate, sunsetDate);

    $("#content").css("display","inline");
    $("#loading").css("display","none");
}

function loadSunPos(sunriseDate, sunsetDate) {
    var timeNow = moment();
    timeNow.local();
    nowMinute = timeNow.hours() * 60 + timeNow.minutes();
    sunriseMinute = sunriseDate.hours() * 60 + sunriseDate.minutes();
    sunsetMinute = sunsetDate.hours() * 60 + sunsetDate.minutes();

    var progress = (((nowMinute - sunriseMinute) / (sunsetMinute - sunriseMinute)) * 87) + 3;

    if (progress < 3) {
        progress = 3;
    } else if (progress > 87) {
        position = 87;
    }

    $("#sun-img").css("margin-left", progress+"%");

    $
}

//helper functions
function displayError(errorInfo) {
    var item_html = $("#error-prototype").html();
    var innerHTML = Mustache.render(item_html, errorInfo);
    $("#content").html(innerHTML);
    $("#content").css("display","inline");
    $("#loading").css("display","none");
}

function getLocalDateFromUTCDate(utcDateString) {
    var offsetHours = date.zone() / 60;
    var localDate = new moment(utcDateString, "h:mm:ss A");

    localDate = localDate.add(-offsetHours, 'hours');

    return localDate;
}
<|endoftext|>