<commit_before>/* globals
window $ document
*/
import { analytics, BaseScript, SettingsEntry } from '../core';
import { TransferMarket, priceTiers } from '../../fut';

export class MinBinSettings extends SettingsEntry {
  static id = 'min-bin';
  constructor() {
    super('min-bin', 'Search minimum BIN');

    this.addSetting('Amount of lowest BINs to determine minimum on', 'mean-count', 3, 'number');
    this.addSetting('Adjust quicklist panel price automatically based on minimum BIN', 'adjust-list-price', true, 'checkbox');
    this.addSettingUnder('adjust-list-price', 'Start price percentage (0 to 100%)', 'start-price-percentage', 90, 'number');
    this.addSettingUnder('adjust-list-price', 'Buy now price percentage (0 to 100%)', 'buy-now-price-percentage', 110, 'number');
  }
}

class MinBin extends BaseScript {
  constructor() {
    super(MinBinSettings.id);

    const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
    this._observer = new MutationObserver(this._mutationHandler.bind(this));

    this._playerPrices = [];
  }

  activate(state) {
    super.activate(state);

    const obsConfig = {
      childList: true,
      characterData: true,
      attributes: false,
      subtree: true,
    };

    setTimeout(() => {
      this._observer.observe($(document)[0], obsConfig);
    }, 0);
  }

  deactivate(state) {
    super.deactivate(state);

    this._observer.disconnect();
  }

  _mutationHandler(mutationRecords) {
    mutationRecords.forEach(function (mutation) {
      if ($(mutation.target).hasClass('DetailView') && $(mutation.target)
        .find('.DetailPanel') && mutation.addedNodes.length > 0) {
        const searchMinBin = $(mutation.target).find('#searchMinBin');
        searchMinBin.remove();

        let selectedItem = this._getSelectedItem();

        if (selectedItem == null || selectedItem.resourceId === 0) {
          return;
        }
        const knownPlayerPrice = this._playerPrices
          .find(p => p.resourceId === selectedItem.resourceId);
        let price = '';
        if (knownPlayerPrice != null) {
          price = `(${knownPlayerPrice.minimumBin})`;

          this._updateListPrice(knownPlayerPrice.minimumBin);
        }
        $(mutation.target).find('.DetailPanel > .ut-button-group').prepend(`<button id="searchMinBin" data-resource-id="${selectedItem.resourceId}" class="list"><span class="btn-text">Search minimum BIN ${price}</span><span class="btn-subtext"></span></button>`);

        $('#searchMinBin').bind('click', async () => {
          const btn = $('#searchMinBin');
          btn.find('.btn-text').html('Searching minimum BIN...');
          analytics.trackEvent('Min BIN', 'Search Min BIN', btn.data('resource-id'));
          const settings = this.getSettings();
          const minimumBin = await new TransferMarket().searchMinBuy(selectedItem, parseInt(settings['mean-count'], 10));
          const playerPrice = this._playerPrices.find(p => p.resourceId === btn.data('resource-id'));
          if (playerPrice != null) {
            this._playerPrices.splice(this._playerPrices.indexOf(playerPrice), 1);
          }
          this._playerPrices.push({
            resourceId: btn.data('resource-id'),
            minimumBin,
          });

          selectedItem = this._getSelectedItem();

          let notificationText = `Minimum BIN found for ${selectedItem._staticData.name} is ${minimumBin}`;
          if (btn.data('resource-id') === selectedItem.resourceId) {
            if (minimumBin === 0) {
              btn.find('.btn-text').html('Search minimum BIN (extinct)');
              notificationText = `Minimum BIN not found for ${selectedItem._staticData.name}, card may be extinct`;
            } else {
              btn.find('.btn-text').html(`Search minimum BIN (${minimumBin})`);

              this._updateListPrice(minimumBin);
            }
          }

          GM_notification({
            text: notificationText,
            title: 'FUT 19 Web App',
            timeout: 5000,
            onclick: () => window.focus(),
          });
        });
      }
    }, this);
  }

  _updateListPrice(minimumBin) {
    const settings = this.getSettings();
    const quicklistPanel = getAppMain().getRootViewController()
      .getPresentedViewController()
      .getCurrentViewController()
      .getCurrentController()
      ._rightController._currentController._quickListPanel;

    if (settings['adjust-list-price'] && quicklistPanel) {
      const quicklistpanelView = quicklistPanel._view;

      const listPrice = priceTiers.determineListPrice(
        minimumBin * (settings['start-price-percentage'] / 100),
        minimumBin * (settings['buy-now-price-percentage'] / 100),
      );

      if (quicklistPanel._item) {
        // sets the values when the quicklistpanel hasn't been initialized
        const auction = quicklistPanel._item._auction;
        if (auction.tradeState !== 'active') {
          auction.startingBid = listPrice.start;
          auction.buyNowPrice = listPrice.buyNow;
          quicklistPanel._item.setAuctionData(auction);
        }
      }

      const bidSpinner = quicklistpanelView._bidNumericStepper;
      const buySpinner = quicklistpanelView._buyNowNumericStepper;
      bidSpinner.value = listPrice.start;
      buySpinner.value = listPrice.buyNow;
    }
  }

  /* eslint-disable class-methods-use-this */
  _getSelectedItem() {
    const listController = getAppMain().getRootViewController()
      .getPresentedViewController()
      .getCurrentViewController()
      .getCurrentController()._listController;
    if (listController) {
      return listController.getIterator().current();
    }

    const detailController = getAppMain().getRootViewController()
      .getPresentedViewController()
      .getCurrentViewController()
      .getCurrentController()._rightController;
    if (detailController) {
      const current = detailController
        ._currentController._viewmodel.current();

      return current._item ? current._item : current;
    }

    return null;
  }
  /* eslint-enable class-methods-use-this */
}

