<commit_before>angular.module('home', [
  'utils'
])

.controller('homeController', [
  '$scope',
  '$http',
  '$state',
  '$stateParams',
  '$location',
  'fileTransfer',
  'linkGeneration',
  'webRTC',
  'packetHandlers',
  function($scope, $http, $state, $stateParams, $location, fileTransfer, linkGeneration, webRTC, packetHandlers) {
    console.log('home controller loaded');

    fileTransferObj.myItems = [];
    fileTransferObj.conn = [];

    var disconnectingSenderId = null;
    var generateLink = function() {
      $scope.hash = linkGeneration.guid();
      $stateParams.test = $scope.hash;
      $location.path('/' + $scope.hash);
    };

    document.getElementById('filesId').addEventListener('change', function() {

      var files = this.files;
      for (var i = 0; i < files.length; i++) {
        if (fileTransfer.myItems.indexOf(files[i]) > -1) {
          continue;
        }
        files[i].beenSent = false;
        fileTransfer.myItems.push(files[i]);
      }

      if (!fileTransfer.peer) {

        fileTransfer.peer = webRTC.createPeer();
        console.log('SENDER peer created');
        fileTransfer.peer.on('open', function(id) {
          disconnectingSenderId = id;
          // TODO: create special link to send with post in data
          $http({
              method: 'POST',
              url: '/api/webrtc/users',
              data: {
                userId: id,
                hash: $scope.hash
              }
            })
            .then(function(result) {
              console.log('SENDER\'s POST response', result.data);
            });
        });

        fileTransfer.peer.on('connection', function(conn) {
          // TODO: add file inside call to send
          fileTransfer.conn.push(conn);
          console.log('peerJS connection object', conn);

          setTimeout(function() {
            fileTransfer.conn.forEach(function(connection) {
              for (var i = 0; i < fileTransfer.myItems.length; i++) {
                if (!fileTransfer.myItems[i].beenSent) {
                  fileTransfer.myItems[i].beenSent = true;
                  console.log('files offered');
                  connection.send({
                    name: fileTransfer.myItems[i].name,
                    size: fileTransfer.myItems[i].size,
                    type: 'file-offer'
                  });
                }
              }
            });
          }, 1800);

          conn.on('data', function(data) {
            if (data.type === 'file-accepted') {
              packetHandlers.accepted(data, conn, $scope);
            } else if (data.type === 'file-offer') {
              packetHandlers.offer(data, conn);
            } else if (data.type === 'file-chunk') {
              packetHandlers.chunk(data, fileTransfer);
            }
          });
        });
        generateLink();
      }

      window.onbeforeunload = function() {
        return ("Your connection will end");
      };

      window.addEventListener('beforeunload', function() {
        console.log("DISCONNECTED")
        $http({
          method: 'POST',
          url: '/api/webrtc/delete',
          data: {
            userId: disconnectingSenderId
          }
        })
      });

    });

    $scope.testParams = $stateParams;

  }
]);<commit_msg>[fix] Remove white spaces from homeController.js<commit_after>angular.module('home', [
  'utils'
])

.controller('homeController', [
  '$scope',
  '$http',
  '$state',
  '$stateParams',
  '$location',
  'fileTransfer',
  'linkGeneration',
  'webRTC',
  'packetHandlers',
  function($scope, $http, $state, $stateParams, $location, fileTransfer, linkGeneration, webRTC, packetHandlers) {
    console.log('home controller loaded');

    fileTransferObj.myItems = [];
    fileTransferObj.conn = [];

    var disconnectingSenderId = null;
    var generateLink = function() {
      $scope.hash = linkGeneration.guid();
      $stateParams.test = $scope.hash;
      $location.path('/' + $scope.hash);
    };

    document.getElementById('filesId').addEventListener('change', function() {

      var files = this.files;
      for (var i = 0; i < files.length; i++) {
        if (fileTransfer.myItems.indexOf(files[i]) > -1) {
          continue;
        }
        files[i].beenSent = false;
        fileTransfer.myItems.push(files[i]);
      }

      if (!fileTransfer.peer) {

        fileTransfer.peer = webRTC.createPeer();
        console.log('SENDER peer created');
        fileTransfer.peer.on('open', function(id) {
          disconnectingSenderId = id;
          // TODO: create special link to send with post in data
          $http({
              method: 'POST',
              url: '/api/webrtc/users',
              data: {
                userId: id,
                hash: $scope.hash
              }
            })
            .then(function(result) {
              console.log('SENDER\'s POST response', result.data);
            });
        });

        fileTransfer.peer.on('connection', function(conn) {
          // TODO: add file inside call to send
          fileTransfer.conn.push(conn);
          console.log('peerJS connection object', conn);

          setTimeout(function() {
            fileTransfer.conn.forEach(function(connection) {
              for (var i = 0; i < fileTransfer.myItems.length; i++) {
                if (!fileTransfer.myItems[i].beenSent) {
                  fileTransfer.myItems[i].beenSent = true;
                  console.log('files offered');
                  connection.send({
                    name: fileTransfer.myItems[i].name,
                    size: fileTransfer.myItems[i].size,
                    type: 'file-offer'
                  });
                }
              }
            });
          }, 1800);

          conn.on('data', function(data) {
            if (data.type === 'file-accepted') {
              packetHandlers.accepted(data, conn, $scope);
            } else if (data.type === 'file-offer') {
              packetHandlers.offer(data, conn);
            } else if (data.type === 'file-chunk') {
              packetHandlers.chunk(data, fileTransfer);
            }
          });
        });
        generateLink();
      }

      window.onbeforeunload = function() {
        return ("Your connection will end");
      };

      window.addEventListener('beforeunload', function() {
        console.log("DISCONNECTED")
        $http({
          method: 'POST',
          url: '/api/webrtc/delete',
          data: {
            userId: disconnectingSenderId
          }
        })
      });

    });

    $scope.testParams = $stateParams;

  }
]);<|endoftext|>


<commit_before>// A list of catagory IDs that should not be included in the left-hand menu.
module.exports = [
	5811,  // "Skal slettes" i Danmarks Middelalder og Renæssance
	11853, // "Fra Gamle Cumulus" i Danmarks Nyere Tid
	11860, // "Fra Gamle Cumulus 2" i Danmarks Nyere Tid
	11857, // Kategori uden titel i temaer i Danmarks Nyere Tid
	543,   // "Test" i Den Kgl. Mønt- og Medaljesamling
	50,    // Kategori unden title i Musikmuseet
];<commit_msg>Update category-blacklist.js<commit_after>// A list of catagory IDs that should not be included in the left-hand menu.
module.exports = [
	5811,  // "Skal slettes" i Danmarks Middelalder og Renæssance
	11853, // "Fra Gamle Cumulus" i Danmarks Nyere Tid
	11860, // "Fra Gamle Cumulus 2" i Danmarks Nyere Tid
	11857, // Kategori uden titel i temaer i Danmarks Nyere Tid
	543,   // "Test" i Den Kgl. Mønt- og Medaljesamling
	50,    // Kategori unden title i Musikmuseet
	949, // AS uddeponering

];
<|endoftext|>


<commit_before>var title = '';

var dailyData = '';
//updated fields
var dailyDataArray;
var symbol_currency_map;

function init(){
  $.getJSON("http://api.fixer.io/latest", storeDailyData);
  setSymbolCurrencyMap();
}

var storeDailyData = function(data){
  dailyData = data;
  console.log(JSON.stringify(data));
  var obj = dailyData.rates;
  var result = Object.keys(obj).map(function(e) {
    return [(e), obj[e]];
  });
  dailyDataArray = result;
}

init();

var makeTitle = function(){
  let gettingItem = browser.storage.local.get();
  gettingItem.then(onGot, onError);
}

function onGot(item){
  console.log(item);
  var emptyObj = isEmpty(item);
  if((! emptyObj)){
    if(item.base_curr.name && item.convert_curr.name){
      var base_curr = item.base_curr.name;
      var convert_curr = item.convert_curr.name;
      title = "Convert from "+ base_curr + " " + " to " + " " + convert_curr;
      browser.contextMenus.create({
        id: "log-selection",
        title: title,
        contexts: ["selection"]
      });
    }
  }else{
    browser.contextMenus.create({
      id: "log-selection",
      title: "Select exchange currency to get started.",
      contexts: ["selection"]
    });

    browser.notifications.create({
      "type": "basic",
      "iconUrl": browser.extension.getURL("icons/curr_converter-100.png"),
      "title": "Getting Started",
      "message": "Please select the exchange currency to get started. Click on the icons on toolbar."
    });
  }
}

makeTitle();

// object constructor
function Conversion(selection_text) {
  this.selection = selection_text;
  this.amount = undefined;
  this.base_curr = undefined;
  this.convert_curr = undefined;
  this.converted_amount = undefined;
  this.extra_msg_text = '';
};

var current_conversion; //global object to hold conversion data

browser.contextMenus.onClicked.addListener(function(info, tab) {
  if (info.menuItemId == "log-selection") {
    current_conversion = new Conversion(info.selectionText);
    current_conversion.start_conversion();
  }
});

Conversion.prototype.start_conversion = function() {
  this.currency_symbol_check();
  this.get_amount();

  if (this.amount == null || isNaN(this.amount)) {
    browser.notifications.create({
      "type": "basic",
      "iconUrl": browser.extension.getURL("icons/curr_converter-100.png"),
      "title": "Oops! Cannot convert this.",
      "message": "Highlight only numbers to convert, without symbols or characters."
    });
    return;
  }

  this.set_currencies();
}

