<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import R from 'ramda';
import { connect } from 'react-redux';
import { browserHistory as history } from 'react-router';

import Grid from 'material-ui/Grid';
import Typography from 'material-ui/Typography';

import HeaderNavigation from '../../../../common/headerNavigation';
import {
  selectApplication,
  selectApplicationStatus,
  isUserAFocalPoint,
  isUserAReviewer,
  selectReview,
  selectAssessment,
} from '../../../../../store';
import ApplicationStatusText from '../applicationStatusText';
import GridRow from '../../../../common/grid/gridRow';
import EditReviewModalButton from './reviewContent/editReviewModalButton';
import AddReviewModalButton from './reviewContent/addReviewModalButton';
import AwardApplicationButton from '../../../buttons/awardApplicationButton';
import WithdrawApplicationButton from '../../../buttons/withdrawApplicationButton';
import { APPLICATION_STATUSES } from '../../../../../helpers/constants';

const messages = {
  header: 'Application from :',
  noCfei: 'Sorry but this application doesn\'t exist',
  button: 'Award',
};

class ApplicationSummaryHeader extends Component {
  constructor() {
    super();
    this.handleBackButton = this.handleBackButton.bind(this);
  }

  handleBackButton() {
    const { params: { type, id } } = this.props;
    history.push(`/cfei/${type}/${id}/applications`);
  }

  renderActionButton() {
    const { loading,
      isUserFocalPoint,
      isUserReviewer,
      reviews,
      user,
      status,
      getAssessment,
      params: { applicationId },
      didWin,
    } = this.props;
    const disabled = loading || status !== APPLICATION_STATUSES.PRE;
    if (isUserFocalPoint) {
      if (didWin) {
        return (<WithdrawApplicationButton
          disabled={disabled}
          raised
          applicationId={applicationId}
        />);
      }
      return (<AwardApplicationButton
        disabled={disabled}
        applicationId={applicationId}
      />);
    } else if (isUserReviewer) {
      if (R.prop(user, reviews)) {
        return (<EditReviewModalButton
          assessmentId={reviews[user]}
          scores={getAssessment(reviews[user])}
          reviewer={user}
          disabled={disabled}
        />);
      }
      return (<AddReviewModalButton
        raised
        reviewer={user}
        disabled={disabled}
      />);
    }
    return <div />;
  }

  renderContent() {
    const {
      partner,
      status,
      children,
      params: { type },
      error,
    } = this.props;
    if (error.notFound) {
      return <Typography >{messages.noApplication}</Typography>;
    } else if (error.message) {
      return <Typography >{error.message}</Typography>;
    }
    return (<HeaderNavigation
      title={`${messages.header} ${partner}`}
      header={<GridRow align="center">
        <ApplicationStatusText status={status} />
        {this.renderActionButton()}
      </GridRow>
      }
      backButton
      handleBackButton={this.handleBackButton}
    >
      {children}
    </HeaderNavigation>);
  }

  render() {
    return (
      <Grid item>
        {this.renderContent()}
      </Grid>
    );
  }
}

ApplicationSummaryHeader.propTypes = {
  partner: PropTypes.string,
  status: PropTypes.string,
  children: PropTypes.node,
  params: PropTypes.object,
  error: PropTypes.object,
  loading: PropTypes.bool,
  user: PropTypes.number,
  isUserFocalPoint: PropTypes.bool,
  isUserReviewer: PropTypes.bool,
  reviews: PropTypes.object,
  getAssessment: PropTypes.func,
  didWin: PropTypes.bool,
};

const mapStateToProps = (state, ownProps) => {
  const application = selectApplication(state, ownProps.params.applicationId) || {};
  const reviews = selectReview(state, ownProps.params.applicationId) || {};
  const { eoi, did_win, did_withdraw, partner: { legal_name } = {} } = application;
  return {
    status: selectApplicationStatus(state, ownProps.params.applicationId),
    partner: legal_name,
    getAssessment: id => selectAssessment(state, id),
    loading: state.applicationDetails.status.loading,
    error: state.applicationDetails.status.error,
    isUserFocalPoint: isUserAFocalPoint(state, eoi),
    isUserReviewer: isUserAReviewer(state, eoi),
    reviews,
    user: state.session.userId,
    didWin: did_win,
    didWithdraw: did_withdraw,
  };
};

const containerApplicationSummaryHeader = connect(
  mapStateToProps,
)(ApplicationSummaryHeader);

export default containerApplicationSummaryHeader;
<commit_msg>application reviews<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import R from 'ramda';
import { connect } from 'react-redux';
import { browserHistory as history } from 'react-router';
import Tooltip from 'material-ui/Tooltip';
import Grid from 'material-ui/Grid';
import Typography from 'material-ui/Typography';

import HeaderNavigation from '../../../../common/headerNavigation';
import {
  selectApplication,
  selectApplicationStatus,
  isUserAFocalPoint,
  isUserAReviewer,
  selectReview,
  selectAssessment,
} from '../../../../../store';
import ApplicationStatusText from '../applicationStatusText';
import GridRow from '../../../../common/grid/gridRow';
import EditReviewModalButton from './reviewContent/editReviewModalButton';
import AddReviewModalButton from './reviewContent/addReviewModalButton';
import AwardApplicationButton from '../../../buttons/awardApplicationButton';
import WithdrawApplicationButton from '../../../buttons/withdrawApplicationButton';
import { APPLICATION_STATUSES } from '../../../../../helpers/constants';

const messages = {
  header: 'Application from :',
  noCfei: 'Sorry but this application doesn\'t exist',
  button: 'Award',
  tooltip: {
    notVerified: 'Partner is not verified',
    notPreselected: 'Application is not preselected',
    redFlag: 'Partner has red flag',
  },
};

const concatText = (text, message) => `${text}${message} \n`;

class ApplicationSummaryHeader extends Component {
  constructor() {
    super();
    this.handleBackButton = this.handleBackButton.bind(this);
  }

  handleBackButton() {
    const { params: { type, id } } = this.props;
    history.push(`/cfei/${type}/${id}/applications`);
  }

  renderTooltipText() {
    const { loading,
      isUserFocalPoint,
      isUserReviewer,
      reviews,
      user,
      status,
      getAssessment,
      params: { applicationId },
      didWin,
      isVerified,
      redFlags,
    } = this.props;
    let text = '';
    if (status !== APPLICATION_STATUSES.PRE) {
      text = concatText(text, messages.tooltip.notPreselected);
    }
    if (!isVerified) text = concatText(text, messages.tooltip.notVerified);
    if (redFlags) text = concatText(text, messages.tooltip.redFlag);
    return text;
  }

  renderActionButton() {
    const { loading,
      isUserFocalPoint,
      isUserReviewer,
      reviews,
      user,
      status,
      getAssessment,
      params: { applicationId },
      didWin,
      isVerified,
      redFlags,
    } = this.props;
    const disableAward = loading
      || status !== APPLICATION_STATUSES.PRE
      || !isVerified
      || redFlags;
    const disableWithdraw = loading || status !== APPLICATION_STATUSES.PRE;
    if (isUserFocalPoint) {
      if (didWin) {
        return (<WithdrawApplicationButton
          disabled={disableWithdraw}
          raised
          applicationId={applicationId}
        />);
      }
      return (
        <Tooltip
          style={{ whiteSpace: 'pre-line' }}
          disableTriggerFocus={!disableAward}
          disableTriggerHover={!disableAward}
          disableTriggerTouch={!disableAward}
          id="tooltip-award-button"
          open
          title={this.renderTooltipText()}
          placement="bottom"
        >
          <div>
            <AwardApplicationButton
              disabled={disableAward}
              applicationId={applicationId}
            />
          </div>
        </Tooltip>);
    } else if (isUserReviewer) {
      if (R.prop(user, reviews)) {
        return (<EditReviewModalButton
          assessmentId={reviews[user]}
          scores={getAssessment(reviews[user])}
          reviewer={user}
          disabled={disabled}
        />);
      }
      return (<AddReviewModalButton
        raised
        reviewer={user}
        disabled={disabled}
      />);
    }
    return <div />;
  }

  renderContent() {
    const {
      partner,
      status,
      children,
      params: { type },
      error,
    } = this.props;
    if (error.notFound) {
      return <Typography >{messages.noApplication}</Typography>;
    } else if (error.message) {
      return <Typography >{error.message}</Typography>;
    }
    return (<HeaderNavigation
      title={`${messages.header} ${partner}`}
      header={<GridRow align="center">
        <ApplicationStatusText status={status} />
        {this.renderActionButton()}
      </GridRow>
      }
      backButton
      handleBackButton={this.handleBackButton}
    >
      {children}
    </HeaderNavigation>);
  }

  render() {
    return (
      <Grid item>
        {this.renderContent()}
      </Grid>
    );
  }
}

ApplicationSummaryHeader.propTypes = {
  partner: PropTypes.string,
  status: PropTypes.string,
  children: PropTypes.node,
  params: PropTypes.object,
  error: PropTypes.object,
  loading: PropTypes.bool,
  user: PropTypes.number,
  isUserFocalPoint: PropTypes.bool,
  isUserReviewer: PropTypes.bool,
  reviews: PropTypes.object,
  getAssessment: PropTypes.func,
  didWin: PropTypes.bool,
  isVerified: PropTypes.bool,
  redFlags: PropTypes.number,
};

const mapStateToProps = (state, ownProps) => {
  const application = selectApplication(state, ownProps.params.applicationId) || {};
  const reviews = selectReview(state, ownProps.params.applicationId) || {};
  const { eoi,
    did_win,
    did_withdraw,
    partner: {
      legal_name,
      partner_additional: {
        flagging_status: {
          red: redFlags = 0,
        } = {},
        is_verified: isVerified,
      } = {},
    } = {},
  } = application;
  return {
    status: selectApplicationStatus(state, ownProps.params.applicationId),
    partner: legal_name,
    getAssessment: id => selectAssessment(state, id),
    loading: state.applicationDetails.status.loading,
    error: state.applicationDetails.status.error,
    isUserFocalPoint: isUserAFocalPoint(state, eoi),
    isUserReviewer: isUserAReviewer(state, eoi),
    reviews,
    user: state.session.userId,
    didWin: did_win,
    didWithdraw: did_withdraw,
    isVerified,
    redFlags,
  };
};

const containerApplicationSummaryHeader = connect(
  mapStateToProps,
)(ApplicationSummaryHeader);

export default containerApplicationSummaryHeader;
<|endoftext|>


<commit_before>const $ = require('jquery');

var assARRAY = ['grunt','grunt','shirt','towel','jesus','jorge','jesus','girly','gushy','tanks'];

var lingo = new Lingo();
var mysteryWord = lingo.generateMysteryWord(assARRAY);
var mysteryWordArray = lingo.generateWordArray(mysteryWord);

function mysteryRow(){
  return "
"+mysteryWordArray[0]+"	"+mysteryWordArray[1]+"	"+mysteryWordArray[2]+"	"+mysteryWordArray[3]+"	"+mysteryWordArray[4]+"
";
}