new MinBin(); // eslint-disable-line no-new
<commit_msg>fix: show correct prices for sold items (#135)<commit_after>/* globals
window $ document
*/
import { analytics, BaseScript, SettingsEntry } from '../core';
import { TransferMarket, priceTiers } from '../../fut';

export class MinBinSettings extends SettingsEntry {
  static id = 'min-bin';
  constructor() {
    super('min-bin', 'Search minimum BIN');

    this.addSetting('Amount of lowest BINs to determine minimum on', 'mean-count', 3, 'number');
    this.addSetting('Adjust quicklist panel price automatically based on minimum BIN', 'adjust-list-price', true, 'checkbox');
    this.addSettingUnder('adjust-list-price', 'Start price percentage (0 to 100%)', 'start-price-percentage', 90, 'number');
    this.addSettingUnder('adjust-list-price', 'Buy now price percentage (0 to 100%)', 'buy-now-price-percentage', 110, 'number');
  }
}

class MinBin extends BaseScript {
  constructor() {
    super(MinBinSettings.id);

    const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
    this._observer = new MutationObserver(this._mutationHandler.bind(this));

    this._playerPrices = [];
  }

  activate(state) {
    super.activate(state);

    const obsConfig = {
      childList: true,
      characterData: true,
      attributes: false,
      subtree: true,
    };

    setTimeout(() => {
      this._observer.observe($(document)[0], obsConfig);
    }, 0);
  }

  deactivate(state) {
    super.deactivate(state);

    this._observer.disconnect();
  }

  _mutationHandler(mutationRecords) {
    mutationRecords.forEach(function (mutation) {
      if ($(mutation.target).hasClass('DetailView') && $(mutation.target)
        .find('.DetailPanel') && mutation.addedNodes.length > 0) {
        const searchMinBin = $(mutation.target).find('#searchMinBin');
        searchMinBin.remove();

        let selectedItem = this._getSelectedItem();

        if (selectedItem == null || selectedItem.resourceId === 0) {
          return;
        }
        const knownPlayerPrice = this._playerPrices
          .find(p => p.resourceId === selectedItem.resourceId);
        let price = '';
        if (knownPlayerPrice != null) {
          price = `(${knownPlayerPrice.minimumBin})`;

          this._updateListPrice(knownPlayerPrice.minimumBin);
        }
        $(mutation.target).find('.DetailPanel > .ut-button-group').prepend(`<button id="searchMinBin" data-resource-id="${selectedItem.resourceId}" class="list"><span class="btn-text">Search minimum BIN ${price}</span><span class="btn-subtext"></span></button>`);

        $('#searchMinBin').bind('click', async () => {
          const btn = $('#searchMinBin');
          btn.find('.btn-text').html('Searching minimum BIN...');
          analytics.trackEvent('Min BIN', 'Search Min BIN', btn.data('resource-id'));
          const settings = this.getSettings();
          const minimumBin = await new TransferMarket().searchMinBuy(selectedItem, parseInt(settings['mean-count'], 10));
          const playerPrice = this._playerPrices.find(p => p.resourceId === btn.data('resource-id'));
          if (playerPrice != null) {
            this._playerPrices.splice(this._playerPrices.indexOf(playerPrice), 1);
          }
          this._playerPrices.push({
            resourceId: btn.data('resource-id'),
            minimumBin,
          });

          selectedItem = this._getSelectedItem();

          let notificationText = `Minimum BIN found for ${selectedItem._staticData.name} is ${minimumBin}`;
          if (btn.data('resource-id') === selectedItem.resourceId) {
            if (minimumBin === 0) {
              btn.find('.btn-text').html('Search minimum BIN (extinct)');
              notificationText = `Minimum BIN not found for ${selectedItem._staticData.name}, card may be extinct`;
            } else {
              btn.find('.btn-text').html(`Search minimum BIN (${minimumBin})`);

              this._updateListPrice(minimumBin);
            }
          }

          GM_notification({
            text: notificationText,
            title: 'FUT 19 Web App',
            timeout: 5000,
            onclick: () => window.focus(),
          });
        });
      }
    }, this);
  }

  _updateListPrice(minimumBin) {
    const settings = this.getSettings();
    const quicklistPanel = getAppMain().getRootViewController()
      .getPresentedViewController()
      .getCurrentViewController()
      .getCurrentController()
      ._rightController._currentController._quickListPanel;

    if (settings['adjust-list-price'] && quicklistPanel) {
      const quicklistpanelView = quicklistPanel._view;

      const listPrice = priceTiers.determineListPrice(
        minimumBin * (settings['start-price-percentage'] / 100),
        minimumBin * (settings['buy-now-price-percentage'] / 100),
      );

      if (quicklistPanel._item) {
        // sets the values when the quicklistpanel hasn't been initialized
        const auction = quicklistPanel._item._auction;
        if (auction.tradeState === 'closed') {
          // item is sold
          return;
        }
        if (auction.tradeState !== 'active') {
          auction.startingBid = listPrice.start;
          auction.buyNowPrice = listPrice.buyNow;
          quicklistPanel._item.setAuctionData(auction);
        }
      }

      const bidSpinner = quicklistpanelView._bidNumericStepper;
      const buySpinner = quicklistpanelView._buyNowNumericStepper;
      bidSpinner.value = listPrice.start;
      buySpinner.value = listPrice.buyNow;
    }
  }

  /* eslint-disable class-methods-use-this */
  _getSelectedItem() {
    const listController = getAppMain().getRootViewController()
      .getPresentedViewController()
      .getCurrentViewController()
      .getCurrentController()._listController;
    if (listController) {
      return listController.getIterator().current();
    }

    const detailController = getAppMain().getRootViewController()
      .getPresentedViewController()
      .getCurrentViewController()
      .getCurrentController()._rightController;
    if (detailController) {
      const current = detailController
        ._currentController._viewmodel.current();

      return current._item ? current._item : current;
    }

    return null;
  }
  /* eslint-enable class-methods-use-this */
}

new MinBin(); // eslint-disable-line no-new
<|endoftext|>


<commit_before>const html = require('choo/html');
const assets = require('../../common/assets');

module.exports = function(state) {
  return html`

        ${state.translate('downloadFinish')}

        ${state.translate('trySendDescription')}

        ${state.translate('sendYourFilesLink')}

        ${state.translate('reportFile')}

  `;
};
<commit_msg>show "OK" button on complete page when logged in instead of "Try Firefox Send"<commit_after>const html = require('choo/html');
const assets = require('../../common/assets');

module.exports = function(state) {
  const btnText = state.user.loggedIn ? 'okButton' : 'sendYourFilesLink';
  return html`

        ${state.translate('downloadFinish')}

        ${state.translate('trySendDescription')}

        ${state.translate(btnText)}

        ${state.translate('reportFile')}

  `;
};
<|endoftext|>


<commit_before>var express = require('express');
var os = require('os');
var cors = require('cors');
var child_process = require('child_process');
var app = express();
var user = 'nobody';

app.use(function(req, res, next) {
    var auth;

    if (req.headers.authorization) {
      auth = new Buffer(req.headers.authorization.substring(6), 'base64').toString().split(':');
    }

    if (!auth || auth[0] !== 'hadoop' || auth[1] !== 'tip') {
        res.statusCode = 401;
        res.setHeader('WWW-Authenticate', 'Basic realm="T Intelligence Platform"');
        res.end('Unauthorized');
    } else {
        user = auth[0];
        next();
    }
});
app.use(cors());

var usage = '\
\

\

predict   	  [Caffe] 	placeholder/predict/bvlc_reference_caffenet%2Fdata%2Fsample%2Fad_sunglass.png,3
\

count      	  [HDFS]  	placeholder/count/%2Fdata%2Ftext%2Fnewsgroup
\

count_line 	  [Spark] 	placeholder/count_line/%2Fdata%2Fimage%2Fimagenet%2F%2A.txt
\

du         	  [HDFS]  	placeholder/du/%2Fdata%2Fsample
\

head       	  [Spark] 	placeholder/head/%2Fdata%2Fimage%2Fimagenet%2F%2A.txt,5
\

ls         	  [HDFS]  	placeholder/ls/%2Fdata%2Fsample
\

ngram_ko   	  [Spark] 	placeholder/ngram_ko/2,%2Fuser%2Fhadoop%2Ftf_result,%2Fuser%2Fhadoop%2Fngram_result
\

sql        	  [Hive]  	placeholder/sql/%27select%20count(%2A)%20from%20data.news%27
\

sql2       	  [Hive]  	placeholder/sql2/%27select%20count(%2A)%20from%20data.news%27
\

text       	  [HDFS]  	placeholder/text/%2Fdata%2Fsample%2Fhani_news.head.txt.gz,5
\

tf_ko      	  [Spark] 	placeholder/tf_ko/%2Fdata%2Ftext%2Fnews%2Fhani%2F%2A,%2Fuser%2Fhadoop%2Ftf_result
\

train_mnist	  [Caffe] 	placeholder/train_mnist/gpu=0,mode=GPU,net=net.prototxt
\

word_cloud 	  [R]     	placeholder/word_cloud/%2Fuser%2Fhadoop%2Fnews_word_count.txt
\

\
';
var hostname = os.hostname();
usage = usage.replace(/placeholder/g, 'http://hadoop:tip@' + hostname + ':8080/api/v1');

app.get('/api/v1/:op/:param', function(req, res) {
    console.log(user + "@" + req.ip + ": " + req.originalUrl);
    console.log('/usr/local/bin/fab -f ../cli/fabfile.py ' + req.params.op + ':' + req.params.param);

    child = child_process.exec('/usr/local/bin/fab -f ../cli/fabfile.py ' + req.params.op + ':' + req.params.param,
        function (error, stdout, stderr) {
            console.log('stdout: ' + stdout);
            console.log('stderr: ' + stderr);
            res.setHeader('Access-Control-Allow-Origin', '*');
            res.json({
                "user": user,
                "ip": req.ip,
                "request": req.originalUrl,
                "result": stdout.toString()
            });
            if (error !== null) {
                console.log('exec error: ' + error);
            }
        });
});

app.get('/api/v1/:op', function(req, res) {
  res.send(usage);
});

app.get('/api/v1/', function(req, res) {
  res.send(usage);
});

app.listen(process.env.PORT || 8080);
<commit_msg>fix typos<commit_after>var express = require('express');
var os = require('os');
var cors = require('cors');
var child_process = require('child_process');
var app = express();
var user = 'nobody';

app.use(function(req, res, next) {
    var auth;

    if (req.headers.authorization) {
      auth = new Buffer(req.headers.authorization.substring(6), 'base64').toString().split(':');
    }

    if (!auth || auth[0] !== 'hadoop' || auth[1] !== 'tip') {
        res.statusCode = 401;
        res.setHeader('WWW-Authenticate', 'Basic realm="T Intelligence Platform"');
        res.end('Unauthorized');
    } else {
        user = auth[0];
        next();
    }
});
app.use(cors());

var usage = '\
\

\

predict   	  [Caffe] 	placeholder/predict/bvlc_reference_caffenet,%2Fdata%2Fsample%2Fad_sunglass.png,3
\

count      	  [HDFS]  	placeholder/count/%2Fdata%2Ftext%2Fnewsgroup
\

count_line 	  [Spark] 	placeholder/count_line/%2Fdata%2Fimage%2Fimagenet%2F%2A.txt
\

du         	  [HDFS]  	placeholder/du/%2Fdata%2Fsample
\

head       	  [Spark] 	placeholder/head/%2Fdata%2Fimage%2Fimagenet%2F%2A.txt,5
\

ls         	  [HDFS]  	placeholder/ls/%2Fdata%2Fsample
\

ngram_ko   	  [Spark] 	placeholder/ngram_ko/2,%2Fuser%2Fhadoop%2Ftf_result,%2Fuser%2Fhadoop%2Fngram_result
\

sql        	  [Hive]  	placeholder/sql/%27select%20count(%2A)%20from%20data.news%27
\

sql2       	  [Hive]  	placeholder/sql2/%27select%20count(%2A)%20from%20data.news%27
\

text       	  [HDFS]  	placeholder/text/%2Fdata%2Fsample%2Fhani_news.head.txt.gz,5
\

tf_ko      	  [Spark] 	placeholder/tf_ko/%2Fdata%2Ftext%2Fnews%2Fhani%2F%2A,%2Fuser%2Fhadoop%2Ftf_result
\

train_mnist	  [Caffe] 	placeholder/train_mnist/gpu=0,mode=GPU,net=net.prototxt
\

word_cloud 	  [R]     	placeholder/word_cloud/%2Fuser%2Fhadoop%2Fnews_word_count.txt
\

\
';
var hostname = os.hostname();
usage = usage.replace(/placeholder/g, 'http://hadoop:tip@' + hostname + ':8080/api/v1');

app.get('/api/v1/:op/:param', function(req, res) {
    console.log(user + "@" + req.ip + ": " + req.originalUrl);
    console.log('/usr/local/bin/fab -f ../cli/fabfile.py ' + req.params.op + ':' + req.params.param);

    child = child_process.exec('/usr/local/bin/fab -f ../cli/fabfile.py ' + req.params.op + ':' + req.params.param,
        function (error, stdout, stderr) {
            console.log('stdout: ' + stdout);
            console.log('stderr: ' + stderr);
            res.setHeader('Access-Control-Allow-Origin', '*');
            res.json({
                "user": user,
                "ip": req.ip,
                "request": req.originalUrl,
                "result": stdout.toString()
            });
            if (error !== null) {
                console.log('exec error: ' + error);
            }
        });
});

app.get('/api/v1/:op', function(req, res) {
  res.send(usage);
});

app.get('/api/v1/', function(req, res) {
  res.send(usage);
});

app.listen(process.env.PORT || 8080);
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.crypto.hash',
  name: 'HashableTest',
  extends: 'foam.nanos.test.Test',

  javaImports: [
    'foam.nanos.auth.User',
    'org.bouncycastle.util.encoders.Hex',
    'java.security.NoSuchAlgorithmException'
  ],

  methods: [
    {
      name: 'runTest',
      javaCode: `
        User input = new User.Builder(x)
          .setId(1000)
          .setFirstName("Foam")
          .setLastName("Test")
          .setEmail("test@foam.net")
          .build();

        // non-chained hash with correct digest
        Hashable_HashWithValidAlgorithm(input, "MD5",
            "47f68c52aaae1c2cdad696c59a248752");
        Hashable_HashWithValidAlgorithm(input, "SHA-1",
            "b56f36f495469a97928e664ccff17ea62d7d4d78");
        Hashable_HashWithValidAlgorithm(input, "SHA-256",
            "ec0604d4874bd8f899a9efcb4e05bd2c83f024b16c5ae8b2a99049a5106b8eb6");
        Hashable_HashWithValidAlgorithm(input, "SHA-384",
            "d2f4e706ec2b7b8f2bfd21b1e80c28bb500453d22a11ab4b6be82dd8de03470b1f172e5b80ffda71f7b5f5f170ec2350");
        Hashable_HashWithValidAlgorithm(input, "SHA-512",
            "d6b71a2d9368fac8aba8b285ea489297a55f99e31a6585a19f524fd09b53375d74563040793195f3dbb1eee6e7defff5d03bff569b9962ae06250626f402903a");

        // hashing same objects produces same digest
        Hashable_HashingSameObjects_ProducesSameDigest(input, input,
            "Hashing the same object produces the same digest");
        Hashable_HashingSameObjects_ProducesSameDigest(input.fclone(), input,
            "Hashing the same object where the first object is fcloned produces the same digest");
        Hashable_HashingSameObjects_ProducesSameDigest(input, input.fclone(),
            "Hashing the same object where the second object is fcloned produces the same digest");
        Hashable_HashingSameObjects_ProducesSameDigest(input.fclone(), input.fclone(),
            "Hashing the same object where both objects are fcloned produces the same digest");

        // hash with invalid algorithm
        Hashable_HashWithInvalidAlgorithm_NoSuchAlgorithmException(input);
      `
    },
    {
      name: 'Hashable_HashWithValidAlgorithm',
      args: [
        { type: 'FObject', name: 'input'     },
        { type: 'String',          name: 'algorithm' },
        { type: 'String',          name: 'expected'  }
      ],
      javaCode: `
        try {
          String produced = Hex.toHexString(input.hash(algorithm));
          test(produced.equals(expected),
              "Input hashed algorithm: " + algorithm + ", produced: "+produced+ ", expected: "+expected);
        } catch ( Throwable t ) {
          test(false, "Input hashed using " + algorithm + " should not throw an exception");
        }
      `
    },
    {
      name: 'Hashable_HashingSameObjects_ProducesSameDigest',
      args: [
        { type: 'FObject', name: 'o1'      },
        { type: 'FObject', name: 'o2'      },
        { type: 'String',          name: 'message' }
      ],
      javaCode: `
        try {
          String d1 = Hex.toHexString(o1.hash("SHA-256"));
          String d2 = Hex.toHexString(o2.hash("SHA-256"));
          test(d1.equals(d2), message);
        } catch ( Throwable t ) {
          test(false, message);
        }
      `
    },
    {
      name: 'Hashable_HashWithInvalidAlgorithm_NoSuchAlgorithmException',
      args: [ { type: 'FObject', name: 'input' } ],
      javaCode: `
        try {
          input.hash("asldkfjaksdjhf");
          test(false, "Hash with invalid algorithm should throw a NoSuchAlgorithmException");
        } catch (Exception e) {
          test(true, "Hash with invalid algorithm throws NoSuchAlgorithmException");
        } catch (Throwable t) {
        }
      `
    }
  ]
});
<commit_msg>revert to medusa hashes<commit_after>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.crypto.hash',
  name: 'HashableTest',
  extends: 'foam.nanos.test.Test',

  javaImports: [
    'foam.nanos.auth.User',
    'org.bouncycastle.util.encoders.Hex',
    'java.security.NoSuchAlgorithmException'
  ],

  methods: [
    {
      name: 'runTest',
      javaCode: `
        User input = new User.Builder(x)
          .setId(1000)
          .setFirstName("Foam")
          .setLastName("Test")
          .setEmail("test@foam.net")
          .build();

        // non-chained hash with correct digest
        Hashable_HashWithValidAlgorithm(input, "MD5",
            "d41d8cd98f00b204e9800998ecf8427e");
        Hashable_HashWithValidAlgorithm(input, "SHA-1",
            "da39a3ee5e6b4b0d3255bfef95601890afd80709");
        Hashable_HashWithValidAlgorithm(input, "SHA-256",
            "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
        Hashable_HashWithValidAlgorithm(input, "SHA-384",
            "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b");
        Hashable_HashWithValidAlgorithm(input, "SHA-512",
            "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e");
        // hashing same objects produces same digest
        Hashable_HashingSameObjects_ProducesSameDigest(input, input,
            "Hashing the same object produces the same digest");
        Hashable_HashingSameObjects_ProducesSameDigest(input.fclone(), input,
            "Hashing the same object where the first object is fcloned produces the same digest");
        Hashable_HashingSameObjects_ProducesSameDigest(input, input.fclone(),
            "Hashing the same object where the second object is fcloned produces the same digest");
        Hashable_HashingSameObjects_ProducesSameDigest(input.fclone(), input.fclone(),
            "Hashing the same object where both objects are fcloned produces the same digest");

        // hash with invalid algorithm
        Hashable_HashWithInvalidAlgorithm_NoSuchAlgorithmException(input);
      `
    },
    {
      name: 'Hashable_HashWithValidAlgorithm',
      args: [
        { type: 'FObject', name: 'input'     },
        { type: 'String',          name: 'algorithm' },
        { type: 'String',          name: 'expected'  }
      ],
      javaCode: `
        try {
          String produced = Hex.toHexString(input.hash(algorithm));
          test(produced.equals(expected),
              "Input hashed algorithm: " + algorithm + ", produced: "+produced+ ", expected: "+expected);
        } catch ( Throwable t ) {
          test(false, "Input hashed using " + algorithm + " should not throw an exception");
        }
      `
    },
    {
      name: 'Hashable_HashingSameObjects_ProducesSameDigest',
      args: [
        { type: 'FObject', name: 'o1'      },
        { type: 'FObject', name: 'o2'      },
        { type: 'String',          name: 'message' }
      ],
      javaCode: `
        try {
          String d1 = Hex.toHexString(o1.hash("SHA-256"));
          String d2 = Hex.toHexString(o2.hash("SHA-256"));
          test(d1.equals(d2), message);
        } catch ( Throwable t ) {
          test(false, message);
        }
      `
    },
    {
      name: 'Hashable_HashWithInvalidAlgorithm_NoSuchAlgorithmException',
      args: [ { type: 'FObject', name: 'input' } ],
      javaCode: `
        try {
          input.hash("asldkfjaksdjhf");
          test(false, "Hash with invalid algorithm should throw a NoSuchAlgorithmException");
        } catch (Exception e) {
          test(true, "Hash with invalid algorithm throws NoSuchAlgorithmException");
        } catch (Throwable t) {
        }
      `
    }
  ]
});
<|endoftext|>