Conversion.prototype.set_currencies = function () {
  let gettingItem = browser.storage.local.get();
  gettingItem.then(function(item) { current_conversion.onGotCurr(item) }, onError);
}

Conversion.prototype.onGotCurr = function (item){
  console.log(item);
  var default_base_curr = 'USD';
  var default_convert_curr = 'MYR';

  if(isEmpty(item)) {
    this.extra_msg_text = "(Currencies not set, assuming USD for base and MYR for target currency.)";
    this.base_curr = default_base_curr;
    this.convert_curr = default_convert_curr;
    return;
  }

  if(item.convert_curr.name){
    this.convert_curr = item.convert_curr.name;
  }
  else {
    this.extra_msg_text = "(Target currency not set, assuming MYR for target currency.)";
    this.convert_curr = default_convert_curr;
  }

  // if base_curr is not already set (from currency_symbol_check), then set it here
  if (!this.base_curr) {
    if(item.base_curr.name) {
      this.base_curr = item.base_curr.name;
    }
    else {
      this.extra_msg_text = "(Base currency not set, assuming USD for base currency.)";
      this.base_curr = default_base_curr;
    }
  }

  this.finish_conversion();
}

Conversion.prototype.get_amount = function () {
  var amount_str = this.selection;

  // two million, ten thousand and a half is 2,010,000.5 in "common" format (US, Asia, etc.)
  var common_num_format = /^\d+(,\d+)+(.\d*)?$/;

  // two million, ten thousand and a half is 2.010.000,5 in European format
  var european_num_format = /^\d+(.\d+){2,}(,\d*)?$/;

  if(!isNaN(amount_str)){
    this.amount = Number(amount_str);

  }else if(common_num_format.test(amount_str)){
    var all_commas = /,/g;
    plain_amount = amount_str.replace(all_commas, '');
    console.log('Common format amount ' + amount_str + ' is now: ' + plain_amount);
    this.amount = Number(plain_amount);

  }else if(european_num_format.test(amount_str)){
    var all_dots = /\./g;
    plain_amount = amount_str.replace(all_dots, '');
    //replace decimal comma with decimal dot that Number understands
    plain_amount = plain_amount.replace(',', '.');
    console.log('European format amount ' + amount_str + ' is now: ' + plain_amount);
    this.amount = Number(plain_amount);

  }
  else {
    this.amount = NaN;
  }
}

// Check if selection includes currency indicator
// (either as a symbol like "$" or as an acronym like "USD")
Conversion.prototype.currency_symbol_check = function () {
  selection = this.selection.trim();

  text_at_start = /^(\w+)[ .]*\d/;
  text_at_end   = /\d\.?\s*(\w+)\.?$/;

  match         = selection.match(text_at_start);
  if (!match) {
    match       = selection.match(text_at_end);
  }

  if (match) {
    text = currency_text = match[1].trim();
    if(text in symbol_currency_map) {
      currency_text = symbol_currency_map[text];
    }

    if(currency_text in dailyData.rates || currency_text === dailyData.base) {
      // currency marker found, set that value in this
      this.base_curr = currency_text;
      console.log('Temporary user base currency set to: ' + currency_text);

      // remove currency marker from selection text so that the amount can be parsed next
      // allows for dot after currency text, for eg "Rs. 45" will become just 45
      text = text.replace(/\$/, '\\$'); // treat $ as a character here, not as special RegExp symbol
      text_re = new RegExp(text + '((\\.\\s)|(\\.\\s*$))?');
      this.selection = selection.replace(text_re, '').trim();
    }
  }
}

Conversion.prototype.finish_conversion = function () {
  if(this.base_curr === "EUR" || this.convert_curr === "EUR"){
    if(this.base_curr === "EUR"){
      var convert_rate;
      for(var n = 0; n < dailyDataArray.length; n++){
        if(this.convert_curr === dailyDataArray[n][0]){
          convert_rate = dailyDataArray[n][1];
          this.converted_amount = this.amount * convert_rate;
          this.converted_amount = Math.round(this.converted_amount * 100) / 100;
        }
      }
      browser.notifications.create({
        "type": "basic",
        "iconUrl": browser.extension.getURL("icons/curr_converter-100.png"),
        "title": "Immediate Currency Converter",
        "message": this.base_curr + " " + this.amount + " = " + this.convert_curr + " " + this.converted_amount
      });
      console.log(convert_rate);
    }
    if(this.convert_curr === "EUR"){
      var convert_rate;
      for(var n = 0; n < dailyDataArray.length; n++){
        if(this.base_curr === dailyDataArray[n][0]){
          convert_rate = dailyDataArray[n][1];
          this.converted_amount = this.amount / convert_rate;
          this.converted_amount = Math.round(this.converted_amount * 100) / 100;
        }
      }
      browser.notifications.create({
        "type": "basic",
        "iconUrl": browser.extension.getURL("icons/curr_converter-100.png"),
        "title": "Immediate Currency Converter",
        "message": this.base_curr + " " + this.amount + " = " + this.convert_curr + " " + this.converted_amount
      });
    }
  }else{
    if(this.base_curr && this.convert_curr){
      fx.rates = dailyData.rates;
      var rate = fx(this.amount).from(this.base_curr).to(this.convert_curr);
      console.log(this.base_curr + " " + this.amount + " = " + this.convert_curr + " " + rate.toFixed(2));

      browser.notifications.create({
        "type": "basic",
        "iconUrl": browser.extension.getURL("icons/curr_converter-100.png"),
        "title": "Immediate Currency Converter",
        "message": this.base_curr + " " + this.amount + " = " + this.convert_curr + " " + rate.toFixed(2) +
          "\n" + this.extra_msg_text
      });
    }
  }
}

function onError(error) {
  console.log(`Error: ${error}`);
}

function isEmpty(obj) {
  for(var prop in obj) {
    if(obj.hasOwnProperty(prop))
      return false;
  }
  //return true;
  return JSON.stringify(obj) === JSON.stringify({});
}

// Currency symbol info largely taken from https://github.com/xsolla/currency-format/
function setSymbolCurrencyMap() {
  symbol_currency_map = {
    "A$": "AUD",
    "лв": "BGN",
    "R$": "BRL",
    "CA$": "CAD",
    "SFr": "CHF",
    "元": "CNY",
    "Kč": "CZK",
    // "kr": "DKK", //kr is used for three currencies, not unique enough to use
    "€": "EUR",
    "£": "GBP",
    "HK$": "HKD",
    "Ft": "HUF",
    "Rp": "IDR",
    "₪": "ILS",
    "₹": "INR",
    "Rs": "INR",
    "¥": "JPY",
    "₩": "KRW",
    "Mex$": "MXN",
    "RM": "MYR",
    //"kr": "NOK",
    "NZ$": "NZD",
    "₱": "PHP",
    "zł": "PLN",
    "lei": "RON",
    "₽": "RUB",
    //"kr": "SEK",
    "S$": "SGD",
    "฿": "THB",
    "₺": "TRY",
    "$": "USD",
    "R": "ZAR"
  };
}

<commit_msg>Refactor out code to display browser notifications<commit_after>var title = '';

var dailyData = '';
//updated fields
var dailyDataArray;
var symbol_currency_map;

function init(){
  $.getJSON("http://api.fixer.io/latest", storeDailyData);
  setSymbolCurrencyMap();
}

var storeDailyData = function(data){
  dailyData = data;
  console.log(JSON.stringify(data));
  var obj = dailyData.rates;
  var result = Object.keys(obj).map(function(e) {
    return [(e), obj[e]];
  });
  dailyDataArray = result;
}

init();

var makeTitle = function(){
  let gettingItem = browser.storage.local.get();
  gettingItem.then(onGot, onError);
}

function onGot(item){
  console.log(item);
  var emptyObj = isEmpty(item);
  if((! emptyObj)){
    if(item.base_curr.name && item.convert_curr.name){
      var base_curr = item.base_curr.name;
      var convert_curr = item.convert_curr.name;
      title = "Convert from "+ base_curr + " " + " to " + " " + convert_curr;
      browser.contextMenus.create({
        id: "log-selection",
        title: title,
        contexts: ["selection"]
      });
    }
  }else{
    browser.contextMenus.create({
      id: "log-selection",
      title: "Select exchange currency to get started.",
      contexts: ["selection"]
    });

    browser.notifications.create({
      "type": "basic",
      "iconUrl": browser.extension.getURL("icons/curr_converter-100.png"),
      "title": "Getting Started",
      "message": "Please select the exchange currency to get started. Click on the icons on toolbar."
    });
  }
}

makeTitle();

// object constructor
function Conversion(selection_text) {
  this.selection = selection_text;
  this.amount = undefined;
  this.base_curr = undefined;
  this.convert_curr = undefined;
  this.converted_amount = undefined;
  this.extra_msg_text = '';
};

var current_conversion; //global object to hold conversion data

browser.contextMenus.onClicked.addListener(function(info, tab) {
  if (info.menuItemId == "log-selection") {
    current_conversion = new Conversion(info.selectionText);
    current_conversion.start_conversion();
  }
});

Conversion.prototype.start_conversion = function() {
  this.currency_symbol_check();
  this.get_amount();

  if (this.amount == null || isNaN(this.amount)) {
    show_browser_notification({
      "message": "Highlight only numbers to convert, without symbols or characters.",
      "title":   "Oops! Cannot convert this."});
    return;
  }

  this.set_currencies();
}

