<commit_before>import utils from "./utils";

// Dependencies
var R        = require("ramda");
var BPromise = require("bluebird");
var path     = require("path");
var fs       = BPromise.promisifyAll(require("fs"));
var stripJsonComments = require("strip-json-comments");

// Log
var chalk = require('chalk');

export class Asana2Pivotal {
  constructor(options) {
    options = R.merge({
      from  : 'debug.json',
      to    : 'normalized.json',
      config: 'map.json'
    }, options);

    if (options.verbose) {
      utils.verbose = options.verbose;
    }

    options.from   = path.resolve(process.cwd(), options.from);
    options.to     = path.resolve(process.cwd(), options.to);
    options.config = path.resolve(process.cwd(), options.config);

    this.map     = this.readMapFile(options.config);
    this.options = options;
  }

  readMapFile(filepath) {
    filepath = filepath || this.options.map;
    var content;

    try {
      content = stripJsonComments(fs.readFileSync(filepath).toString());
      content = JSON.parse(content);
    } catch (e) {
      throw e;
    }
    return content;
  }

  run() {
    return BPromise.coroutine(function* () {
      var workspace, json, stories;

      json = yield this.readFile();
      json = this.replaceUsers(json);

      workspace = JSON.parse(json);

      if (R.is(Object, workspace) && !R.isEmpty(workspace.tasks)) {
        stories = workspace.tasks.map(this.taskToStorie.bind(this));
      }

      var normalized_json = JSON.stringify(stories, null, 2);
      this.saveFile(normalized_json);

      return stories;
    }.bind(this))();
  }

  readFile(filepath) {
    filepath = filepath || this.options.from;
    return fs.readFileAsync(filepath)
      .then(function (data) {
        utils.log("Successful read file " + chalk.green(filepath));
        return data.toString();
      })
      .catch(BPromise.OperationalError, function (e) {
        console.error("unable to read file, because: ", e.message);
      });
  }

  saveFile(json) {
    var filepath = this.options.to;
    fs.writeFileAsync(filepath, json)
      .then(function() {
        utils.log("Successful saved file " + chalk.green(filepath));
      });
  }

  replaceUsers(json) {
    var asana_ids = Object.keys(this.map.users);

    for (var i = 0; asana_ids.length > i; i++) {
      var user_id = asana_ids[i];
      var user    = this.map.users[user_id];

      // Mention Replaces
      var url   = 'https://app.asana.com/0/' + user.mention_id + '/' + user.mention_id;
      var regex = new RegExp(url, "gm");
      json = json.replace(regex, '@' + user.username);

      // UserID replace
      regex = new RegExp(user_id, "gm");
      json  = json.replace(regex, user.pivotal_id);
    }

    return json;
  }

  projectMap(task) {
    var projectMaped = this.map.defaults.projects;

    if (!R.isEmpty(task.projects) && !R.isEmpty(task.projects[0])) {
      projectMaped = this.map.projects[task.projects[0].id] || projectMaped;
    }

    // Replaces the state based in section
    var membership = R.find(R.prop('section'))(task.memberships);
    var section    = (membership && membership.section.name);
    if (!R.isNil(section) && this.map.sections.hasOwnProperty(section)) {
      var sectionMaped = this.map.sections[section];
      if (!R.isNil(sectionMaped)) {
        if (sectionMaped.hasOwnProperty("state")) {
          projectMaped.state = sectionMaped.state;
        }
        if (sectionMaped.hasOwnProperty("labels") && R.isArrayLike(sectionMaped.labels)) {
          projectMaped.labels = projectMaped.labels.concat(sectionMaped.labels);
        }
      }
    }

    return projectMaped;
  }

  taskToStorie(task) {
    var projectMaped = this.projectMap(task);
    var comments     = this.comments(task);
    var assignee     = (task.assignee) ? [task.assignee] : [];
    var labels       = projectMaped.labels.concat(task.tags);

    var [subtasks, owners, subtasks_comments] = this.subtasksToTasks(task.subtasks);
    labels = R.map((label) => {
      if (R.is(Object, label) && label.hasOwnProperty('name')) {
        label = label.name;
      } else if (!R.is(String, label)) {
        label = null;
      }
      return label;
    }, labels);

    // array of object to array of ids
    var owner_ids = R.map((owner) => owner.id, assignee.concat(owners));

    // Clean duplicated and limit to three owners.
    owner_ids = R.slice(0, 3)(R.uniq(owner_ids));
    labels = R.uniq(labels);

    // clean nil or empty
    labels = R.filter(((label) => !R.isNil(label) && !R.isEmpty(label)), labels);

    // Clean invalid person_id in comments
    var user_keys   = Object.keys(this.map.users);
    var user_values = Object.values(this.map.users);
    var removeInvalidPerson_ids = (comment) => {
      if (comment.person_id) {
        var result = R.contains(comment.person_id)(user_keys);
        if (!result) {
          var filterPersonId = R.propEq('pivotal_id', (comment.person_id || '').toString());
          var pivotal_user   = R.find(filterPersonId)(user_values);

          if (!pivotal_user) {
            delete(comment.person_id);
          }
        }
      }
      return comment;
    };
    comments = R.map(removeInvalidPerson_ids, comments.concat(subtasks_comments));

    var story = {
      name         : task.name,
      labels       : labels,
      description  : task.notes,
      project_id   : projectMaped.pivotal_id,
      current_state: projectMaped.state,
      tasks        : subtasks,
      owner_ids    : owner_ids,
      comments     : comments
    };

    if (!R.isNil(task.due_on)) {
      story.deadline   = (new Date(task.due_on)).toISOString();
      story.story_type = "release";
    }

    return story;
  }

  subtasksToTasks(tasks) {
    var assignees     = [];
    var descriptions  = [];
    var normalize = function(subtask) {
      if (!R.isEmpty(subtask.notes)) {
        descriptions.push({
          text: '`[' + subtask.name + ']:`' + subtask.notes
        });
      }

      if (subtask.assignee) { assignees.push(subtask.assignee); }

      return {
        description: subtask.name,
        complete   : !!subtask.completed
      };
    };
    var subtasks = R.map(normalize, tasks);
    return [subtasks, assignees, descriptions];
  }

  comments(task) {
    // stories (comments)
    var normalize = function(storie) {
      return {
        text: storie.text,
        person_id: storie.created_by.id
      };
    };
    var stories = R.map(normalize, (task.stories || []));

    // attachments
    var attachments = R.map(((attach) => {
      return {
        name: attach.name,
        url : attach.download_url
      };
    }), (task.attachments || []));
    attachments = (!R.isEmpty(attachments)) ? [{ file_attachments: attachments }] : [];

    return attachments.concat(stories);
  }
}
<commit_msg>[Normalize] Fixing persisten label of others tasks;<commit_after>import utils from "./utils";

// Dependencies
var R        = require("ramda");
var BPromise = require("bluebird");
var path     = require("path");
var fs       = BPromise.promisifyAll(require("fs"));
var stripJsonComments = require("strip-json-comments");

// Log
var chalk = require('chalk');

export class Asana2Pivotal {
  constructor(options) {
    options = R.merge({
      from  : 'debug.json',
      to    : 'normalized.json',
      config: 'map.json'
    }, options);

    if (options.verbose) {
      utils.verbose = options.verbose;
    }

    options.from   = path.resolve(process.cwd(), options.from);
    options.to     = path.resolve(process.cwd(), options.to);
    options.config = path.resolve(process.cwd(), options.config);

    this.map     = this.readMapFile(options.config);
    this.options = options;
  }

  readMapFile(filepath) {
    filepath = filepath || this.options.map;
    var content;

    try {
      content = stripJsonComments(fs.readFileSync(filepath).toString());
      content = JSON.parse(content);
    } catch (e) {
      throw e;
    }
    return content;
  }

  run() {
    return BPromise.coroutine(function* () {
      var workspace, json, stories;

      json = yield this.readFile();
      json = this.replaceUsers(json);

      workspace = JSON.parse(json);

      if (R.is(Object, workspace) && !R.isEmpty(workspace.tasks)) {
        var old_length = workspace.tasks.length;
        utils.log("  Normalize", chalk.green(workspace.tasks.length), "tasks");
        workspace.tasks = R.filter((task) => !R.isNil(task), workspace.tasks);
        utils.log("  Remove", chalk.green(old_length - workspace.tasks.length), "empty tasks");
        stories = workspace.tasks.map(this.taskToStorie.bind(this));
      }

      utils.log("  " + chalk.green(stories.length), chalk.blue("normalized stories"));
      var normalized_json = JSON.stringify(stories, null, 2);
      this.saveFile(normalized_json);

      return stories;
    }.bind(this))();
  }

  readFile(filepath) {
    filepath = filepath || this.options.from;
    return fs.readFileAsync(filepath)
      .then(function (data) {
        utils.log("Successful read file " + chalk.green(filepath));
        return data.toString();
      })
      .catch(BPromise.OperationalError, function (e) {
        console.error("unable to read file, because: ", e.message);
      });
  }

  saveFile(json) {
    var filepath = this.options.to;
    fs.writeFileAsync(filepath, json)
      .then(function() {
        utils.log("Successful saved file " + chalk.green(filepath));
      });
  }

  replaceUsers(json) {
    var asana_ids = Object.keys(this.map.users);

    for (var i = 0; asana_ids.length > i; i++) {
      var user_id = asana_ids[i];
      var user    = this.map.users[user_id];

      // Mention Replaces
      var url   = 'https://app.asana.com/0/' + user.mention_id + '/' + user.mention_id;
      var regex = new RegExp(url, "gm");
      json = json.replace(regex, '@' + user.username);

      // UserID replace
      regex = new RegExp(user_id, "gm");
      json  = json.replace(regex, user.pivotal_id);
    }

    return json;
  }