<commit_before><commit_msg>Remove debug logging. Make random selector random.<commit_after><|endoftext|>


<commit_before>var Manager,
    ASSETS_NS = 'http://www.wso2.org/governance/metadata';

var log = new Log();

var ASSET_LCSTATE_PROP = 'lifecycleState';
var DEFAULT_ASSET_VIEW_STATE = 'published';

(function () {

    var dataInjector=require('/modules/data/data.injector.js').dataInjectorModule();
    var DataInjectorModes=dataInjector.Modes;

    var matchAttr = function (searchAttr, artifactAttr) {
        var attribute, attr, val, match;
        for (attribute in searchAttr) {
            if (searchAttr.hasOwnProperty(attribute)) {
                attr = searchAttr[attribute];
                val = artifactAttr[attribute];
                match = (attr instanceof RegExp) ? attr.test(val) : (attr == val);
                if (!match) {
                    return false;
                }
            }
        }
        return true;
    };

    /*
     The function checks whether two artifacts are similar
     @searchArtifact: The artifact containing the search criteria
     @artifact: The artifact to which the searchArtifact must be compared
     @return: If the two artifacts are similar True ,else False.
     */
    var matchArtifact = function (searchArtifact, artifact) {
        var status = true;//We assume that all attributes will match
        var ignoredProperty = 'attributes';
        var term = '';

        log.debug('Invoked matchArtifact: '+artifact.attributes.overview_name);
        log.debug('Ignoring property: ' + ignoredProperty);

        //First go through all of the non attribute properties
        for (var searchKey in searchArtifact) {

            log.debug('Examining property: ' + searchKey);

            if ((searchKey != ignoredProperty) && (artifact.hasOwnProperty(searchKey))) {

                //Match against spaces and lower case
                term = artifact[searchKey] || '';
                term = term.toString().toLowerCase().trim() + '';

                //Determine if the searchKey points to an array
                if (searchArtifact[searchKey] instanceof Array) {

                    log.debug('Checking against array of values: ' + searchArtifact[searchKey]);
                    log.debug('Artifact value '+term);
                    //Check if the value of the artifact property is defined in the
                    //searchArtifact property array.
                    status = (searchArtifact[searchKey].indexOf(term) != -1) ? true : false;
                }
                else {
                    log.debug('Artifact value: '+term);
                    log.debug('Searched value:'+searchArtifact[searchKey]);
                    //Update the status
                    status = (searchArtifact[searchKey] == term);
                }

            }
        }

        log.debug('Properties match: ' + status);

        //If it is not a match at this time then return false, no need to check
        //if the attributes match.
        if(status==false){

            log.debug(artifact.attributes.overview_name+' no match.');
            return status;
        }

        //Only search attributes if the user has provided any
        if (searchArtifact.attributes) {

            //Check if the attributes match
            status = matchAttr(searchArtifact.attributes, artifact.attributes);

            log.debug('Attribute match : ' + status);

        }

        return status;
    }

    var search = function (that, options,paging ) {
    var assets;

        if (options.tag) {
            var registry = that.registry,
                tag = options.tag;
            assets=that.manager.find(function (artifact) {
                if (registry.tags(artifact.path).indexOf(tag) != -1) {
                    //return matchAttr(options.attributes, artifact.attributes); -To accommodate filtering by lifecycle state
                    return matchArtifact(options, artifact);
                }
                return false;
            },paging);

            dataInjector.cached().inject(assets,DataInjectorModes.DISPLAY);

            return assets;
        }
        if (options.query) {
            var query = options.query;
            assets= that.manager.search(query,paging);

            dataInjector.cached().inject(assets,DataInjectorModes.DISPLAY);

            return assets;

        } if (options.attributes) {

        	var searchArtifact = options.attributes;

            assets= that.manager.search(searchArtifact,paging);

            dataInjector.cached().inject(assets,DataInjectorModes.DISPLAY);

            return assets;
        }
        if (options) {

            assets= that.manager.find(function (artifact) {
                // return matchAttr(options.attributes, artifact.attributes);
                return matchArtifact(options, artifact);

            },paging);

            dataInjector.cached().inject(assets,DataInjectorModes.DISPLAY);

            return assets;
        }
        return [];
    };

    var loadRatings = function (manager, items) {
        var i, asset,
            username = manager.username,
            length = items.length;
        for (i = 0; i < length; i++) {
            asset = items[i];
            asset.rating = manager.registry.rating(asset.path, username);
        }
        return items;
    };

    Manager = function (registry, type) {
        var carbon = require('carbon');
        this.registry = registry;
        this.type = type;
        this.username = registry.username;
        Packages.org.wso2.carbon.governance.api.util.GovernanceUtils.loadGovernanceArtifacts(registry.registry);
        this.manager = new carbon.registry.ArtifactManager(registry, type);
        this.sorter = new Sorter(registry);
    };

    var Sorter = function (registry) {
        this.registry = registry;
    };

    Sorter.prototype.recent = function (items) {
        var registry = this.registry;
        items.sort(function (l, r) {
            return registry.get(l.path).created.time < registry.get(r.path).created.time;
        });
        return items;
    };

    Sorter.prototype.popular = function (items) {
        var registry = this.registry;
        items.sort(function (l, r) {
            return registry.rating(l.path).average < registry.rating(r.path).average;
        });
        return items;
    };

    Sorter.prototype.unpopular = function (items) {
        var registry = this.registry;
        items.sort(function (l, r) {
            return registry.rating(l.path).average > registry.rating(r.path).average;
        });
        return items;
    };

    Sorter.prototype.older = function (items) {
        var registry = this.registry;
        items.sort(function (l, r) {
            return registry.get(l.path).created.time > registry.get(r.path).created.time;
        });
        return items;
    };

    Sorter.prototype.az = function (items) {
        items.sort(function (l, r) {
            return l['overview_name'] > r['overview_name'];
        });
        return items;
    };

    Sorter.prototype.za = function (items) {
        items.sort(function (l, r) {
            return l['overview_name'] < r['overview_name'];
        });
        return items;
    };

    Sorter.prototype.paginate = function (items, paging) {
        switch (paging.sort) {
            case 'recent':
                this.recent(items);
                break;
            case 'older':
                this.older(items);
                break;
            case 'popular':
                this.popular(items);
                break;
            case 'unpopular':
                this.unpopular(items);
                break;
            case 'az':
                this.az(items);
                break;
            case 'za':
                this.za(items);
                break;
            default:
                this.recent(items);
        }
        return items.slice(paging.start, (paging.start + paging.count));
    };

    /*Manager.prototype.search = function (filters, paging) {
     var all = this.manager.find(function (artifact) {
     var expected, field, actual;
     for (field in filters) {
     if (filters.hasOwnProperty(field)) {
     expected = filters[field];
     actual = artifact.attribute(field);
     if (expected instanceof RegExp) {
     if (!expected.test(actual)) {
     return false;
     }
     } else {
     return expected == actual;
     }
     }
     }
     return true;
     });
     return this.sorter.paginate(all, paging);
     };*/

    Manager.prototype.search = function (options, paging) {
        return loadRatings(this, search(this, options,paging), paging);
    };

    Manager.prototype.checkTagAssets = function (options) {
        return search(this, options,null);
    };

    /*
     * Assets matching the filter
     */
    Manager.prototype.get = function (id) {
        var asset=this.manager.get(id);

        dataInjector.cached().inject(asset,DataInjectorModes.DISPLAY);

        return asset;
    };

    /*
     * Assets matching the filter
     */
    Manager.prototype.add = function (options) {
        return this.manager.add(options);
    };

    /*
     * Assets matching the filter
     */
    Manager.prototype.update = function (options) {
        return this.manager.update(options);
    };

    /*
     * Assets matching the filter
     */
    Manager.prototype.remove = function (options) {
        var assets;
        if (options.id) {
            this.manager.remove(options.id);
            return;
        }
        assets = this.search(options);
        if (assets.length > 0) {
            this.manager.remove(assets[0].id);
        }
    };

    /*
     * Assets matching the filter
     * METHOD IS DEPRECATED
     */
    Manager.prototype.list = function (paging) {
        log.info('Calling deprecated method list - A method from down under-give him a vegimite sandwich');
        //Obtain the visible states from the
        /*var storeConfig = require('/store.json').lifeCycleBehaviour;
        var visibleStates = storeConfig.visibleIn || DEFAULT_ASSET_VIEW_STATE;

        log.info('Searching for assets in the ' + visibleStates + ' states.');

        var all = this.search({
            lifecycleState: visibleStates
        }, paging);

        log.debug('Obtained assets: ' + all.length + ' in the ' + visibleStates + ' states');

        return loadRatings(this, this.sorter.paginate(all, paging));*/
        return null;
    };

    /*
    The method will now count the number of assets matching the query
    encapsulated in the options object.
    @options: An object with properties that must be matched
    @return:An integer count of the number of matches,else false.
     */
    Manager.prototype.count = function (options) {
        if (options) {
            return search(this, options).length;
        }

        var matchingCount = 0;

        this.manager.find(function (asset) {

            //If the passed in asset matches the current asset we
            //increase published count.
            if(matchArtifact(options,asset)){
                matchingCount++;
            }

        },null);

        log.debug('Number of assets counted : ' + matchingCount);

        //return this.manager.count();
        return matchingCount;
    };

    /*
     *
     * Add comment
     Manager.prototype.comment = function (path, comment) {
     this.registry.comment(path, comment);
     };

     */
    /**
     * Get comments
     */
    /*

     Manager.prototype.comments = function () {
     return this.registry.comments();
     };

     Manager.prototype.rate = function () {

     };

     Manager.prototype.rating = function () {

     };

     Manager.prototype.invokeAspect = function () {

     };

     Manager.prototype.lifecycles = function () {

     };*/
}());
<commit_msg>adding sorting for store<commit_after>var Manager,
    ASSETS_NS = 'http://www.wso2.org/governance/metadata';