Conversion.prototype.set_currencies = function () {
  let gettingItem = browser.storage.local.get();
  gettingItem.then(function(item) { current_conversion.onGotCurr(item) }, onError);
}

Conversion.prototype.onGotCurr = function (item){
  console.log(item);
  var default_base_curr = 'USD';
  var default_convert_curr = 'MYR';

  if(isEmpty(item)) {
    this.extra_msg_text = "(Currencies not set, assuming USD for base and MYR for target currency.)";
    this.base_curr = default_base_curr;
    this.convert_curr = default_convert_curr;
    return;
  }

  if(item.convert_curr.name){
    this.convert_curr = item.convert_curr.name;
  }
  else {
    this.extra_msg_text = "(Target currency not set, assuming MYR for target currency.)";
    this.convert_curr = default_convert_curr;
  }

  // if base_curr is not already set (from currency_symbol_check), then set it here
  if (!this.base_curr) {
    if(item.base_curr.name) {
      this.base_curr = item.base_curr.name;
    }
    else {
      this.extra_msg_text = "(Base currency not set, assuming USD for base currency.)";
      this.base_curr = default_base_curr;
    }
  }

  this.finish_conversion();
}

Conversion.prototype.get_amount = function () {
  var amount_str = this.selection;

  // two million, ten thousand and a half is 2,010,000.5 in "common" format (US, Asia, etc.)
  var common_num_format = /^\d+(,\d+)+(.\d*)?$/;

  // two million, ten thousand and a half is 2.010.000,5 in European format
  var european_num_format = /^\d+(.\d+){2,}(,\d*)?$/;

  if(!isNaN(amount_str)){
    this.amount = Number(amount_str);

  }else if(common_num_format.test(amount_str)){
    var all_commas = /,/g;
    plain_amount = amount_str.replace(all_commas, '');
    console.log('Common format amount ' + amount_str + ' is now: ' + plain_amount);
    this.amount = Number(plain_amount);

  }else if(european_num_format.test(amount_str)){
    var all_dots = /\./g;
    plain_amount = amount_str.replace(all_dots, '');
    //replace decimal comma with decimal dot that Number understands
    plain_amount = plain_amount.replace(',', '.');
    console.log('European format amount ' + amount_str + ' is now: ' + plain_amount);
    this.amount = Number(plain_amount);

  }
  else {
    this.amount = NaN;
  }
}

// Check if selection includes currency indicator
// (either as a symbol like "$" or as an acronym like "USD")
Conversion.prototype.currency_symbol_check = function () {
  selection = this.selection.trim();

  text_at_start = /^(\w+)[ .]*\d/;
  text_at_end   = /\d\.?\s*(\w+)\.?$/;

  match         = selection.match(text_at_start);
  if (!match) {
    match       = selection.match(text_at_end);
  }

  if (match) {
    text = currency_text = match[1].trim();
    if(text in symbol_currency_map) {
      currency_text = symbol_currency_map[text];
    }

    if(currency_text in dailyData.rates || currency_text === dailyData.base) {
      // currency marker found, set that value in this
      this.base_curr = currency_text;
      console.log('Temporary user base currency set to: ' + currency_text);

      // remove currency marker from selection text so that the amount can be parsed next
      // allows for dot after currency text, for eg "Rs. 45" will become just 45
      text = text.replace(/\$/, '\\$'); // treat $ as a character here, not as special RegExp symbol
      text_re = new RegExp(text + '((\\.\\s)|(\\.\\s*$))?');
      this.selection = selection.replace(text_re, '').trim();
    }
  }
}

Conversion.prototype.finish_conversion = function () {
  if(this.base_curr === "EUR" || this.convert_curr === "EUR"){
    if(this.base_curr === "EUR"){
      var convert_rate;
      for(var n = 0; n < dailyDataArray.length; n++){
        if(this.convert_curr === dailyDataArray[n][0]){
          convert_rate = dailyDataArray[n][1];
          this.converted_amount = this.amount * convert_rate;
          this.converted_amount = Math.round(this.converted_amount * 100) / 100;
        }
      }
      console.log(convert_rate);
    }
    if(this.convert_curr === "EUR"){
      var convert_rate;
      for(var n = 0; n < dailyDataArray.length; n++){
        if(this.base_curr === dailyDataArray[n][0]){
          convert_rate = dailyDataArray[n][1];
          this.converted_amount = this.amount / convert_rate;
          this.converted_amount = Math.round(this.converted_amount * 100) / 100;
        }
      }
    }
  }else{
    if(this.base_curr && this.convert_curr){
      fx.rates = dailyData.rates;
      var rate = fx(this.amount).from(this.base_curr).to(this.convert_curr);
      this.converted_amount = rate.toFixed(2);
    }
  }
  console.log(this);
  show_browser_notification({
    "message": this.base_curr + " " + this.amount + " = " + this.convert_curr + " " + this.converted_amount +
      "\n" + this.extra_msg_text
  });
}

function show_browser_notification({message, title = "Immediate Currency Converter"}) {
  browser.notifications.create({
    "type": "basic",
    "iconUrl": browser.extension.getURL("icons/curr_converter-100.png"),
    "title": title,
    "message": message
  });
}

function onError(error) {
  console.log(`Error: ${error}`);
}

function isEmpty(obj) {
  for(var prop in obj) {
    if(obj.hasOwnProperty(prop))
      return false;
  }
  //return true;
  return JSON.stringify(obj) === JSON.stringify({});
}

// Currency symbol info largely taken from https://github.com/xsolla/currency-format/
function setSymbolCurrencyMap() {
  symbol_currency_map = {
    "A$": "AUD",
    "лв": "BGN",
    "R$": "BRL",
    "CA$": "CAD",
    "SFr": "CHF",
    "元": "CNY",
    "Kč": "CZK",
    // "kr": "DKK", //kr is used for three currencies, not unique enough to use
    "€": "EUR",
    "£": "GBP",
    "HK$": "HKD",
    "Ft": "HUF",
    "Rp": "IDR",
    "₪": "ILS",
    "₹": "INR",
    "Rs": "INR",
    "¥": "JPY",
    "₩": "KRW",
    "Mex$": "MXN",
    "RM": "MYR",
    //"kr": "NOK",
    "NZ$": "NZD",
    "₱": "PHP",
    "zł": "PLN",
    "lei": "RON",
    "₽": "RUB",
    //"kr": "SEK",
    "S$": "SGD",
    "฿": "THB",
    "₺": "TRY",
    "$": "USD",
    "R": "ZAR"
  };
}

<|endoftext|>