$('.input-tile').before(mysteryRow());
function Lingo(){
  $(document).ready(function(){
    $('#start-button').on('click',function(){
    });
  });
  Lingo.prototype.generateMysteryWord = function(array) {
      var mysteryWord = array[(Math.floor(Math.random()*(array.length)))];
      return mysteryWord;
  };
  Lingo.prototype.generateWordArray = function(word) {
    return word.toLowerCase().split('');
  };
  Lingo.prototype.checkWordArrayForLetter = function(wordArray, character) {
    for (var i = 0; i < wordArray.length; i++) {
      if (wordArray[i] === character) {
        return true;
      }
    }
  };
  Lingo.prototype.getCharIndex = function(wordArray, character) {
    for (var i = 0; i < wordArray.length; i++) {
      if (wordArray[i] === character) {
        return i;
      }
    }
  };
  Lingo.prototype.getGridOrange = function (wordArray, character, index) {
     var mysteryCharacterIndex = this.getCharIndex(wordArray, character);
     if (mysteryCharacterIndex === index) { return 'orange'; }
   };
  Lingo.prototype.getGridYellow = function (wordArray, character) {
     var characterExistsInWord = this.checkWordArrayForLetter(wordArray, character);
     if (characterExistsInWord) { return 'yellow'; }
   };
var guess = $('input').on('keypress',function(event){
  if (isLetter(event)) {
    var nextInput = guess.get(guess.index(this)+1);
    if (nextInput) { nextInput.focus(); }
  }
  function swapRow(){
    var row = guess.closest('tr');
    row.insertAfter(row.next());
  }
  function clearInputRow(){
    guess.map(function(){
      return this.value = "";
    });
  }
  function getUserWordArray(){
    var userWordArray = guess.map(function(){
       return this.value;
    }).get();
    return userWordArray;
  }
  function newWordRow(){
    var userWordArray = getUserWordArray();
    return "
"+userWordArray[0]+"	"+userWordArray[1]+"	"+userWordArray[2]+"	"+userWordArray[3]+"	"+userWordArray[4]+"
";
  }
  function prependRow(){
    guess.closest('tr').after(newWordRow());
  }
  if (event.which === 13) {
    var userWordArray = getUserWordArray();
    checkUserGuess(userWordArray, mysteryWordArray);
    prependRow();
    swapRow();
    clearInputRow();
    removeRow();
    $('#1').focus();
  }
});

$('input').keydown(function(){ // DELETE KEY NOT PERFECT
  if (event.which === 8) {
    console.log('delete');
    var lastInput = guess.get(guess.index(this)-1);
    if (lastInput) { lastInput.focus(); }
  }
});
function removeRow() {
  // $('tr:last').remove();
}

function isLetter(event){
  if (event.keyCode >= 97 && event.keyCode <= 122 ) {
    return true;
  }
}
function checkUserGuess(userWordArray, mysteryWordArray){
  for (var i = 0; i < userWordArray.length; i++) {
    var lingo = new Lingo();
    var character = userWordArray[i];
    var mysteryCharacter = mysteryWordArray[i];
    if (character === mysteryCharacter) {
      console.log('orange');
    } else if (lingo.checkWordArrayForLetter(mysteryWordArray, character)){
      console.log('yellow');
    } else {
      console.log('not there');
    }
  }
}

}
module.exports = Lingo;
<commit_msg>adds color classes to row<commit_after>const $ = require('jquery');

var assARRAY = ['grunt','grunt','shirt','towel','jesus','jorge','jesus','girly','gushy','tanks'];

var lingo = new Lingo();
var mysteryWord = lingo.generateMysteryWord(assARRAY);
var mysteryWordArray = lingo.generateWordArray(mysteryWord);

function mysteryRow(){
  return "
"+mysteryWordArray[0]+"	"+mysteryWordArray[1]+"	"+mysteryWordArray[2]+"	"+mysteryWordArray[3]+"	"+mysteryWordArray[4]+"
";
}

$('.input-tile').before(mysteryRow());
function Lingo(){
  $(document).ready(function(){
    $('#start-button').on('click',function(){
    });
  });
  Lingo.prototype.generateMysteryWord = function(array) {
      var mysteryWord = array[(Math.floor(Math.random()*(array.length)))];
      return mysteryWord;
  };
  Lingo.prototype.generateWordArray = function(word) {
    return word.toLowerCase().split('');
  };
  Lingo.prototype.checkWordArrayForLetter = function(wordArray, character) {
    for (var i = 0; i < wordArray.length; i++) {
      if (wordArray[i] === character) {
        return true;
      }
    }
  };
  Lingo.prototype.getCharIndex = function(wordArray, character) {
    for (var i = 0; i < wordArray.length; i++) {
      if (wordArray[i] === character) {
        return i;
      }
    }
  };
  Lingo.prototype.getGridOrange = function (wordArray, character, index) {
     var mysteryCharacterIndex = this.getCharIndex(wordArray, character);
     if (mysteryCharacterIndex === index) { return 'orange'; }
   };
  Lingo.prototype.getGridYellow = function (wordArray, character) {
     var characterExistsInWord = this.checkWordArrayForLetter(wordArray, character);
     if (characterExistsInWord) { return 'yellow'; }
   };
var guess = $('input').on('keypress',function(event){
  if (isLetter(event)) {
    var nextInput = guess.get(guess.index(this)+1);
    if (nextInput) { nextInput.focus(); }
  }
  function swapRow(){
    var row = guess.closest('tr');
    row.insertAfter(row.next());
  }
  function clearInputRow(){
    guess.map(function(){
      return this.value = "";
    });
  }
  function getUserWordArray(){
    var userWordArray = guess.map(function(){
       return this.value;
    }).get();
    return userWordArray;
  }
  function newWordRow(){
    var userWordArray = getUserWordArray();
    var colorArray = checkUserGuess(userWordArray,mysteryWordArray);
    return "
"+userWordArray[0]+"	"+userWordArray[1]+"	"+userWordArray[2]+"	"+userWordArray[3]+"	"+userWordArray[4]+"
";
  }
  function prependRow(){
    guess.closest('tr').after(newWordRow());
  }
  if (event.which === 13) {
    debugger;
    prependRow();
    clearInputRow();
    swapRow();
    removeRow();
    $('#1').focus();
  }
});

$('input').keydown(function(){ // DELETE KEY NOT PERFECT
  if (event.which === 8) {
    console.log('delete');
    var lastInput = guess.get(guess.index(this)-1);
    if (lastInput) { lastInput.focus(); }
  }
});
function removeRow() {
  $('tr:last').remove();
}

function isLetter(event){
  if (event.keyCode >= 97 && event.keyCode <= 122 ) {
    return true;
  }
}
function checkUserGuess(userWordArray, mysteryWordArray){
  var colorArray = [];
  for (var i = 0; i < userWordArray.length; i++) {
    var lingo = new Lingo();
    var character = userWordArray[i];
    var mysteryCharacter = mysteryWordArray[i];
    if (character === mysteryCharacter) {
      colorArray.push('orange');
    } else if (lingo.checkWordArrayForLetter(mysteryWordArray, character)){
      colorArray.push('yellow');
    } else {
      colorArray.push('none');
    }
  }
  return colorArray;
}

}
module.exports = Lingo;
<|endoftext|>


<commit_before>import SPELLS from 'common/SPELLS';
import ITEMS from 'common/ITEMS';
import CoreAbilities from 'parser/core/modules/Abilities';

class Abilities extends CoreAbilities {
  spellbook() {
    const combatant = this.selectedCombatant;
    const brewCooldown = 15 - (combatant.hasTalent(SPELLS.LIGHT_BREWING_TALENT.id) ? 3 : 0);
    return [
      // Rotational Spells
      {
        spell: SPELLS.KEG_SMASH,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 8 / (1 + haste),
        charges: combatant.hasShoulder(ITEMS.STORMSTOUTS_LAST_GASP.id) ? 2 : 1,
        castEfficiency: {
          suggestion: true,
        },
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.BLACKOUT_STRIKE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: 3,
        castEfficiency: {
          suggestion: true,
        },
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.BREATH_OF_FIRE,
        isDefensive: true,
        buffSpellId: SPELLS.BREATH_OF_FIRE_DEBUFF.id,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: 15,
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.TIGER_PALM,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.RUSHING_JADE_WIND_TALENT_BREWMASTER,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 6 / (1 + haste),
        enabled: combatant.hasTalent(SPELLS.RUSHING_JADE_WIND_TALENT_BREWMASTER.id),
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.CRACKLING_JADE_LIGHTNING,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          // This was tested in-game (in Legion): it does NOT have a static GCD but a base GCD of 1sec and scales with Haste
          base: 1500,
        },
      },
      // Cooldowns
      {
        // it is possible to refer to the shared CD using *either* spell
        // id
        spell: [SPELLS.IRONSKIN_BREW, SPELLS.PURIFYING_BREW],
        buffSpellId: SPELLS.IRONSKIN_BREW_BUFF.id,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: haste => brewCooldown / (1 + haste),
        charges: combatant.hasTalent(SPELLS.LIGHT_BREWING_TALENT.id) ? 4 : 3,
        gcd: null,
        castEfficiency: {
          recommendedEfficiency: 0.9,
        },
      },
      {
        spell: SPELLS.BLACK_OX_BREW_TALENT,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 120,
        castEfficiency: {
          suggestion: false,
          recommendedEfficiency: 0.7,
        },
        enabled: combatant.hasTalent(SPELLS.BLACK_OX_BREW_TALENT.id),
        gcd: null,
      },
      {
        spell: SPELLS.GUARD_TALENT,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 30,
        castEfficiency: {
          suggestion: false,
          recommendedEfficiency: 0.7,
        },
        enabled: combatant.hasTalent(SPELLS.GUARD_TALENT.id),
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.EXPEL_HARM,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        gcd: {
          static: 500,
        },
      },
      {
        spell: SPELLS.FORTIFYING_BREW_BRM,
        buffSpellId: SPELLS.FORTIFYING_BREW_BRM_BUFF.id,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 420,
        gcd: null,
      },
      {
        spell: SPELLS.HEALING_ELIXIR_TALENT,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 30,
        enabled: combatant.hasTalent(SPELLS.HEALING_ELIXIR_TALENT.id),
        gcd: null,
      },
      {
        spell: SPELLS.DAMPEN_HARM_TALENT,
        buffSpellId: SPELLS.DAMPEN_HARM_TALENT.id,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 120,
        enabled: combatant.hasTalent(SPELLS.DAMPEN_HARM_TALENT.id),
        gcd: null,
      },
      {
        spell: SPELLS.ZEN_MEDITATION,
        buffSpellId: SPELLS.ZEN_MEDITATION.id,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 300,
        gcd: null,
      },
      // Utility
      {
        spell: SPELLS.RING_OF_PEACE_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: combatant.hasTalent(SPELLS.RING_OF_PEACE_TALENT.id),
        gcd: {
          // This was tested in-game (in Legion): it does NOT have a static GCD but a base GCD of 1sec and scales with Haste
          base: 1500,
        },
      },
      {
        spell: SPELLS.CHI_TORPEDO_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: combatant.hasTalent(SPELLS.CHI_TORPEDO_TALENT.id),
        // Both Roll and Chi Torpedo don't actually have a GCD but block all spells during its animation for about the same duration, so maybe time it in-game and mark it as channeling instead? The issue is you can follow up any ability on the GCD with chi torpedo/roll, so it can still cause overlap.
        gcd: null,
      },
      {
        spell: SPELLS.ROLL,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: !combatant.hasTalent(SPELLS.CHI_TORPEDO_TALENT.id),
        // Both Roll and Chi Torpedo don't actually have a GCD but block all spells during its animation for about the same duration, so maybe time it in-game and mark it as channeling instead? The issue is you can follow up any ability on the GCD with chi torpedo/roll, so it can still cause overlap.
        gcd: null,
      },
      {
        spell: SPELLS.TRANSCENDENCE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.TRANSCENDENCE_TRANSFER,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          // This was tested in-game (in Legion): it does NOT have a static GCD but a base GCD of 1sec and scales with Haste
          base: 1500,
        },
      },
      {
        spell: SPELLS.INVOKE_NIUZAO_THE_BLACK_OX_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: combatant.hasTalent(SPELLS.INVOKE_NIUZAO_THE_BLACK_OX_TALENT.id),
        cooldown: 180,
        gcd: null,
      },
      {
        spell: SPELLS.SUMMON_BLACK_OX_STATUE_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: combatant.hasTalent(SPELLS.SUMMON_BLACK_OX_STATUE_TALENT.id),
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.PARALYSIS,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.PROVOKE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: null,
      },
      {
        spell: SPELLS.SPEAR_HAND_STRIKE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: null,
      },
      // Its unlikely that these spells will ever be cast but if they are they will show.
      {
        spell: SPELLS.DETOX_ENERGY,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          // This was tested in-game (in Legion): it does NOT have a static GCD but a base GCD of 1sec and scales with Haste
          base: 1500,
        },
      },
      {
        spell: SPELLS.VIVIFY, // don't know if the vivify spell has been updated to the new ID yet
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.TIGERS_LUST_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: combatant.hasTalent(SPELLS.TIGERS_LUST_TALENT.id),
        gcd: {
          static: 1000,
        },
      },
    ];
  }
}