var log = new Log();

var ASSET_LCSTATE_PROP = 'lifecycleState';
var DEFAULT_ASSET_VIEW_STATE = 'published';

(function () {

    var dataInjector=require('/modules/data/data.injector.js').dataInjectorModule();
    var DataInjectorModes=dataInjector.Modes;

    var matchAttr = function (searchAttr, artifactAttr) {
        var attribute, attr, val, match;
        for (attribute in searchAttr) {
            if (searchAttr.hasOwnProperty(attribute)) {
                attr = searchAttr[attribute];
                val = artifactAttr[attribute];
                match = (attr instanceof RegExp) ? attr.test(val) : (attr == val);
                if (!match) {
                    return false;
                }
            }
        }
        return true;
    };

    /*
     The function checks whether two artifacts are similar
     @searchArtifact: The artifact containing the search criteria
     @artifact: The artifact to which the searchArtifact must be compared
     @return: If the two artifacts are similar True ,else False.
     */
    var matchArtifact = function (searchArtifact, artifact) {
        var status = true;//We assume that all attributes will match
        var ignoredProperty = 'attributes';
        var term = '';

        log.debug('Invoked matchArtifact: '+artifact.attributes.overview_name);
        log.debug('Ignoring property: ' + ignoredProperty);

        //First go through all of the non attribute properties
        for (var searchKey in searchArtifact) {

            log.debug('Examining property: ' + searchKey);

            if ((searchKey != ignoredProperty) && (artifact.hasOwnProperty(searchKey))) {

                //Match against spaces and lower case
                term = artifact[searchKey] || '';
                term = term.toString().toLowerCase().trim() + '';

                //Determine if the searchKey points to an array
                if (searchArtifact[searchKey] instanceof Array) {

                    log.debug('Checking against array of values: ' + searchArtifact[searchKey]);
                    log.debug('Artifact value '+term);
                    //Check if the value of the artifact property is defined in the
                    //searchArtifact property array.
                    status = (searchArtifact[searchKey].indexOf(term) != -1) ? true : false;
                }
                else {
                    log.debug('Artifact value: '+term);
                    log.debug('Searched value:'+searchArtifact[searchKey]);
                    //Update the status
                    status = (searchArtifact[searchKey] == term);
                }

            }
        }

        log.debug('Properties match: ' + status);

        //If it is not a match at this time then return false, no need to check
        //if the attributes match.
        if(status==false){

            log.debug(artifact.attributes.overview_name+' no match.');
            return status;
        }

        //Only search attributes if the user has provided any
        if (searchArtifact.attributes) {

            //Check if the attributes match
            status = matchAttr(searchArtifact.attributes, artifact.attributes);

            log.debug('Attribute match : ' + status);

        }

        return status;
    }

	var search = function(that, options, paging) {
		var assets;

		if(options.tag) {
			var registry = that.registry, tag = options.tag;
			assets = that.manager.find(function(artifact) {
				if(registry.tags(artifact.path).indexOf(tag) != -1) {
					//return matchAttr(options.attributes, artifact.attributes); -To accommodate filtering by lifecycle state
					return matchArtifact(options, artifact);
				}
				return false;
			}, paging);

			dataInjector.cached().inject(assets, DataInjectorModes.DISPLAY);

			return assets;
		}
		if(options.query) {
			var query = options.query;
			assets = that.manager.search(query, paging);

			dataInjector.cached().inject(assets, DataInjectorModes.DISPLAY);

			return assets;

		} else if(options.attributes) {

			var searchArtifact = options.attributes;
			assets = that.manager.search(searchArtifact, paging);

			dataInjector.cached().inject(assets, DataInjectorModes.DISPLAY);

			return assets;
		} else if(options) {
			assets = that.manager.search(null, paging);
			dataInjector.cached().inject(assets, DataInjectorModes.DISPLAY);

			return assets;
		}

		return [];
	};

    var loadRatings = function (manager, items) {
        var i, asset,
            username = manager.username,
            length = items.length;
        for (i = 0; i < length; i++) {
            asset = items[i];
            asset.rating = manager.registry.rating(asset.path, username);
        }
        return items;
    };

    Manager = function (registry, type) {
        var carbon = require('carbon');
        this.registry = registry;
        this.type = type;
        this.username = registry.username;
        Packages.org.wso2.carbon.governance.api.util.GovernanceUtils.loadGovernanceArtifacts(registry.registry);
        this.manager = new carbon.registry.ArtifactManager(registry, type);
        this.sorter = new Sorter(registry);
    };

    var Sorter = function (registry) {
        this.registry = registry;
    };

    Sorter.prototype.recent = function (items) {
        var registry = this.registry;
        items.sort(function (l, r) {
            return registry.get(l.path).created.time < registry.get(r.path).created.time;
        });
        return items;
    };

    Sorter.prototype.popular = function (items) {
        var registry = this.registry;
        items.sort(function (l, r) {
            return registry.rating(l.path).average < registry.rating(r.path).average;
        });
        return items;
    };

    Sorter.prototype.unpopular = function (items) {
        var registry = this.registry;
        items.sort(function (l, r) {
            return registry.rating(l.path).average > registry.rating(r.path).average;
        });
        return items;
    };

    Sorter.prototype.older = function (items) {
        var registry = this.registry;
        items.sort(function (l, r) {
            return registry.get(l.path).created.time > registry.get(r.path).created.time;
        });
        return items;
    };

    Sorter.prototype.az = function (items) {
        items.sort(function (l, r) {
            return l['overview_name'] > r['overview_name'];
        });
        return items;
    };

    Sorter.prototype.za = function (items) {
        items.sort(function (l, r) {
            return l['overview_name'] < r['overview_name'];
        });
        return items;
    };

    Sorter.prototype.paginate = function (items, paging) {
        switch (paging.sort) {
            case 'recent':
                this.recent(items);
                break;
            case 'older':
                this.older(items);
                break;
            case 'popular':
                this.popular(items);
                break;
            case 'unpopular':
                this.unpopular(items);
                break;
            case 'az':
                this.az(items);
                break;
            case 'za':
                this.za(items);
                break;
            default:
                this.recent(items);
        }
        return items.slice(paging.start, (paging.start + paging.count));
    };

    /*Manager.prototype.search = function (filters, paging) {
     var all = this.manager.find(function (artifact) {
     var expected, field, actual;
     for (field in filters) {
     if (filters.hasOwnProperty(field)) {
     expected = filters[field];
     actual = artifact.attribute(field);
     if (expected instanceof RegExp) {
     if (!expected.test(actual)) {
     return false;
     }
     } else {
     return expected == actual;
     }
     }
     }
     return true;
     });
     return this.sorter.paginate(all, paging);
     };*/

    Manager.prototype.search = function (options, paging) {
        return loadRatings(this, search(this, options,paging), paging);
    };

    Manager.prototype.checkTagAssets = function (options) {
        return search(this, options,null);
    };

    /*
     * Assets matching the filter
     */
    Manager.prototype.get = function (id) {
        var asset=this.manager.get(id);

        dataInjector.cached().inject(asset,DataInjectorModes.DISPLAY);

        return asset;
    };

    /*
     * Assets matching the filter
     */
    Manager.prototype.add = function (options) {
        return this.manager.add(options);
    };

    /*
     * Assets matching the filter
     */
    Manager.prototype.update = function (options) {
        return this.manager.update(options);
    };

    /*
     * Assets matching the filter
     */
    Manager.prototype.remove = function (options) {
        var assets;
        if (options.id) {
            this.manager.remove(options.id);
            return;
        }
        assets = this.search(options);
        if (assets.length > 0) {
            this.manager.remove(assets[0].id);
        }
    };

    /*
     * Assets matching the filter
     * METHOD IS DEPRECATED
     */
    Manager.prototype.list = function (paging) {
        log.info('Calling deprecated method list - A method from down under-give him a vegimite sandwich');
        //Obtain the visible states from the
        /*var storeConfig = require('/store.json').lifeCycleBehaviour;
        var visibleStates = storeConfig.visibleIn || DEFAULT_ASSET_VIEW_STATE;

        log.info('Searching for assets in the ' + visibleStates + ' states.');

        var all = this.search({
            lifecycleState: visibleStates
        }, paging);

        log.debug('Obtained assets: ' + all.length + ' in the ' + visibleStates + ' states');

        return loadRatings(this, this.sorter.paginate(all, paging));*/
        return null;
    };

    /*
    The method will now count the number of assets matching the query
    encapsulated in the options object.
    @options: An object with properties that must be matched
    @return:An integer count of the number of matches,else false.
     */
    Manager.prototype.count = function (options) {
        if (options) {
            return search(this, options).length;
        }

        var matchingCount = 0;

        this.manager.find(function (asset) {

            //If the passed in asset matches the current asset we
            //increase published count.
            if(matchArtifact(options,asset)){
                matchingCount++;
            }

        },null);

        log.debug('Number of assets counted : ' + matchingCount);

        //return this.manager.count();
        return matchingCount;
    };

    /*
     *
     * Add comment
     Manager.prototype.comment = function (path, comment) {
     this.registry.comment(path, comment);
     };

     */
    /**
     * Get comments
     */
    /*

     Manager.prototype.comments = function () {
     return this.registry.comments();
     };

     Manager.prototype.rate = function () {

     };

     Manager.prototype.rating = function () {

     };

     Manager.prototype.invokeAspect = function () {

     };

     Manager.prototype.lifecycles = function () {

     };*/
}());
<|endoftext|>


<commit_before>// ==========================================================================
// Project:   TestRunner.Target
// Copyright: ©2009 My Company, Inc.
// ==========================================================================
/*globals TestRunner */