<commit_before>define(
        [ "AttackDice", "DamageDealer", "DefenseDice", "Phase", "Pilot", "RangeRuler", "ShipDestroyedAction",
                "TargetLock", "UpgradeCard" ],
        function(AttackDice, DamageDealer, DefenseDice, Phase, Pilot, RangeRuler, ShipDestroyedAction, TargetLock,
                UpgradeCard)
        {
            "use strict";
            function CombatAction(environment, adjudicator, attacker, attackerPosition, weapon, defender,
                    defenderPosition, callback)
            {
                InputValidator.validateNotNull("environment", environment);
                InputValidator.validateNotNull("adjudicator", adjudicator);
                InputValidator.validateNotNull("attacker", attacker);
                InputValidator.validateNotNull("attackerPosition", attackerPosition);
                InputValidator.validateNotNull("weapon", weapon);
                InputValidator.validateNotNull("defender", defender);
                InputValidator.validateNotNull("defenderPosition", defenderPosition);

                var that = this;

                this.environment = function()
                {
                    return environment;
                };

                this.adjudicator = function()
                {
                    return adjudicator;
                };

                this.attacker = function()
                {
                    return attacker;
                };

                this.attackerPosition = function()
                {
                    return attackerPosition;
                };

                this.weapon = function()
                {
                    return weapon;
                };

                this.defender = function()
                {
                    return defender;
                };

                this.defenderPosition = function()
                {
                    return defenderPosition;
                };

                var executionCount = 0;

                this.executionCount = function()
                {
                    return executionCount;
                };

                this.doIt = function()
                {
                    executionCount++;
                    var upgrade = weapon.upgrade();

                    if (upgrade)
                    {
                        if (upgrade.spendFocus)
                        {
                            attacker.focus().decrease();
                        }

                        if (upgrade.spendTargetLock)
                        {
                            var targetLock = attacker.findTargetLockByDefender(defender);

                            if (targetLock)
                            {
                                attacker.removeAttackerTargetLock(targetLock);
                                defender.removeDefenderTargetLock(targetLock);
                            }
                        }

                        if (upgrade.discardThisCard)
                        {
                            attacker.discardUpgrade(weapon.upgradeKey());
                        }
                    }

                    var range = RangeRuler.getRange(attacker, attackerPosition, defender, defenderPosition);
                    attacker.combatState().range(range);

                    if (range)
                    {
                        attacker.combatState().combatAction(this);

                        // Roll attack dice.
                        var attackDiceCount = attacker.computeAttackDiceCount(environment, weapon, defender, range);
                        var attackDice = new AttackDice(attackDiceCount);

                        if (weapon.upgradeKey() === UpgradeCard.ADVANCED_PROTON_TORPEDOES)
                        {
                            attackDice.changeOneToValue(AttackDice.Value.BLANK, AttackDice.Value.FOCUS);
                            attackDice.changeOneToValue(AttackDice.Value.BLANK, AttackDice.Value.FOCUS);
                            attackDice.changeOneToValue(AttackDice.Value.BLANK, AttackDice.Value.FOCUS);
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.CONCUSSION_MISSILES)
                        {
                            attackDice.changeOneToValue(AttackDice.Value.BLANK, AttackDice.Value.HIT);
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.HEAVY_LASER_CANNON)
                        {
                            attackDice.changeAllToValue(AttackDice.Value.CRITICAL_HIT, AttackDice.Value.HIT);
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.MANGLER_CANNON)
                        {
                            attackDice.changeOneToValue(AttackDice.Value.HIT, AttackDice.Value.CRITICAL_HIT);
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.PROTON_TORPEDOES)
                        {
                            attackDice.changeOneToValue(AttackDice.Value.FOCUS, AttackDice.Value.CRITICAL_HIT);
                        }

                        if (attacker.pilotKey() === Pilot.POE_DAMERON && attacker.focus().count() > 0)
                        {
                            attackDice.changeOneToValue(AttackDice.Value.FOCUS, AttackDice.Value.HIT);
                        }

                        if (attacker.isUpgradedWith(UpgradeCard.LONE_WOLF) && attackDice.blankCount() > 0)
                        {
                            var tokens1 = environment.getFriendlyTokensAtRange(attacker, RangeRuler.ONE);
                            var tokens2 = environment.getFriendlyTokensAtRange(attacker, RangeRuler.TWO);

                            if (tokens1.length === 0 && tokens2.length === 0)
                            {
                                attackDice.rerollBlank();
                            }
                        }

                        attacker.combatState().attackDice(attackDice);
                        environment.phase(Phase.COMBAT_ROLL_ATTACK_DICE);

                        // Modify attack dice.
                        var agent = attacker.agent();
                        agent.getModifyAttackDiceAction(environment, adjudicator, attacker, attackDice, defender,
                                finishModifyAttackDice);
                    }
                };

                function finishModifyAttackDice(attackAction)
                {
                    LOGGER.debug("CombatAction.finishModifyAttackDice() attackAction = " + attackAction);

                    if (attackAction)
                    {
                        attackAction.doIt();
                    }

                    environment.phase(Phase.COMBAT_MODIFY_ATTACK_DICE);
                    var attackDice = attacker.combatState().attackDice();

                    // Roll defense dice.
                    var range = attacker.combatState().range();
                    var defenderDiceCount = defender.computeDefenseDiceCount(weapon, range);
                    var defenseDice = new DefenseDice(defenderDiceCount);

                    if (defender.pilotKey() === Pilot.LUKE_SKYWALKER && defenseDice.focusCount() > 0)
                    {
                        defenseDice.changeOneToValue(DefenseDice.Value.FOCUS, DefenseDice.Value.EVADE);
                    }

                    if (defender.pilotKey() === Pilot.POE_DAMERON && defender.focus().count() > 0)
                    {
                        defenseDice.changeOneToValue(DefenseDice.Value.FOCUS, DefenseDice.Value.EVADE);
                    }

                    if (defender.isUpgradedWith(UpgradeCard.AUTOTHRUSTERS) && defenseDice.blankCount() > 0)
                    {
                        var isBeyondRange2 = (range === undefined || range === RangeRuler.THREE);
                        var isOutsideFiringArc = !weapon.isDefenderInFiringArc(attackerPosition, weapon
                                .primaryFiringArc(), defender, defenderPosition);

                        if (isBeyondRange2 || isOutsideFiringArc)
                        {
                            defenseDice.changeOneToValue(DefenseDice.Value.BLANK, DefenseDice.Value.EVADE);
                        }
                    }

                    if (defender.isUpgradedWith(UpgradeCard.LONE_WOLF) && defenseDice.blankCount() > 0)
                    {
                        var tokens1 = environment.getFriendlyTokensAtRange(defender, RangeRuler.ONE);
                        var tokens2 = environment.getFriendlyTokensAtRange(defender, RangeRuler.TWO);

                        if (tokens1.length === 0 && tokens2.length === 0)
                        {
                            defenseDice.rerollBlank();
                        }
                    }

                    attacker.combatState().defenseDice(defenseDice);
                    environment.phase(Phase.COMBAT_ROLL_DEFENSE_DICE);

                    // Modify defense dice.
                    var defenderAgent = defender.agent();
                    defenderAgent.getModifyDefenseDiceAction(environment, adjudicator, attacker, attackDice, defender,
                            defenseDice, finishModifyDefenseDice);
                }

                function finishModifyDefenseDice(defenseAction)
                {
                    LOGGER.debug("defenseAction = " + defenseAction);

                    if (defenseAction)
                    {
                        defenseAction.doIt();
                    }

                    environment.phase(Phase.COMBAT_MODIFY_DEFENSE_DICE);
                    var defenseDice = attacker.combatState().defenseDice();

                    // Compare results.
                    // Deal damage.
                    var attackDice = attacker.combatState().attackDice();
                    var damageDealer = new DamageDealer(environment, attackDice.hitCount(), attackDice
                            .criticalHitCount(), defender, defenseDice.evadeCount());

                    // Four possibilities:
                    // computer vs computer: call finishDealDamage() once
                    // computer vs human: call finishDealDamage() once
                    // human vs computer: call finishDealDamage() once
                    // human vs human: call finishDealDamage() once
                    var attackerAgent = attacker.agent();
                    var defenderAgent = defender.agent();
                    var attackerIsComputerAgent = attackerAgent.isComputerAgent();
                    var defenderIsComputerAgent = defenderAgent.isComputerAgent();
                    var callbackFunction = function()
                    {
                        finishDealDamage(damageDealer);
                    };

                    if (attackerIsComputerAgent && defenderIsComputerAgent)
                    {
                        // Both computer agents.
                        setTimeout(callbackFunction, 1000);
                    }
                    else if (attackerIsComputerAgent && !defenderIsComputerAgent)
                    {
                        defenderAgent.dealDamage(environment, adjudicator, attacker, attackDice, defender, defenseDice,
                                damageDealer, callbackFunction);
                    }
                    else if (!attackerIsComputerAgent && defenderIsComputerAgent)
                    {
                        attackerAgent.dealDamage(environment, adjudicator, attacker, attackDice, defender, defenseDice,
                                damageDealer, callbackFunction);
                    }
                    else if (!attackerIsComputerAgent && !defenderIsComputerAgent)
                    {
                        // Both human agents.
                        attackerAgent.dealDamage(environment, adjudicator, attacker, attackDice, defender, defenseDice,
                                damageDealer, callbackFunction);
                    }

                    environment.phase(Phase.COMBAT_DEAL_DAMAGE);
                }

                function finishDealDamage(damageDealer)
                {
                    LOGGER.trace("CombatAction.finishDealDamage() start");

                    var isDefenderHit = (damageDealer.hits() + damageDealer.criticalHits() > 0);
                    attacker.combatState().isDefenderHit(isDefenderHit);
                    LOGGER.debug("isDefenderHit ? " + isDefenderHit);

                    if (isDefenderHit)
                    {
                        if (weapon.upgradeKey() === UpgradeCard.ADVANCED_HOMING_MISSILES)
                        {
                            defender.addCriticalDamage(environment.drawDamage());
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.FLECHETTE_CANNON)
                        {
                            defender.addDamage(environment.drawDamage());
                            if (!defender.isStressed())
                            {
                                defender.receiveStress();
                            }
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.ION_CANNON ||
                                weapon.upgradeKey() === UpgradeCard.ION_CANNON_TURRET)
                        {
                            defender.addDamage(environment.drawDamage());
                            defender.ion().increase();
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.ION_PULSE_MISSILES)
                        {
                            defender.addDamage(environment.drawDamage());
                            defender.ion().increase();
                            defender.ion().increase();
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.TWIN_LASER_TURRET)
                        {
                            defender.addDamage(environment.drawDamage());
                        }
                        else
                        {
                            damageDealer.dealDamage();
                        }

                        if (attacker.pilotKey() === Pilot.WHISPER)
                        {
                            attacker.focus().increase();
                        }

                        if (weapon.upgradeKey() === UpgradeCard.ASSAULT_MISSILES)
                        {
                            environment.getTokensAtRange(defender, RangeRuler.ONE).forEach(function(token)
                            {
                                token.addDamage(environment.drawDamage());
                            });
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.FLECHETTE_TORPEDOES && defender.hullValue() <= 4)
                        {
                            defender.receiveStress();
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.ION_TORPEDOES)
                        {
                            environment.getTokensAtRange(defender, RangeRuler.ONE).forEach(function(token)
                            {
                                token.ion().increase();
                            });
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.PLASMA_TORPEDOES)
                        {
                            defender.shield().decrease();
                        }

                        if (defender.isUpgradedWith(UpgradeCard.STEALTH_DEVICE))
                        {
                            defender.upgrades().vizziniRemove(UpgradeCard.STEALTH_DEVICE);
                        }
                    }
                    else
                    {
                        // Defender not hit.
                        if (attacker.isUpgradedWith(UpgradeCard.BOSSK))
                        {
                            if (!attacker.isStressed())
                            {
                                attacker.receiveStress();
                            }

                            attacker.focus().increase();
                            var targetLock = new TargetLock(attacker, defender);
                            attacker.addAttackerTargetLock(targetLock);
                            defender.addDefenderTargetLock(targetLock);
                        }
                    }

                    if (attacker.isUpgradedWith(UpgradeCard.TACTICIAN) &&
                            attacker.combatState().range() === RangeRuler.TWO)
                    {
                        var firingArc = attacker.pilot().shipTeam.ship.primaryFiringArc;

                        if (weapon.isDefenderInFiringArc(attackerPosition, firingArc, defender, defenderPosition))
                        {
                            defender.receiveStress();
                        }
                    }

                    if (defender.isDestroyed())
                    {
                        if (attacker.pilotKey() === Pilot.IG_88A)
                        {
                            attacker.recoverShield();
                        }

                        var shipDestroyedAction = new ShipDestroyedAction(environment, defender, defenderPosition);
                        shipDestroyedAction.doIt();
                        var delay = 1500;
                        setTimeout(function()
                        {
                            if (callback)
                            {
                                callback();
                            }
                        }, delay);
                    }
                    else
                    {
                        if ((weapon.upgradeKey() === UpgradeCard.CLUSTER_MISSILES || weapon.upgradeKey() === UpgradeCard.TWIN_LASER_TURRET) &&
                                executionCount < 2)
                        {
                            that.doIt();
                        }
                        else
                        {
                            if (callback)
                            {
                                callback();
                            }
                        }
                    }

                    LOGGER.trace("CombatAction.finishDealDamage() end");
                }
            }

            return CombatAction;
        });