  projectMap(task) {
    var projectMaped = R.clone(this.map.defaults.projects);

    console.log('task:', task);
    if (!R.isEmpty(task.projects) && !R.isEmpty(task.projects[0])) {
      projectMaped = R.clone(this.map.projects[task.projects[0].id]) || projectMaped;
    }

    // Replaces the state based in section
    var membership = R.find(R.prop('section'))(task.memberships);
    var section    = (membership && membership.section.name);
    if (!R.isNil(section) && this.map.sections.hasOwnProperty(section)) {
      var sectionMaped = R.clone(this.map.sections[section]);
      if (!R.isNil(sectionMaped)) {
        if (sectionMaped.hasOwnProperty("state")) {
          projectMaped.state = sectionMaped.state;
        }
        if (sectionMaped.hasOwnProperty("labels") && R.isArrayLike(sectionMaped.labels)) {
          projectMaped.labels = projectMaped.labels.concat(sectionMaped.labels);
        }
      }
    }

    return projectMaped;
  }

  taskToStorie(task) {
    var projectMaped = this.projectMap(task);
    var comments     = this.comments(task);
    var assignee     = (task.assignee) ? [task.assignee] : [];
    var labels       = projectMaped.labels.concat(task.tags);

    var [subtasks, owners, subtasks_comments] = this.subtasksToTasks(task.subtasks);

    labels = R.map((label) => {
      if (R.is(Object, label) && label.hasOwnProperty('name')) {
        label = label.name;
      } else if (!R.is(String, label)) {
        label = null;
      }
      return label;
    }, labels);

    // array of object to array of ids
    var owner_ids = R.map((owner) => owner.id, assignee.concat(owners));

    // Clean duplicated and limit to three owners.
    owner_ids = R.slice(0, 3)(R.uniq(owner_ids));
    labels = R.uniq(labels);

    // clean nil or empty
    labels = R.filter(((label) => !R.isNil(label) && !R.isEmpty(label)), labels);

    // Clean invalid person_id in comments
    var user_keys   = Object.keys(this.map.users);
    var user_values = Object.values(this.map.users);
    var removeInvalidPerson_ids = (comment) => {
      if (comment.person_id) {
        var result = R.contains(comment.person_id)(user_keys);
        if (!result) {
          var filterPersonId = R.propEq('pivotal_id', (comment.person_id || '').toString());
          var pivotal_user   = R.find(filterPersonId)(user_values);

          if (!pivotal_user) {
            delete(comment.person_id);
          }
        }
      }
      return comment;
    };
    comments = R.map(removeInvalidPerson_ids, comments.concat(subtasks_comments));

    var story = {
      name         : task.name,
      labels       : labels,
      description  : task.notes,
      project_id   : projectMaped.pivotal_id,
      current_state: projectMaped.state,
      tasks        : subtasks,
      owner_ids    : owner_ids,
      comments     : comments
    };

    if (!R.isNil(task.due_on)) {
      story.deadline   = (new Date(task.due_on)).toISOString();
      story.story_type = "release";
    }

    return story;
  }

  subtasksToTasks(tasks) {
    var assignees     = [];
    var descriptions  = [];
    var normalize = function(subtask) {
      if (!R.isEmpty(subtask.notes)) {
        descriptions.push({
          text: '`[' + subtask.name + ']:`' + subtask.notes
        });
      }

      if (subtask.assignee) { assignees.push(subtask.assignee); }

      return {
        description: subtask.name,
        complete   : !!subtask.completed
      };
    };
    var subtasks = R.map(normalize, tasks);
    return [subtasks, assignees, descriptions];
  }

  comments(task) {
    // stories (comments)
    var normalize = function(storie) {
      return {
        text: storie.text,
        person_id: storie.created_by.id
      };
    };
    var stories = R.map(normalize, (task.stories || []));

    // attachments
    var attachments = R.map(((attach) => {
      return {
        name: attach.name,
        url : attach.download_url
      };
    }), (task.attachments || []));
    attachments = (!R.isEmpty(attachments)) ? [{ file_attachments: attachments }] : [];

    return attachments.concat(stories);
  }
}
<|endoftext|>


<commit_before>module.exports = {
  base: '/',
  head: [['link', { rel: 'icon', href: '/favicon.png' }]],
  port: 8081,
  themeConfig: {
    repo: 'DivanteLtd/vue-storefront',
    docsDir: 'docs',
    editLinks: true,
    sidebarDepth: 3,
    nav: [
      {
        text: 'YouTube',
        link: 'https://www.youtube.com/channel/UCkm1F3Cglty3CE1QwKQUhhg',
      },
      {
        text: 'Medium',
        link: 'https://medium.com/the-vue-storefront-journal',
      },
    ],
    sidebar: {
      '/guide/': [
      	{
          title : 'General Information',
          collapsable: false,
          children: [
            'general/introduction'
          ]
	      },
        'upgrade-notes/',
        {
          title: 'Cookbook',
          collapsable: false,
          children: [
            'cookbook/data-import',
            'cookbook/elastic',
            'cookbook/setup',
            'cookbook/integration',
            'cookbook/extend-module',
            'cookbook/theme',
            'cookbook/common-pitfall',
          ],
        },
        {
          title: 'Installation',
          collapsable: false,
          children: [
            'installation/linux-mac',
            'installation/windows',
            'installation/magento',
            'installation/production-setup',
          ],
        },
        {
          title: 'Basics',
          collapsable: false,
          children: [
            'basics/release-cycle',
            'basics/project-structure',
            'basics/configuration',
            'basics/contributing',
            'basics/feature-list',
            'basics/recipes',
            'basics/typescript',
            'basics/graphql',
            'basics/ssr-cache',
            'basics/amp',
            'basics/e2e',
            'basics/url'
          ],
        },
        {
          title: 'Core and themes',
          collapsable: false,
          children: [
            'core-themes/themes',
            'core-themes/layouts',
            'core-themes/core-components',
            'core-themes/ui-store',
            'core-themes/translations',
            'core-themes/service-workers',
            'core-themes/webpack',
            'core-themes/plugins',
            'core-themes/stylesheets',
          ],
        },
        {
          title: 'Components',
          collapsable: false,
          children: [
            'components/home-page',
            'components/category-page',
            'components/product',
            'components/modal',
            'components/events-list'
          ],
        },
        {
          title: 'Data in Vue Storefront',
          collapsable: false,
          children: [
            'data/data',
            'data/elasticsearch',
            'data/data-migrations',
            'data/elastic-queries',
            'data/database-tool',
            'data/entity-types',
            'data/static-data',
            'data/data-loader'
          ],
        },
        {
          title: 'Extensions',
          collapsable: false,
          children: [
            'extensions/introduction',
            'extensions/extending-api',
            'extensions/extending-server-side-routes',
          ],
        },
        {
          title: 'Working with Vuex',
          collapsable: false,
          children: [
            'vuex/introduction',
            'vuex/vuex-conventions',
            'vuex/product-store',
            'vuex/category-store',
            'vuex/stock-store',
            'vuex/attribute-store',
          ],
        },
        {
          title: 'Modules',
          collapsable: false,
          children: [
            'modules/introduction',
            'modules/cart',
            // 'modules/catalog',
            'modules/user',
            'modules/checkout',
            'modules/order',
            //'modules/review'
          ],
        },
        {
          title: 'Integrations',
          collapsable: false,
          children: [
            'integrations/integrations',
            'integrations/reviews',
            'integrations/payment-gateway',
            'integrations/paypal-payments',
            'integrations/direct-prices-sync',
            'integrations/tier-prices-sync',
            'integrations/totals-sync',
            'integrations/multistore',
          ],
        },
      ],
    },
  },
  title: 'Vue Storefront',
  description: 'Headless PWA for eCommerce',
};
<commit_msg>[docs] fix for vuepress port<commit_after>module.exports = {
  base: '/',
  head: [['link', { rel: 'icon', href: '/favicon.png' }]],
  themeConfig: {
    repo: 'DivanteLtd/vue-storefront',
    docsDir: 'docs',
    editLinks: true,
    sidebarDepth: 3,
    nav: [
      {
        text: 'YouTube',
        link: 'https://www.youtube.com/channel/UCkm1F3Cglty3CE1QwKQUhhg',
      },
      {
        text: 'Medium',
        link: 'https://medium.com/the-vue-storefront-journal',
      },
    ],
    sidebar: {
      '/guide/': [
      	{
          title : 'General Information',
          collapsable: false,
          children: [
            'general/introduction'
          ]
	      },
        'upgrade-notes/',
        {
          title: 'Cookbook',
          collapsable: false,
          children: [
            'cookbook/data-import',
            'cookbook/elastic',
            'cookbook/setup',
            'cookbook/integration',
            'cookbook/extend-module',
            'cookbook/theme',
            'cookbook/common-pitfall',
          ],
        },
        {
          title: 'Installation',
          collapsable: false,
          children: [
            'installation/linux-mac',
            'installation/windows',
            'installation/magento',
            'installation/production-setup',
          ],
        },
        {
          title: 'Basics',
          collapsable: false,
          children: [
            'basics/release-cycle',
            'basics/project-structure',
            'basics/configuration',
            'basics/contributing',
            'basics/feature-list',
            'basics/recipes',
            'basics/typescript',
            'basics/graphql',
            'basics/ssr-cache',
            'basics/amp',
            'basics/e2e',
            'basics/url'
          ],
        },
        {
          title: 'Core and themes',
          collapsable: false,
          children: [
            'core-themes/themes',
            'core-themes/layouts',
            'core-themes/core-components',
            'core-themes/ui-store',
            'core-themes/translations',
            'core-themes/service-workers',
            'core-themes/webpack',
            'core-themes/plugins',
            'core-themes/stylesheets',
          ],
        },
        {
          title: 'Components',
          collapsable: false,
          children: [
            'components/home-page',
            'components/category-page',
            'components/product',
            'components/modal',
            'components/events-list'
          ],
        },
        {
          title: 'Data in Vue Storefront',
          collapsable: false,
          children: [
            'data/data',
            'data/elasticsearch',
            'data/data-migrations',
            'data/elastic-queries',
            'data/database-tool',
            'data/entity-types',
            'data/static-data',
            'data/data-loader'
          ],
        },
        {
          title: 'Extensions',
          collapsable: false,
          children: [
            'extensions/introduction',
            'extensions/extending-api',
            'extensions/extending-server-side-routes',
          ],
        },
        {
          title: 'Working with Vuex',
          collapsable: false,
          children: [
            'vuex/introduction',
            'vuex/vuex-conventions',
            'vuex/product-store',
            'vuex/category-store',
            'vuex/stock-store',
            'vuex/attribute-store',
          ],
        },
        {
          title: 'Modules',
          collapsable: false,
          children: [
            'modules/introduction',
            'modules/cart',
            // 'modules/catalog',
            'modules/user',
            'modules/checkout',
            'modules/order',
            //'modules/review'
          ],
        },
        {
          title: 'Integrations',
          collapsable: false,
          children: [
            'integrations/integrations',
            'integrations/reviews',
            'integrations/payment-gateway',
            'integrations/paypal-payments',
            'integrations/direct-prices-sync',
            'integrations/tier-prices-sync',
            'integrations/totals-sync',
            'integrations/multistore',
          ],
        },
      ],
    },
  },
  title: 'Vue Storefront',
  description: 'Headless PWA for eCommerce',
};
<|endoftext|>