/** @class

  Describes a single target in the current project.  A target can have a name,
  a type and one or more tests that are loaded on demand.

  @extends SC.Record
  @author Charles Jolley
*/
TestRunner.Target = SC.Record.extend(
/** @scope TestRunner.Target.prototype */ {

  /** Load the tests for the target. */
  tests: function() {
    this.refreshTests();
    return this._tests;
  }.property().cacheable(),

  /**
    Loads the targets from the server.  When the targets have loaded, adds
    them to the store and then sets the local content.
  */
  refreshTests: function() {
    if (!this._tests) this._tests = [] ;
    SC.Request.getUrl(this.get('link_tests'))
      .notify(this, 'testsDidRefresh').set('isJSON', YES).send();
  },

  testsDidRefresh: function(request) {
    var json = request.get('response'), len = json.length, idx;
    for(idx=0;idx<len;idx++) json[idx].guid = json[idx].url ; // patch
    var tests = SC.Store.updateRecords(json, SC.Store, TestRunner.Test);
    tests = tests.sort(function(a,b) {
      a = a.get('filename');
      b = b.get('filename');
      return (a<b) ? -1 : (a>b) ? 1 : 0;
    });

    this.propertyWillChange('tests');
    this._tests = tests ;
    this.propertyDidChange('tests');
  }

}) ;
<commit_msg>Update unit test Target model.<commit_after>// ==========================================================================
// Project:   TestRunner.Target
// Copyright: ©2009 My Company, Inc.
// ==========================================================================
/*globals TestRunner */

/** @class

  Describes a single target in the current project.  A target can have a name,
  a type and one or more tests that are loaded on demand.

  @extends SC.Record
  @author Charles Jolley
*/
TestRunner.Target = SC.Record.extend(
/** @scope TestRunner.Target.prototype */ {

  primaryKey: "name",

  /**
    The target name.  This is the primary key

    @property
  */
  name: SC.Record.attr(String),

  /**
    The kind of target.  Usually is one of "app" or "framework".

    @property
  */
  kind: SC.Record.attr(String),

  /**
    Link to the document index json

    @property
  */
  docsUrl: SC.Record.attr(String, { key: "link_docs" }),

  /**
    Link to the test index json

    @property
  */
  testsUrl: SC.Record.attr(String, { key: "link_tests" }),

  /**
    Link to the target itself.  This is only useful for applications.

    @property
  */
  rootUrl: SC.Record.attr(String, { key: "link_root" }),

  /**
    The parent target, if there is one.  This is a reference to the primary
    key.

    @property
  */
  parent: SC.Record.hasOne("TestRuner.Target"),

  /**
    The display name for the target.  Computed by taking the last part of the
    target name.
  */
  displayName: function() {
    var name = this.get('name').split('/');
    name = name[name.length-1] || '(none)';
    return name.titleize();
  }.property('name').cacheable()

}) ;
<|endoftext|>


<commit_before>
import {findWhere} from 'underline'
import invariant from 'invariant'

import {camelify} from '../util/format'
import os from '../util/os'
import mklog from '../util/log'
const log = mklog('tasks/find-upload')

import client from '../util/api'

import ClassificationActions from '../constants/classification-actions'

export function filterUploads (action, uploads) {
  if (action === 'open') {
    // don't filter if we're just downloading a bunch of files
    return uploads
  }

  // Filter by platform
  const prop = camelify(`p_${os.itchPlatform()}`)
  const platformUploads = uploads.filter((upload) => !!upload[prop] || upload.type === 'html')

  // Filter by format
  const compatibleUploads = platformUploads.filter((upload) =>
    !(/\.(rpm|deb|rar)$/i.test(upload.filename.toLowerCase()))
  )

  return compatibleUploads
}

export function scoreUpload (upload) {
  let filename = upload.filename.toLowerCase()
  let score = 50

  /* Preferred formats */
  if (/\.(zip|7z)$/i.test(filename)) {
    score += 10
  }

  /* Usually not what you want (usually set of sources on Linux) */
  if (/\.tar\.(gz|bz2|xz)$/i.test(filename)) {
    score -= 10
  }

  /* Definitely not something we can launch */
  if (/soundtrack/.test(filename)) {
    score -= 100
  }

  /* Native uploads are preferred */
  if (upload.type === 'html') {
    score -= 40
  }

  return {...upload, score}
}

export function sortUploads (scoredUploads) {
  return scoredUploads.sort((a, b) =>
    (b.score - a.score)
  )
}

export default async function start (out, opts) {
  const {game, gameId, credentials, market} = opts
  invariant(typeof gameId === 'number', 'find-upload has gameId')
  invariant(typeof market === 'object', 'find-upload has market')

  invariant(credentials && credentials.key, 'find-upload has valid key')
  const keyClient = client.withKey(credentials.key)

  const grabKey = () => market.getEntities('downloadKeys')::findWhere({gameId})
  const {downloadKey = grabKey()} = opts

  if (downloadKey) {
    log(opts, 'bought game, using download key')
  } else {
    log(opts, 'no download key, seeking available uploads')
  }
  let {uploads} = (await keyClient.listUploads(downloadKey, gameId))

  log(opts, `got a list of ${uploads.length} uploads`)

  if (uploads.length > 0) {
    const freshGame = market.getEntities('games')[gameId] || game
    const action = ClassificationActions[freshGame.classification] || 'launch'

    uploads = filterUploads(action, uploads)
    uploads = uploads.map(scoreUpload)
    uploads = sortUploads(uploads)

    log(opts, `sorted uploads: ${JSON.stringify(uploads, null, 2)}`)
  }
  return {uploads, downloadKey}
}
<commit_msg>Penalize demo uploads<commit_after>
import {findWhere} from 'underline'
import invariant from 'invariant'

import {camelify} from '../util/format'
import os from '../util/os'
import mklog from '../util/log'
const log = mklog('tasks/find-upload')

import client from '../util/api'

import ClassificationActions from '../constants/classification-actions'

export function filterUploads (action, uploads) {
  if (action === 'open') {
    // don't filter if we're just downloading a bunch of files
    return uploads
  }

  // Filter by platform
  const prop = camelify(`p_${os.itchPlatform()}`)
  const platformUploads = uploads.filter((upload) => !!upload[prop] || upload.type === 'html')

  // Filter by format
  const compatibleUploads = platformUploads.filter((upload) =>
    !(/\.(rpm|deb|rar)$/i.test(upload.filename.toLowerCase()))
  )

  return compatibleUploads
}

export function scoreUpload (upload) {
  let filename = upload.filename.toLowerCase()
  let score = 500

  /* Preferred formats */
  if (/\.(zip|7z)$/i.test(filename)) {
    score += 100
  }

  /* Usually not what you want (usually set of sources on Linux) */
  if (/\.tar\.(gz|bz2|xz)$/i.test(filename)) {
    score -= 100
  }

  /* Definitely not something we can launch */
  if (/soundtrack/.test(filename)) {
    score -= 1000
  }

  /* Native uploads are preferred */
  if (upload.type === 'html') {
    score -= 400
  }

  /* Demos are penalized (if we have access to non-demo files) */
  if (upload.demo) {
    score -= 50
  }

  return {...upload, score}
}

export function sortUploads (scoredUploads) {
  return scoredUploads.sort((a, b) =>
    (b.score - a.score)
  )
}

export default async function start (out, opts) {
  const {game, gameId, credentials, market} = opts
  invariant(typeof gameId === 'number', 'find-upload has gameId')
  invariant(typeof market === 'object', 'find-upload has market')

  invariant(credentials && credentials.key, 'find-upload has valid key')
  const keyClient = client.withKey(credentials.key)

  const grabKey = () => market.getEntities('downloadKeys')::findWhere({gameId})
  const {downloadKey = grabKey()} = opts

  if (downloadKey) {
    log(opts, 'bought game, using download key')
  } else {
    log(opts, 'no download key, seeking available uploads')
  }
  let {uploads} = (await keyClient.listUploads(downloadKey, gameId))

  log(opts, `got a list of ${uploads.length} uploads`)

  if (uploads.length > 0) {
    const freshGame = market.getEntities('games')[gameId] || game
    const action = ClassificationActions[freshGame.classification] || 'launch'

    uploads = filterUploads(action, uploads)
    uploads = uploads.map(scoreUpload)
    uploads = sortUploads(uploads)

    log(opts, `sorted uploads: ${JSON.stringify(uploads, null, 2)}`)
  }
  return {uploads, downloadKey}
}
<|endoftext|>


<commit_before>import {
  Vector2,
  Raycaster,
  Plane,
  Vector3
} from 'three';

import Events from 'minivents';

export class VirtualMouse extends Events {
  mouse = new Vector2();
  raycaster = new Raycaster();
  world = null;
  projectionPlane = new Plane(new Vector3(0, 0, 1), 0);

  constructor(world) {
    super();

    world.mouse = this;
    this.world = world;
    window.addEventListener('mousemove', this.update.bind(this));
    window.addEventListener('click', () => this.emit('click'));
    window.addEventListener('mousedown', () => this.emit('mousedown'));
    window.addEventListener('mouseup', () => this.emit('mouseup'));
  }

  update(e) {
    this.mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
    this.mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
    this.projectionPlane.normal.copy(this.world.$camera.native.getWorldDirection());

    this.raycaster.setFromCamera(this.mouse, this.world.$camera.native);
    this.emit('move');
  }

  track(component) {
    let isHovered = false;

    this.on('move', () => {
      if (this.hovers(component)) {
        if (isHovered) component.emit('mousemove');
        else {
          component.emit('mouseover');
          isHovered = true;
        }
      } else if (isHovered) {
        component.emit('mouseout');
        isHovered = false;
      }
    });

    this.on('click', () => {
      if (isHovered) component.emit('click');
    });

    this.on('mousedown', () => {
      if (isHovered) component.emit('mousedown');
    });

    this.on('mouseup', () => {
      if (isHovered) component.emit('mouseup');
    });
  }

  intersection(component) {
    return this.raycaster.intersectObject(component.native);
  }

  project(plane = this.projectionPlane) {
    return this.raycaster.ray.intersectPlane(plane);
  }

  hovers(component) {
    const intersection = this.intersection(component)[0];
    return intersection ? intersection.object === component.native : false;
  }

  get ray() {
    return this.raycaster.ray;
  }

  get x() {
    return this.mouse.x;
  }

  get y() {
    return this.mouse.y;
  }
}
<commit_msg>Refactor VirtualMouse<commit_after>import {
  Vector2,
  Raycaster,
  Plane,
  Vector3
} from 'three';

import Events from 'minivents';

export class VirtualMouse extends Events {
  mouse = new Vector2();
  raycaster = new Raycaster();
  world = null;
  canvas = null;
  projectionPlane = new Plane(new Vector3(0, 0, 1), 0);

  constructor(world) {
    super();

    world.mouse = this;
    this.world = world;
    this.canvas = world.$rendering.renderer.domElement;
    window.addEventListener('mousemove', this.update.bind(this));
    window.addEventListener('click', () => this.emit('click'));
    window.addEventListener('mousedown', () => this.emit('mousedown'));
    window.addEventListener('mouseup', () => this.emit('mouseup'));
  }

  update(e) {
    var rect = this.canvas.getBoundingClientRect();
    // this.mouse.x = (e.clientX - rect.left);
    // this.mouse.y = (e.clientY - rect.top);
    this.mouse.x = ((e.clientX - rect.left) / window.innerWidth) * 2 - 1;
    this.mouse.y = -((e.clientY - rect.top) / window.innerHeight) * 2 + 1;
    this.projectionPlane.normal.copy(this.world.$camera.native.getWorldDirection());

    this.raycaster.setFromCamera(this.mouse, this.world.$camera.native);
    this.emit('move');
  }

  track(component) {
    let isHovered = false;

    this.on('move', () => {
      if (this.hovers(component)) {
        if (isHovered) component.emit('mousemove');
        else {
          component.emit('mouseover');
          isHovered = true;
        }
      } else if (isHovered) {
        component.emit('mouseout');
        isHovered = false;
      }
    });

    this.on('click', () => {
      if (isHovered) component.emit('click');
    });

    this.on('mousedown', () => {
      if (isHovered) component.emit('mousedown');
    });

    this.on('mouseup', () => {
      if (isHovered) component.emit('mouseup');
    });
  }