<commit_msg>Fixed a bug involving the stealth upgrade.<commit_after>define(
        [ "AttackDice", "DamageDealer", "DefenseDice", "Phase", "Pilot", "RangeRuler", "ShipDestroyedAction",
                "TargetLock", "UpgradeCard" ],
        function(AttackDice, DamageDealer, DefenseDice, Phase, Pilot, RangeRuler, ShipDestroyedAction, TargetLock,
                UpgradeCard)
        {
            "use strict";
            function CombatAction(environment, adjudicator, attacker, attackerPosition, weapon, defender,
                    defenderPosition, callback)
            {
                InputValidator.validateNotNull("environment", environment);
                InputValidator.validateNotNull("adjudicator", adjudicator);
                InputValidator.validateNotNull("attacker", attacker);
                InputValidator.validateNotNull("attackerPosition", attackerPosition);
                InputValidator.validateNotNull("weapon", weapon);
                InputValidator.validateNotNull("defender", defender);
                InputValidator.validateNotNull("defenderPosition", defenderPosition);

                var that = this;

                this.environment = function()
                {
                    return environment;
                };

                this.adjudicator = function()
                {
                    return adjudicator;
                };

                this.attacker = function()
                {
                    return attacker;
                };

                this.attackerPosition = function()
                {
                    return attackerPosition;
                };

                this.weapon = function()
                {
                    return weapon;
                };

                this.defender = function()
                {
                    return defender;
                };

                this.defenderPosition = function()
                {
                    return defenderPosition;
                };

                var executionCount = 0;

                this.executionCount = function()
                {
                    return executionCount;
                };

                this.doIt = function()
                {
                    executionCount++;
                    var upgrade = weapon.upgrade();

                    if (upgrade)
                    {
                        if (upgrade.spendFocus)
                        {
                            attacker.focus().decrease();
                        }

                        if (upgrade.spendTargetLock)
                        {
                            var targetLock = attacker.findTargetLockByDefender(defender);

                            if (targetLock)
                            {
                                attacker.removeAttackerTargetLock(targetLock);
                                defender.removeDefenderTargetLock(targetLock);
                            }
                        }

                        if (upgrade.discardThisCard)
                        {
                            attacker.discardUpgrade(weapon.upgradeKey());
                        }
                    }

                    var range = RangeRuler.getRange(attacker, attackerPosition, defender, defenderPosition);
                    attacker.combatState().range(range);

                    if (range)
                    {
                        attacker.combatState().combatAction(this);

                        // Roll attack dice.
                        var attackDiceCount = attacker.computeAttackDiceCount(environment, weapon, defender, range);
                        var attackDice = new AttackDice(attackDiceCount);

                        if (weapon.upgradeKey() === UpgradeCard.ADVANCED_PROTON_TORPEDOES)
                        {
                            attackDice.changeOneToValue(AttackDice.Value.BLANK, AttackDice.Value.FOCUS);
                            attackDice.changeOneToValue(AttackDice.Value.BLANK, AttackDice.Value.FOCUS);
                            attackDice.changeOneToValue(AttackDice.Value.BLANK, AttackDice.Value.FOCUS);
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.CONCUSSION_MISSILES)
                        {
                            attackDice.changeOneToValue(AttackDice.Value.BLANK, AttackDice.Value.HIT);
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.HEAVY_LASER_CANNON)
                        {
                            attackDice.changeAllToValue(AttackDice.Value.CRITICAL_HIT, AttackDice.Value.HIT);
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.MANGLER_CANNON)
                        {
                            attackDice.changeOneToValue(AttackDice.Value.HIT, AttackDice.Value.CRITICAL_HIT);
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.PROTON_TORPEDOES)
                        {
                            attackDice.changeOneToValue(AttackDice.Value.FOCUS, AttackDice.Value.CRITICAL_HIT);
                        }

                        if (attacker.pilotKey() === Pilot.POE_DAMERON && attacker.focus().count() > 0)
                        {
                            attackDice.changeOneToValue(AttackDice.Value.FOCUS, AttackDice.Value.HIT);
                        }

                        if (attacker.isUpgradedWith(UpgradeCard.LONE_WOLF) && attackDice.blankCount() > 0)
                        {
                            var tokens1 = environment.getFriendlyTokensAtRange(attacker, RangeRuler.ONE);
                            var tokens2 = environment.getFriendlyTokensAtRange(attacker, RangeRuler.TWO);

                            if (tokens1.length === 0 && tokens2.length === 0)
                            {
                                attackDice.rerollBlank();
                            }
                        }

                        attacker.combatState().attackDice(attackDice);
                        environment.phase(Phase.COMBAT_ROLL_ATTACK_DICE);

                        // Modify attack dice.
                        var agent = attacker.agent();
                        agent.getModifyAttackDiceAction(environment, adjudicator, attacker, attackDice, defender,
                                finishModifyAttackDice);
                    }
                };

                function finishModifyAttackDice(attackAction)
                {
                    LOGGER.debug("CombatAction.finishModifyAttackDice() attackAction = " + attackAction);

                    if (attackAction)
                    {
                        attackAction.doIt();
                    }

                    environment.phase(Phase.COMBAT_MODIFY_ATTACK_DICE);
                    var attackDice = attacker.combatState().attackDice();

                    // Roll defense dice.
                    var range = attacker.combatState().range();
                    var defenderDiceCount = defender.computeDefenseDiceCount(weapon, range);
                    var defenseDice = new DefenseDice(defenderDiceCount);

                    if (defender.pilotKey() === Pilot.LUKE_SKYWALKER && defenseDice.focusCount() > 0)
                    {
                        defenseDice.changeOneToValue(DefenseDice.Value.FOCUS, DefenseDice.Value.EVADE);
                    }

                    if (defender.pilotKey() === Pilot.POE_DAMERON && defender.focus().count() > 0)
                    {
                        defenseDice.changeOneToValue(DefenseDice.Value.FOCUS, DefenseDice.Value.EVADE);
                    }

                    if (defender.isUpgradedWith(UpgradeCard.AUTOTHRUSTERS) && defenseDice.blankCount() > 0)
                    {
                        var isBeyondRange2 = (range === undefined || range === RangeRuler.THREE);
                        var isOutsideFiringArc = !weapon.isDefenderInFiringArc(attackerPosition, weapon
                                .primaryFiringArc(), defender, defenderPosition);

                        if (isBeyondRange2 || isOutsideFiringArc)
                        {
                            defenseDice.changeOneToValue(DefenseDice.Value.BLANK, DefenseDice.Value.EVADE);
                        }
                    }

                    if (defender.isUpgradedWith(UpgradeCard.LONE_WOLF) && defenseDice.blankCount() > 0)
                    {
                        var tokens1 = environment.getFriendlyTokensAtRange(defender, RangeRuler.ONE);
                        var tokens2 = environment.getFriendlyTokensAtRange(defender, RangeRuler.TWO);

                        if (tokens1.length === 0 && tokens2.length === 0)
                        {
                            defenseDice.rerollBlank();
                        }
                    }

                    attacker.combatState().defenseDice(defenseDice);
                    environment.phase(Phase.COMBAT_ROLL_DEFENSE_DICE);

                    // Modify defense dice.
                    var defenderAgent = defender.agent();
                    defenderAgent.getModifyDefenseDiceAction(environment, adjudicator, attacker, attackDice, defender,
                            defenseDice, finishModifyDefenseDice);
                }

                function finishModifyDefenseDice(defenseAction)
                {
                    LOGGER.debug("defenseAction = " + defenseAction);

                    if (defenseAction)
                    {
                        defenseAction.doIt();
                    }

                    environment.phase(Phase.COMBAT_MODIFY_DEFENSE_DICE);
                    var defenseDice = attacker.combatState().defenseDice();

                    // Compare results.
                    // Deal damage.
                    var attackDice = attacker.combatState().attackDice();
                    var damageDealer = new DamageDealer(environment, attackDice.hitCount(), attackDice
                            .criticalHitCount(), defender, defenseDice.evadeCount());

                    // Four possibilities:
                    // computer vs computer: call finishDealDamage() once
                    // computer vs human: call finishDealDamage() once
                    // human vs computer: call finishDealDamage() once
                    // human vs human: call finishDealDamage() once
                    var attackerAgent = attacker.agent();
                    var defenderAgent = defender.agent();
                    var attackerIsComputerAgent = attackerAgent.isComputerAgent();
                    var defenderIsComputerAgent = defenderAgent.isComputerAgent();
                    var callbackFunction = function()
                    {
                        finishDealDamage(damageDealer);
                    };

                    if (attackerIsComputerAgent && defenderIsComputerAgent)
                    {
                        // Both computer agents.
                        setTimeout(callbackFunction, 1000);
                    }
                    else if (attackerIsComputerAgent && !defenderIsComputerAgent)
                    {
                        defenderAgent.dealDamage(environment, adjudicator, attacker, attackDice, defender, defenseDice,
                                damageDealer, callbackFunction);
                    }
                    else if (!attackerIsComputerAgent && defenderIsComputerAgent)
                    {
                        attackerAgent.dealDamage(environment, adjudicator, attacker, attackDice, defender, defenseDice,
                                damageDealer, callbackFunction);
                    }
                    else if (!attackerIsComputerAgent && !defenderIsComputerAgent)
                    {
                        // Both human agents.
                        attackerAgent.dealDamage(environment, adjudicator, attacker, attackDice, defender, defenseDice,
                                damageDealer, callbackFunction);
                    }

                    environment.phase(Phase.COMBAT_DEAL_DAMAGE);
                }

                function finishDealDamage(damageDealer)
                {
                    LOGGER.trace("CombatAction.finishDealDamage() start");

                    var isDefenderHit = (damageDealer.hits() + damageDealer.criticalHits() > 0);
                    attacker.combatState().isDefenderHit(isDefenderHit);
                    LOGGER.debug("isDefenderHit ? " + isDefenderHit);

                    if (isDefenderHit)
                    {
                        if (weapon.upgradeKey() === UpgradeCard.ADVANCED_HOMING_MISSILES)
                        {
                            defender.addCriticalDamage(environment.drawDamage());
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.FLECHETTE_CANNON)
                        {
                            defender.addDamage(environment.drawDamage());
                            if (!defender.isStressed())
                            {
                                defender.receiveStress();
                            }
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.ION_CANNON ||
                                weapon.upgradeKey() === UpgradeCard.ION_CANNON_TURRET)
                        {
                            defender.addDamage(environment.drawDamage());
                            defender.ion().increase();
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.ION_PULSE_MISSILES)
                        {
                            defender.addDamage(environment.drawDamage());
                            defender.ion().increase();
                            defender.ion().increase();
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.TWIN_LASER_TURRET)
                        {
                            defender.addDamage(environment.drawDamage());
                        }
                        else
                        {
                            damageDealer.dealDamage();
                        }

                        if (attacker.pilotKey() === Pilot.WHISPER)
                        {
                            attacker.focus().increase();
                        }

                        if (weapon.upgradeKey() === UpgradeCard.ASSAULT_MISSILES)
                        {
                            environment.getTokensAtRange(defender, RangeRuler.ONE).forEach(function(token)
                            {
                                token.addDamage(environment.drawDamage());
                            });
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.FLECHETTE_TORPEDOES && defender.hullValue() <= 4)
                        {
                            defender.receiveStress();
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.ION_TORPEDOES)
                        {
                            environment.getTokensAtRange(defender, RangeRuler.ONE).forEach(function(token)
                            {
                                token.ion().increase();
                            });
                        }
                        else if (weapon.upgradeKey() === UpgradeCard.PLASMA_TORPEDOES)
                        {
                            defender.shield().decrease();
                        }

                        if (defender.isUpgradedWith(UpgradeCard.STEALTH_DEVICE))
                        {
                            defender.upgradeKeys().vizziniRemove(UpgradeCard.STEALTH_DEVICE);
                        }
                    }
                    else
                    {
                        // Defender not hit.
                        if (attacker.isUpgradedWith(UpgradeCard.BOSSK))
                        {
                            if (!attacker.isStressed())
                            {
                                attacker.receiveStress();
                            }

                            attacker.focus().increase();
                            var targetLock = new TargetLock(attacker, defender);
                            attacker.addAttackerTargetLock(targetLock);
                            defender.addDefenderTargetLock(targetLock);
                        }
                    }

                    if (attacker.isUpgradedWith(UpgradeCard.TACTICIAN) &&
                            attacker.combatState().range() === RangeRuler.TWO)
                    {
                        var firingArc = attacker.pilot().shipTeam.ship.primaryFiringArc;

                        if (weapon.isDefenderInFiringArc(attackerPosition, firingArc, defender, defenderPosition))
                        {
                            defender.receiveStress();
                        }
                    }

                    if (defender.isDestroyed())
                    {
                        if (attacker.pilotKey() === Pilot.IG_88A)
                        {
                            attacker.recoverShield();
                        }

                        var shipDestroyedAction = new ShipDestroyedAction(environment, defender, defenderPosition);
                        shipDestroyedAction.doIt();
                        var delay = 1500;
                        setTimeout(function()
                        {
                            if (callback)
                            {
                                callback();
                            }
                        }, delay);
                    }
                    else
                    {
                        if ((weapon.upgradeKey() === UpgradeCard.CLUSTER_MISSILES || weapon.upgradeKey() === UpgradeCard.TWIN_LASER_TURRET) &&
                                executionCount < 2)
                        {
                            that.doIt();
                        }
                        else
                        {
                            if (callback)
                            {
                                callback();
                            }
                        }
                    }

                    LOGGER.trace("CombatAction.finishDealDamage() end");
                }
            }

            return CombatAction;
        });