<commit_before>/* global Vue*/
/* global io*/
/* global $*/
'use strict';
var socket = io.connect(GLOBAL.url);

var test = new Vue({
    el: '#content',
    data: {
        error : GLOBAL.error,
        players : [], //tableau des joueurs (token, username, points)
        nbUsersMax : '',
        nbUsersConnectes : 0,
        nbQuestions : '',
        pageQRCode :  '', //lien du QRcode (page admin-room ou room)
        timerQuestion : '',
        timerDebutPartie : 30,
        affichageExplication : false,
        affichageInfos : true,
        infos : '',
        affichageScore : false,
        affichageReponse1 : true, //gestion de l'animation pour afficher la bonne reponse
        affichageReponse2 : true, //gestion de l'animation pour afficher la bonne reponse
        affichageReponse3 : true, //gestion de l'animation pour afficher la bonne reponse
        affichageReponse4 : true, //gestion de l'animation pour afficher la bonne reponse
        tempsDeTransition : 8000, //temps entre affichage de la réponse et debut de la question suivante
        instructions : '', //Instructions afficher sur la page dashboard
        eventQuestion : '',
        eventTimerAvantDebutPartie : '',
        state: {
            loading : false,
            step : '' //waitParam, waitPlayer, waitGame, game, result
        },
        question: {} //tableau des questions (idquestion, question, reponse1, reponse2, reponse3, reponse4, good, explication)
    },
    ready: function() {

        this.pageQRCode = 'admin-room';
        this.state.loading = true;
        this.state.step = 'waitParam';

        this.instructions = 'Scanne ce QR Code pour parametrer la partie.',
        $('#content').show();

        var that = this;

        //socket ajout d'un joueur dans le salon
        socket.on('new-user-' + GLOBAL.token, function(data) {
            that.nbUsersConnectes = that.nbUsersConnectes + 1;
            that.players.push({token:data['usertoken'], username:data['user'],points:0}); //ajout d'un player
            that.players.splice(0,1);   //suppression d'un joueur "attente"
        }),

        //socket création d'une partie avec les params que l'utilisateur a saisi.
        socket.on('create-room-' + GLOBAL.token, function(data) {
            that.nbUsersMax = parseInt(data.nbUsersMax);
            that.nbQuestions = parseInt(data.nbQuestions);
            that.timerQuestion = parseInt(data.timerQuestion);

            for (var i = 1; i <= that.nbUsersMax ; i++) {
                that.players.push({token:'attente', username:'attente'});
            }
            that.pageQRCode = 'access-room';
            that.instructions = 'Scanne ce QR Code pour rejoindre la partie.';
            that.infos = 'Demarrage de la partie dans ' + that.timerDebutPartie + ' secondes';
            that.eventTimerAvantDebutPartie = setInterval(function () {
                if (that.timerDebutPartie == 0 ) {
                    clearInterval(that.eventTimerAvantDebutPartie);
                    that.affichageInfos = false;
                    that.players.splice(0,(that.nbUsersMax - that.nbUsersConnectes));
                    that.nbUsersMax = that.nbUsersConnectes;

                    that.state.step = 'waitPlay';
                    that.instructions = 'Tout le monde est la. Préparez vous !';

                    setTimeout (function(){
                        socket.emit('start', {room : GLOBAL.token}, function (data) {
                            console.log("Démarrage partie");
                            that.cptQuestion = 0;

                            //ici, une question durera xx secondes, paramétré par l'utilisateur, 10 secondes par défaut.
                            that.lancerIntervalQuestion();
                            //Je lance ma fonction en même temps que l'event
                            //car la première itération de mon event se fait au bon de 10 sec.
                            that.myGame();
                        });
                    }, 5000);
                } else {
                    that.timerDebutPartie = that.timerDebutPartie -1;
                    that.infos = 'Demarrage de la partie dans ' + that.timerDebutPartie + ' secondes';
                }
            }, 1000 );

        }),

        //socket lancement d'un partie nombre de joueur suffisant
        socket.on('start-party-room-' + GLOBAL.token, function(user) {

            that.state.step = 'waitPlay';
            that.instructions = 'Tout le monde est la. Préparez vous !';
            clearInterval(that.eventTimerAvantDebutPartie);
            that.affichageInfos = false;

            setTimeout (function(){
                socket.emit('start', {room : GLOBAL.token}, function (data) {
                    console.log("Démarrage partie");
                    that.cptQuestion = 0;

                    //ici, une question durera xx secondes, paramétré par l'utilisateur, 10 secondes par défaut.
                    that.lancerIntervalQuestion();
                    //Je lance ma fonction en même temps que l'event
                    //car la première itération de mon event se fait au bon de 10 sec.
                    that.myGame();
                });
            }, 5000);
        }),

        //socket mise a jour score après reponse d'un utilisateur
        socket.on('maj-party-users-' + GLOBAL.token, function(data) {
            for (var i = 0; i < that.nbUsersMax ; i++) {
                if (that.players[i].token == data['usertoken']) {
                    that.players[i].points = that.players[i].points + parseInt(data['nbPoint']);
                }
            }

            console.log('maj-party-users', data);

            that.nbReponseRecu++;
            //si tout le monde a repondu alors transition et on passe à la question suivante.
            if (that.nbUsersMax==that.nbReponseRecu) {
                that.arreterIntervalQuestion();
                clearInterval(that.interval);

                that.animationReponses(that.question.good);
                //envoi au serveur fin du temps pour repondre à la question + cumul points sur les téléphones
                socket.emit('fin-temps-reponse', function (data) {});

                //relance question dans 6 secondes (après le recap des scores)
                if (that.cptQuestion < that.nbQuestions) {
                    setTimeout (function(){
                        that.lancerIntervalQuestion();
                        that.myGame();
                    },that.tempsDeTransition);
                } else {
                    setTimeout (function(){
                        that.state.step = 'result';
                        setTimeout (function(){
                            socket.emit('display-reload-party', {room : GLOBAL.token}, function (data) {});
                        },3000);
                    },that.tempsDeTransition);

                }
            }
        })
    },
    methods: {
        /**
         * Functions permettant de comptabiliser et recupérer les questions
         **/
        myGame: function() {
            var that = this;

            if (this.cptQuestion == this.nbQuestions) {
                this.arreterIntervalQuestion();
                this.state.step = 'result';

                setTimeout (function(){
                    socket.emit('display-reload-party', {room : GLOBAL.token}, function (data) {});
                },3000);
            } else if (this.cptQuestion % 5 == 0 && this.affichageScore) {
                this.arreterIntervalQuestion();
                this.affichageScore = false;
                this.state.step = 'result';
                setTimeout (function(){
                    //ici, une question durera xx secondes, paramétré par l'utilisateur, 10 secondes par défaut.
                    that.lancerIntervalQuestion();
                    that.myGame();
                },5000);
            } else {
                socket.emit('recup-question', {room : GLOBAL.token}, function (data) {

                    that.affichageScore =true;

                    that.nbReponseRecu = 0;
                    that.cptQuestion = that.cptQuestion + 1;

                    console.log('affichage question', that.cptQuestion);

                    that.question = data;
                    that.state.step = 'game';

                    that.animationReponses('');

                    clearInterval(that.interval);

                    that.gererTimer();
                });
            }
        },

        /**
         * Function gérant l'animation des réponses.
         * @arg nomClass classe css a ajouter aux réponses
         * @arg bonneReponse div reponse qui ne doit pas prendre la classe css
         **/
        animationReponses : function (bonneReponse){

            if (bonneReponse == "reponse1") {
                this.affichageReponse2 =  false;
                this.affichageReponse3 =  false;
                this.affichageReponse4 =  false;
                this.affichageExplication =  true;
            } else if (bonneReponse == "reponse2") {
                this.affichageReponse1 =  false;
                this.affichageReponse3 =  false;
                this.affichageReponse4 =  false;
                this.affichageExplication =  true;
            } else if (bonneReponse == "reponse3") {
                this.affichageReponse2 =  false;
                this.affichageReponse1 =  false;
                this.affichageReponse4 =  false;
                this.affichageExplication =  true;
            } else if (bonneReponse == "reponse4") {
                this.affichageReponse2 =  false;
                this.affichageReponse3 =  false;
                this.affichageReponse1 =  false;
                this.affichageExplication =  true;
            } else {
                this.affichageReponse1 =  true;
                this.affichageReponse2 =  true;
                this.affichageReponse3 =  true;
                this.affichageReponse4 =  true;
                this.affichageExplication =  false;
            }

        },

        gererTimer : function () {
            // gestion du timer
            var $timelapsWrapper = document.querySelector('.canvas-wrapper'),
                $timelaps = document.querySelector('#timelaps'),
                timelapsCtx = $timelaps.getContext("2d");

            var timelapsH = $timelapsWrapper.offsetHeight,
                timelapsW = $timelapsWrapper.offsetWidth,
                timelapsCenter = timelapsW / 2;

            var r = timelapsW/2,
                x = 0,
                y = 0;

            var angle = -90;
            var totalTime = this.timerQuestion * 1000; //ms
            var tickInterval = 250;
            var step = tickInterval * 360 / totalTime;
            var tick = 0;
            var nextStep = 0;

            timelapsCtx.strokeStyle = "rgb(106, 150, 241)";
            timelapsCtx.lineWidth = 1;
            timelapsCtx.beginPath();
            angle = -90;
            tick = 0;
            timelapsCtx.clearRect(0, 0, timelapsW, timelapsH);
            var that = this;
            this.interval = setInterval(function () {
                nextStep = angle + step;

                while(angle < nextStep){
                    x = r + r*Math.cos(angle*(Math.PI/180));
                    y = r + r*Math.sin(angle*(Math.PI/180));

                    timelapsCtx.moveTo(timelapsW/2, timelapsH/2);
                    timelapsCtx.lineTo(x,y);
                    timelapsCtx.stroke();
                    angle++;
                }

                tick += tickInterval;
                if (tick >= totalTime) {
                    console.log('stop temps de reponse ' + (tick/1000) + 's');
                    clearInterval(that.interval);

                    that.animationReponses(that.question.good);
                    //envoi au serveur fin du temps pour repondre à la question + cumul points sur les téléphones
                    socket.emit('fin-temps-reponse', function (data) {});
                }
            }, tickInterval);
        },

        lancerIntervalQuestion : function () {
            test.eventQuestion = setInterval(this.myGame, ((this.timerQuestion * 1000) + this.tempsDeTransition) );
        },

        arreterIntervalQuestion : function () {
            clearInterval(test.eventQuestion);
        }
    }
});<commit_msg>revue de code<commit_after>/* global Vue*/
/* global io*/
/* global $*/
'use strict';
var socket = io.connect(GLOBAL.url);