  intersection(component) {
    return this.raycaster.intersectObject(component.native);
  }

  project(plane = this.projectionPlane) {
    return this.raycaster.ray.intersectPlane(plane);
  }

  hovers(component) {
    const intersection = this.intersection(component)[0];
    return intersection ? intersection.object === component.native : false;
  }

  get ray() {
    return this.raycaster.ray;
  }

  get x() {
    return this.mouse.x;
  }

  get y() {
    return this.mouse.y;
  }
}
<|endoftext|>


<commit_before>import React from 'react'
import ReactDOM from 'react-dom'
import Relay from 'react-relay'
import GCForm from './forms/GCForm'
import Form from 'react-formal'
import yup from 'yup'
import moment from 'moment'
import {AllHtmlEntities, XmlEntities} from 'html-entities'
import {Card, CardActions, CardExpandable, CardTitle, CardHeader, CardText, FlatButton, TextField, DropDownMenu, SelectField, DatePicker, TimePicker, Checkbox} from 'material-ui'
import InfoHeader from './InfoHeader'
import {USTimeZones} from './data/USTimeZones'

const entities = new AllHtmlEntities()
const xmlEntities = new XmlEntities()

class EventEdit extends React.Component {

  componentDidMount() {
    if (this.props.event.host){
      let {email} = this.props.event.host
      this.props.relay.setVariables({personFilters: {email}})
    }
  }

  eventTypes() {
    let allTypes = {}
    this.props.listContainer.eventTypes.forEach((eventType) => {
      allTypes[eventType.id] = eventType.name
    })
    return allTypes;
  }

  timezones() {
    let allZones = {}
    USTimeZones.forEach((zone) => {
      allZones[zone.value] = zone.name
    })
    return allZones;
  }

  volunteerShowOptions() {
    return {
      '1': 'Yes',
      '0': 'No',
      '-1': 'Use Event Type Default'
    }
  }

  eventSearchableOptions() {
    // actually get valid options for event type later
    let eventSearchableOptions = {
      '1': 'Make Public',
      '0': 'Make Private',
      '-2': 'Use Event Type Default'
    };
    return eventSearchableOptions;
  }

  renderForm() {
    let event = this.props.event
    const people = this.props.listContainer.people.edges
    const host = (people.length === 0) ? null : people[0].node

    const eventSchema = yup.object({
      name: yup
        .string()
        .default(event.name)
        .required(),

      eventTypeId: yup
        .string()
        .default(event.eventType.id)
        .required(),

      description: yup.string().default(event.description)
        .required(),

      rsvpEmailReminderHours: yup.number()
        .default(event.rsvpEmailReminderHours)
        .min(0)
        .nullable(),

      startDate: yup.date()
        .default(event.startDate)
        .required(),

      localTimezone: yup.string()
        .default(event.localTimezone)
        .required(),

      duration: yup.object({
        h: yup.number()
          .default(Math.floor(event.duration / 60))
          .min(-1)
          .nullable()
          .required(),

        m: yup.number()
          .default(event.duration % 60)
          .min(-1).max(59)
          .nullable()
          .required(),
      }),

      venueName: yup.string().default(event.venueName)
        .required(),

      venueAddr1: yup.string().default(event.venueAddr1)
        .required(),

      venueAddr2: yup.string().default(event.venueAddr2)
        .nullable(),

      venueCity: yup.string().default(event.venueCity)
        .required(),

      venueState: yup.string().default(event.venueState)
        .required(),

      venueZip: yup.string().default(event.venueZip)
        .required(),

      venueCountry: yup.string().default(event.venueCountry)
        .required(),

      venueDirections: yup.string().default(event.venueDirections)
        .nullable(),
      capacity: yup.number()
        .default(event.capacity)
        .min(0)
        .required(),

      creatorName: yup.string()
        .default(event.creatorName),

      hostEmail: yup.string().email()
        .default((event.host) ? event.host.email : null),

      contactPhone: yup.string()
        .default(event.contactPhone),

      publicPhone: yup.boolean()
        .default(event.publicPhone),

      hostReceiveRsvpEmails: yup.boolean()
        .default(event.hostReceiveRsvpEmails),

      rsvpUseReminderEmail: yup.boolean()
        .default(event.rsvpUseReminderEmail),

      attendeeVolunteerShow: yup.string()
        .default(String(event.attendeeVolunteerShow)),

      attendeeVolunteerMessage: yup.string()
        .default(event.attendeeVolunteerMessage),

      isSearchable: yup.string()
        .default(String(event.isSearchable)),

      isOfficial: yup.boolean()
        .default(event.isOfficial)

    });

    const form = (
      <GCForm
        ref="form"
        schema={eventSchema}
        defaultValue={eventSchema.default()}
        onSubmit={ (data) => {
          data.duration = data.duration.h * 60 + data.duration.m
          data.isSearchable = Number(data.isSearchable)
          // Encode special characters to HTML entities, but avoid encoding <>"'& + &#...;
          data.description = xmlEntities.decode(entities.encode(data.description))
          if (host)
            data.hostId = host.id
          delete data.hostEmail

          this.props.onSubmit(data)
        }}
      >
        <InfoHeader content='Event Information' />
        <Form.Field
          name='eventTypeId'
          type='select'
          label='Event Type'
          choices={this.eventTypes()}
        />

        <Form.Field
          name='name'
          label='Event Name'
          fullWidth={true}
        />

        <Form.Field
          name='description'
          type='richtext'
          placeholder='Event Description'
        />

        <InfoHeader content='Event Date & Time' />

        <Form.Field
          name='startDate'
          label='Start Date'
          type='date'
          utcOffset={event.localUTCOffset}
        />

        <Form.Field
          name='startDate'
          label='Start Time'
          type='time'
          utcOffset={event.localUTCOffset}
        />

        <Form.Field
          name='localTimezone'
          type='select'
          label='Time Zone'
          choices={this.timezones()}
          style={{
            marginTop: 5
          }}
        />

        <Form.Field
          name='duration.h'
          label="Duration (Hours)"
          type='number'
          min="0"
        />

        <Form.Field
          name='duration.m'
          label="Duration (Minutes)"
          type='number'
          min="0"
          max="59"
        />

        <InfoHeader content='Event Location' />

        <Form.Field
          name='venueName'
          label='Venue Name'
        />

        <Form.Field
          name='capacity'
          label="Venue Capacity (enter 0 for unlimited)"
          type='number'
          min="0"
        />

        <Form.Field
          name='venueAddr1'
          label='Address Line 1'
          fullWidth={true}
        />

        <Form.Field
          name='venueAddr2'
          label='Address Line 2'
          fullWidth={true}
        />

        <Form.Field
          name='venueCity'
          label='City'
        />

        <Form.Field
          name='venueState'
          label='State'
        />

        <Form.Field
          name='venueZip'
          label='Zip Code'
        />

        <Form.Field
          name='venueCountry'
          label='Country'
        />

        <Form.Field
          name='venueDirections'
          label='Directions to Venue'
          multiLine={true}
          fullWidth={true}
        />

        <InfoHeader content='Event Host' />
        <Form.Field
          name="creatorName"
          label="Host Name"
        />

        <Form.Field
          name="hostEmail"
          type="email"
          label="Host Email"
          errorText={(host) ? null : 'No account found'}
          onChange={(value) => {
            this.props.relay.setVariables({personFilters: {email: value}})
          }}
        /> {(host) ? ({host.firstName} {host.lastName}) : ''}

        <Form.Field
          name="contactPhone"
          type="phone"
          label="Contact Phone"
        />

        <Form.Field
          name="publicPhone"
          label="Make Contact Number Public"
        />

        <Form.Field
          name="hostReceiveRsvpEmails"
          label="Send Host RSVPs via Email"
        />

        <InfoHeader content='Event Attendees' />

        <Form.Field
          name="rsvpUseReminderEmail"
          label="Send Guests RSVP Email Reminder"
        />

        <Form.Field
          name='rsvpEmailReminderHours'
          label="RSVP Reminder Hours"
          type='number'
          min="0"
        />

        <Form.Field
          name="attendeeVolunteerShow"
          type='select'
          label="Ask Attendees to Volunteer"
          choices={this.volunteerShowOptions()}
        />

        <Form.Field
          name='attendeeVolunteerMessage'
          label="Message for Event Volunteers"
          multiLine={true}
          fullWidth={true}
        />

        <InfoHeader content='Event Settings' />

        <Form.Field
          name='isSearchable'
          type='select'
          label='Make Event Public?'
          choices={this.eventSearchableOptions()}
        />

        <Form.Field
          name="isOfficial"
          label="Mark as an official campaign event"
        />

      <Form.Button  style={ { display: "none" } } ref="submit" type='submit' label='Submit Changes' fullWidth={true} />

    </GCForm>)

    return form
  }

  render() {
    return (

      <CardText>
        {this.renderForm()}
      </CardText>

    )
  }

  submit() {
    jQuery("button", ReactDOM.findDOMNode(this.refs.submit)).click()
  }
}

export default Relay.createContainer(EventEdit, {
  initialVariables: {
    personFilters: {},
  },
  fragments: {
    listContainer: () => Relay.QL`
      fragment on ListContainer {
        eventTypes {
          id
          name
        }
        people(
          first: 1
          personFilters: $personFilters
        ) {
          edges {
            cursor
            node {
              id
              firstName
              lastName
              email
            }
          }
        }
      }
    `
  }
})
<commit_msg>Only show host name if first/last exists<commit_after>import React from 'react'
import ReactDOM from 'react-dom'
import Relay from 'react-relay'
import GCForm from './forms/GCForm'
import Form from 'react-formal'
import yup from 'yup'
import moment from 'moment'
import {AllHtmlEntities, XmlEntities} from 'html-entities'
import {Card, CardActions, CardExpandable, CardTitle, CardHeader, CardText, FlatButton, TextField, DropDownMenu, SelectField, DatePicker, TimePicker, Checkbox} from 'material-ui'
import InfoHeader from './InfoHeader'
import {USTimeZones} from './data/USTimeZones'

const entities = new AllHtmlEntities()
const xmlEntities = new XmlEntities()

class EventEdit extends React.Component {

  componentDidMount() {
    if (this.props.event.host){
      let {email} = this.props.event.host
      this.props.relay.setVariables({personFilters: {email}})
    }
  }

  eventTypes() {
    let allTypes = {}
    this.props.listContainer.eventTypes.forEach((eventType) => {
      allTypes[eventType.id] = eventType.name
    })
    return allTypes;
  }

  timezones() {
    let allZones = {}
    USTimeZones.forEach((zone) => {
      allZones[zone.value] = zone.name
    })
    return allZones;
  }

  volunteerShowOptions() {
    return {
      '1': 'Yes',
      '0': 'No',
      '-1': 'Use Event Type Default'
    }
  }

  eventSearchableOptions() {
    // actually get valid options for event type later
    let eventSearchableOptions = {
      '1': 'Make Public',
      '0': 'Make Private',
      '-2': 'Use Event Type Default'
    };
    return eventSearchableOptions;
  }