<|endoftext|>


<commit_before>/*jslint browser: true*/
/*global  $, chrome, moment*/

"use strict";
var isItAfterTwelve = function () {
    if (moment.utc().add('hours', 4).format('H') > 12) {
        return true;
    }
    return false;
}, getCurrentTime = function () {
    return moment.utc().add('hours', 4).format('DD.MM.YYYY HH:mm');
}, saveCurrentTime = function (fn) {
    chrome.storage.local.set({
        time_updated: getCurrentTime()
    }, function () {
        fn();
    });
}, getLastUpdated = function (fn) {
    chrome.storage.local.get('time_updated', function (updated) {
        fn(updated);
    });
}, updateProxies = function (fn) {
    $.getJSON('http://api.proxyhood.com:81/reliable.json', function (list) {
        chrome.storage.local.remove('proxyList');
        chrome.storage.local.set({
            proxyList: list
        }, function () {
            saveCurrentTime(function () {
                fn(list);
            });
        });
    });
}, prepareToUpdate = function (fn) {
    getLastUpdated(function (time) {
        var dayUpdated = moment(time).format('D'),
            dayNow = moment.utc().add('hours', 4).format('D');
        if ($.isEmptyObject(time.time_updated) || ((dayNow > dayUpdated) && isItAfterTwelve() === true)) {
            updateProxies(fn);
        } else {
            fn(null);
        }
    });
}, guuid = function (pre) {
    var d = new Date().getTime(),
        uuid = pre + '_xxxxxxxx_xxxx_4xxx_yxxx_xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            var r = (d + Math.random() * 16) % 16 | 0;
            d = Math.floor(d / 16);
            return (c === 'x' ? r : (r & 0x7 | 0x8)).toString(16);
        });
    return uuid;
}, getInfo = function (fn) {
    chrome.proxy.settings.get({},
        function (config) {
            fn(config);
        });
}, isProxy = function (fn) {
    getInfo(function (config) {
        fn(config.value.mode === 'fixed_servers');
    });
}, clearProxy = function (fn) {
    chrome.proxy.settings.set({
        value: {
            mode: "direct"
        },
        scope: 'regular'
    },
        function () {
            fn();
        });
}, runProxy = function (protocol, host, fn) {
    var scheme = protocol.toLowerCase(),
        proxy_config = {
            mode: "fixed_servers",
            rules: {
                singleProxy: {
                    scheme: scheme,
                    host: host.split(":")[0],
                    port: parseInt(host.split(":")[1], 10)
                },
                bypassList: []
            }
        };
    if (scheme === 'https') {
        scheme = 'http';
    }
    chrome.proxy.settings.set({
        value: proxy_config,
        scope: 'regular'
    },
        function () {
            fn();
        });
};<commit_msg>Fix auto-update time<commit_after>/*jslint browser: true*/
/*global  $, chrome, moment*/

"use strict";
var isItAfterTwelve = function () {
    if (moment.utc().add('hours', 4).format('H') > 12) {
        return true;
    }
    return false;
}, getCurrentTime = function () {
    return moment.utc().add('hours', 4).format('DD.MM.YYYY HH:mm');
}, saveCurrentTime = function (fn) {
    chrome.storage.local.set({
        time_updated: getCurrentTime()
    }, function () {
        fn();
    });
}, getLastUpdated = function (fn) {
    chrome.storage.local.get('time_updated', function (updated) {
        fn(updated);
    });
}, updateProxies = function (fn) {
    $.getJSON('http://api.proxyhood.com:81/reliable.json', function (list) {
        chrome.storage.local.remove('proxyList');
        chrome.storage.local.set({
            proxyList: list
        }, function () {
            saveCurrentTime(function () {
                fn(list);
            });
        });
    });
}, prepareToUpdate = function (fn) {
    getLastUpdated(function (time) {
        var dayUpdated = moment(time['time_updated'], 'DD.MM.YYYY').format('D'),
            dayNow = moment.utc().add('hours', 4).format('D');
        if ($.isEmptyObject(time.time_updated) || ((dayNow > dayUpdated) && isItAfterTwelve() === true)) {
            updateProxies(fn);
        } else {
            fn(null);
        }
    });
}, guuid = function (pre) {
    var d = new Date().getTime(),
        uuid = pre + '_xxxxxxxx_xxxx_4xxx_yxxx_xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            var r = (d + Math.random() * 16) % 16 | 0;
            d = Math.floor(d / 16);
            return (c === 'x' ? r : (r & 0x7 | 0x8)).toString(16);
        });
    return uuid;
}, getInfo = function (fn) {
    chrome.proxy.settings.get({},
        function (config) {
            fn(config);
        });
}, isProxy = function (fn) {
    getInfo(function (config) {
        fn(config.value.mode === 'fixed_servers');
    });
}, clearProxy = function (fn) {
    chrome.proxy.settings.set({
        value: {
            mode: "direct"
        },
        scope: 'regular'
    },
        function () {
            fn();
        });
}, runProxy = function (protocol, host, fn) {
    var scheme = protocol.toLowerCase(),
        proxy_config = {
            mode: "fixed_servers",
            rules: {
                singleProxy: {
                    scheme: scheme,
                    host: host.split(":")[0],
                    port: parseInt(host.split(":")[1], 10)
                },
                bypassList: []
            }
        };
    if (scheme === 'https') {
        scheme = 'http';
    }
    chrome.proxy.settings.set({
        value: proxy_config,
        scope: 'regular'
    },
        function () {
            fn();
        });
};<|endoftext|>