export default Abilities;
<commit_msg>[Monk] Remove legion Legendary affecting an ability<commit_after>import SPELLS from 'common/SPELLS';
import CoreAbilities from 'parser/core/modules/Abilities';

class Abilities extends CoreAbilities {
  spellbook() {
    const combatant = this.selectedCombatant;
    const brewCooldown = 15 - (combatant.hasTalent(SPELLS.LIGHT_BREWING_TALENT.id) ? 3 : 0);
    return [
      // Rotational Spells
      {
        spell: SPELLS.KEG_SMASH,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 8 / (1 + haste),
        charges: 1,
        castEfficiency: {
          suggestion: true,
        },
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.BLACKOUT_STRIKE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: 3,
        castEfficiency: {
          suggestion: true,
        },
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.BREATH_OF_FIRE,
        isDefensive: true,
        buffSpellId: SPELLS.BREATH_OF_FIRE_DEBUFF.id,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: 15,
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.TIGER_PALM,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.RUSHING_JADE_WIND_TALENT_BREWMASTER,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 6 / (1 + haste),
        enabled: combatant.hasTalent(SPELLS.RUSHING_JADE_WIND_TALENT_BREWMASTER.id),
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.CRACKLING_JADE_LIGHTNING,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        gcd: {
          // This was tested in-game (in Legion): it does NOT have a static GCD but a base GCD of 1sec and scales with Haste
          base: 1500,
        },
      },
      // Cooldowns
      {
        // it is possible to refer to the shared CD using *either* spell
        // id
        spell: [SPELLS.IRONSKIN_BREW, SPELLS.PURIFYING_BREW],
        buffSpellId: SPELLS.IRONSKIN_BREW_BUFF.id,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: haste => brewCooldown / (1 + haste),
        charges: combatant.hasTalent(SPELLS.LIGHT_BREWING_TALENT.id) ? 4 : 3,
        gcd: null,
        castEfficiency: {
          recommendedEfficiency: 0.9,
        },
      },
      {
        spell: SPELLS.BLACK_OX_BREW_TALENT,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 120,
        castEfficiency: {
          suggestion: false,
          recommendedEfficiency: 0.7,
        },
        enabled: combatant.hasTalent(SPELLS.BLACK_OX_BREW_TALENT.id),
        gcd: null,
      },
      {
        spell: SPELLS.GUARD_TALENT,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 30,
        castEfficiency: {
          suggestion: false,
          recommendedEfficiency: 0.7,
        },
        enabled: combatant.hasTalent(SPELLS.GUARD_TALENT.id),
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.EXPEL_HARM,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        gcd: {
          static: 500,
        },
      },
      {
        spell: SPELLS.FORTIFYING_BREW_BRM,
        buffSpellId: SPELLS.FORTIFYING_BREW_BRM_BUFF.id,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 420,
        gcd: null,
      },
      {
        spell: SPELLS.HEALING_ELIXIR_TALENT,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 30,
        enabled: combatant.hasTalent(SPELLS.HEALING_ELIXIR_TALENT.id),
        gcd: null,
      },
      {
        spell: SPELLS.DAMPEN_HARM_TALENT,
        buffSpellId: SPELLS.DAMPEN_HARM_TALENT.id,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 120,
        enabled: combatant.hasTalent(SPELLS.DAMPEN_HARM_TALENT.id),
        gcd: null,
      },
      {
        spell: SPELLS.ZEN_MEDITATION,
        buffSpellId: SPELLS.ZEN_MEDITATION.id,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 300,
        gcd: null,
      },
      // Utility
      {
        spell: SPELLS.RING_OF_PEACE_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: combatant.hasTalent(SPELLS.RING_OF_PEACE_TALENT.id),
        gcd: {
          // This was tested in-game (in Legion): it does NOT have a static GCD but a base GCD of 1sec and scales with Haste
          base: 1500,
        },
      },
      {
        spell: SPELLS.CHI_TORPEDO_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: combatant.hasTalent(SPELLS.CHI_TORPEDO_TALENT.id),
        // Both Roll and Chi Torpedo don't actually have a GCD but block all spells during its animation for about the same duration, so maybe time it in-game and mark it as channeling instead? The issue is you can follow up any ability on the GCD with chi torpedo/roll, so it can still cause overlap.
        gcd: null,
      },
      {
        spell: SPELLS.ROLL,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: !combatant.hasTalent(SPELLS.CHI_TORPEDO_TALENT.id),
        // Both Roll and Chi Torpedo don't actually have a GCD but block all spells during its animation for about the same duration, so maybe time it in-game and mark it as channeling instead? The issue is you can follow up any ability on the GCD with chi torpedo/roll, so it can still cause overlap.
        gcd: null,
      },
      {
        spell: SPELLS.TRANSCENDENCE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.TRANSCENDENCE_TRANSFER,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          // This was tested in-game (in Legion): it does NOT have a static GCD but a base GCD of 1sec and scales with Haste
          base: 1500,
        },
      },
      {
        spell: SPELLS.INVOKE_NIUZAO_THE_BLACK_OX_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: combatant.hasTalent(SPELLS.INVOKE_NIUZAO_THE_BLACK_OX_TALENT.id),
        cooldown: 180,
        gcd: null,
      },
      {
        spell: SPELLS.SUMMON_BLACK_OX_STATUE_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: combatant.hasTalent(SPELLS.SUMMON_BLACK_OX_STATUE_TALENT.id),
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.PARALYSIS,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          static: 1000,
        },
      },
      {
        spell: SPELLS.PROVOKE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: null,
      },
      {
        spell: SPELLS.SPEAR_HAND_STRIKE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: null,
      },
      // Its unlikely that these spells will ever be cast but if they are they will show.
      {
        spell: SPELLS.DETOX_ENERGY,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          // This was tested in-game (in Legion): it does NOT have a static GCD but a base GCD of 1sec and scales with Haste
          base: 1500,
        },
      },
      {
        spell: SPELLS.VIVIFY, // don't know if the vivify spell has been updated to the new ID yet
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        gcd: {
          base: 1500,
        },
      },
      {
        spell: SPELLS.TIGERS_LUST_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: combatant.hasTalent(SPELLS.TIGERS_LUST_TALENT.id),
        gcd: {
          static: 1000,
        },
      },
    ];
  }
}

export default Abilities;
<|endoftext|>


<commit_before><commit_msg>Added tests for isTitleCase validation API<commit_after>var isTitleCase = require('../validate.js').isTitleCase,
    expect      = require('chai').expect;

describe('isTitleCase API Tests', function () {
    describe('Valid tests for isTitleCase API', function () {
        it('Gaurav is a valid title case value', function () {
            expect(isTitleCase('Gaurav')).to.be.true;
        });

        it('Gaurav Luthra is a valid title case value', function () {
            expect(isTitleCase('Gaurav Luthra')).to.be.true;
        });

        it('Gaurav This Is Really Awesome is a valid title case value', function () {
            expect(isTitleCase('Gaurav This Is Really Awesome')).to.be.true;
        });

        it('Luthra is a valid title case value', function () {
            expect(isTitleCase('Luthra')).to.be.true;
        });

        it('gaurav is not a title case value', function () {
            expect(isTitleCase('gaurav')).to.be.false;
        });

        it('gauraV is not a title case value', function () {
            expect(isTitleCase('gauraV')).to.be.false;
        });

        it('A is a valid title case value', function () {
            expect(isTitleCase('A')).to.be.true;
        });

        it('### is a valid title case value', function () {
            expect(isTitleCase('###')).to.be.true;
        });

        it('string value 12 is a valid title case value', function () {
            expect(isTitleCase('12')).to.be.true;
        });

        it('empty string is a valid title case value', function () {
            expect(isTitleCase('')).to.be.true;
        });

        it('no parameter to method is not a valid title case value', function () {
            expect(isTitleCase()).to.be.false;
        });
    });

    describe('Invalid tests for isTitleCase API', function () {
        it('Date.now() is not a valid title case value', function () {
            expect(isTitleCase(Date.now())).to.be.false;
        });

        it('Date.UTC() is not a valid title case value', function () {
            expect(isTitleCase(Date.UTC())).to.be.false;
        });

        it('Boolean true is not a valid title case value', function () {
            expect(isTitleCase(true)).to.be.false;
        });

        it('undefined is not a valid title case value', function () {
            expect(isTitleCase(undefined)).to.be.false;
        });

        it('null is a valid title case value', function () {
            expect(isTitleCase(null)).to.be.false;
        });

        it('new Number(5) does not return a valid title case value', function () {
            expect(isTitleCase(new Number(5))).to.be.false;
        });

        it('new Array("hellow") does not return a valid title case value', function () {
            expect(isTitleCase(new Array('hellow'))).to.be.false;
        });

        it('["hello", "world", 1, 2, 3] is not a valid title case value value', function () {
            expect(isTitleCase(["hello", "world", 1, 2, 3])).to.be.false;
        });

        it('Number 12 is not a valid title case value', function () {
            expect(isTitleCase(12)).to.be.false;
        });
    });
});<|endoftext|>