  renderForm() {
    let event = this.props.event
    const people = this.props.listContainer.people.edges
    const host = (people.length === 0) ? null : people[0].node

    const eventSchema = yup.object({
      name: yup
        .string()
        .default(event.name)
        .required(),

      eventTypeId: yup
        .string()
        .default(event.eventType.id)
        .required(),

      description: yup.string().default(event.description)
        .required(),

      rsvpEmailReminderHours: yup.number()
        .default(event.rsvpEmailReminderHours)
        .min(0)
        .nullable(),

      startDate: yup.date()
        .default(event.startDate)
        .required(),

      localTimezone: yup.string()
        .default(event.localTimezone)
        .required(),

      duration: yup.object({
        h: yup.number()
          .default(Math.floor(event.duration / 60))
          .min(-1)
          .nullable()
          .required(),

        m: yup.number()
          .default(event.duration % 60)
          .min(-1).max(59)
          .nullable()
          .required(),
      }),

      venueName: yup.string().default(event.venueName)
        .required(),

      venueAddr1: yup.string().default(event.venueAddr1)
        .required(),

      venueAddr2: yup.string().default(event.venueAddr2)
        .nullable(),

      venueCity: yup.string().default(event.venueCity)
        .required(),

      venueState: yup.string().default(event.venueState)
        .required(),

      venueZip: yup.string().default(event.venueZip)
        .required(),

      venueCountry: yup.string().default(event.venueCountry)
        .required(),

      venueDirections: yup.string().default(event.venueDirections)
        .nullable(),
      capacity: yup.number()
        .default(event.capacity)
        .min(0)
        .required(),

      creatorName: yup.string()
        .default(event.creatorName),

      hostEmail: yup.string().email()
        .default((event.host) ? event.host.email : null),

      contactPhone: yup.string()
        .default(event.contactPhone),

      publicPhone: yup.boolean()
        .default(event.publicPhone),

      hostReceiveRsvpEmails: yup.boolean()
        .default(event.hostReceiveRsvpEmails),

      rsvpUseReminderEmail: yup.boolean()
        .default(event.rsvpUseReminderEmail),

      attendeeVolunteerShow: yup.string()
        .default(String(event.attendeeVolunteerShow)),

      attendeeVolunteerMessage: yup.string()
        .default(event.attendeeVolunteerMessage),

      isSearchable: yup.string()
        .default(String(event.isSearchable)),

      isOfficial: yup.boolean()
        .default(event.isOfficial)

    });

    const form = (
      <GCForm
        ref="form"
        schema={eventSchema}
        defaultValue={eventSchema.default()}
        onSubmit={ (data) => {
          data.duration = data.duration.h * 60 + data.duration.m
          data.isSearchable = Number(data.isSearchable)
          // Encode special characters to HTML entities, but avoid encoding <>"'& + &#...;
          data.description = xmlEntities.decode(entities.encode(data.description))
          if (host)
            data.hostId = host.id
          delete data.hostEmail

          this.props.onSubmit(data)
        }}
      >
        <InfoHeader content='Event Information' />
        <Form.Field
          name='eventTypeId'
          type='select'
          label='Event Type'
          choices={this.eventTypes()}
        />

        <Form.Field
          name='name'
          label='Event Name'
          fullWidth={true}
        />

        <Form.Field
          name='description'
          type='richtext'
          placeholder='Event Description'
        />

        <InfoHeader content='Event Date & Time' />

        <Form.Field
          name='startDate'
          label='Start Date'
          type='date'
          utcOffset={event.localUTCOffset}
        />

        <Form.Field
          name='startDate'
          label='Start Time'
          type='time'
          utcOffset={event.localUTCOffset}
        />

        <Form.Field
          name='localTimezone'
          type='select'
          label='Time Zone'
          choices={this.timezones()}
          style={{
            marginTop: 5
          }}
        />

        <Form.Field
          name='duration.h'
          label="Duration (Hours)"
          type='number'
          min="0"
        />

        <Form.Field
          name='duration.m'
          label="Duration (Minutes)"
          type='number'
          min="0"
          max="59"
        />

        <InfoHeader content='Event Location' />

        <Form.Field
          name='venueName'
          label='Venue Name'
        />

        <Form.Field
          name='capacity'
          label="Venue Capacity (enter 0 for unlimited)"
          type='number'
          min="0"
        />

        <Form.Field
          name='venueAddr1'
          label='Address Line 1'
          fullWidth={true}
        />

        <Form.Field
          name='venueAddr2'
          label='Address Line 2'
          fullWidth={true}
        />

        <Form.Field
          name='venueCity'
          label='City'
        />

        <Form.Field
          name='venueState'
          label='State'
        />

        <Form.Field
          name='venueZip'
          label='Zip Code'
        />

        <Form.Field
          name='venueCountry'
          label='Country'
        />

        <Form.Field
          name='venueDirections'
          label='Directions to Venue'
          multiLine={true}
          fullWidth={true}
        />

        <InfoHeader content='Event Host' />
        <Form.Field
          name="creatorName"
          label="Host Name"
        />

        <Form.Field
          name="hostEmail"
          type="email"
          label="Host Email"
          errorText={(host) ? null : 'No account found'}
          onChange={(value) => {
            this.props.relay.setVariables({personFilters: {email: value}})
          }}
        /> {(host.firstName || host.lastName) ? ({host.firstName} {host.lastName}) : ''}

        <Form.Field
          name="contactPhone"
          type="phone"
          label="Contact Phone"
        />

        <Form.Field
          name="publicPhone"
          label="Make Contact Number Public"
        />

        <Form.Field
          name="hostReceiveRsvpEmails"
          label="Send Host RSVPs via Email"
        />

        <InfoHeader content='Event Attendees' />

        <Form.Field
          name="rsvpUseReminderEmail"
          label="Send Guests RSVP Email Reminder"
        />

        <Form.Field
          name='rsvpEmailReminderHours'
          label="RSVP Reminder Hours"
          type='number'
          min="0"
        />

        <Form.Field
          name="attendeeVolunteerShow"
          type='select'
          label="Ask Attendees to Volunteer"
          choices={this.volunteerShowOptions()}
        />

        <Form.Field
          name='attendeeVolunteerMessage'
          label="Message for Event Volunteers"
          multiLine={true}
          fullWidth={true}
        />

        <InfoHeader content='Event Settings' />

        <Form.Field
          name='isSearchable'
          type='select'
          label='Make Event Public?'
          choices={this.eventSearchableOptions()}
        />

        <Form.Field
          name="isOfficial"
          label="Mark as an official campaign event"
        />

      <Form.Button  style={ { display: "none" } } ref="submit" type='submit' label='Submit Changes' fullWidth={true} />

    </GCForm>)

    return form
  }

  render() {
    return (

      <CardText>
        {this.renderForm()}
      </CardText>

    )
  }

  submit() {
    jQuery("button", ReactDOM.findDOMNode(this.refs.submit)).click()
  }
}

export default Relay.createContainer(EventEdit, {
  initialVariables: {
    personFilters: {},
  },
  fragments: {
    listContainer: () => Relay.QL`
      fragment on ListContainer {
        eventTypes {
          id
          name
        }
        people(
          first: 1
          personFilters: $personFilters
        ) {
          edges {
            cursor
            node {
              id
              firstName
              lastName
              email
            }
          }
        }
      }
    `
  }
})
<|endoftext|>


<commit_before>/**
 * @author       Richard Davey
 * @copyright    2020 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

var Vector3 = require('../../math/Vector3');

/**
 * Checks for intersection between the two line segments and returns the intersection point as a Vector3,
 * or `null` if the lines are parallel, or do not intersect.
 *
 * The `z` property of the Vector3 contains the intersection distance, which can be used to find
 * the closest intersecting point from a group of line segments.
 *
 * @function Phaser.Geom.Intersects.GetLineToLine
 * @since 3.50.0
 *
 * @param {Phaser.Geom.Line} line1 - The first line segment to check.
 * @param {Phaser.Geom.Line} line2 - The second line segment to check.
 * @param {Phaser.Math.Vector3} [out] - A Vector3 to store the intersection results in.
 *
 * @return {Phaser.Math.Vector3} A Vector3 containing the intersection results, or `null`.
 */
var GetLineToLine = function (line1, line2, out)
{
    var x1 = line1.x1;
    var y1 = line1.y1;
    var x2 = line1.x2;
    var y2 = line1.y2;

    var x3 = line2.x1;
    var y3 = line2.y1;
    var x4 = line2.x2;
    var y4 = line2.y2;

    var dx1 = x2 - x1;
    var dy1 = y2 - y1;

    var dx2 = x4 - x3;
    var dy2 = y4 - y3;

    var denom = dy2 * dx1 - dx2 * dy1;

    //  Make sure there is not a division by zero - this also indicates that the lines are parallel.
    //  If numA and numB were both equal to zero the lines would be on top of each other (coincidental).
    //  This check is not done because it is not necessary for this implementation (the parallel check accounts for this).

    if (dx1 === 0 || denom === 0)
    {
        return false;
    }

    var T2 = (dx1 * (y3 - y1) + dy1 * (x1 - x3)) / (dx2 * dy1 - dy2 * dx1);
    var T1 = (x3 + dx2 * T2 - x1) / dx1;

    //  Intersects?
    if (T1 < 0 || T2 < 0 || T2 > 1)
    {
        return null;
    }

    if (out === undefined)
    {
        out = new Vector3();
    }

    return out.set(
        x1 + dx1 * T1,
        y1 + dy1 * T1,
        T1
    );
};

module.exports = GetLineToLine;
<commit_msg>dx1 !== 0 was an unnecessary restriction<commit_after>/**
 * @author       Richard Davey
 * @copyright    2020 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

var Vector3 = require('../../math/Vector3');

/**
 * Checks for intersection between the two line segments and returns the intersection point as a Vector3,
 * or `null` if the lines are parallel, or do not intersect.
 *
 * The `z` property of the Vector3 contains the intersection distance, which can be used to find
 * the closest intersecting point from a group of line segments.
 *
 * @function Phaser.Geom.Intersects.GetLineToLine
 * @since 3.50.0
 *
 * @param {Phaser.Geom.Line} line1 - The first line segment to check.
 * @param {Phaser.Geom.Line} line2 - The second line segment to check.
 * @param {Phaser.Math.Vector3} [out] - A Vector3 to store the intersection results in.
 *
 * @return {Phaser.Math.Vector3} A Vector3 containing the intersection results, or `null`.
 */
var GetLineToLine = function (line1, line2, out)
{
    var x1 = line1.x1;
    var y1 = line1.y1;
    var x2 = line1.x2;
    var y2 = line1.y2;

    var x3 = line2.x1;
    var y3 = line2.y1;
    var x4 = line2.x2;
    var y4 = line2.y2;

    var dx1 = x2 - x1;
    var dy1 = y2 - y1;

    var dx2 = x4 - x3;
    var dy2 = y4 - y3;

    var denom = (dx1*dy2 - dy1*dx2);

    //  Make sure there is not a division by zero - this also indicates that the lines are parallel.
    //  If numA and numB were both equal to zero the lines would be on top of each other (coincidental).
    //  This check is not done because it is not necessary for this implementation (the parallel check accounts for this).

    if (denom === 0)
    {
        return false;
    }

    var t = ((x3 - x1)*dy2 - (y3 - y1)*dx2) / denom;
    var u = ((y1 - y3)*dx1 - (x1 - x3)*dy1) / denom;

    //  Intersects?
    if (t < 0 || t > 1 || u < 0 || u > 1)
    {
        return null;
    }

    if (out === undefined)
    {
        out = new Vector3();
    }

    return out.set(
        x1 + dx1 * t,
        y1 + dy1 * t,
        t
    );
};

module.exports = GetLineToLine;
<|endoftext|>


<commit_before>import {promises} from 'jsonld';
import Api from '../Api'
import Field from '../Field'
import Resource from '../Resource'
import fetchJsonLd from './fetchJsonLd';

/**
 * Extracts the short name of a resource.
 *
 * @param {string} url
 * @param {string} entrypointUrl
 * @return {string}
 */
function guessNameFromUrl(url, entrypointUrl) {
  return url.substr(entrypointUrl.length + 1);
}