<commit_before>/*
 * DealPort
 * Copyright (c) 2014  DealPort B.V.
 *
 * This file is part of DealPort
 *
 * DealPort is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * DealPort is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with DealPort.  If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, the following supplemental terms apply, based on section 7 of
 * the GNU Affero General Public License (version 3):
 * a) Preservation of all legal notices and author attributions
 */

'use strict';

//var P = require('bluebird');
var clone = require('clone');

var Controller = require('./Controller');
var HomePageController = require('./HomePageController');
var swissarmyknife = require('../swissarmyknife');

var HomePage = require('../view/page/HomePage');
var CompanyDetailPage = require('../view/page/CompanyDetailPage');

function PageController(context)
{
        Controller.call(this, context);

        this.pageView = null;
        this.homePageController = new HomePageController(context);
        this.companyContexts = null;
        this.companyDetailContext = null;
}

require('inherits')(PageController, Controller);
module.exports = PageController;

PageController.prototype.leave = function()
{
        if (this.companyContexts)
        {
                this.companyContexts.destroy();
                this.companyContexts = null;
        }

        if (this.pageView)
        {
                this.pageView.removeNode();
                this.pageView = null;
        }
};

PageController.prototype._companyAcquireContexts = function(ids)
{
        var Company = this.context.resource.Company;

        var acquire = ids
                ? Company.acquireContexts(ids)
                : Company.acquireAllContexts();

        return acquire
        .bind(this)
        .then(function(acquireContextResult)
        {
                this.companyContexts = acquireContextResult;
                this.companyContexts.onOp = this._onCompanyOp.bind(this);
                return acquireContextResult.allSnapshots;
        });
};

PageController.prototype._onCompanyOp = function(id, snapshot, components)
{
        // todo really apply operations

        var keys = components.map(function(comp)
        {
                return comp.p[0];
        });

        var set = {};

        keys.forEach(function(key)
        {
                set[key] = snapshot[key];
        });

        if (this.state === 'home')
        {
                console.info('Applying new data for keys ', keys, 'on company', id);

                var companyItem = this.pageView.companyGrid.companiesById[id];
                if (!companyItem)
                {
                        return;
                }

                companyItem.setValues(set);
        }
        else if (this.state.type === 'NamedEntity' &&
                 this.pageView &&
                 this.pageView.id === id)
        {
                console.info('Applying new data for keys ', keys, 'on company', id);
                this.pageView.setValues(set);
        }
};

PageController.prototype.enterHome = function(state, upgrade)
{
        var doc = this.context.document;
        var Company = this.context.resource.Company;

        this.child = this.homePageController;

        if (upgrade)
        {
                this.pageView = doc.assertSelector('> .HomePage', HomePage, this.context.router);
                return this._companyAcquireContexts();
        }

        var allCompaniesPromise = this.context.server
                ? Company.all()
                : this._companyAcquireAllContexts();

        return allCompaniesPromise.then(function(companies)
        {
                companies = clone(companies, false, 1);
                swissarmyknife.sortByStringProperty(companies, 'name');
                var homePage = new HomePage(doc.document, this.context.router);
                homePage.companyGrid.addCompany(companies);
                homePage.companyGrid.addPlaceholder();

                this.pageView = homePage;
                doc.appendChild(homePage);
                doc.title = homePage.title + ' :: DealPort.co';
        }.bind(this));
};

PageController.prototype.enterNamedEntity = function(namedEntityState, upgrade)
{
        var Company = this.context.resource.Company;
        var NamedEntity = this.context.resource.NamedEntity;
        var doc = this.context.document;
        // Determine which page to display based on the matching entity

        if (upgrade)
        {
                this.pageView = doc.selector('> .notFound');
                if (this.pageView)
                {
                        return;
                }

                this.pageView = doc.selector('> .CompanyDetailPage', CompanyDetailPage, this.context.router);
                if (this.pageView)
                {
                        return this._companyAcquireContexts([this.pageView.id]).get('0');
                        // company
                }

                // todo also try user here

                throw Error('Unable to match a Page view');
        }

        return NamedEntity.byName(namedEntityState.name)
        .bind(this)
        .then(function(named)
        {
                if (named && named.company)
                {
                        return [named,
                                this.context.server
                                ? Company.ids([named.company]).get(0)
                                : this._companyAcquireContexts([named.company]).get('0')
                        ];
                }

                return [named, null];
        })
        .spread(function(named, entity)
        {
                if (!named ||
                    !named.company ||
                    !entity)
                {
                        if (named)
                        {
                                // database inconsistency
                                console.error('Found NamedEntity however the entity it references does not exist!', named);
                        }
                        // todo 404 header
                        this.pageView = doc.create('p', 'notFound', 'Route not found');
                        doc.appendChild(this.pageView);
                        return;
                }

                if (named.company)
                {
                        // todo pass company
                        this.pageView = new CompanyDetailPage(doc.document, this.context.router, entity);
                        doc.appendChild(this.pageView);
                }
                else if (named.user)
                {
                        // todo
                }
        });

};<commit_msg>Bug fix<commit_after>/*
 * DealPort
 * Copyright (c) 2014  DealPort B.V.
 *
 * This file is part of DealPort
 *
 * DealPort is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * DealPort is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with DealPort.  If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, the following supplemental terms apply, based on section 7 of
 * the GNU Affero General Public License (version 3):
 * a) Preservation of all legal notices and author attributions
 */

'use strict';

//var P = require('bluebird');
var clone = require('clone');

var Controller = require('./Controller');
var HomePageController = require('./HomePageController');
var swissarmyknife = require('../swissarmyknife');

var HomePage = require('../view/page/HomePage');
var CompanyDetailPage = require('../view/page/CompanyDetailPage');

function PageController(context)
{
        Controller.call(this, context);

        this.pageView = null;
        this.homePageController = new HomePageController(context);
        this.companyContexts = null;
        this.companyDetailContext = null;
}

require('inherits')(PageController, Controller);
module.exports = PageController;

PageController.prototype.leave = function()
{
        if (this.companyContexts)
        {
                this.companyContexts.destroy();
                this.companyContexts = null;
        }

        if (this.pageView)
        {
                this.pageView.removeNode();
                this.pageView = null;
        }
};

PageController.prototype._companyAcquireContexts = function(ids)
{
        var Company = this.context.resource.Company;

        var acquire = ids
                ? Company.acquireContexts(ids)
                : Company.acquireAllContexts();

        return acquire
        .bind(this)
        .then(function(acquireContextResult)
        {
                this.companyContexts = acquireContextResult;
                this.companyContexts.onOp = this._onCompanyOp.bind(this);
                return acquireContextResult.allSnapshots;
        });
};

PageController.prototype._onCompanyOp = function(id, snapshot, components)
{
        // todo really apply operations

        var keys = components.map(function(comp)
        {
                return comp.p[0];
        });

        var set = {};

        keys.forEach(function(key)
        {
                set[key] = snapshot[key];
        });

        if (this.state === 'home')
        {
                console.info('Applying new data for keys ', keys, 'on company', id);

                var companyItem = this.pageView.companyGrid.companiesById[id];
                if (!companyItem)
                {
                        return;
                }

                companyItem.setValues(set);
        }
        else if (this.state.type === 'NamedEntity' &&
                 this.pageView &&
                 this.pageView.id === id)
        {
                console.info('Applying new data for keys ', keys, 'on company', id);
                this.pageView.setValues(set);
        }
};

PageController.prototype.enterHome = function(state, upgrade)
{
        var doc = this.context.document;
        var Company = this.context.resource.Company;

        this.child = this.homePageController;

        if (upgrade)
        {
                this.pageView = doc.assertSelector('> .HomePage', HomePage, this.context.router);
                return this._companyAcquireContexts();
        }

        var allCompaniesPromise = this.context.server
                ? Company.all()
                : this._companyAcquireContexts();

        return allCompaniesPromise.then(function(companies)
        {
                companies = clone(companies, false, 1);
                swissarmyknife.sortByStringProperty(companies, 'name');
                var homePage = new HomePage(doc.document, this.context.router);
                homePage.companyGrid.addCompany(companies);
                homePage.companyGrid.addPlaceholder();

                this.pageView = homePage;
                doc.appendChild(homePage);
                doc.title = homePage.title + ' :: DealPort.co';
        }.bind(this));
};