<commit_before>import Canvas from 'canvas/Canvas.js';
import AddToDOM from 'dom/AddToDOM.js';
import BackgroundColor from 'canvas/BackgroundColor.js';

//*********//
// Globals //
//*********//

let gl = null;
let canvas = null;

//**********//
// GL Utils //
//**********//
function assert(exp, message) {
    if (!exp) {
        alert('Failed Assertion: ' + message);
        throw 'Failed Assertion: ' + message;
    }
}

function Shader(program, vs, fs) {
    return {
        program: program,
        vertexShader: vs,
        fragmentShader: fs,
        enable: function () {
            gl.useProgram(program);
        },
        disable: function () {
            gl.useProgram(null);
        },
        discard: function () {
            gl.deleteShader(vs);
            gl.deleteShader(fs);
            gl.deleteProgram(program);
        }
    };
}

function CompileShader(src, type) {
    var shader = gl.createShader(type);
    gl.shaderSource(shader, src);
    gl.compileShader(shader);
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.log('WebGL %s Shader Error: %s', type === gl.FRAGMENT_SHADER ? 'Fragment' : type === gl.VERTEX_SHADER ? 'Vertex' : 'Undefined', gl.getShaderInfoLog(shader));
        return null;
    }
    return shader;
}

function CreateShaderProgram(vs, fs) {
    var program = gl.createProgram(),
        vertexShader = CompileShader(vs, gl.VERTEX_SHADER),
        fragmentShader = CompileShader(fs, gl.FRAGMENT_SHADER);

    if (vertexShader === null || fragmentShader === null)
        return null;

    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        console.log('WebGL Program Error: %s', gl.getProgramInfoLog(program));
        return null;
    }
    return Shader(program, vertexShader, fragmentShader);
}

function CreateComputeTexture(jsArray) {
    var floatArray = new Float32Array(jsArray);
    var texture = gl.createTexture();
    var dimensions = Math.sqrt(floatArray.length) | 0;
    var byteData = new Uint8Array(floatArray.buffer);
    assert(IsPow2(floatArray.length), 'Data length is not power of 2.');
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, dimensions, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, byteData);
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, null);
    texture.floatBuffer = floatArray;
    texture.byteBuffer = byteData;
    texture.dimensions = dimensions;
    return texture;
}

function CreateRenderTarget(width, height) {
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
    gl.activeTexture(gl.TEXTURE0);
    return texture;
}

function CreateFramebuffer(dimensions) {
    var fbo = gl.createFramebuffer();
    var rbo = gl.createRenderbuffer();
    var tex = null;
    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
    gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
    tex = CreateRenderTarget(dimensions, dimensions);
    gl.framebufferTexture2D(
        gl.FRAMEBUFFER,
        gl.COLOR_ATTACHMENT0,
        gl.TEXTURE_2D,
        tex,
        0
    );
    assert(gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE, 'Frame buffer incomplete');
    gl.bindRenderbuffer(gl.RENDERBUFFER, null);
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    fbo.dimensions = dimensions;
    fbo.targetTexture = tex;
    return fbo;
}

function BindComputeFramebuffer(fbo) {
    gl.viewport(0, 0, fbo.dimensions, fbo.dimensions);
    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
}

function UnbindComputeFramebuffer() {
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    gl.viewport(0, 0, canvas.width, canvas.height);
}

function IsPow2(value) {
    return (value & (value - 1)) == 0;
}

function copyObject(obj) {
    var copy = {};
    for (var n in obj) {
        if (typeof obj[n] !== 'function') {
            copy[n] = obj[n];
        } else if (typeof obj[n] === 'object') {
            copy[n] = obj[n].toString();
        }
    }
    return copy;
}

function getGPUOutput(computeTexture, sampleSize) {
    var buffer = new Uint8Array(computeTexture.floatBuffer.byteLength);
    var output = null;
    gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
    output = new Float32Array(buffer.buffer);
    console.log('original uint8:', computeTexture.byteBuffer.subarray(0, sampleSize * 4));
    console.log('original float32:', computeTexture.floatBuffer.subarray(0, sampleSize))
    console.log('output uint8 buffer:', buffer.subarray(0, sampleSize * 4));
    console.log('output float32 buffer:', output.subarray(0, sampleSize));
}

//*************//
// Entry Point //
//*************//
(function main() {
    let vComputeSource = [
            'attribute vec4 inUV;',
            'varying vec2 outUV;',
            'void main() {',
            '   outUV = inUV.zy;',
            '   gl_Position = vec4(inUV.xy, 1.0, 1.0);',
            '}'
        ].join('\n'),
        fComputeSource = [
            'precision highp float;',
            'varying vec2 outUV;',
            'uniform sampler2D sampler;',
            'highp vec4 encode32(highp float f) {',
            '    highp float e =5.0;',
            '    highp float F = abs(f); ',
            '    highp float Sign = step(0.0,-f);',
            '    highp float Exponent = floor(log2(F)); ',
            '    highp float Mantissa = (exp2(- Exponent) * F);',
            '    Exponent = floor(log2(F) + 127.0) + floor(log2(Mantissa));',
            '    highp vec4 rgba;',
            '    rgba[0] = 128.0 * Sign  + floor(Exponent*exp2(-1.0));',
            '    rgba[1] = 128.0 * mod(Exponent,2.0) + mod(floor(Mantissa*128.0),128.0);  ',
            '    rgba[2] = floor(mod(floor(Mantissa*exp2(23.0 -8.0)),exp2(8.0)));',
            '    rgba[3] = floor(exp2(23.0)*mod(Mantissa,exp2(-15.0)));',
            '    return rgba;',
            '}',
            'highp float decode32(highp vec4 rgba) {',
            '    highp float Sign = 1.0 - step(128.0,rgba[0])*2.0;',
            '    highp float Exponent = 2.0 * mod(rgba[0],128.0) + step(128.0,rgba[1]) - 127.0; ',
            '    highp float Mantissa = mod(rgba[1],128.0)*65536.0 + rgba[2]*256.0 +rgba[3] + float(0x800000);',
            '    highp float Result =  Sign * exp2(Exponent) * (Mantissa * exp2(-23.0 )); ',
            '    return Result;',
            '}',
            'void main() {',
            '   float scalar = decode32(texture2D(sampler, outUV).abgr * 255.0) ;',
            //  Simple Computation for testing.
            '   scalar *= 2.0;',
            '   vec4 result = encode32(scalar).abgr / 255.0;',
            '   gl_FragColor = result;',
            '}'
        ].join('\n'),
        fOutputSource = [
            'precision mediump float;',
            'varying vec2 outUV;',
            'uniform sampler2D sampler;',
            'void main() {',
            '   gl_FragColor = texture2D(sampler,  outUV);',
            '}'
        ].join('\n'),
        shaderCompute = null,
        shaderOutput = null,
        loc = null,
        vbo = null,
        fbo = null,
        uvData = new Float32Array([-1, -1, 0, 0, 1, 1, 1, 1, -1, 1, 0, 1, -1, -1, 0, 0, 1, -1, 1, 0, 1, 1, 1, 1]),
        computeTexture = null;

    canvas = Canvas(512, 512);
    AddToDOM(canvas, 'game');

    //***************//
    // WebGL Prelude //
    //***************//
    gl = canvas.getContext('experimental-webgl');
    window.gl = gl;
    shaderOutput = CreateShaderProgram(vComputeSource, fOutputSource);
    shaderCompute = CreateShaderProgram(vComputeSource, fComputeSource);
    shaderCompute.enable();
    loc = gl.getAttribLocation(shaderCompute.program, 'inUV');
    vbo = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
    gl.bufferData(gl.ARRAY_BUFFER, uvData, gl.STATIC_DRAW);
    gl.enableVertexAttribArray(loc);
    gl.vertexAttribPointer(loc, 4, gl.FLOAT, gl.FALSE, 0, 0);
    //***************//

    //********************//
    // Setup Compute Data //
    //********************//
    computeTexture = CreateComputeTexture(
    //  Simple input data to feed the GPU
        [1.4, 2.3, 3.2, 4.1]
    );
    gl.bindTexture(gl.TEXTURE_2D, null);
    fbo = CreateFramebuffer(computeTexture.dimensions);
    BindComputeFramebuffer(fbo);
    //*********************//
    // Execute GPU Compute //
    //*********************//
    gl.bindTexture(gl.TEXTURE_2D, computeTexture);
    gl.drawArrays(gl.TRIANGLES, 0, 6);
    getGPUOutput(computeTexture, 4);
    shaderCompute.disable();
    //**************//
    // Draw Output  //
    //**************//
    // This part isn't necessary
    UnbindComputeFramebuffer();
    shaderOutput.enable();
    gl.clearColor(0, 0, 0, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.bindTexture(gl.TEXTURE_2D, fbo.targetTexture);
    gl.drawArrays(gl.TRIANGLES, 0, 6);
}());<commit_msg>multitexture gpgpu test<commit_after>//*********//
// Globals //
//*********//

let gl = null;
let canvas = null;

//**********//
// GL Utils //
//**********//
function assert(exp, message) {
    if (!exp) {
        alert('Failed Assertion: ' + message);
        throw 'Failed Assertion: ' + message;
    }
}

function Shader(program, vs, fs) {
    return {
        program: program,
        vertexShader: vs,
        fragmentShader: fs,
        enable: function () {
            gl.useProgram(program);
        },
        disable: function () {
            gl.useProgram(null);
        },
        discard: function () {
            gl.deleteShader(vs);
            gl.deleteShader(fs);
            gl.deleteProgram(program);
        }
    };
}

function CompileShader(src, type) {
    var shader = gl.createShader(type);
    gl.shaderSource(shader, src);
    gl.compileShader(shader);
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.log('WebGL %s Shader Error: %s', type === gl.FRAGMENT_SHADER ? 'Fragment' : type === gl.VERTEX_SHADER ? 'Vertex' : 'Undefined', gl.getShaderInfoLog(shader));
        return null;
    }
    return shader;
}

function CreateShaderProgram(vs, fs) {
    var program = gl.createProgram(),
        vertexShader = CompileShader(vs, gl.VERTEX_SHADER),
        fragmentShader = CompileShader(fs, gl.FRAGMENT_SHADER);

    if (vertexShader === null || fragmentShader === null)
        return null;

    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        console.log('WebGL Program Error: %s', gl.getProgramInfoLog(program));
        return null;
    }
    return Shader(program, vertexShader, fragmentShader);
}

function CreateRenderTarget(width, height) {
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
    gl.activeTexture(gl.TEXTURE0);
    return texture;
}