var test = new Vue({
    el: '#content',
    data: {
        error : GLOBAL.error,
        players : [], //tableau des joueurs (token, username, points)
        nbUsersMax : '',
        nbUsersConnectes : 0,
        nbQuestions : '',
        pageQRCode :  '', //lien du QRcode (page admin-room ou room)
        timerQuestion : '',
        timerDebutPartie : 30,
        affichageExplication : false,
        affichageInfos : true,
        infos : '',
        affichageScore : false,
        affichageReponse1 : true, //gestion de l'animation pour afficher la bonne reponse
        affichageReponse2 : true, //gestion de l'animation pour afficher la bonne reponse
        affichageReponse3 : true, //gestion de l'animation pour afficher la bonne reponse
        affichageReponse4 : true, //gestion de l'animation pour afficher la bonne reponse
        tempsDeTransition : 8000, //temps entre affichage de la réponse et debut de la question suivante
        instructions : '', //Instructions afficher sur la page dashboard
        eventQuestion : '',
        eventTimerAvantDebutPartie : '',
        state: {
            loading : false,
            step : '' //waitParam, waitPlayer, waitGame, game, result
        },
        question: {} //tableau des questions (idquestion, question, reponse1, reponse2, reponse3, reponse4, good, explication)
    },
    ready: function() {

        this.pageQRCode = 'admin-room';
        this.state.loading = true;
        this.state.step = 'waitParam';

        this.instructions = 'Scanne ce QR Code pour parametrer la partie.',
        $('#content').show();

        var that = this;

        //socket ajout d'un joueur dans le salon
        socket.on('new-user-' + GLOBAL.token, function(data) {
            that.nbUsersConnectes = that.nbUsersConnectes + 1;
            that.players.push({token:data['usertoken'], username:data['user'],points:0}); //ajout d'un player
            that.players.splice(0,1);   //suppression d'un joueur "attente"
        }),

        //socket création d'une partie avec les params que l'utilisateur a saisi.
        socket.on('create-room-' + GLOBAL.token, function(data) {
            that.nbUsersMax = parseInt(data.nbUsersMax);
            that.nbQuestions = parseInt(data.nbQuestions);
            that.timerQuestion = parseInt(data.timerQuestion);

            for (var i = 1; i <= that.nbUsersMax ; i++) {
                that.players.push({token:'attente', username:'attente'});
            }
            that.pageQRCode = 'access-room';
            that.instructions = 'Scanne ce QR Code pour rejoindre la partie.';
            that.infos = 'Demarrage de la partie dans ' + that.timerDebutPartie + ' secondes';
            that.eventTimerAvantDebutPartie = setInterval(function () {
                if (that.timerDebutPartie == 0 ) {
                    clearInterval(that.eventTimerAvantDebutPartie);
                    that.affichageInfos = false;
                    that.players.splice(0,(that.nbUsersMax - that.nbUsersConnectes));
                    that.nbUsersMax = that.nbUsersConnectes;

                    that.state.step = 'waitPlay';
                    that.instructions = 'Tout le monde est la. Préparez vous !';

                    setTimeout (function(){
                        socket.emit('start', {room : GLOBAL.token}, function (data) {
                            console.log("Démarrage partie");
                            that.cptQuestion = 0;

                            //ici, une question durera xx secondes, paramétré par l'utilisateur, 10 secondes par défaut.
                            that.lancerIntervalQuestion();
                            //Je lance ma fonction en même temps que l'event
                            //car la première itération de mon event se fait au bon de 10 sec.
                            that.myGame();
                        });
                    }, 5000);
                } else {
                    that.timerDebutPartie = that.timerDebutPartie -1;
                    that.infos = 'Demarrage de la partie dans ' + that.timerDebutPartie + ' secondes';
                }
            }, 1000 );

        }),

        //socket lancement d'un partie nombre de joueur suffisant
        socket.on('start-party-room-' + GLOBAL.token, function(user) {

            that.state.step = 'waitPlay';
            that.instructions = 'Tout le monde est la. Préparez vous !';
            clearInterval(that.eventTimerAvantDebutPartie);
            that.affichageInfos = false;

            setTimeout (function(){
                socket.emit('start', {room : GLOBAL.token}, function (data) {
                    console.log("Démarrage partie");
                    that.cptQuestion = 0;

                    //ici, une question durera xx secondes, paramétré par l'utilisateur, 10 secondes par défaut.
                    that.lancerIntervalQuestion();
                    //Je lance ma fonction en même temps que l'event
                    //car la première itération de mon event se fait au bon de 10 sec.
                    that.myGame();
                });
            }, 5000);
        }),

        //socket mise a jour score après reponse d'un utilisateur
        socket.on('maj-party-users-' + GLOBAL.token, function(data) {
            for (var i = 0; i < that.nbUsersMax ; i++) {
                if (that.players[i].token == data['usertoken']) {
                    that.players[i].points = that.players[i].points + parseInt(data['nbPoint']);
                }
            }

            console.log('maj-party-users', data);

            that.nbReponseRecu++;
            //si tout le monde a repondu alors transition et on passe à la question suivante.
            if (that.nbUsersMax==that.nbReponseRecu) {
                that.arreterIntervalQuestion();
                clearInterval(that.interval);

                that.animationReponses(that.question.good);
                //envoi au serveur fin du temps pour repondre à la question + cumul points sur les téléphones
                socket.emit('fin-temps-reponse', function (data) {});

                //relance question dans 6 secondes (après le recap des scores)
                if (that.cptQuestion < that.nbQuestions) {
                    setTimeout (function(){
                        that.lancerIntervalQuestion();
                        that.myGame();
                    },that.tempsDeTransition);
                } else {
                    setTimeout (function(){
                        that.state.step = 'result';
                        setTimeout (function(){
                            socket.emit('display-reload-party', {room : GLOBAL.token}, function (data) {});
                        },3000);
                    },that.tempsDeTransition);

                }
            }
        })
    },
    methods: {
        /**
         * Functions permettant de comptabiliser et recupérer les questions
         **/
        myGame: function() {
            var that = this;

            if (this.cptQuestion == this.nbQuestions) {
                this.arreterIntervalQuestion();
                this.state.step = 'result';

                setTimeout (function(){
                    socket.emit('display-reload-party', {room : GLOBAL.token}, function (data) {});
                },3000);
            } else if (this.cptQuestion % 5 == 0 && this.affichageScore) {
                this.arreterIntervalQuestion();
                this.affichageScore = false;
                this.state.step = 'result';
                setTimeout (function(){
                    //ici, une question durera xx secondes, paramétré par l'utilisateur, 10 secondes par défaut.
                    that.lancerIntervalQuestion();
                    that.myGame();
                },5000);
            } else {
                socket.emit('recup-question', {room : GLOBAL.token}, function (data) {

                    that.affichageScore =true;

                    that.nbReponseRecu = 0;
                    that.cptQuestion = that.cptQuestion + 1;

                    console.log('affichage question', that.cptQuestion);

                    that.question = data;
                    that.state.step = 'game';

                    that.animationReponses('');

                    clearInterval(that.interval);

                    that.gererTimer();
                });
            }
        },

        /**
         * Function gérant l'animation des réponses.
         * @arg nomClass classe css a ajouter aux réponses
         * @arg bonneReponse div reponse qui ne doit pas prendre la classe css
         **/
        animationReponses : function (bonneReponse){

            if(bonneReponse){
                this.affichageReponse1 =  false;
                this.affichageReponse2 =  false;
                this.affichageReponse3 =  false;
                this.affichageReponse4 =  false;
                this.affichageExplication =  true;

                switch (bonneReponse) {
                    case "reponse1":
                        this.affichageReponse1 =  true;
                        break;
                    case "reponse2":
                        this.affichageReponse2 =  true;
                        break;
                    case "reponse3":
                        this.affichageReponse3 =  true;
                        break;
                    case "reponse4":
                        this.affichageReponse4 =  true;
                        break;
                }
            } else {
                this.affichageReponse1 =  true;
                this.affichageReponse2 =  true;
                this.affichageReponse3 =  true;
                this.affichageReponse4 =  true;
                this.affichageExplication =  false;
            }
        },

        gererTimer : function () {
            // gestion du timer
            var $timelapsWrapper = document.querySelector('.canvas-wrapper'),
                $timelaps = document.querySelector('#timelaps'),
                timelapsCtx = $timelaps.getContext("2d");

            var timelapsH = $timelapsWrapper.offsetHeight,
                timelapsW = $timelapsWrapper.offsetWidth,
                timelapsCenter = timelapsW / 2;

            var r = timelapsW/2,
                x = 0,
                y = 0;

            var angle = -90;
            var totalTime = this.timerQuestion * 1000; //ms
            var tickInterval = 250;
            var step = tickInterval * 360 / totalTime;
            var tick = 0;
            var nextStep = 0;

            timelapsCtx.strokeStyle = "rgb(106, 150, 241)";
            timelapsCtx.lineWidth = 1;
            timelapsCtx.beginPath();
            angle = -90;
            tick = 0;
            timelapsCtx.clearRect(0, 0, timelapsW, timelapsH);
            var that = this;
            this.interval = setInterval(function () {
                nextStep = angle + step;

                while(angle < nextStep){
                    x = r + r*Math.cos(angle*(Math.PI/180));
                    y = r + r*Math.sin(angle*(Math.PI/180));

                    timelapsCtx.moveTo(timelapsW/2, timelapsH/2);
                    timelapsCtx.lineTo(x,y);
                    timelapsCtx.stroke();
                    angle++;
                }

                tick += tickInterval;
                if (tick >= totalTime) {
                    console.log('stop temps de reponse ' + (tick/1000) + 's');
                    clearInterval(that.interval);

                    that.animationReponses(that.question.good);
                    //envoi au serveur fin du temps pour repondre à la question + cumul points sur les téléphones
                    socket.emit('fin-temps-reponse', function (data) {});
                }
            }, tickInterval);
        },

        lancerIntervalQuestion : function () {
            test.eventQuestion = setInterval(this.myGame, ((this.timerQuestion * 1000) + this.tempsDeTransition) );
        },

        arreterIntervalQuestion : function () {
            clearInterval(test.eventQuestion);
        }
    }
});<|endoftext|>