PageController.prototype.enterNamedEntity = function(namedEntityState, upgrade)
{
        var Company = this.context.resource.Company;
        var NamedEntity = this.context.resource.NamedEntity;
        var doc = this.context.document;
        // Determine which page to display based on the matching entity

        if (upgrade)
        {
                this.pageView = doc.selector('> .notFound');
                if (this.pageView)
                {
                        return;
                }

                this.pageView = doc.selector('> .CompanyDetailPage', CompanyDetailPage, this.context.router);
                if (this.pageView)
                {
                        return this._companyAcquireContexts([this.pageView.id]).get('0');
                        // company
                }

                // todo also try user here

                throw Error('Unable to match a Page view');
        }

        return NamedEntity.byName(namedEntityState.name)
        .bind(this)
        .then(function(named)
        {
                if (named && named.company)
                {
                        return [named,
                                this.context.server
                                ? Company.ids([named.company]).get(0)
                                : this._companyAcquireContexts([named.company]).get('0')
                        ];
                }

                return [named, null];
        })
        .spread(function(named, entity)
        {
                if (!named ||
                    !named.company ||
                    !entity)
                {
                        if (named)
                        {
                                // database inconsistency
                                console.error('Found NamedEntity however the entity it references does not exist!', named);
                        }
                        // todo 404 header
                        this.pageView = doc.create('p', 'notFound', 'Route not found');
                        doc.appendChild(this.pageView);
                        return;
                }

                if (named.company)
                {
                        // todo pass company
                        this.pageView = new CompanyDetailPage(doc.document, this.context.router, entity);
                        doc.appendChild(this.pageView);
                }
                else if (named.user)
                {
                        // todo
                }
        });

};<|endoftext|>


<commit_before>// Show/hide search bar
//

'use strict';

const _  = require('lodash');

// Hide search bar if user presses Escape key,
// and focus is inside search bar
//
function keydown_handler(event) {
  if (event.which !== 27 /* ESC */) return;

  event.preventDefault();
  event.stopPropagation();

  /* eslint-disable no-use-before-define */
  hide_search_bar();
}

// Click inside form, need to stop propagation of this event
// to global handlers
//
function click_inside_form_handler(event) {
  event.stopPropagation();
}

// Hide search bar if user clicks anywhere outside of it
//
function click_outside_form_handler(event) {
  if (event.which === 3 /* right mouse button */) return;

  hide_search_bar();
}

// Show search bar
//
function show_search_bar() {
  $('.navbar').addClass('nav-search-on');
  $('.nav-search__input').focus();

  $(document).on('keydown', '.nav-search__form', keydown_handler);
  $(document).on('click focusin', '.nav-search__form', click_inside_form_handler);
  $(document).on('click focusin', click_outside_form_handler);
}

// Hide search bar
//
function hide_search_bar() {
  $('.navbar').removeClass('nav-search-on');

  $(document).off('keydown', '.nav-search__form', keydown_handler);
  $(document).off('click focusin', '.nav-search__form', click_inside_form_handler);
  $(document).off('click focusin', click_outside_form_handler);
}

N.wire.on(module.apiPath + ':show', show_search_bar);
N.wire.on(module.apiPath + ':hide', hide_search_bar);

N.wire.on(module.apiPath + ':change_area', function set_search_area(data) {
  let select = data.$this.closest('.input-group-btn').find('.nav-search__select');

  select.text(data.$this.text());
  select.data('method', data.$this.data('method') || null);
  select.data('params', data.$this.data('params') || null);
});

N.wire.on(module.apiPath + ':submit', function submit_search(data) {
  // remove click and keydown listeners
  hide_search_bar();

  let select = data.$this.find('.nav-search__select');
  let params = _.assign({}, select.data('params'));
  let apiPath = select.data('method') || 'search.general';

  if (data.fields.query) {
    params.query = data.fields.query;
  }

  return N.wire.emit('navigate.to', {
    apiPath,
    params: { $query: params },
    force: true
  });
});
<commit_msg>Fix dropdown closing when user selects a search area<commit_after>// Show/hide search bar
//

'use strict';

const _  = require('lodash');

// Hide search bar if user presses Escape key,
// and focus is inside search bar
//
function keydown_handler(event) {
  if (event.which !== 27 /* ESC */) return;

  event.preventDefault();
  event.stopPropagation();

  /* eslint-disable no-use-before-define */
  hide_search_bar();
}

// Hide search bar if user clicks or moves with "tab" key
// anywhere outside of it
//
function hide_form_on_focus_out_handler(event) {
  if (event.which === 3 /* right mouse button */) return;

  if ($(event.target).closest('.nav-search__form').length === 0) {
    hide_search_bar();
  }
}

// Show search bar
//
function show_search_bar() {
  $('.navbar').addClass('nav-search-on');
  $('.nav-search__input').focus();

  $(document).on('keydown', '.nav-search__form', keydown_handler);
  $(document).on('click focusin', hide_form_on_focus_out_handler);
}

// Hide search bar
//
function hide_search_bar() {
  $('.navbar').removeClass('nav-search-on');

  $(document).off('keydown', '.nav-search__form', keydown_handler);
  $(document).off('click focusin', hide_form_on_focus_out_handler);
}

N.wire.on(module.apiPath + ':show', show_search_bar);
N.wire.on(module.apiPath + ':hide', hide_search_bar);

N.wire.on(module.apiPath + ':change_area', function set_search_area(data) {
  let select = data.$this.closest('.input-group-btn').find('.nav-search__select');

  select.text(data.$this.text());
  select.data('method', data.$this.data('method') || null);
  select.data('params', data.$this.data('params') || null);
});

N.wire.on(module.apiPath + ':submit', function submit_search(data) {
  // remove click and keydown listeners
  hide_search_bar();

  let select = data.$this.find('.nav-search__select');
  let params = _.assign({}, select.data('params'));
  let apiPath = select.data('method') || 'search.general';

  if (data.fields.query) {
    params.query = data.fields.query;
  }

  return N.wire.emit('navigate.to', {
    apiPath,
    params: { $query: params },
    force: true
  });
});
<|endoftext|>


<commit_before>/*
 * Backpack - Skyscanner's Design System
 *
 * Copyright 2017 Skyscanner Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import React from 'react';
import PropTypes from 'prop-types';
import { Text, Platform, StyleSheet } from 'react-native';
import iconMappings from 'bpk-svgs/dist/font/iconMapping.json';

const tokens = Platform.select({
  ios: () => require('bpk-tokens/tokens/ios/base.react.native.common.js'), // eslint-disable-line global-require
  android: () => require('bpk-tokens/tokens/android/base.react.native.common.js'), // eslint-disable-line global-require
})();

const {
  spacingBase,
  spacingLg,
  colorGray700,
} = tokens;

const styles = StyleSheet.create({
  icon: {
    fontFamily: 'BpkIcon',
    fontSize: spacingLg,
    lineHeight: spacingLg,
    color: colorGray700,
  },
  small: {
    fontSize: spacingBase,
    lineHeight: spacingBase,
  },
});

const mapCharacterCode = characterCode => String.fromCharCode(parseInt(characterCode, 16));

const BpkIcon = (props) => {
  const { icon, small, style, ...rest } = props;

  const characterCode = iconMappings[icon];

  const textStyleFinal = [styles.icon];

  if (small) {
    textStyleFinal.push(styles.small);
  }

  if (style) {
    textStyleFinal.push(style);
  }

  return (<Text style={textStyleFinal} {...rest} >{mapCharacterCode(characterCode)}</Text>);
};

BpkIcon.propTypes = {
  icon: PropTypes.oneOf(Object.keys(iconMappings)),
  small: PropTypes.bool,
  style: Text.propTypes.style,
};

BpkIcon.defaultProps = {
  icon: undefined,
  small: false,
  style: null,
};

export default BpkIcon;
<commit_msg>[BPK-841] icon prop is required<commit_after>/*
 * Backpack - Skyscanner's Design System
 *
 * Copyright 2017 Skyscanner Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import React from 'react';
import PropTypes from 'prop-types';
import { Text, Platform, StyleSheet } from 'react-native';
import iconMappings from 'bpk-svgs/dist/font/iconMapping.json';

const tokens = Platform.select({
  ios: () => require('bpk-tokens/tokens/ios/base.react.native.common.js'), // eslint-disable-line global-require
  android: () => require('bpk-tokens/tokens/android/base.react.native.common.js'), // eslint-disable-line global-require
})();

const {
  spacingBase,
  spacingLg,
  colorGray700,
} = tokens;

const styles = StyleSheet.create({
  icon: {
    fontFamily: 'BpkIcon',
    fontSize: spacingLg,
    lineHeight: spacingLg,
    color: colorGray700,
  },
  small: {
    fontSize: spacingBase,
    lineHeight: spacingBase,
  },
});

const mapCharacterCode = characterCode => String.fromCharCode(parseInt(characterCode, 16));

const BpkIcon = (props) => {
  const { icon, small, style, ...rest } = props;

  const characterCode = iconMappings[icon];

  const textStyleFinal = [styles.icon];

  if (small) {
    textStyleFinal.push(styles.small);
  }

  if (style) {
    textStyleFinal.push(style);
  }

  return (<Text style={textStyleFinal} {...rest} >{mapCharacterCode(characterCode)}</Text>);
};

BpkIcon.propTypes = {
  icon: PropTypes.oneOf(Object.keys(iconMappings)).isRequired,
  small: PropTypes.bool,
  style: Text.propTypes.style,
};

BpkIcon.defaultProps = {
  small: false,
  style: null,
};

export default BpkIcon;
<|endoftext|>