function CreateFramebuffer(width, height) {
    var fbo = gl.createFramebuffer();
    var rbo = gl.createRenderbuffer();
    var tex = null;
    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
    gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
    tex = CreateRenderTarget(width, height);
    gl.framebufferTexture2D(
        gl.FRAMEBUFFER,
        gl.COLOR_ATTACHMENT0,
        gl.TEXTURE_2D,
        tex,
        0
    );
    assert(gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE, 'Frame buffer incomplete');
    gl.bindTexture(gl.TEXTURE_2D, null);
    gl.bindRenderbuffer(gl.RENDERBUFFER, null);
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    fbo.width = width;
    fbo.height = height;
    fbo.targetTexture = tex;
    return fbo;
}

function BindFramebuffer(fbo) {
    gl.viewport(0, 0, fbo.width, fbo.height);
    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
}

function UnbindFramebuffer() {
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    gl.viewport(0, 0, canvas.width, canvas.height);
}

//****************//
// GPGPU Specific //
//****************//
function CreateComputeTexture(shaderProgram, samplerName, jsArray) {
    var floatArray = new Float32Array(jsArray);
    var texture = gl.createTexture();
    var dimensions = Math.sqrt(floatArray.length) | 0;
    var byteData = new Uint8Array(floatArray.buffer);
    assert(IsPow2(floatArray.length), 'Data length is not power of 2.');
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, dimensions, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, byteData);
    gl.bindTexture(gl.TEXTURE_2D, null);
    texture.floatBuffer = floatArray;
    texture.byteBuffer = byteData;
    texture.dimensions = dimensions;
    texture.itemCount = jsArray.length;
    texture.samplerLocation = gl.getUniformLocation(shaderProgram, samplerName);
    //console.log('Packed 32-Bit Float Data: ', floatArray);
    return texture;
}

function BindComputeTexture(texture, textureUnit) {
    gl.uniform1i(texture.samplerLocation, textureUnit);
    gl.activeTexture(gl.TEXTURE0 + textureUnit);
    gl.bindTexture(gl.TEXTURE_2D, texture);
}

function IsPow2(value) {
    return (value & (value - 1)) == 0;
}