<commit_before>/*global chrome, define, nodeRequire*/
define(function(require, exports, module) {
    plugin.consumes = ["command", "background"];
    plugin.provides = ["window"];
    return plugin;

    function plugin(options, imports, register) {
        var gui = nodeRequire("nw.gui");
        var opts = require("./lib/options");

        var command = imports.command;
        var background = imports.background;

        var win = gui.Window.get();

        background.registerWindow(opts.get("title"), opts.get("url"), win);

        var closeHandler = null;

        var isMaximized = false;

        var api = {
            close: function(force) {
                if(force) {
                    win.close(true);
                } else {
                    closeHandler();
                }
            },
            setCloseHandler: function(handler) {
                closeHandler = handler;
                win.on("close", handler);
            },
            useNativeFrame: function() {
                return true;
            },
            fullScreen: function() {
                if (win.isFullscreen) {
                    win.leaveFullscreen();
                } else {
                    win.enterFullscreen();
                }
            },
            maximize: function() {
                win.maximize();
            },
            minimize: function() {
                win.minimize();
            },
            getBounds: function() {
                return {
                    width: win.width,
                    height: win.height,
                    top: win.y,
                    left: win.x,
                    isMaximized: isMaximized
                };
            },
            setBounds: function(bounds) {
                win.width = bounds.width;
                win.height = bounds.height;
                win.y = bounds.top;
                win.x = bounds.left;
                if(bounds.isMaximized) {
                    win.maximize();
                }

                setTimeout(function() {
                    if(win.width < 300) {
                        win.width = 300;
                    }
                    if(win.height < 300) {
                        win.height = 300;
                    }
                }, 1000);
            },
            addResizeListener: function(listener) {
                win.on("resize", function() {
                    isMaximized = false;
                    listener();
                });
                win.on("move", function() {
                    isMaximized = false;
                    listener();
                });
                win.on("maximize", function() {
                    // Give other events time to trigger (resize, move), then override
                    setTimeout(function() {
                        isMaximized = true;
                        listener();
                    }, 1000);
                });
            },
            focus: function() {
                win.focus();
            }
        };

        command.define("Development:Reload window", {
            doc: "Reload the current window.",
            exec: function() {
                win.reload();
            },
            readOnly: true
        });

        command.define("Development:Show DevTools", {
            doc: "Show the node-webkit developer tools.",
            exec: function() {
                win.showDevTools();
            },
            readOnly: true
        });

        register(null, {
            window: api
        });
    }
});
<commit_msg>hack to get restoring window size and position to work in linux<commit_after>/*global chrome, define, nodeRequire*/
define(function(require, exports, module) {
    plugin.consumes = ["command", "background"];
    plugin.provides = ["window"];
    return plugin;

    function plugin(options, imports, register) {
        var gui = nodeRequire("nw.gui");
        var opts = require("./lib/options");

        var command = imports.command;
        var background = imports.background;

        var win = gui.Window.get();

        background.registerWindow(opts.get("title"), opts.get("url"), win);

        var closeHandler = null;

        var isMaximized = false;

        var api = {
            close: function(force) {
                if(force) {
                    win.close(true);
                } else {
                    closeHandler();
                }
            },
            setCloseHandler: function(handler) {
                closeHandler = handler;
                win.on("close", handler);
            },
            useNativeFrame: function() {
                return true;
            },
            fullScreen: function() {
                if (win.isFullscreen) {
                    win.leaveFullscreen();
                } else {
                    win.enterFullscreen();
                }
            },
            maximize: function() {
                win.maximize();
            },
            minimize: function() {
                win.minimize();
            },
            getBounds: function() {
                return {
                    width: win.width,
                    height: win.height,
                    top: win.y,
                    left: win.x,
                    isMaximized: isMaximized
                };
            },
            setBounds: function(bounds) {
                win.x = bounds.left;
                win.width = bounds.width;

                // hack to get restoring window position and size to work in
                // linux
                setTimeout(function() {
                    win.y = bounds.top;
                    win.height = bounds.height;
                }, 500);

                if(bounds.isMaximized) {
                    win.maximize();
                }

                setTimeout(function() {
                    if(win.width < 300) {
                        win.width = 300;
                    }
                    if(win.height < 300) {
                        win.height = 300;
                    }
                }, 1000);
            },
            addResizeListener: function(listener) {
                win.on("resize", function() {
                    isMaximized = false;
                    listener();
                });
                win.on("move", function() {
                    isMaximized = false;
                    listener();
                });
                win.on("maximize", function() {
                    // Give other events time to trigger (resize, move), then override
                    setTimeout(function() {
                        isMaximized = true;
                        listener();
                    }, 1000);
                });
            },
            focus: function() {
                win.focus();
            }
        };

        command.define("Development:Reload window", {
            doc: "Reload the current window.",
            exec: function() {
                win.reload();
            },
            readOnly: true
        });

        command.define("Development:Show DevTools", {
            doc: "Show the node-webkit developer tools.",
            exec: function() {
                win.showDevTools();
            },
            readOnly: true
        });

        register(null, {
            window: api
        });
    }
});
<|endoftext|>


<commit_before>/**
 * Logger function, by Ian Isted
 * @string The string you'd like to output to the log
 * @logID A unique id to be given to your ouput. This allows you to extend the specific output later
 * @status Adds a class name to your output, allowing you style based on status types, etc.
 */