/**
 * Finds the description of the class with the given id.
 *
 * @param {object[]} docs
 * @param {string} supportedClass
 * @return {object}
 */
function findSupportedClass(docs, supportedClass) {
  const supportedClasses = docs[0]['http://www.w3.org/ns/hydra/core#supportedClass'];

  for (let i = 0; i < supportedClasses.length; i++) {
    if (supportedClasses[i]['@id'] === supportedClass) {
      return supportedClasses[i];
    }
  }

  throw new Error(`The class ${supportedClass} doesn't exist.`);
}

export function getDocumentationUrlFromHeaders(headers) {
  const linkHeader = headers.get('Link');
  if (!linkHeader) {
    Promise.reject(new Error('The response has no "Link" HTTP header.'));
  }

  const matches = linkHeader.match(/<(.+)>; rel="http:\/\/www.w3.org\/ns\/hydra\/core#apiDocumentation"/);
  if (!matches[1]) {
    Promise.reject(new Error('The "Link" HTTP header is not of the type "http://www.w3.org/ns/hydra/core#apiDocumentation".'));
  }

  return matches[1];
}

/**
 * Retrieves Hydra's entrypoint and API docs.
 *
 * @param {string} entrypointUrl
 * @return {Promise}
 */
function fetchEntrypointAndDocs(entrypointUrl) {
  return fetchJsonLd(entrypointUrl).then(d => {
    return {
      entrypointUrl,
      docsUrl: getDocumentationUrlFromHeaders(d.response.headers),
      entrypoint: d.body
    }
  }).then(data =>
    fetchJsonLd(data.docsUrl).then(d => {
      data.docs = d.body;

      return data;
    }).then(data =>
      promises.expand(data.docs, { base: data.docsUrl }).then(docs => {
        data.docs = docs;

        return data;
      })
    ).then(data =>
      promises.expand(data.entrypoint, { base: data.entrypointUrl }).then(entrypoint => {
        data.entrypoint = entrypoint;

        return data;
      })
    )
  );
}

/**
 * Parses a Hydra documentation and converts it to an intermediate representation.
 *
 * @param {string} entrypointUrl
 * @return {Promise.<Api>}
 */
export default function parseHydraDocumentation(entrypointUrl) {
  return fetchEntrypointAndDocs(entrypointUrl).then(({ entrypoint, docs }) => {
    const title = 'undefined' === typeof docs[0]['http://www.w3.org/ns/hydra/core#title'] ? docs[0]['http://www.w3.org/ns/hydra/core#title'][0]['@value'] : 'API Platform';
    const entrypointSupportedClass = findSupportedClass(docs, entrypoint[0]['@type'][0]);

    let resources = [];
    let fields = [];

    // Add resources
    for (let properties of entrypointSupportedClass['http://www.w3.org/ns/hydra/core#supportedProperty']) {
      const property = properties['http://www.w3.org/ns/hydra/core#property'][0];
      const entrypointSupportedOperations = property['http://www.w3.org/ns/hydra/core#supportedOperation'];

      let readableFields = [];
      let writableFields = [];

      // Add fields
      for (let j = 0; j < entrypointSupportedOperations.length; j++) {
        const className = entrypointSupportedOperations[j]['http://www.w3.org/ns/hydra/core#returns'][0]['@id'];
        if (0 === className.indexOf('http://www.w3.org/ns/hydra/core')) {
          continue;
        }

        const supportedClass = findSupportedClass(docs, className);
        for (let supportedProperty of supportedClass['http://www.w3.org/ns/hydra/core#supportedProperty']) {
          const range = supportedProperty['http://www.w3.org/ns/hydra/core#property'][0]['http://www.w3.org/2000/01/rdf-schema#range'][0]['@id'];

          const field = new Field(
            supportedProperty['http://www.w3.org/ns/hydra/core#property'][0]['http://www.w3.org/2000/01/rdf-schema#label'][0]['@value'],
            supportedProperty['http://www.w3.org/ns/hydra/core#property'][0]['@id'],
            range,
            'http://www.w3.org/ns/hydra/core#Link' === supportedProperty['http://www.w3.org/ns/hydra/core#property'][0]['@type'][0] ? range : null, // Will be updated in a subsequent pass
            supportedProperty['http://www.w3.org/ns/hydra/core#required'] ? supportedProperty['http://www.w3.org/ns/hydra/core#required'][0]['@value'] : false,
            supportedProperty['http://www.w3.org/ns/hydra/core#description'] ? supportedProperty['http://www.w3.org/ns/hydra/core#description'][0]['@value'] : ''
          );

          fields.push(field);

          if (supportedProperty['http://www.w3.org/ns/hydra/core#readable'][0]['@value']) {
            readableFields.push(field);
          }

          if (supportedProperty['http://www.w3.org/ns/hydra/core#writable'][0]['@value']) {
            writableFields.push(field);
          }
        }

        resources.push(new Resource(
          guessNameFromUrl(entrypoint[0][property['@id']][0]['@id'], entrypointUrl),
          entrypoint[0][property['@id']][0]['@id'],
          supportedClass['@id'],
          readableFields,
          writableFields
        ));

        break;
      }
    }

    // Resolve references
    for (let field of fields) {
      if (null !== field.reference) {
        field.reference = resources.find(resource => resource.id === field.reference);
      }
    }

    return new Api(entrypointUrl, title, resources);
  });
}
<commit_msg>Fix title test<commit_after>import {promises} from 'jsonld';
import Api from '../Api'
import Field from '../Field'
import Resource from '../Resource'
import fetchJsonLd from './fetchJsonLd';

/**
 * Extracts the short name of a resource.
 *
 * @param {string} url
 * @param {string} entrypointUrl
 * @return {string}
 */
function guessNameFromUrl(url, entrypointUrl) {
  return url.substr(entrypointUrl.length + 1);
}

/**
 * Finds the description of the class with the given id.
 *
 * @param {object[]} docs
 * @param {string} supportedClass
 * @return {object}
 */
function findSupportedClass(docs, supportedClass) {
  const supportedClasses = docs[0]['http://www.w3.org/ns/hydra/core#supportedClass'];

  for (let i = 0; i < supportedClasses.length; i++) {
    if (supportedClasses[i]['@id'] === supportedClass) {
      return supportedClasses[i];
    }
  }

  throw new Error(`The class ${supportedClass} doesn't exist.`);
}

export function getDocumentationUrlFromHeaders(headers) {
  const linkHeader = headers.get('Link');
  if (!linkHeader) {
    Promise.reject(new Error('The response has no "Link" HTTP header.'));
  }

  const matches = linkHeader.match(/<(.+)>; rel="http:\/\/www.w3.org\/ns\/hydra\/core#apiDocumentation"/);
  if (!matches[1]) {
    Promise.reject(new Error('The "Link" HTTP header is not of the type "http://www.w3.org/ns/hydra/core#apiDocumentation".'));
  }

  return matches[1];
}

/**
 * Retrieves Hydra's entrypoint and API docs.
 *
 * @param {string} entrypointUrl
 * @return {Promise}
 */
function fetchEntrypointAndDocs(entrypointUrl) {
  return fetchJsonLd(entrypointUrl).then(d => {
    return {
      entrypointUrl,
      docsUrl: getDocumentationUrlFromHeaders(d.response.headers),
      entrypoint: d.body
    }
  }).then(data =>
    fetchJsonLd(data.docsUrl).then(d => {
      data.docs = d.body;

      return data;
    }).then(data =>
      promises.expand(data.docs, { base: data.docsUrl }).then(docs => {
        data.docs = docs;

        return data;
      })
    ).then(data =>
      promises.expand(data.entrypoint, { base: data.entrypointUrl }).then(entrypoint => {
        data.entrypoint = entrypoint;

        return data;
      })
    )
  );
}

/**
 * Parses a Hydra documentation and converts it to an intermediate representation.
 *
 * @param {string} entrypointUrl
 * @return {Promise.<Api>}
 */
export default function parseHydraDocumentation(entrypointUrl) {
  return fetchEntrypointAndDocs(entrypointUrl).then(({ entrypoint, docs }) => {
    const title = 'undefined' === typeof docs[0]['http://www.w3.org/ns/hydra/core#title'] ? 'API Platform' : docs[0]['http://www.w3.org/ns/hydra/core#title'][0]['@value'];
    const entrypointSupportedClass = findSupportedClass(docs, entrypoint[0]['@type'][0]);

    let resources = [];
    let fields = [];

    // Add resources
    for (let properties of entrypointSupportedClass['http://www.w3.org/ns/hydra/core#supportedProperty']) {
      const property = properties['http://www.w3.org/ns/hydra/core#property'][0];
      const entrypointSupportedOperations = property['http://www.w3.org/ns/hydra/core#supportedOperation'];

      let readableFields = [];
      let writableFields = [];

      // Add fields
      for (let j = 0; j < entrypointSupportedOperations.length; j++) {
        const className = entrypointSupportedOperations[j]['http://www.w3.org/ns/hydra/core#returns'][0]['@id'];
        if (0 === className.indexOf('http://www.w3.org/ns/hydra/core')) {
          continue;
        }

        const supportedClass = findSupportedClass(docs, className);
        for (let supportedProperty of supportedClass['http://www.w3.org/ns/hydra/core#supportedProperty']) {
          const range = supportedProperty['http://www.w3.org/ns/hydra/core#property'][0]['http://www.w3.org/2000/01/rdf-schema#range'][0]['@id'];

          const field = new Field(
            supportedProperty['http://www.w3.org/ns/hydra/core#property'][0]['http://www.w3.org/2000/01/rdf-schema#label'][0]['@value'],
            supportedProperty['http://www.w3.org/ns/hydra/core#property'][0]['@id'],
            range,
            'http://www.w3.org/ns/hydra/core#Link' === supportedProperty['http://www.w3.org/ns/hydra/core#property'][0]['@type'][0] ? range : null, // Will be updated in a subsequent pass
            supportedProperty['http://www.w3.org/ns/hydra/core#required'] ? supportedProperty['http://www.w3.org/ns/hydra/core#required'][0]['@value'] : false,
            supportedProperty['http://www.w3.org/ns/hydra/core#description'] ? supportedProperty['http://www.w3.org/ns/hydra/core#description'][0]['@value'] : ''
          );

          fields.push(field);

          if (supportedProperty['http://www.w3.org/ns/hydra/core#readable'][0]['@value']) {
            readableFields.push(field);
          }

          if (supportedProperty['http://www.w3.org/ns/hydra/core#writable'][0]['@value']) {
            writableFields.push(field);
          }
        }

        resources.push(new Resource(
          guessNameFromUrl(entrypoint[0][property['@id']][0]['@id'], entrypointUrl),
          entrypoint[0][property['@id']][0]['@id'],
          supportedClass['@id'],
          readableFields,
          writableFields
        ));

        break;
      }
    }

    // Resolve references
    for (let field of fields) {
      if (null !== field.reference) {
        field.reference = resources.find(resource => resource.id === field.reference);
      }
    }

    return new Api(entrypointUrl, title, resources);
  });
}
<|endoftext|>


<commit_before>import Router from 'src/router';

//set initial url to /
window.history.replaceState(null, null, '/');

describe("Base functionality", () => {
  const router = new Router();
  it('returns root correctly', () => {
    expect(router.root).to.be.equal('');
  });
  it('returns query params correctly', () => {
    expect(router.params).to.deep.equal({});
  });
});
<commit_msg>change assertion<commit_after>import Router from 'src/router';

//set initial url to /
window.history.replaceState(null, null, '/');

describe("Base functionality", () => {
  const router = new Router();
  it('returns root correctly', () => {
    assert.equal(router.root, '');
  });
  it('returns query params correctly', () => {
    assert.deepEqual(router.params, {});
  });
});
<|endoftext|>