function getGPUOutput(fsize, fbo) {
    var buffer = null;
    var output = null;
    output = new Float32Array(fsize);
    buffer = new Uint8Array(output.buffer);
    gl.readPixels(0, 0, fbo.width, fbo.height, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
    return output;
}

function getMaxValue(array) {
    var max = 0;
    for (var i = 0, l = array.length; i < l; ++i) {
        max = array[i] > max ? array[i] : max;
    }
    return max;
}

//*************//
// Entry Point //
//*************//
(function main() {
    let vComputeSource = [
            'attribute vec4 inUV;',
            'varying vec2 outUV;',
            'void main() {',
            '   outUV = inUV.zy;',
            '   gl_Position = vec4(inUV.xy, 1.0, 1.0);',
            '}'
        ].join('\n'),
        fComputeSource = [
            'precision highp float;',
            'varying vec2 outUV;',
            'uniform sampler2D sampler0;',
            'uniform sampler2D sampler1;',
            'uniform sampler2D sampler2;',
            'uniform sampler2D sampler3;',
            // Source for RGBA <-> 32-Bit Float Encoding
            // http://stackoverflow.com/a/7237286
            'highp vec4 encode32(highp float f) {',
            '    highp float e =5.0;',
            '    highp float F = abs(f); ',
            '    highp float Sign = step(0.0,-f);',
            '    highp float Exponent = floor(log2(F)); ',
            '    highp float Mantissa = (exp2(- Exponent) * F);',
            '    Exponent = floor(log2(F) + 127.0) + floor(log2(Mantissa));',
            '    highp vec4 rgba;',
            '    rgba[0] = 128.0 * Sign  + floor(Exponent*exp2(-1.0));',
            '    rgba[1] = 128.0 * mod(Exponent,2.0) + mod(floor(Mantissa*128.0),128.0);  ',
            '    rgba[2] = floor(mod(floor(Mantissa*exp2(23.0 -8.0)),exp2(8.0)));',
            '    rgba[3] = floor(exp2(23.0)*mod(Mantissa,exp2(-15.0)));',
            '    return rgba;',
            '}',
            'highp float decode32(highp vec4 rgba) {',
            '    highp float Sign = 1.0 - step(128.0,rgba[0])*2.0;',
            '    highp float Exponent = 2.0 * mod(rgba[0],128.0) + step(128.0,rgba[1]) - 127.0; ',
            '    highp float Mantissa = mod(rgba[1],128.0)*65536.0 + rgba[2]*256.0 +rgba[3] + float(0x800000);',
            '    highp float Result =  Sign * exp2(Exponent) * (Mantissa * exp2(-23.0 )); ',
            '    return Result;',
            '}',
            'void main() {',
            '   float aX = decode32(texture2D(sampler0, outUV).abgr * 255.0) ;',
            '   float aY = decode32(texture2D(sampler1, outUV).abgr * 255.0) ;',
            '   float bX = decode32(texture2D(sampler2, outUV).abgr * 255.0) ;',
            '   float bY = decode32(texture2D(sampler3, outUV).abgr * 255.0) ;',
            //  Simple Computation for testing.
            '   vec4 vecResult = encode32(sqrt((aX  - bX) * (aX  - bX) + (aY  - bY) * (aY  - bY))).abgr / 255.0;',
            '   gl_FragColor = vecResult;',
            '}'
        ].join('\n'),
        fOutputSource = [
            'precision mediump float;',
            'varying vec2 outUV;',
            'uniform sampler2D sampler;',
            'void main() {',
            '   gl_FragColor = texture2D(sampler,  outUV);',
            '}'
        ].join('\n'),
        shaderCompute = null,
        shaderOutput = null,
        loc = null,
        vbo = null,
        fbo = null,
        computeTexture0 = null,
        computeTexture1 = null,
        computeTexture2 = null,
        computeTexture3 = null,
        sqrtSampleSize = 1024,
        maxComp = sqrtSampleSize * sqrtSampleSize,
        testDataPX = new Float32Array(maxComp),
        testDataPY = new Float32Array(maxComp),
        testDataVX = new Float32Array(maxComp),
        testDataVY = new Float32Array(maxComp),
        t0 = 0,
        t1 = 0,
        gpuTime = 0,
        cpuTime = 0,
        cpuOutput = new Float32Array(maxComp);

    //***************//
    // WebGL Prelude //
    //***************//
    canvas = document.createElement('canvas');
    gl = canvas.getContext('experimental-webgl');
    window.gl = gl;
    shaderOutput = CreateShaderProgram(vComputeSource, fOutputSource);
    shaderCompute = CreateShaderProgram(vComputeSource, fComputeSource);
    shaderCompute.enable();
    loc = gl.getAttribLocation(shaderCompute.program, 'inUV');
    vbo = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
    gl.bufferData(
        gl.ARRAY_BUFFER,
        new Float32Array([-1, -1, 0, 0, 1, 1, 1, 1, -1, 1, 0, 1, -1, -1, 0, 0, 1, -1, 1, 0, 1, 1, 1, 1]),
        gl.STATIC_DRAW
    );
    gl.enableVertexAttribArray(loc);
    gl.vertexAttribPointer(loc, 4, gl.FLOAT, gl.FALSE, 0, 0);

    //***************//
    // Generate Data //
    //***************//
    for (var i = 0; i < maxComp; ++i) {
        testDataPX[i] = i + ((Math.random() * i) % 10);
        testDataPY[i] = i + ((Math.random() * i) % 10);
        testDataVX[i] = i + ((Math.random() * i) % 10);
        testDataVY[i] = i + ((Math.random() * i) % 10);
    }

    //********************//
    // Setup Compute Data //
    //********************//
    fbo = CreateFramebuffer(sqrtSampleSize, sqrtSampleSize);
    BindFramebuffer(fbo);
    computeTexture0 = CreateComputeTexture(
        shaderCompute.program, 'sampler0',
        testDataPX
    );
    computeTexture1 = CreateComputeTexture(
        shaderCompute.program, 'sampler1',
        testDataPY
    );
    computeTexture2 = CreateComputeTexture(
        shaderCompute.program, 'sampler2',
        testDataVX
    );
    computeTexture3 = CreateComputeTexture(
        shaderCompute.program, 'sampler3',
        testDataVY
    );
    //*********************//
    // Execute GPU Compute //
    //*********************//
    BindComputeTexture(computeTexture0, 0);
    BindComputeTexture(computeTexture1, 1);
    BindComputeTexture(computeTexture2, 2);
    BindComputeTexture(computeTexture3, 3);
    console.log('Sampling %d 2D vectors', maxComp * 2);
    t0 = performance.now();
    gl.drawArrays(gl.TRIANGLES, 0, 6);
    t1 = performance.now();
    //var maxValue = getMaxValue(getGPUOutput(maxComp, fbo));
    gpuTime = t1 - t0;
    console.log('GPU Execution Time: %f milliseconds', gpuTime);

    t0 = performance.now();
    for (var i = 0, aX = 0, aY = 0, bX = 0, bY = 0, sqrt = Math.sqrt; i < maxComp; ++i) {
        aX = testDataPX[i];
        aY = testDataPY[i];
        bX = testDataVX[i];
        bY = testDataVY[i];
        cpuOutput[i] = sqrt((aX - bX) * (aX - bX) + (aY - bY) * (aY - bY));
    }
    //maxValue = getMaxValue(cpuOutput);
    t1 = performance.now();
    cpuTime = t1 - t0;
    console.log('CPU Execution Time: %f milliseconds', cpuTime);

    // Cleanup
    UnbindFramebuffer();
    shaderCompute.disable();
    shaderCompute.discard();
    shaderOutput.enable();
    shaderOutput.discard();
}());<|endoftext|>


<commit_before>module.exports = function (kuzzle) {
  var
    _ = require('lodash'),
    jwt = require('jsonwebtoken'),
    ms = require('ms'),
    q = require('q'),
    Token = require('../security/token'),
    Repository = require('./repository'),
    InternalError = require('kuzzle-common-objects').Errors.internalError,
    UnauthorizedError = require('kuzzle-common-objects').Errors.unauthorizedError;

  function parseTimespan(time) {
    var milliseconds;

    if (typeof time === 'string') {
      milliseconds = ms(time);

      if (typeof milliseconds === 'undefined') {
        return -1;
      }

      return milliseconds;
    }
    else if (typeof time === 'number') {
      return time;
    }

    return -1;
  }

  function TokenRepository (opts) {
    var options = opts || {};

    if (options.ttl !== undefined) {
      this.ttl = options.ttl;
    }
  }

  TokenRepository.prototype = new Repository(kuzzle, {
    index: kuzzle.config.internalIndex,
    collection: 'token',
    ObjectConstructor: Token,
    cacheEngine: kuzzle.services.list.tokenCache,
    readEngine: null
  });

  TokenRepository.prototype.expire = function(token) {
    var
      error,
      deferred = q.defer();

    Repository.prototype.expireFromCache.call(this, token)
      .then(() => {
        kuzzle.tokenManager.expire(token);

        deferred.resolve();
      })
      .catch(err => {
        error = new InternalError('Error expiring token');
        error.details = err;

        deferred.reject(error);
      });

    return deferred.promise;
  };

  TokenRepository.prototype.generateToken = function (user, context, opts) {
    var
      expiresIn,
      token = new Token(),
      deferred,
      options = opts || {},
      encodedToken,
      error;

    if (!user || user._id === null) {
      error = new InternalError('Unknown User : cannot generate token');
      return q.reject(error);
    }

    if (!context || context.connection === null) {
      error = new InternalError('Unknown context connection : cannot generate token');
      return q.reject(error);
    }

    deferred = q.defer();

    if (!options.algorithm) {
      options.algorithm = kuzzle.config.jsonWebToken.algorithm;
    }
    if (!options.expiresIn) {
      options.expiresIn = kuzzle.config.jsonWebToken.expiresIn;
    }

    try {
      expiresIn = parseTimespan(options.expiresIn);
      encodedToken = jwt.sign({_id: user._id}, kuzzle.config.jsonWebToken.secret, options);
      this.hydrate(token, {
        _id: encodedToken,
        user: user._id,
        ttl: expiresIn,
        expiresAt: Date.now() + expiresIn
      })
      .then((result) => {
        this.persistToCache(result);

        kuzzle.tokenManager.add(result, context);

        deferred.resolve(result);
      })
      .catch((err) => {
        error = new InternalError('Unable to generate token for unknown user');
        error.details = err.message;
        error.stack = err.stack;
        deferred.reject(error);
      });
    }
    catch (err) {
      error = new InternalError('Error while generating token');
      error.details = err.message;
      error.stack = err.stack;
      deferred.reject(error);
    }

    return deferred.promise;
  };

  TokenRepository.prototype.verifyToken = function (token) {
    var
      deferred,
      error;

    if (token === null) {
      return this.anonymous();
    }

    deferred = q.defer();

    try {
      jwt.verify(token, kuzzle.config.jsonWebToken.secret);

      Repository.prototype.load.call(this, token)
        .then(userToken => {
          if (userToken === null) {
            error = new UnauthorizedError('Invalid token', 401);
            deferred.reject(error);
            return deferred;
          }

          deferred.resolve(userToken);
        })
        .catch(function (err) {
          error = new InternalError('Unknown user');
          error.details = err;

          deferred.reject(error);
        });
    }
    catch (err) {
      if (err instanceof jwt.TokenExpiredError) {
        error = new UnauthorizedError('Token expired', 401);
        error.details = {
          subCode: error.subCodes.TokenExpired,
          expiredAt: err.expiredAt
        };
      }
      else if (err instanceof jwt.JsonWebTokenError) {
        error = new UnauthorizedError('Json Web Token Error', 401);
        error.details = {
          subCode: error.subCodes.JsonWebTokenError,
          description: err.message
        };
      }
      else {
        error = new InternalError('Error verifying token');
        error.details = err;
      }

      deferred.reject(error);
    }

    return deferred.promise;
  };

  TokenRepository.prototype.hydrate = function (userToken, data) {
    var
      deferred = q.defer(),
      result;

    if (!_.isObject(data)) {
      return q(userToken);
    }

    Repository.prototype.hydrate.call(this, userToken, data)
      .then(t => {
        result = t;
        if (!t.user || t.user === undefined || t.user === null) {
          t._id = undefined;
          return kuzzle.repositories.user.anonymous();
        }

        return kuzzle.repositories.user.load(t.user);
      })
      .then(function (user) {
        result.user = user;
        deferred.resolve(result);
      })
      .catch(function (error) {
        deferred.reject(error);
      });

    return deferred.promise;
  };

  TokenRepository.prototype.serializeToCache = function (token) {
    var result = {};

    Object.keys(token).forEach(function (key) {
      if (key !== 'user') {
        result[key] = token[key];
      }
    });
    result.user = token.user._id;

    return result;
  };

  TokenRepository.prototype.anonymous = function () {
    var
      token = new Token();

    token._id = undefined;

    return kuzzle.repositories.user.anonymous()
      .then(user => {
        token.user = user;
        return token;
      });
  };

  TokenRepository.prototype.serializeToDatabase = TokenRepository.prototype.serializeToCache;

  return TokenRepository;
};

<commit_msg>Reverting changes to call parent implicitly<commit_after>module.exports = function (kuzzle) {
  var
    _ = require('lodash'),
    jwt = require('jsonwebtoken'),
    ms = require('ms'),
    q = require('q'),
    Token = require('../security/token'),
    Repository = require('./repository'),
    InternalError = require('kuzzle-common-objects').Errors.internalError,
    UnauthorizedError = require('kuzzle-common-objects').Errors.unauthorizedError;

  function parseTimespan(time) {
    var milliseconds;

    if (typeof time === 'string') {
      milliseconds = ms(time);

      if (typeof milliseconds === 'undefined') {
        return -1;
      }

      return milliseconds;
    }
    else if (typeof time === 'number') {
      return time;
    }

    return -1;
  }

  function TokenRepository (opts) {
    var options = opts || {};

    if (options.ttl !== undefined) {
      this.ttl = options.ttl;
    }
  }

  TokenRepository.prototype = new Repository(kuzzle, {
    index: kuzzle.config.internalIndex,
    collection: 'token',
    ObjectConstructor: Token,
    cacheEngine: kuzzle.services.list.tokenCache,
    readEngine: null
  });

  TokenRepository.prototype.expire = function(token) {
    var
      error,
      deferred = q.defer();

    Repository.prototype.expireFromCache.call(this, token)
      .then(() => {
        kuzzle.tokenManager.expire(token);

        deferred.resolve();
      })
      .catch(err => {
        error = new InternalError('Error expiring token');
        error.details = err;

        deferred.reject(error);
      });

    return deferred.promise;
  };

  TokenRepository.prototype.generateToken = function (user, context, opts) {
    var
      expiresIn,
      token = new Token(),
      deferred,
      options = opts || {},
      encodedToken,
      error;

    if (!user || user._id === null) {
      error = new InternalError('Unknown User : cannot generate token');
      return q.reject(error);
    }

    if (!context || context.connection === null) {
      error = new InternalError('Unknown context connection : cannot generate token');
      return q.reject(error);
    }

    deferred = q.defer();

    if (!options.algorithm) {
      options.algorithm = kuzzle.config.jsonWebToken.algorithm;
    }
    if (!options.expiresIn) {
      options.expiresIn = kuzzle.config.jsonWebToken.expiresIn;
    }

    try {
      expiresIn = parseTimespan(options.expiresIn);
      encodedToken = jwt.sign({_id: user._id}, kuzzle.config.jsonWebToken.secret, options);
      this.hydrate(token, {
        _id: encodedToken,
        user: user._id,
        ttl: expiresIn,
        expiresAt: Date.now() + expiresIn
      })
      .then((result) => {
        this.persistToCache(result);

        kuzzle.tokenManager.add(result, context);

        deferred.resolve(result);
      })
      .catch((err) => {
        error = new InternalError('Unable to generate token for unknown user');
        error.details = err.message;
        error.stack = err.stack;
        deferred.reject(error);
      });
    }
    catch (err) {
      error = new InternalError('Error while generating token');
      error.details = err.message;
      error.stack = err.stack;
      deferred.reject(error);
    }

    return deferred.promise;
  };

  TokenRepository.prototype.verifyToken = function (token) {
    var
      deferred,
      error;

    if (token === null) {
      return this.anonymous();
    }

    deferred = q.defer();

    try {
      jwt.verify(token, kuzzle.config.jsonWebToken.secret);

      this.load(token)
        .then(userToken => {
          if (userToken === null) {
            error = new UnauthorizedError('Invalid token', 401);
            deferred.reject(error);
            return deferred;
          }

          deferred.resolve(userToken);
        })
        .catch(function (err) {
          error = new InternalError('Unknown user');
          error.details = err;

          deferred.reject(error);
        });
    }
    catch (err) {
      if (err instanceof jwt.TokenExpiredError) {
        error = new UnauthorizedError('Token expired', 401);
        error.details = {
          subCode: error.subCodes.TokenExpired,
          expiredAt: err.expiredAt
        };
      }
      else if (err instanceof jwt.JsonWebTokenError) {
        error = new UnauthorizedError('Json Web Token Error', 401);
        error.details = {
          subCode: error.subCodes.JsonWebTokenError,
          description: err.message
        };
      }
      else {
        error = new InternalError('Error verifying token');
        error.details = err;
      }

      deferred.reject(error);
    }

    return deferred.promise;
  };

  TokenRepository.prototype.hydrate = function (userToken, data) {
    var
      deferred = q.defer(),
      result;

    if (!_.isObject(data)) {
      return q(userToken);
    }

    Repository.prototype.hydrate.call(this, userToken, data)
      .then(t => {
        result = t;
        if (!t.user || t.user === undefined || t.user === null) {
          t._id = undefined;
          return kuzzle.repositories.user.anonymous();
        }

        return kuzzle.repositories.user.load(t.user);
      })
      .then(function (user) {
        result.user = user;
        deferred.resolve(result);
      })
      .catch(function (error) {
        deferred.reject(error);
      });

    return deferred.promise;
  };

  TokenRepository.prototype.serializeToCache = function (token) {
    var result = {};

    Object.keys(token).forEach(function (key) {
      if (key !== 'user') {
        result[key] = token[key];
      }
    });
    result.user = token.user._id;

    return result;
  };

  TokenRepository.prototype.anonymous = function () {
    var
      token = new Token();

    token._id = undefined;

    return kuzzle.repositories.user.anonymous()
      .then(user => {
        token.user = user;
        return token;
      });
  };

  TokenRepository.prototype.serializeToDatabase = TokenRepository.prototype.serializeToCache;

  return TokenRepository;
};

<|endoftext|>


<commit_before>function initMap() {
    "use strict";
    var ctx = $("#pings")[0].getContext("2d"),
        currentData = [],
        start = 0, total = 0, duration = 0, extra = 0;

    glow.map = {};
    glow.map.scale = $mc.width() / 3600;

    ctx.fillStyle = "#fff";

    /* Shuffle the array in place. (Fisher-Yates) */
    var shuffle = function(xs) {
        var i = xs.length, j, tmp;
        if (i == 0) { return; }
        while (--i) {
            j = Math.floor(Math.random() * (i + 1));
            tmp = xs[j];
            xs[j] = xs[i];
            xs[i] = tmp;
        }
    };

    /* Each ping looks like [latitude, longitude, count]. It represents the
     * numbers of downloads in the timeframe from this location. */
    glow.map.playNext = function() {
        var response = glow.data.map.next,
            /* [date, total, [pings]] */
            data = response.data,
            pings = data[2],
            newData = [];

        /* Add `count` [lat, long] pairs to newData, then shuffle the whole
         * thing. */
        for (var j = 0, jj = pings.length; j < jj; j++) {
            var ping = pings[j],
                latitude = ~~((parseFloat(ping[0]) + 180) * 10),
                longitude = ~~((-parseFloat(ping[1]) + 90) * 10),
                count = ping[2];
            for (var k = 0; k < count; k++) {
                newData.push([0, latitude, longitude]);
            }
        }
        shuffle(newData);

        /* Ping animations last 1 second so some are going to roll over. This
         * updates the time left to work with the reset timer and adds them to
         * the front of newData. */
        extra = Math.max(0, currentData.length - 1 - start);
        if (extra > 0) {
            for (var i = start, ii = currentData.length; i < ii; i++) {
                currentData[i][0] = currentData[i][0] - response.interval;
            }
            newData.unshift.apply(newData, currentData.slice(start));
        }

        /* Reset all the globals and kick off a new animation interval. */
        currentData = newData;
        start = 0;
        total = currentData.length;
        duration = response.interval * 1000;
        dbg('map total', total);

        glow.fetchMap(response.interval);
        vast.animate.over(response.interval * 1000, iteratePings, this,
                          {after: glow.map.playNext});
    };

    function iteratePings(t) {
        // t marks our progress through the interval from 0..1.
        if (start == total) {
            return;
        }
        /* We ignore the extra items when figuring out how many new pings to
         * play this iteration. The extra items get picked up as start moves
         * along. */
        var end = extra + (t * (total - extra)),
            currentAge = -1,
            progress = t * (duration / 1000),
            i, ping, age;

        // Clear out the canvas.
        for (i = start; i < end; i++) {
            ping = currentData[i];
            ctx.clearRect(ping[1] * glow.map.scale - 5, ping[2] * glow.map.scale- 5, 10, 10);
        }

        for (i = start; i < end; i++) {
            ping = currentData[i];
            if (ping[0] == 0) {
                ping[0] = progress;
            } else {
                age = progress - ping[0];
                if (age > 1) {
                    // This ping has played out, don't come back to it.
                    start++;
                } else {
                    /* Setting fillStyle is expensive according to Chrome's
                     * profiler, so only set it if the fillStyle has
                     * changed. */
                    if (age != currentAge) {
                        /* Bound the alpha between 0.01 and .99 so JavaScript
                         * doesn't write scientific notation. */
                        ctx.fillStyle = "rgba(255, 255, 255, " +
                                        Math.max(.01, Math.min(.99, (1 - age))) + ")";
                        currentAge = age;
                    }
                    ctx.beginPath();
                    ctx.arc(ping[1] * glow.map.scale, ping[2] * glow.map.scale, 5 * age, 0, Math.PI * 2);
                    ctx.fill();
                }
            }
        }
    }
}
<commit_msg>Firefox 3.6 requires the anticlockwise argument (bug 641564)<commit_after>function initMap() {
    "use strict";
    var ctx = $("#pings")[0].getContext("2d"),
        currentData = [],
        start = 0, total = 0, duration = 0, extra = 0;

    glow.map = {};
    glow.map.scale = $mc.width() / 3600;

    ctx.fillStyle = "#fff";

    /* Shuffle the array in place. (Fisher-Yates) */
    var shuffle = function(xs) {
        var i = xs.length, j, tmp;
        if (i == 0) { return; }
        while (--i) {
            j = Math.floor(Math.random() * (i + 1));
            tmp = xs[j];
            xs[j] = xs[i];
            xs[i] = tmp;
        }
    };

    /* Each ping looks like [latitude, longitude, count]. It represents the
     * numbers of downloads in the timeframe from this location. */
    glow.map.playNext = function() {
        var response = glow.data.map.next,
            /* [date, total, [pings]] */
            data = response.data,
            pings = data[2],
            newData = [];

        /* Add `count` [lat, long] pairs to newData, then shuffle the whole
         * thing. */
        for (var j = 0, jj = pings.length; j < jj; j++) {
            var ping = pings[j],
                latitude = ~~((parseFloat(ping[0]) + 180) * 10),
                longitude = ~~((-parseFloat(ping[1]) + 90) * 10),
                count = ping[2];
            for (var k = 0; k < count; k++) {
                newData.push([0, latitude, longitude]);
            }
        }
        shuffle(newData);

        /* Ping animations last 1 second so some are going to roll over. This
         * updates the time left to work with the reset timer and adds them to
         * the front of newData. */
        extra = Math.max(0, currentData.length - 1 - start);
        if (extra > 0) {
            for (var i = start, ii = currentData.length; i < ii; i++) {
                currentData[i][0] = currentData[i][0] - response.interval;
            }
            newData.unshift.apply(newData, currentData.slice(start));
        }

        /* Reset all the globals and kick off a new animation interval. */
        currentData = newData;
        start = 0;
        total = currentData.length;
        duration = response.interval * 1000;
        dbg('map total', total);

        glow.fetchMap(response.interval);
        vast.animate.over(response.interval * 1000, iteratePings, this,
                          {after: glow.map.playNext});
    };

    function iteratePings(t) {
        // t marks our progress through the interval from 0..1.
        if (start == total) {
            return;
        }
        /* We ignore the extra items when figuring out how many new pings to
         * play this iteration. The extra items get picked up as start moves
         * along. */
        var end = extra + (t * (total - extra)),
            currentAge = -1,
            progress = t * (duration / 1000),
            i, ping, age;

        // Clear out the canvas.
        for (i = start; i < end; i++) {
            ping = currentData[i];
            ctx.clearRect(ping[1] * glow.map.scale - 5, ping[2] * glow.map.scale- 5, 10, 10);
        }

        for (i = start; i < end; i++) {
            ping = currentData[i];
            if (ping[0] == 0) {
                ping[0] = progress;
            } else {
                age = progress - ping[0];
                if (age > 1) {
                    // This ping has played out, don't come back to it.
                    start++;
                } else {
                    /* Setting fillStyle is expensive according to Chrome's
                     * profiler, so only set it if the fillStyle has
                     * changed. */
                    if (age != currentAge) {
                        /* Bound the alpha between 0.01 and .99 so JavaScript
                         * doesn't write scientific notation. */
                        ctx.fillStyle = "rgba(255, 255, 255, " +
                                        Math.max(.01, Math.min(.99, (1 - age))) + ")";
                        currentAge = age;
                    }
                    ctx.beginPath();
                    // Firefox 3.6 requires the anticlockwise argument.
                    ctx.arc(ping[1] * glow.map.scale, ping[2] * glow.map.scale,
                            5 * age, 0, Math.PI * 2, false);
                    ctx.fill();
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>/*global angular, _*/
/*jslint nomen: true, es5: true */
angular.module('core').directive('tagAndNameFilter', ['$cacheFactory', function ($cacheFactory) {
    'use strict';

    function link(scope, element, attrs) {
        var cachedSettings,
            cacheId = 'core.tagAndNameFilter',
            cachedFilterParametersId = cacheId + '.' + scope.searchProvider.cacheId;

        scope.cache = $cacheFactory.get(cacheId);
        if (angular.isUndefined(scope.cache)) {
            scope.cache = $cacheFactory(cacheId);
        }

        var filter = function () {
            scope.filterParameters.nameFilters = _.filter(scope.filterParameters.filterItems, function (filterItem) {
                return filterItem._id !== 'tag';
            });
            scope.filterParameters.nameFilters = _.map(scope.filterParameters.nameFilters, function (nameFilterItem) {
                return nameFilterItem.name;
            });

            scope.filterParameters.tagFilters = _.filter(scope.filterParameters.filterItems, function (filterItem) {
                return filterItem._id === 'tag';
            });
            scope.filterParameters.tagFilters = _.map(scope.filterParameters.tagFilters, function (tagFilterItem) {
                return tagFilterItem.name.slice(1);
            });
            scope.searchProvider.filter(scope.filterParameters);
        };

        scope.filterParameters = scope.cache.get(cachedFilterParametersId);
        if (angular.isUndefined(scope.filterParameters)) {
            scope.filterParameters = {
                namesAndTagsFilter: '',
                filterItems: [],
                filterEventName: scope.searchProvider.filterEventName,
                removeItemFromFilter: function (item) {
                    _.pull(this.filterItems, item);
                    filter();
                },
                isNotEmpty: function () {
                    return this.filterItems.length > 0;
                },
                clear: function () {
                    this.filterItems = [];
                    this.namesAndTagsFilter = '';
                    filter();
                }
            };
        }

        scope.filterValuePlaceholder = '';

        scope.initNamesAndTagsFilter = function (select) {
            select.search = scope.filterParameters.namesAndTagsFilter;
        };

        scope.filterUpdated = function (select) {
            var clickTriggeredTheSelect = select.clickTriggeredSelect === true;

            if (!scope.noSummary) {
                if (clickTriggeredTheSelect) {
                    if (!_.includes(scope.filterParameters.filterItems, scope.filterParameters.namesAndTagsFilter)) {
                        scope.filterParameters.filterItems.push(scope.filterParameters.namesAndTagsFilter);
                    }
                    scope.filterParameters.namesAndTagsFilter = '';
                } else {
                    scope.filterParameters.namesAndTagsFilter = select.search;
                }
            } else {
                if (clickTriggeredTheSelect) {
                    scope.filterParameters.namesAndTagsFilter = scope.filterParameters.namesAndTagsFilter.name;
                } else {
                    scope.filterParameters.namesAndTagsFilter = select.search;
                }
            }

            scope.filterValuePlaceholder = select.search;
            filter();
            if (clickTriggeredTheSelect && !scope.noSummary) {
                scope.filterParameters.namesAndTagsFilter = null;
            }
        };

        scope.possibleFilterValues = [];

        scope.refreshPossibleFilterValues = function (select) {
            scope.filterParameters.namesAndTagsFilter = select.search;

            if (!scope.filterParameters.namesAndTagsFilter || scope.filterParameters.namesAndTagsFilter.length === 0) {
                scope.possibleFilterValues = [];
                filter();
                return;
            }

            scope.filterValuePlaceholder = select.search;

            var toLowerCase = function (item) {
                return item.name.toLowerCase();
            };

            scope.searchProvider.getPossibleFilterValues(scope.filterParameters.namesAndTagsFilter, function (filterResult) {
                var tags;

                scope.possibleFilterValues = _.sortBy(filterResult.names, toLowerCase);

                tags = _.map(filterResult.tags, function (tag) { return {_id: 'tag', name: '#' + tag }; });
                tags = _.sortBy(tags, toLowerCase);
                scope.possibleFilterValues = scope.possibleFilterValues.concat(tags);
            });
        };

        scope.$on("$destroy", function () {
            scope.cache.put(cachedFilterParametersId, scope.filterParameters);
        });
    }

    return {
        link: link,
        transclude: true,
        templateUrl: 'modules/core/templates/tagAndNameFilter.html',
        scope: {
            label: '=',
            searchProvider: '=',
            noSummary: '='
        }
    };
}]);
<commit_msg>Fix clicking on search autocomplete results not working on mobile [IQSLDSH-249].<commit_after>/*global angular, _*/
/*jslint nomen: true, es5: true */
angular.module('core').directive('tagAndNameFilter', ['$cacheFactory', function ($cacheFactory) {
    'use strict';

    function link(scope, element, attrs) {
        var cachedSettings,
            cacheId = 'core.tagAndNameFilter',
            cachedFilterParametersId = cacheId + '.' + scope.searchProvider.cacheId;

        scope.cache = $cacheFactory.get(cacheId);
        if (angular.isUndefined(scope.cache)) {
            scope.cache = $cacheFactory(cacheId);
        }

        var filter = function () {
            scope.filterParameters.nameFilters = _.filter(scope.filterParameters.filterItems, function (filterItem) {
                return filterItem._id !== 'tag';
            });
            scope.filterParameters.nameFilters = _.map(scope.filterParameters.nameFilters, function (nameFilterItem) {
                return nameFilterItem.name;
            });

            scope.filterParameters.tagFilters = _.filter(scope.filterParameters.filterItems, function (filterItem) {
                return filterItem._id === 'tag';
            });
            scope.filterParameters.tagFilters = _.map(scope.filterParameters.tagFilters, function (tagFilterItem) {
                return tagFilterItem.name.slice(1);
            });
            scope.searchProvider.filter(scope.filterParameters);
        };

        scope.filterParameters = scope.cache.get(cachedFilterParametersId);
        if (angular.isUndefined(scope.filterParameters)) {
            scope.filterParameters = {
                namesAndTagsFilter: '',
                filterItems: [],
                filterEventName: scope.searchProvider.filterEventName,
                removeItemFromFilter: function (item) {
                    _.pull(this.filterItems, item);
                    filter();
                },
                isNotEmpty: function () {
                    return this.filterItems.length > 0;
                },
                clear: function () {
                    this.filterItems = [];
                    this.namesAndTagsFilter = '';
                    filter();
                }
            };
        }

        scope.filterValuePlaceholder = '';

        scope.initNamesAndTagsFilter = function (select) {
            select.search = scope.filterParameters.namesAndTagsFilter;
        };

        scope.filterUpdated = function (select) {
            if (!scope.noSummary) {
                if (!_.includes(scope.filterParameters.filterItems, scope.filterParameters.namesAndTagsFilter)) {
                    scope.filterParameters.filterItems.push(scope.filterParameters.namesAndTagsFilter);
                }
                scope.filterParameters.namesAndTagsFilter = '';
            } else {
                scope.filterParameters.namesAndTagsFilter = scope.filterParameters.namesAndTagsFilter.name;
            }

            scope.filterValuePlaceholder = select.search;
            filter();
            if (!scope.noSummary) {
                scope.filterParameters.namesAndTagsFilter = null;
            }
        };

        scope.possibleFilterValues = [];

        scope.refreshPossibleFilterValues = function (select) {
            scope.filterParameters.namesAndTagsFilter = select.search;

            if (!scope.filterParameters.namesAndTagsFilter || scope.filterParameters.namesAndTagsFilter.length === 0) {
                scope.possibleFilterValues = [];
                filter();
                return;
            }

            scope.filterValuePlaceholder = select.search;

            var toLowerCase = function (item) {
                return item.name.toLowerCase();
            };

            scope.searchProvider.getPossibleFilterValues(scope.filterParameters.namesAndTagsFilter, function (filterResult) {
                var tags;

                scope.possibleFilterValues = _.sortBy(filterResult.names, toLowerCase);

                tags = _.map(filterResult.tags, function (tag) { return {_id: 'tag', name: '#' + tag }; });
                tags = _.sortBy(tags, toLowerCase);
                scope.possibleFilterValues = scope.possibleFilterValues.concat(tags);
            });
        };

        scope.$on("$destroy", function () {
            scope.cache.put(cachedFilterParametersId, scope.filterParameters);
        });
    }

    return {
        link: link,
        transclude: true,
        templateUrl: 'modules/core/templates/tagAndNameFilter.html',
        scope: {
            label: '=',
            searchProvider: '=',
            noSummary: '='
        }
    };
}]);
<|endoftext|>


<commit_before>const puppeteer = require('puppeteer');
const assert = require('assert');

(async () => {
    const browser = await puppeteer.launch({
        ignoreHTTPSErrors: true,
        headless: true
    });
    const page = await browser.newPage();
    await page.goto("https://localhost:8443/cas/login?service=https://example.org");

    await page.type('#username', "casuser");
    await page.type('#password', "Mellon");
    await page.keyboard.press('Enter');
    await page.waitForNavigation();

    var element = await page.$('#content h2');
    var header = await page.evaluate(element => element.textContent, element);
    console.log(header)
    assert(header === "Attribute Consent")

    element = await page.$('#appTitle');
    header = await page.evaluate(element => element.textContent, element);
    console.log(header)
    assert(header === "The following attributes will be released to [https://example.org]:")

    element = await page.$('#first-name');
    header = await page.evaluate(element => element.textContent.trim(), element);
    console.log(header)
    assert(header === "first-name")

    element = await page.$('#first-name-value');
    header = await page.evaluate(element => element.textContent.trim(), element);
    console.log(header)
    assert(header === "[Apereo]")

    element = await page.$('#last-name');
    header = await page.evaluate(element => element.textContent.trim(), element);
    console.log(header)
    assert(header === "last-name")

    element = await page.$('#last-name-value');
    header = await page.evaluate(element => element.textContent.trim(), element);
    console.log(header)
    assert(header === "[CAS]")

    element = await page.$('#email');
    header = await page.evaluate(element => element.textContent.trim(), element);
    console.log(header)
    assert(header === "email")

    element = await page.$('#email-value');
    header = await page.evaluate(element => element.textContent.trim(), element);
    console.log(header)
    assert(header === "[casuser@example.org]")

    await page.click("#optionsButton");
    await page.waitForTimeout(2500)

    var opt = await page.$('#optionAlways');
    assert(await opt.boundingBox() != null);
    opt = await page.$('#optionAttributeName');
    assert(await opt.boundingBox() != null);
    opt = await page.$('#optionAttributeValue');
    assert(await opt.boundingBox() != null);

    element = await page.$('#reminderTitle');
    header = await page.evaluate(element => element.textContent.trim(), element);
    console.log(header)
    assert(header === "How often should I be reminded to consent again?")

    opt = await page.$('#reminder');
    assert(await opt.boundingBox() != null);

    opt = await page.$('#reminderTimeUnit');
    assert(await opt.boundingBox() != null);

    opt = await page.$('#confirm');
    assert(await opt.boundingBox() != null);

    opt = await page.$('#cancel');
    assert(await opt.boundingBox() != null);

    await browser.close();
})();
<commit_msg>switch test script to use native dom click<commit_after>const puppeteer = require('puppeteer');
const assert = require('assert');

(async () => {
    const browser = await puppeteer.launch({
        ignoreHTTPSErrors: true,
        headless: true
    });
    const page = await browser.newPage();
    await page.goto("https://localhost:8443/cas/login?service=https://example.org");

    await page.type('#username', "casuser");
    await page.type('#password', "Mellon");
    await page.keyboard.press('Enter');
    await page.waitForNavigation();

    var element = await page.$('#content h2');
    var header = await page.evaluate(element => element.textContent, element);
    console.log(header)
    assert(header === "Attribute Consent")

    element = await page.$('#appTitle');
    header = await page.evaluate(element => element.textContent, element);
    console.log(header)
    assert(header === "The following attributes will be released to [https://example.org]:")

    element = await page.$('#first-name');
    header = await page.evaluate(element => element.textContent.trim(), element);
    console.log(header)
    assert(header === "first-name")

    element = await page.$('#first-name-value');
    header = await page.evaluate(element => element.textContent.trim(), element);
    console.log(header)
    assert(header === "[Apereo]")

    element = await page.$('#last-name');
    header = await page.evaluate(element => element.textContent.trim(), element);
    console.log(header)
    assert(header === "last-name")

    element = await page.$('#last-name-value');
    header = await page.evaluate(element => element.textContent.trim(), element);
    console.log(header)
    assert(header === "[CAS]")

    element = await page.$('#email');
    header = await page.evaluate(element => element.textContent.trim(), element);
    console.log(header)
    assert(header === "email")

    element = await page.$('#email-value');
    header = await page.evaluate(element => element.textContent.trim(), element);
    console.log(header)
    assert(header === "[casuser@example.org]")

    await click(page,"#optionsButton");
    await page.waitForTimeout(2500)

    var opt = await page.$('#optionAlways');
    assert(await opt.boundingBox() != null);
    opt = await page.$('#optionAttributeName');
    assert(await opt.boundingBox() != null);
    opt = await page.$('#optionAttributeValue');
    assert(await opt.boundingBox() != null);

    element = await page.$('#reminderTitle');
    header = await page.evaluate(element => element.textContent.trim(), element);
    console.log(header)
    assert(header === "How often should I be reminded to consent again?")

    opt = await page.$('#reminder');
    assert(await opt.boundingBox() != null);

    opt = await page.$('#reminderTimeUnit');
    assert(await opt.boundingBox() != null);

    opt = await page.$('#confirm');
    assert(await opt.boundingBox() != null);

    opt = await page.$('#cancel');
    assert(await opt.boundingBox() != null);

    await browser.close();
})();

async function click(page, button) {
    await page.evaluate((button) => {
        document.querySelector(button).click();
    }, button);
}
<|endoftext|>


<commit_before>var Webpack = require('webpack');
var path = require('path');
var nodeModulesPath = path.resolve(__dirname, 'node_modules');
var buildPath = path.resolve(__dirname, 'public', 'build');
var mainPath = path.resolve(__dirname, 'app', 'main.js');

var config = {

  // We change to normal source mapping
  devtool: 'source-map',
  entry: mainPath,
  output: {
    path: buildPath,
    filename: 'bundle.js'
  },
  module: {
    loaders: [{
      test: /\.js$/,
      loader: 'babel',
      exclude: [nodeModulesPath]
    },{
      test: /\.css$/,
      loader: 'style!css'
    }]
  }
};

module.exports = config;<commit_msg>updated to include uglify and env production variable<commit_after>var Webpack = require('webpack');
var path = require('path');
var nodeModulesPath = path.resolve(__dirname, 'node_modules');
var buildPath = path.resolve(__dirname, 'public', 'build');
var mainPath = path.resolve(__dirname, 'app', 'main.js');

var config = {

  // We change to normal source mapping
  devtool: 'source-map',
  entry: mainPath,
  output: {
    path: buildPath,
    filename: 'bundle.js'
  },
  module: {
    loaders: [{
      test: /\.js$/,
      loader: 'babel',
      exclude: [nodeModulesPath]
    },{
      test: /\.css$/,
      loader: 'style!css'
    }]
  }
  plugins:[
  new webpack.DefinePlugin({
    'process.env':{
      'NODE_ENV': JSON.stringify('production')
    }
  }),
  new webpack.optimize.UglifyJsPlugin({
    compress:{
      warnings: true
    }
  })
]
};

module.exports = config;<|endoftext|>