function logger(string,logID,status) {
	var terminal = '#terminal'; // ID of your output container. e.g. #terminal

	if ( typeof status !=='undefined') {
		status = ' class="' + status + '"';
	} else {
		status = '';
	}
	if ( typeof logID !=='undefined' && logID !== false) {
		//logID = ' id="' + logID + '"'
		if ($(terminal + ' ul li#logger-id-' + logID).length !== 0) {
			$(terminal + ' ul li#logger-id-' + logID).append(string);
		} else {
			$(terminal + ' ul').append('
' + arguments.callee.caller.name + '' + string + '
');
		}

	} else {
		$(terminal + ' ul').append('
' + arguments.callee.caller.name + '' + string + '
');
	};
	$(terminal).scrollTop(900000);
}

var connection = false; // Boolean to tell the system if a server connection has been made

var Game = {
	init:function() {
		// Initialise the game, and begin listening for key presses.

		logger('Application version: ' + version);

		$('.cmd').keydown(function(event) {
				switch(event.which) {
					case 13: //Enter Key
						if ($('.cmd').val() == "") {
							return false;
						}
						Game.Cmd.input($('.cmd').val());
						break;
					case 27: //Escape Key
					//Clears current line
						$('.cmd').val('');
						break;
					case 38: //Up Arrow
					//Rotates through Command History
						Game.Cmd.History.previous();
						event.preventDefault();
						break;
					case 40: //Down Arrow
					//Rotates through Command History
						Game.Cmd.History.next();
						event.preventDefault();
						break;
					case 9: //Tab
					//Reserved for Tab-complete
						event.preventDefault();
						break;

				}
		});
	},
	Cmd: {
		input:function(e) {

			var input = e;

			//Naughty script catcher
			// looks for "<", and prevents bad guys!
			if (input.toLowerCase().indexOf("<") >= 0) {
				logger("Not cool dude");
				$('.cmd').val('');
				return false;
			}

			//Adds input to Command History
			Game.Cmd.History.list.push(input);

			//splits string on first "space"
			// i.e. [cmd] [string]
			// converts cmd part to lowercase.
			// string is not converted to lowercase
			var cmd = $('.cmd').val().split(' ')[ 0 ].toLowerCase();
			var string = input.substr(input.indexOf(" ") + 1);

			//Look up [cmd] and take action
			switch(cmd) {
				case "connect":
				//Attempts to connect to server
				// not implemented
					if (string == "true") {
						Game.connect(true);
					} else {
						Game.connect();
					}
					break;
				case "h4x0r": case "hacktheplanet": case "hacker": case "l33t": case "1337":
				//Secret Hacker colours enabled!
					$('html').toggleClass('hacker');
					break;
				case "time": case "clock": case "date":
				//Displays unix timecode
					logger('' + cmd + ': ' + $.now() + '');
					break;
				case "print": case "echo":
				//Echos [string]
					logger('' + string + '');
					break;
				case "about":
				//Prints about info
					logger('CLI version 1.0.
Built by @ianisted.
Released under MIT license. Type about-license to see the license.');
					break;
				case "about-license":
				//Prints licence info
					logger('The MIT License (MIT)

Copyright (c) 2016 Ian Isted
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.');
					break;
				case "clear": case "cls":
				//Clears terminal
					$('#terminal ul').html('');
					break;
				case "history":
				//Prints history of commands
					historylog = "";
					$.each(Game.Cmd.History.list, function(i,val) {
						historylog = historylog + i + ': ' + val + "
";
					});
					logger(historylog);
					break;
				case "help": case "/?": case "?":
				//Basic help function
					logger('Help, we all need some,
Avaliable Commands
 - About
 - About-Licence
 - Clear
 - Connect
 - Echo
 - History
 - Help
 - Time');
					break;
				default:
				//If command not recognized by CLI then send on.
					Game.Cmd.send(e);
					break;
			}

			$('.cmd').val('');

		},
		send:function(e) {
			//Sends command to server to be processed
			// not implemented yet
			// all commands that arrive simply return "not valid command"
			logger('' + e + ' is not a valid command.');
		},
		History: {
			//Creates and manages the Command History
			list: [],
			list_position:0,
			previous:function() {
				var list = Game.Cmd.History.list;
				var pos = Game.Cmd.History.list_position;

					if (pos == 0) {
						pos = list.length - 1;
						Game.Cmd.History.list_position = pos;
						$('.cmd').val(Game.Cmd.History.list[pos]);
					} else {
						pos = pos - 1;
						Game.Cmd.History.list_position = pos;
						$('.cmd').val(Game.Cmd.History.list[pos]);
					}

			},
			next:function() {
				var list = Game.Cmd.History.list;
				var pos = Game.Cmd.History.list_position;

					if (pos == 0) {
						//Game.Cmd.History.list_position = list.length - 1;
						//pos = Game.Cmd.History.list_position;
						$('.cmd').val(Game.Cmd.History.list[pos]);
						pos = pos + 1;
						Game.Cmd.History.list_position = pos;
					} else if (pos < list.length) {
						$('.cmd').val(Game.Cmd.History.list[pos]);
						if (pos != list.length - 1) {
							pos = pos + 1;
							Game.Cmd.History.list_position = pos;
						} else {
							pos = 0;
							Game.Cmd.History.list_position = pos;
						}
					}

			}
		}

	},
	connect:function(params) {
		//Connect to server
		// not implemented, hence fails
		logger('Could not connect. Application has not been setup to connect to a server.');

	}
}
<commit_msg>testing git cli on MintyJarvis<commit_after>/**
 * Logger function, by Ian Isted
 * @string The string you'd like to output to the log
 * @logID A unique id to be given to your ouput. This allows you to extend the specific output later
 * @status Adds a class name to your output, allowing you style based on status types, etc.
 */

function logger(string,logID,status) {
	var terminal = '#terminal'; // ID of your output container. e.g. #terminal

	if ( typeof status !=='undefined') {
		status = ' class="' + status + '"';
	} else {
		status = '';
	}
	if ( typeof logID !=='undefined' && logID !== false) {
		//logID = ' id="' + logID + '"'
		if ($(terminal + ' ul li#logger-id-' + logID).length !== 0) {
			$(terminal + ' ul li#logger-id-' + logID).append(string);
		} else {
			$(terminal + ' ul').append('
' + arguments.callee.caller.name + '' + string + '
');
		}

	} else {
		$(terminal + ' ul').append('
' + arguments.callee.caller.name + '' + string + '
');
	};
	$(terminal).scrollTop(900000);
}

var connection = false; // Boolean to tell the system if a server connection has been made

var Game = {
	init:function() {
		// Initialise the game, and begin listening for key presses.

		logger('Application version: ' + version);

		$('.cmd').keydown(function(event) {
				switch(event.which) {
					case 13: //Enter Key
						if ($('.cmd').val() == "") {
							return false;
						}
						Game.Cmd.input($('.cmd').val());
						break;
					case 27: //Escape Key
					//Clears current line
						$('.cmd').val('');
						break;
					case 38: //Up Arrow
					//Rotates through Command History
						Game.Cmd.History.previous();
						event.preventDefault();
						break;
					case 40: //Down Arrow
					//Rotates through Command History
						Game.Cmd.History.next();
						event.preventDefault();
						break;
					case 9: //Tab
					//Reserved for Tab-complete
						event.preventDefault();
						break;

				}
		});
	},
	Cmd: {
		input:function(e) {

			var input = e;

			//Naughty script catcher
			// looks for "<", and prevents bad guys!
			if (input.toLowerCase().indexOf("<") >= 0) {
				logger("Not cool dude");
				$('.cmd').val('');
				return false;
			}

			//Adds input to Command History
			Game.Cmd.History.list.push(input);

			//splits string on first "space"
			// i.e. [cmd] [string]
			// converts cmd part to lowercase.
			// string is not converted to lowercase
			var cmd = $('.cmd').val().split(' ')[ 0 ].toLowerCase();
			var string = input.substr(input.indexOf(" ") + 1);

			//Look up [cmd] and take action
			switch(cmd) {
				case "connect":
				//Attempts to connect to server
				// not implemented
					if (string == "true") {
						Game.connect(true);
					} else {
						Game.connect();
					}
					break;
				case "h4x0r": case "hacktheplanet": case "hacker": case "l33t": case "1337":
				//Secret Hacker colours enabled!
					$('html').toggleClass('hacker');
					break;
				case "time": case "clock": case "date":
				//Displays unix timecode
					logger('' + cmd + ': ' + $.now() + '');
					break;
				case "print": case "echo":
				//Echos [string]
					logger('' + string + '');
					break;
				case "about":
				//Prints about info
					logger('CLI version 1.0.
Built by @ianisted.
Released under MIT license. Type about-license to see the license.');
					break;
				case "about-license":
				//Prints licence info
					logger('The MIT License (MIT)

Copyright (c) 2016 Ian Isted
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.');
					break;
				case "clear": case "cls":
				//Clears terminal
					$('#terminal ul').html('');
					break;
				case "history":
				//Prints history of commands
					historylog = "";
					$.each(Game.Cmd.History.list, function(i,val) {
						historylog = historylog + i + ': ' + val + "
";
					});
					logger(historylog);
					break;
				case "help": case "/?": case "?":
				//Basic help function
					logger('Help, we all need some,
Avaliable Commands
 - About
 - About-Licence
 - Clear
 - Connect
 - Echo
 - History
 - Help
 - Time');
					break;
				default:
				//If command not recognized by CLI then send on.
					Game.Cmd.send(e);
					break;
			}

			$('.cmd').val('');

		},
		send:function(e) {
			//Sends command to server to be processed
			// not implemented yet
			// all commands that arrive simply return "not valid command"
			logger('' + e + ' is not a valid command.');
		},
		History: {
			//Creates and manages the Command History
			list: [],
			list_position:0,
			previous:function() {
				var list = Game.Cmd.History.list;
				var pos = Game.Cmd.History.list_position;

					if (pos == 0) {
						pos = list.length - 1;
						Game.Cmd.History.list_position = pos;
						$('.cmd').val(Game.Cmd.History.list[pos]);
					} else {
						pos = pos - 1;
						Game.Cmd.History.list_position = pos;
						$('.cmd').val(Game.Cmd.History.list[pos]);
					}

			},
			next:function() {
				var list = Game.Cmd.History.list;
				var pos = Game.Cmd.History.list_position;

					if (pos == 0) {
						//Game.Cmd.History.list_position = list.length - 1;
						//pos = Game.Cmd.History.list_position;
						$('.cmd').val(Game.Cmd.History.list[pos]);
						pos = pos + 1;
						Game.Cmd.History.list_position = pos;
					} else if (pos < list.length) {
						$('.cmd').val(Game.Cmd.History.list[pos]);
						if (pos != list.length - 1) {
							pos = pos + 1;
							Game.Cmd.History.list_position = pos;
						} else {
							pos = 0;
							Game.Cmd.History.list_position = pos;
						}
					}

			}
		}

	},
	connect:function(params) {
		//Connect to server
		// not implemented, hence fails
		logger('Could not connect. Application has not been setup to connect to a server.');

	}
}
//test comment
<|endoftext|>


<commit_before>})(window.parent, window.parent.document);

if (window.parent.jQuery) window.parent.jQuery(window.parent).trigger('factlink.libraryLoaded');
<commit_msg>Moved event trigger inside the closure, so we can remove the closure more easily<commit_after>  if (window.jQuery) window.jQuery(window).trigger('factlink.libraryLoaded');
})(window.parent, window.parent.document);

<|endoftext|>


<commit_before>(function () {

  var Utils = {
    capitalize: function(string) {
      return string ? string.charAt(0).toUpperCase() + string.substring(1).toLowerCase() : null;
    },
    urlBase64Decode: function(str) {
      var output = str.replace('-', '+').replace('_', '/');
      switch (output.length % 4) {
        case 0: { break; }
        case 2: { output += '=='; break; }
        case 3: { output += '='; break; }
        default: {
          throw 'Illegal base64url string!';
        }
      }
      return window.atob(output); //polifyll https://github.com/davidchambers/Base64.js
    }
  };

  angular.module('auth0', ['auth0.storage', 'auth0.service', 'auth0.interceptor']);

  angular.module('auth0.interceptor', [])
  .factory('authInterceptor', function ($rootScope, $q, $injector) {
    return {
      request: function (config) {
        // When using auth dependency is never loading, we need to do this manually
        // This issue should be related with: https://github.com/angular/angular.js/issues/2367
        if (!$injector.has('auth')) {
          return config;
        }
        var auth = $injector.get('auth');
        config.headers = config.headers || {};
        if (auth.idToken && !config.headers.Authorization) {
          config.headers.Authorization = 'Bearer '+ auth.idToken;
        }
        return config;
      },
      responseError: function (response) {
        // handle the case where the user is not authenticated
        if (response.status === 401) {
          $rootScope.$broadcast('auth0.forbidden', response);
        }
        return $q.reject(response);
      }
    };
  });

  angular.module('auth0.storage', ['ngCookies'])
    .service('authStorage', function($cookieStore) {
      this.store = function(idToken, accessToken, state) {
        $cookieStore.put('idToken', idToken);
        $cookieStore.put('accessToken', accessToken);
        if (state) {
          $cookieStore.put('state', state);
        }
      };

      this.get = function() {
        return {
          idToken: $cookieStore.get('idToken'),
          accessToken: $cookieStore.get('accessToken'),
          state: $cookieStore.get('state')
        };
      };

      this.remove = function() {
        $cookieStore.remove('idToken');
        $cookieStore.remove('accessToken');
        $cookieStore.remove('state');
      };
    });

  angular.module('auth0.service', ['auth0.storage']).provider('auth', function() {
    var defaultOptions = {
      callbackOnLocationHash: true
    };
    var config = this;

    this.init = function(options, Auth0Constructor) {
      if (!Auth0Constructor && typeof Auth0Widget === 'undefined' && typeof Auth0 === 'undefined') {
        throw new Error('You must add either Auth0Widget.js or Auth0.js');
      }
      if (!options) {
        throw new Error('You must set options when calling init');
      }
      this.loginUrl = options.loginUrl;
      this.loginState = options.loginState;
      this.clientID = options.clientID;
      this.sso = options.sso;

      var Constructor = Auth0Constructor;
      if (!Constructor && typeof Auth0Widget !== 'undefined') {
        Constructor = Auth0Widget;
      }
      if (!Constructor && typeof Auth0 !== 'undefined') {
        Constructor = Auth0;
      }

      this.auth0lib = new Constructor(angular.extend(defaultOptions, options));
      if (this.auth0lib.getClient) {
        this.auth0js = this.auth0lib.getClient();
        this.isWidget = true;
      } else {
        this.auth0js = this.auth0lib;
        this.isWidget = false;
      }
    };

    this.eventHandlers = {};

    this.on = function(anEvent, handler) {
      if (!this.eventHandlers[anEvent]) {
        this.eventHandlers[anEvent] = [];
      }
      this.eventHandlers[anEvent].push(handler);
    };

    var events = ['loginSuccess', 'loginFailure', 'logout', 'forbidden'];
    angular.forEach(events, function(anEvent) {
      config['add' + Utils.capitalize(anEvent) + 'Handler'] = function(handler) {
        config.on(anEvent, handler);
      };
    });

    this.$get = function($rootScope, $q, $injector, authStorage, $window, $location) {
      var auth = {
        isAuthenticated: false
      };

      var getHandlers = function(anEvent) {
        return config.eventHandlers[anEvent];
      };

      var callHandler = function(anEvent, locals) {
        angular.forEach(getHandlers(anEvent) || [], function(handler) {
          $injector.invoke(handler, auth, locals);
        });
      };

      var safeApply = function(fn) {
        var phase = $rootScope.$root.$$phase;
        if(phase === '$apply' || phase === '$digest') {
          if(fn && (typeof(fn) === 'function')) {
            fn();
          }
        } else {
          $rootScope.$apply(fn);
        }
      };

      var applied = function(fn) {
        // Adding arguments just due to a bug in Auth0.js.
        /*jshint ignore:start */
        return function (err, response) {
          /*jshint ignore:end */
          var argsCall = arguments;
          safeApply(function() {
            fn.apply(null, argsCall);
          });
          /*jshint ignore:start */
        };
        /*jshint ignore:end */
      };

      // SignIn

      // Generic things

      var onSigninOk = function(idToken, accessToken, state, locationEvent) {
          authStorage.store(idToken, accessToken, state);

          var profilePromise = auth.getProfile(idToken);

          var response = {
            idToken: idToken,
            accessToken: accessToken,
            state: state,
            isAuthenticated: true
          };

          angular.extend(auth, response);
          callHandler('loginSuccess', angular.extend({
            profile: profilePromise,
            locationEvent: locationEvent
          }, response));

          return profilePromise;
      };

      // Redirect mode
      $rootScope.$on('$locationChangeStart', function(e) {
        var hashResult = config.auth0lib.parseHash($window.location.hash);
        if (!auth.isAuthenticated) {
          if (hashResult && hashResult.id_token) {
            onSigninOk(hashResult.id_token, hashResult.access_token, hashResult.state, e);
            return;
          }
          var storedValues = authStorage.get();
          if (storedValues && storedValues.idToken) {
            onSigninOk(storedValues.idToken, storedValues.accessToken, storedValues.state, e);
            return;
          }
          if (config.sso) {
            config.auth0js.getSSOData(applied(function(err, ssoData) {
              if (ssoData.sso) {
                auth.signin({
                  popup: false,
                  connection: ssoData.lastUsedConnection.strategy
                }, config.auth0js);
              }
            }));
          }
        }
      });

      $rootScope.$on('auth0.forbidden', function(e, response) {
        callHandler('forbidden', {response: response});
      });

      if (config.loginUrl) {
        $rootScope.$on('$routeChangeStart', function(e, nextRoute) {
          if (nextRoute.$$route && nextRoute.$$route.requiresLogin) {
            if (!auth.isAuthenticated) {
              $location.path(config.loginUrl);
            }
          }
        });
      }

      if (config.loginState) {
        $rootScope.$on('$stateChangeStart', function(e, to) {
          if (to.data && to.data.requiresLogin) {
            if (!auth.isAuthenticated) {
              e.preventDefault();
              $injector.get('$state').go(config.loginState);
            }
          }
        });
      }

      // Start auth service

      auth.config = config;

      var checkHandlers = function(options) {
        var successHandlers = getHandlers('loginSuccess');
        if (!options.popup && !options.username && (!successHandlers || successHandlers.length === 0)) {
            throw new Error('You must define a loginSuccess handler' +
              'if not using popup mode or not doing ro call because that means you are doing a redirect');
          }
      };

      auth.hasTokenExpired = function (token) {
        if (!token) {
          return true;
        }

        var parts = token.split('.');

        if (parts.length !== 3) {
          return true;
        }

        var decoded = Utils.urlBase64Decode(parts[1]);
        if (!decoded) {
          return true;
        }

        try {
          decoded = JSON.parse(decoded);
        } catch (e) {
          return true;
        }

        if(!decoded.exp) {
          return true;
        }

        var d = new Date(0); // The 0 here is the key, which sets the date to the epoch
        d.setUTCSeconds(decoded.exp);

        if (isNaN(d)) {
          return true;
        }

        // Token expired?
        if( d.valueOf() > new Date().valueOf()) {
          // No
          return false;
        } else {
          // Yes
          return true;
        }
      };

      auth.getToken = function(clientID, options) {
        options = options || { scope: 'openid' };

        var defered = $q.defer();
        config.auth0js.getDelegationToken(clientID, this.idToken, options, applied(function(err, delegationResult) {
          if (err) {
            defered.reject(err);
          } else {
            defered.resolve(delegationResult.id_token);
          }
        }));

        return defered.promise;
      };

      auth.refreshToken = function(options) {
        return auth.getToken(config.clientID, options);
      };

      auth.signin = function(options, lib) {
        options = options || {};
        checkHandlers(options);

        var onPopupSignin = function(defered) {
          return function(err, profile, idToken, accessToken, state) {
            if (err) {
              callHandler('loginFailure', {error: err});
              defered.reject(err);
              return;
            }

            var profilePromise = onSigninOk(idToken, accessToken, state);

            profilePromise
              .then(function(profile) {
                defered.resolve(profile);
              }, function(err) {
                callHandler('loginFailure', {error: err});
                defered.reject(err);
              });
          };
        };

        var defered = $q.defer();
        var auth0lib = lib || config.auth0lib;
        if (config.isWidget) {
          auth0lib.signin(options, null, applied(onPopupSignin(defered)));
        } else {
          auth0lib.signin(options, applied(onPopupSignin(defered)));
        }

        return defered.promise;
      };

      auth.signout = function() {
        authStorage.remove();
        auth.profile = null;
        auth.idToken = null;
        auth.state = null;
        auth.accessToken = null;
        auth.isAuthenticated = false;
      };

      auth.getProfile = function(idToken) {
        var defered = $q.defer();

        var onProfile = function(err, profile) {
          if (err) {
            defered.reject(err);
            return;
          }
          auth.profile = profile;
          defered.resolve(profile);
        };

        config.auth0lib.getProfile(idToken || auth.idToken, applied(onProfile));

        return defered.promise;
      };

      return auth;
    };
  });
}());
<commit_msg>Minor: Typo<commit_after>(function () {

  var Utils = {
    capitalize: function(string) {
      return string ? string.charAt(0).toUpperCase() + string.substring(1).toLowerCase() : null;
    },
    urlBase64Decode: function(str) {
      var output = str.replace('-', '+').replace('_', '/');
      switch (output.length % 4) {
        case 0: { break; }
        case 2: { output += '=='; break; }
        case 3: { output += '='; break; }
        default: {
          throw 'Illegal base64url string!';
        }
      }
      return window.atob(output); //polifyll https://github.com/davidchambers/Base64.js
    }
  };

  angular.module('auth0', ['auth0.storage', 'auth0.service', 'auth0.interceptor']);

  angular.module('auth0.interceptor', [])
  .factory('authInterceptor', function ($rootScope, $q, $injector) {
    return {
      request: function (config) {
        // When using auth dependency is never loading, we need to do this manually
        // This issue should be related with: https://github.com/angular/angular.js/issues/2367
        if (!$injector.has('auth')) {
          return config;
        }
        var auth = $injector.get('auth');
        config.headers = config.headers || {};
        if (auth.idToken && !config.headers.Authorization) {
          config.headers.Authorization = 'Bearer '+ auth.idToken;
        }
        return config;
      },
      responseError: function (response) {
        // handle the case where the user is not authenticated
        if (response.status === 401) {
          $rootScope.$broadcast('auth0.forbidden', response);
        }
        return $q.reject(response);
      }
    };
  });

  angular.module('auth0.storage', ['ngCookies'])
    .service('authStorage', function($cookieStore) {
      this.store = function(idToken, accessToken, state) {
        $cookieStore.put('idToken', idToken);
        $cookieStore.put('accessToken', accessToken);
        if (state) {
          $cookieStore.put('state', state);
        }
      };

      this.get = function() {
        return {
          idToken: $cookieStore.get('idToken'),
          accessToken: $cookieStore.get('accessToken'),
          state: $cookieStore.get('state')
        };
      };

      this.remove = function() {
        $cookieStore.remove('idToken');
        $cookieStore.remove('accessToken');
        $cookieStore.remove('state');
      };
    });

  angular.module('auth0.service', ['auth0.storage']).provider('auth', function() {
    var defaultOptions = {
      callbackOnLocationHash: true
    };
    var config = this;

    this.init = function(options, Auth0Constructor) {
      if (!Auth0Constructor && typeof Auth0Widget === 'undefined' && typeof Auth0 === 'undefined') {
        throw new Error('You must add either Auth0Widget.js or Auth0.js');
      }
      if (!options) {
        throw new Error('You must set options when calling init');
      }
      this.loginUrl = options.loginUrl;
      this.loginState = options.loginState;
      this.clientID = options.clientID;
      this.sso = options.sso;

      var Constructor = Auth0Constructor;
      if (!Constructor && typeof Auth0Widget !== 'undefined') {
        Constructor = Auth0Widget;
      }
      if (!Constructor && typeof Auth0 !== 'undefined') {
        Constructor = Auth0;
      }

      this.auth0lib = new Constructor(angular.extend(defaultOptions, options));
      if (this.auth0lib.getClient) {
        this.auth0js = this.auth0lib.getClient();
        this.isWidget = true;
      } else {
        this.auth0js = this.auth0lib;
        this.isWidget = false;
      }
    };

    this.eventHandlers = {};

    this.on = function(anEvent, handler) {
      if (!this.eventHandlers[anEvent]) {
        this.eventHandlers[anEvent] = [];
      }
      this.eventHandlers[anEvent].push(handler);
    };

    var events = ['loginSuccess', 'loginFailure', 'logout', 'forbidden'];
    angular.forEach(events, function(anEvent) {
      config['add' + Utils.capitalize(anEvent) + 'Handler'] = function(handler) {
        config.on(anEvent, handler);
      };
    });

    this.$get = function($rootScope, $q, $injector, authStorage, $window, $location) {
      var auth = {
        isAuthenticated: false
      };

      var getHandlers = function(anEvent) {
        return config.eventHandlers[anEvent];
      };

      var callHandler = function(anEvent, locals) {
        angular.forEach(getHandlers(anEvent) || [], function(handler) {
          $injector.invoke(handler, auth, locals);
        });
      };

      var safeApply = function(fn) {
        var phase = $rootScope.$root.$$phase;
        if(phase === '$apply' || phase === '$digest') {
          if(fn && (typeof(fn) === 'function')) {
            fn();
          }
        } else {
          $rootScope.$apply(fn);
        }
      };

      var applied = function(fn) {
        // Adding arguments just due to a bug in Auth0.js.
        /*jshint ignore:start */
        return function (err, response) {
          /*jshint ignore:end */
          var argsCall = arguments;
          safeApply(function() {
            fn.apply(null, argsCall);
          });
          /*jshint ignore:start */
        };
        /*jshint ignore:end */
      };

      // SignIn

      // Generic things

      var onSigninOk = function(idToken, accessToken, state, locationEvent) {
          authStorage.store(idToken, accessToken, state);

          var profilePromise = auth.getProfile(idToken);

          var response = {
            idToken: idToken,
            accessToken: accessToken,
            state: state,
            isAuthenticated: true
          };

          angular.extend(auth, response);
          callHandler('loginSuccess', angular.extend({
            profile: profilePromise,
            locationEvent: locationEvent
          }, response));

          return profilePromise;
      };

      // Redirect mode
      $rootScope.$on('$locationChangeStart', function(e) {
        var hashResult = config.auth0lib.parseHash($window.location.hash);
        if (!auth.isAuthenticated) {
          if (hashResult && hashResult.id_token) {
            onSigninOk(hashResult.id_token, hashResult.access_token, hashResult.state, e);
            return;
          }
          var storedValues = authStorage.get();
          if (storedValues && storedValues.idToken) {
            onSigninOk(storedValues.idToken, storedValues.accessToken, storedValues.state, e);
            return;
          }
          if (config.sso) {
            config.auth0js.getSSOData(applied(function(err, ssoData) {
              if (ssoData.sso) {
                auth.signin({
                  popup: false,
                  connection: ssoData.lastUsedConnection.strategy
                }, config.auth0js);
              }
            }));
          }
        }
      });

      $rootScope.$on('auth0.forbidden', function(e, response) {
        callHandler('forbidden', {response: response});
      });

      if (config.loginUrl) {
        $rootScope.$on('$routeChangeStart', function(e, nextRoute) {
          if (nextRoute.$$route && nextRoute.$$route.requiresLogin) {
            if (!auth.isAuthenticated) {
              $location.path(config.loginUrl);
            }
          }
        });
      }

      if (config.loginState) {
        $rootScope.$on('$stateChangeStart', function(e, to) {
          if (to.data && to.data.requiresLogin) {
            if (!auth.isAuthenticated) {
              e.preventDefault();
              $injector.get('$state').go(config.loginState);
            }
          }
        });
      }

      // Start auth service

      auth.config = config;

      var checkHandlers = function(options) {
        var successHandlers = getHandlers('loginSuccess');
        if (!options.popup && !options.username && (!successHandlers || successHandlers.length === 0)) {
            throw new Error('You must define a loginSuccess handler ' +
              'if not using popup mode or not doing ro call because that means you are doing a redirect');
          }
      };

      auth.hasTokenExpired = function (token) {
        if (!token) {
          return true;
        }

        var parts = token.split('.');

        if (parts.length !== 3) {
          return true;
        }

        var decoded = Utils.urlBase64Decode(parts[1]);
        if (!decoded) {
          return true;
        }

        try {
          decoded = JSON.parse(decoded);
        } catch (e) {
          return true;
        }

        if(!decoded.exp) {
          return true;
        }

        var d = new Date(0); // The 0 here is the key, which sets the date to the epoch
        d.setUTCSeconds(decoded.exp);

        if (isNaN(d)) {
          return true;
        }

        // Token expired?
        if( d.valueOf() > new Date().valueOf()) {
          // No
          return false;
        } else {
          // Yes
          return true;
        }
      };

      auth.getToken = function(clientID, options) {
        options = options || { scope: 'openid' };

        var defered = $q.defer();
        config.auth0js.getDelegationToken(clientID, this.idToken, options, applied(function(err, delegationResult) {
          if (err) {
            defered.reject(err);
          } else {
            defered.resolve(delegationResult.id_token);
          }
        }));

        return defered.promise;
      };

      auth.refreshToken = function(options) {
        return auth.getToken(config.clientID, options);
      };

      auth.signin = function(options, lib) {
        options = options || {};
        checkHandlers(options);

        var onPopupSignin = function(defered) {
          return function(err, profile, idToken, accessToken, state) {
            if (err) {
              callHandler('loginFailure', {error: err});
              defered.reject(err);
              return;
            }

            var profilePromise = onSigninOk(idToken, accessToken, state);

            profilePromise
              .then(function(profile) {
                defered.resolve(profile);
              }, function(err) {
                callHandler('loginFailure', {error: err});
                defered.reject(err);
              });
          };
        };

        var defered = $q.defer();
        var auth0lib = lib || config.auth0lib;
        if (config.isWidget) {
          auth0lib.signin(options, null, applied(onPopupSignin(defered)));
        } else {
          auth0lib.signin(options, applied(onPopupSignin(defered)));
        }

        return defered.promise;
      };

      auth.signout = function() {
        authStorage.remove();
        auth.profile = null;
        auth.idToken = null;
        auth.state = null;
        auth.accessToken = null;
        auth.isAuthenticated = false;
      };

      auth.getProfile = function(idToken) {
        var defered = $q.defer();

        var onProfile = function(err, profile) {
          if (err) {
            defered.reject(err);
            return;
          }
          auth.profile = profile;
          defered.resolve(profile);
        };

        config.auth0lib.getProfile(idToken || auth.idToken, applied(onProfile));

        return defered.promise;
      };

      return auth;
    };
  });
}());
<|endoftext|>