<commit_before>import React, {Component} from 'react';
import TextField from 'material-ui/TextField';
import Button from 'material-ui/Button';
import {momentFromNow} from '../../lib/util';
import {sealedBids} from '../../lib/ensService';
import {RevealAuctionConfirmDialog} from './RevealAuctionConfirmDialog';
import './RevealAuctionForm.css';

const EmailTextField = (props) => (
  <TextField
    id="email"
    name="email"
    label="Email"
    value={props.value}
    onChange={props.onChange}
    margin="normal"
    placeholder="youremail@example.com"
    helperText="The bid information will send to this email"
  />
);

const EthBidTextField = (props) => (
  <TextField
    error={props.error}
    id="ethBid"
    name="ethBid"
    label="ETH"
    value={props.value}
    onChange={props.onChange}
    margin="normal"
    placeholder="0.01"
    helperText={props.error ? props.errMsg : 'Bid amount'}
  />
);

const SecretTextField = (props) => (
  <TextField
    error={props.error}
    id="secret"
    name="secret"
    label="Secret"
    value={props.value}
    onChange={props.onChange}
    margin="normal"
    placeholder="pass phrase"
    helperText={props.error ? props.errMsg :"Please protect your bid with random numbers and characters"}
  />
);

const GasTextField = (props) => (
  <TextField
    error={props.error}
    id="gas"
    name="gas"
    label="Gas Price (Gwei)"
    type="number"
    value={props.value}
    onChange={props.onChange}
    margin="normal"
    helperText={props.error ? props.errMsg : "Recommend use 21 Gwei"}
  />
);

const ConfirmFormSubmit = (props) => (

    <Button
      raised
      label="Dialog"
      disabled={props.disabled}
      onClick={props.handleOpen}
    >
      Confirm Submit
    </Button>

);

const FormComponent = (props) => (

      {/* <EmailTextField
        value={props.email}
        onChange={props.handleInputChange}
      /> */}
      <EthBidTextField
        error={props.ethBidErr}
        errMsg={props.ethBidErrMsg}
        value={props.ethBid}
        onChange={props.handleInputChange}
      />
      <SecretTextField
        error={props.secretErr}
        errMsg={props.secretErrMsg}
        value={props.secret}
        onChange={props.handleInputChange}
      />
      <GasTextField
        error={props.gasErr}
        errMsg={props.gasErrMsg}
        value={props.gas}
        onChange={props.handleInputChange}
      />

    <ConfirmFormSubmit
      onClick={props.handleOpen}
      disabled={props.submitDisabled()}
    />

);

export class RevealAuctionForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      open: false,
      email: '',
      ethBid: '0.01',
      ethBidErr: false,
      ethBidErrMsg: '',
      secret: '0',
      secretErr: false,
      secretErrMsg: '',
      gas: '21',
      gasErr: false,
      gasErrMsg: ''
    }
    this.handleOpen = this.handleOpen.bind(this);
    this.handleClose = this.handleClose.bind(this);
    this.handleInputChange = this.handleInputChange.bind(this);
    this.checkEthBid = this.checkEthBid.bind(this);
    this.checkSecret = this.checkSecret.bind(this);
    this.checkGas = this.checkGas.bind(this);
    this.submitDisabled = this.submitDisabled.bind(this);
    this.inputResult = this.inputResult.bind(this);
  }

  handleOpen = () => {
    if (!(this.props.address && this.props.privateKey)) {
      this.props.handleWarningMessageOpen("Should login first");
      return
    }

    const checkValue = sealedBids(
      this.props.searchResult.searchName,
      this.props.ethBid,
      this.props.secret,
      this.props.privateKey
    );
    if (checkValue === '0x0000000000000000000000000000000000000000') {
      this.props.handleWarningMessageOpen("Invalid sealed bids");
      return
    }

    this.setState({open: true});
  }

  handleClose = () => {
    this.setState({open: false});
  }

  handleInputChange(event) {
    const {name, value} = event.target;
    this.setState({ [name]: value });

    switch (name) {
      case 'ethBid':
        this.checkEthBid(value);
        break;
      case 'secret':
        this.checkSecret(value);
        break;
      case 'gas':
        this.checkGas(value);
        break;
      default:
    }
  }

  checkEthBid = (v) => {

    // validate input only number
    const reg = /^[+-]?\d+(\.\d+)?$/;
    if (!reg.test(v)) {
      this.setState({
        ethBidErr: true,
        ethBidErrMsg: 'Bid amount: Please input a valid number'
      })
      return;
    }

    // validate input should not be zero
    if (parseFloat(v, 10) === 0) {
      this.setState({
        ethBidErr: true,
        ethBidErrMsg: 'Bid amount: Please input a non-zero number'
      });
      return;
    }

    this.setState({
      ethBidErr: false,
      ethBidErrMsg: ''
    })
  }

  checkSecret = (v) => {
    // validate value should present
    if (v === '') {
      this.setState({
        secretErr: true,
        secretErrMsg: 'Please input random numbers and characters.'
      })
      return;
    }

    this.setState({
      secretErr: false,
      secretErrMsg: ''
    });
  }

  checkGas = (v) => {
    // validate value should present
    if (v === '') {
      this.setState({
        gasErr: true,
        gasErrMsg: 'Please input a number.'
      });
      return;
    }

    // validate should greater than one
    if (parseFloat(v, 10) <= 1) {
      this.setState({
        gasErr: true,
        gasErrMsg: 'Please input a number large than one'
      })
      return;
    }

    this.setState({
      gasErr: false,
      gasErrMsg: ''
    })
  }

  submitDisabled = () => {
    const {ethBidErr, secretErr, gasErr} = this.state;
    return ethBidErr || secretErr || gasErr;
  }

  inputResult = () => ({
    email: this.state.email,
    ethBid: this.state.ethBid,
    secret: this.state.secret,
    gas: this.state.gas
  })

  render() {
    const domainName =
{this.props.searchResult.searchName}.eth
;
    const timeDuration = (

Reveal Auction On

{this.props.unsealStartsAt.toString()}

{momentFromNow(this.props.unsealStartsAt).toString()}

Finalize Auction On

{this.props.registratesAt.toString()}

{momentFromNow(this.props.registratesAt).toString()}

    );
    const revealAuctionConfirmDialog =
      (this.state.open && this.props.address && this.props.privateKey) &&
        <RevealAuctionConfirmDialog
          {...this.props}
          inputResult={this.inputResult()}
          open={this.state.open}
          handleClose={this.handleClose}
        />;

    return (

        {domainName}
        {timeDuration}
        <FormComponent
          {...this.props}
          {...this.state}
          handleInputChange={this.handleInputChange}
          handleOpen={this.handleOpen}
          submitDisabled={this.submitDisabled}
        />
        {revealAuctionConfirmDialog}

    );
  }
};
<commit_msg>fix bugs<commit_after>import React, {Component} from 'react';
import TextField from 'material-ui/TextField';
import Button from 'material-ui/Button';
import {momentFromNow} from '../../lib/util';
import {sealedBids} from '../../lib/ensService';
import {RevealAuctionConfirmDialog} from './RevealAuctionConfirmDialog';
import './RevealAuctionForm.css';

const EmailTextField = (props) => (
  <TextField
    id="email"
    name="email"
    label="Email"
    value={props.value}
    onChange={props.onChange}
    margin="normal"
    placeholder="youremail@example.com"
    helperText="The bid information will send to this email"
  />
);

const EthBidTextField = (props) => (
  <TextField
    error={props.error}
    id="ethBid"
    name="ethBid"
    label="ETH"
    value={props.value}
    onChange={props.onChange}
    margin="normal"
    placeholder="0.01"
    helperText={props.error ? props.errMsg : 'Bid amount'}
  />
);

const SecretTextField = (props) => (
  <TextField
    error={props.error}
    id="secret"
    name="secret"
    label="Secret"
    value={props.value}
    onChange={props.onChange}
    margin="normal"
    placeholder="pass phrase"
    helperText={props.error ? props.errMsg :"Please protect your bid with random numbers and characters"}
  />
);

const GasTextField = (props) => (
  <TextField
    error={props.error}
    id="gas"
    name="gas"
    label="Gas Price (Gwei)"
    type="number"
    value={props.value}
    onChange={props.onChange}
    margin="normal"
    helperText={props.error ? props.errMsg : "Recommend use 21 Gwei"}
  />
);

const ConfirmFormSubmit = (props) => (

    <Button
      raised
      label="Dialog"
      disabled={props.disabled}
      onClick={props.onClick}
    >
      Confirm Submit
    </Button>

);

const FormComponent = (props) => (

      {/* <EmailTextField
        value={props.email}
        onChange={props.handleInputChange}
      /> */}
      <EthBidTextField
        error={props.ethBidErr}
        errMsg={props.ethBidErrMsg}
        value={props.ethBid}
        onChange={props.handleInputChange}
      />
      <SecretTextField
        error={props.secretErr}
        errMsg={props.secretErrMsg}
        value={props.secret}
        onChange={props.handleInputChange}
      />
      <GasTextField
        error={props.gasErr}
        errMsg={props.gasErrMsg}
        value={props.gas}
        onChange={props.handleInputChange}
      />

    <ConfirmFormSubmit
      onClick={props.handleOpen}
      disabled={props.submitDisabled()}
    />

);

export class RevealAuctionForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      open: false,
      email: '',
      ethBid: '0.01',
      ethBidErr: false,
      ethBidErrMsg: '',
      secret: '0',
      secretErr: false,
      secretErrMsg: '',
      gas: '21',
      gasErr: false,
      gasErrMsg: ''
    }
    this.handleOpen = this.handleOpen.bind(this);
    this.handleClose = this.handleClose.bind(this);
    this.handleInputChange = this.handleInputChange.bind(this);
    this.checkEthBid = this.checkEthBid.bind(this);
    this.checkSecret = this.checkSecret.bind(this);
    this.checkGas = this.checkGas.bind(this);
    this.submitDisabled = this.submitDisabled.bind(this);
    this.inputResult = this.inputResult.bind(this);
  }

  handleOpen = () => {
    if (!(this.props.address && this.props.privateKey)) {
      this.props.handleWarningMessageOpen("Should login first");
      return
    }

    const checkValue = sealedBids(
      this.props.searchResult.searchName,
      this.props.ethBid,
      this.props.secret,
      this.props.privateKey
    );
    if (checkValue === '0x0000000000000000000000000000000000000000') {
      this.props.handleWarningMessageOpen("Invalid sealed bids");
      return
    }

    this.setState({open: true});
  }

  handleClose = () => {
    this.setState({open: false});
  }

  handleInputChange(event) {
    const {name, value} = event.target;
    this.setState({ [name]: value });

    switch (name) {
      case 'ethBid':
        this.checkEthBid(value);
        break;
      case 'secret':
        this.checkSecret(value);
        break;
      case 'gas':
        this.checkGas(value);
        break;
      default:
    }
  }

  checkEthBid = (v) => {

    // validate input only number
    const reg = /^[+-]?\d+(\.\d+)?$/;
    if (!reg.test(v)) {
      this.setState({
        ethBidErr: true,
        ethBidErrMsg: 'Bid amount: Please input a valid number'
      })
      return;
    }

    // validate input should not be zero
    if (parseFloat(v, 10) === 0) {
      this.setState({
        ethBidErr: true,
        ethBidErrMsg: 'Bid amount: Please input a non-zero number'
      });
      return;
    }

    this.setState({
      ethBidErr: false,
      ethBidErrMsg: ''
    })
  }

  checkSecret = (v) => {
    // validate value should present
    if (v === '') {
      this.setState({
        secretErr: true,
        secretErrMsg: 'Please input random numbers and characters.'
      })
      return;
    }

    this.setState({
      secretErr: false,
      secretErrMsg: ''
    });
  }

  checkGas = (v) => {
    // validate value should present
    if (v === '') {
      this.setState({
        gasErr: true,
        gasErrMsg: 'Please input a number.'
      });
      return;
    }

    // validate should greater than one
    if (parseFloat(v, 10) <= 1) {
      this.setState({
        gasErr: true,
        gasErrMsg: 'Please input a number large than one'
      })
      return;
    }

    this.setState({
      gasErr: false,
      gasErrMsg: ''
    })
  }

  submitDisabled = () => {
    const {ethBidErr, secretErr, gasErr} = this.state;
    return ethBidErr || secretErr || gasErr;
  }

  inputResult = () => ({
    email: this.state.email,
    ethBid: this.state.ethBid,
    secret: this.state.secret,
    gas: this.state.gas
  })

  render() {
    const domainName =
{this.props.searchResult.searchName}.eth
;
    const timeDuration = (

Reveal Auction On

{this.props.unsealStartsAt.toString()}

{momentFromNow(this.props.unsealStartsAt).toString()}

Finalize Auction On

{this.props.registratesAt.toString()}

{momentFromNow(this.props.registratesAt).toString()}

    );
    const revealAuctionConfirmDialog =
      (this.state.open && this.props.address && this.props.privateKey) &&
        <RevealAuctionConfirmDialog
          {...this.props}
          inputResult={this.inputResult()}
          open={this.state.open}
          handleClose={this.handleClose}
        />;

    return (

        {domainName}
        {timeDuration}
        <FormComponent
          {...this.props}
          {...this.state}
          handleInputChange={this.handleInputChange}
          handleOpen={this.handleOpen}
          submitDisabled={this.submitDisabled}
        />
        {revealAuctionConfirmDialog}

    );
  }
};
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import cn from 'classnames';
import i from 'common/icons';
import styles from './RateButtonElement.module.css';

const RateButtonElement = ({ hover, active, onClick }) => (
  <i.Glike
    className={cn(styles.container, {
      [styles.hover]: hover,
      [styles.active]: active,
    })}
    onClick={onClick}
  />
);

RateButtonElement.propTypes = {
  hover: PropTypes.bool,
  active: PropTypes.bool,
  onClick: PropTypes.func,
};

export default RateButtonElement;
<commit_msg>adjust RateButtonElement Glike import way (#276)<commit_after>import React, { PropTypes } from 'react';
import cn from 'classnames';
import { Glike } from 'common/icons';
import styles from './RateButtonElement.module.css';

const RateButtonElement = ({ hover, active, onClick }) => (
  <Glike
    className={cn(styles.container, {
      [styles.hover]: hover,
      [styles.active]: active,
    })}
    onClick={onClick}
  />
);

RateButtonElement.propTypes = {
  hover: PropTypes.bool,
  active: PropTypes.bool,
  onClick: PropTypes.func,
};

export default RateButtonElement;
<|endoftext|>


<commit_before>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2017, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

import _ from 'lodash';
import { TimelineMax } from 'gsap';
import React, { Component, PropTypes } from 'react';

import { classifyBgValue } from '../../../utils/bloodglucose';

import styles from './CBGDateTraceAnimated.css';

class CBGDateTraceAnimated extends Component {
  static defaultProps = {
    cbgRadius: 2.5,
  };

  static propTypes = {
    bgBounds: PropTypes.shape({
      veryHighThreshold: PropTypes.number.isRequired,
      targetUpperBound: PropTypes.number.isRequired,
      targetLowerBound: PropTypes.number.isRequired,
      veryLowThreshold: PropTypes.number.isRequired,
    }).isRequired,
    cbgRadius: PropTypes.number.isRequired,
    data: PropTypes.arrayOf(PropTypes.shape({
      // here only documenting the properties we actually use rather than the *whole* data model!
      id: PropTypes.string.isRequired,
      msPer24: PropTypes.number.isRequired,
      value: PropTypes.number.isRequired,
    })).isRequired,
    date: PropTypes.string.isRequired,
    xScale: PropTypes.func.isRequired,
    yScale: PropTypes.func.isRequired,
  };

  componentWillEnter(cb) {
    const { data } = this.props;
    const targets = _.map(data, (d) => (this[d.id]));
    const t = new TimelineMax({ onComplete: cb });

    t.staggerTo(targets, 0.2, { opacity: 1 }, 0.0015);
  }

  // TransitionGroupPlus gets mad if this isn't defined :(
  componentDidEnter() {}

  componentWillLeave(cb) {
    const { data } = this.props;
    const targets = _.map(data, (d) => (this[d.id]));
    const t = new TimelineMax({ onComplete: cb });

    t.staggerTo(targets, 0.2, { opacity: 0 }, 0.0015);
  }

  render() {
    const { bgBounds, cbgRadius, data, date, xScale, yScale } = this.props;
    return (
      <g id={`cbgDateTrace-${date}`}>
        {_.map(data, (d) => (
          <circle
            className={`cbgCircle ${styles[classifyBgValue(bgBounds, d.value)]}`}
            cx={xScale(d.msPer24)}
            cy={yScale(d.value)}
            key={d.id}
            opacity={0}
            pointerEvents="none"
            r={cbgRadius}
            ref={(node) => { this[d.id] = node; }}
          />
        ))}
      </g>
    );
  }
}

export default CBGDateTraceAnimated;
<commit_msg>delete incorrect comment<commit_after>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2017, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

import _ from 'lodash';
import { TimelineMax } from 'gsap';
import React, { Component, PropTypes } from 'react';

import { classifyBgValue } from '../../../utils/bloodglucose';

import styles from './CBGDateTraceAnimated.css';

class CBGDateTraceAnimated extends Component {
  static defaultProps = {
    cbgRadius: 2.5,
  };

  static propTypes = {
    bgBounds: PropTypes.shape({
      veryHighThreshold: PropTypes.number.isRequired,
      targetUpperBound: PropTypes.number.isRequired,
      targetLowerBound: PropTypes.number.isRequired,
      veryLowThreshold: PropTypes.number.isRequired,
    }).isRequired,
    cbgRadius: PropTypes.number.isRequired,
    data: PropTypes.arrayOf(PropTypes.shape({
      // here only documenting the properties we actually use rather than the *whole* data model!
      id: PropTypes.string.isRequired,
      msPer24: PropTypes.number.isRequired,
      value: PropTypes.number.isRequired,
    })).isRequired,
    date: PropTypes.string.isRequired,
    xScale: PropTypes.func.isRequired,
    yScale: PropTypes.func.isRequired,
  };

  componentWillEnter(cb) {
    const { data } = this.props;
    const targets = _.map(data, (d) => (this[d.id]));
    const t = new TimelineMax({ onComplete: cb });

    t.staggerTo(targets, 0.2, { opacity: 1 }, 0.0015);
  }

  componentDidEnter() {}

  componentWillLeave(cb) {
    const { data } = this.props;
    const targets = _.map(data, (d) => (this[d.id]));
    const t = new TimelineMax({ onComplete: cb });

    t.staggerTo(targets, 0.2, { opacity: 0 }, 0.0015);
  }

  render() {
    const { bgBounds, cbgRadius, data, date, xScale, yScale } = this.props;
    return (
      <g id={`cbgDateTrace-${date}`}>
        {_.map(data, (d) => (
          <circle
            className={`cbgCircle ${styles[classifyBgValue(bgBounds, d.value)]}`}
            cx={xScale(d.msPer24)}
            cy={yScale(d.value)}
            key={d.id}
            opacity={0}
            pointerEvents="none"
            r={cbgRadius}
            ref={(node) => { this[d.id] = node; }}
          />
        ))}
      </g>
    );
  }
}

export default CBGDateTraceAnimated;
<|endoftext|>


<commit_before>import compareHelper from '../../helper/equals';

export default {
  name: 'multi-select',
  props: {
    options: {
      type: Object,
      default: () => ({}),
    },
    filters: {
      type: Array,
      default: () => [],
    },
    selectOptions: {
      type: Array,
      default: () => [],
    },
    eventName: {
      type: String,
      default: 'selectionChanged',
    },
    reloadInit: {
      type: Boolean,
      default: false,
    },
    value: {
      type: Array,
      default: () => ([]),
    },
    btnClass: {
      type: String,
      default: '',
    },
    popoverClass: {
      type: String,
      default: '',
    },
    btnLabel: {
      type: Function,
      default: () => ('multi-select'),
    },
    search: {
      type: Boolean,
      default: false,
    },
    searchPlaceholder: {
      type: String,
      default: 'Search...',
    },
    historyButton: {
      type: Boolean,
      default: false,
    },
    historyButtonText: {
      type: String,
      default: '↶',
    },
    position: {
      type: String,
      default: 'bottom-left',
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    disabledUnSelect: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      valueSelected: [],
      simpleArray: false,
      multiSelect: null,
      groups: null,
      isOpen: false,
      globalModel: [],
      idSelectedTab: 0,
      searchInput: '',
      optionsAllHide: false,
      previousSelected: [],
    };
  },
  created() {
    this.setConfig();
  },
  methods: {
    setConfig() {
      this.multi = typeof (this.options.multi) !== 'undefined'
        ? this.options.multi : false;
      this.groups = typeof (this.options.groups) !== 'undefined'
        ? this.options.groups : false;
      this.list = this.options.labelList || 'list';
      this.labelName = this.options.labelName || 'name';
      this.labelValue = this.options.labelValue || this.labelName;
      this.groupName = this.options.groupName || 'name';
      this.labelSelected = this.options.labelSelected || 'selected';
      this.labelDisabled = this.options.labelDisabled || 'disabled';
      this.cssSelected = this.options.cssSelected || (
        option => (option[this.labelSelected]
          ? {
            'font-weight': 'bold',
            color: '#5755d9',
          } : ''));
      this.init();
    },
    init() {
      const clone = this.cloneData(this.selectOptions);
      if (!this.groups) {
        if (typeof this.selectOptions[0] === 'string'
          || typeof this.selectOptions[0] === 'number') {
          this.simpleArray = true;
          this.globalModel = [{ [this.list]: this.prepareArray(clone) }];
        } else {
          this.globalModel = [{ [this.list]: clone }];
        }
      } else {
        if (typeof clone[0][this.list][0] === 'string'
        || typeof clone[0][this.list][0] === 'number') {
          for (let i = 0; i < clone.length; i += 1) {
            clone[i][this.list] = this.prepareArray(clone[i][this.list]);
          }
          this.simpleArray = true;
        }
        this.globalModel = clone;
      }
      this.initValues();
    },
    initValues() {
      this.valueSelected = [];
      for (let i = 0; i < this.globalModel.length; i += 1) {
        for (let j = 0; j < this.globalModel[i][this.list].length; j += 1) {
          if (typeof this.globalModel[i][this.list][j][this.labelSelected]
            === 'boolean') {
            this.globalModel[i][this.list][j][this.labelSelected] = false;
          } else {
            this.$set(this.globalModel[i][this.list][j], this.labelSelected, false);
            this.$set(this.globalModel[i][this.list][j], 'visible', true);
          }
          for (let k = 0; k < this.value.length; k += 1) {
            if (this.simpleArray
              && this.globalModel[i][this.list][j][this.labelValue] === this.value[k]) {
              this.globalModel[i][this.list][j][this.labelSelected] = true;
              this.valueSelected.push(this.globalModel[i][
                this.list][j][this.labelValue]);
            } else if (!this.simpleArray
              && this.globalModel[i][this.list][j][this.labelValue]
              === this.value[k][this.labelValue]) {
              this.globalModel[i][this.list][j][this.labelSelected] = true;
              const opt = Object.assign({}, this.globalModel[i][this.list][j]);
              delete opt[this.labelSelected];
              delete opt.visible;
              this.valueSelected.push(opt);
            }
          }
        }
      }
      this.filter();
      this.$emit('input', this.valueSelected.slice(0));
      this.$emit(this.eventName, this.valueSelected.slice(0));
    },
    toggleCheckboxes(event) {
      this.multiSelect = event.target;
      if (this.multiSelect.className === 'buttonLabel') {
        this.multiSelect = this.multiSelect.parentNode;
      }
      this.isOpen = !this.isOpen;
      this.openStatus(this.isOpen);
    },
    externalClick(event) {
      if (this.isOpen) {
        let elem = event.target;
        if (!!elem && elem.className === 'buttonLabel') {
          elem = elem.parentNode;
        }
        if (!!elem && elem.isSameNode(this.multiSelect)) {
          return;
        }
        this.isOpen = false;
        this.openStatus(this.isOpen);
      }
    },
    /* eslint no-param-reassign: ["error", { "props": false }] */
    selectOption(option) {
      if (option[this.labelDisabled]) {
        return;
      }
      if (!option[this.labelSelected]) {
        this.previousSelected.push(this.cloneData(this.valueSelected));
        if (!this.multi) {
          this.deselctAll();
          this.valueSelected = [];
          this.externalClick({ path: [] });
        }
        this.pushOption(option);
        this.$emit('input', this.valueSelected.slice(0));
        this.$emit(this.eventName, this.valueSelected.slice(0));
      } else {
        if (!this.multi && this.disabledUnSelect) {
          return;
        }
        this.previousSelected.push(this.cloneData(this.valueSelected));
        this.popOption(option);
        this.$emit('input', this.valueSelected.slice(0));
        this.$emit(this.eventName, this.valueSelected.slice(0));
      }
      option[this.labelSelected] = !option[this.labelSelected];
      this.filter();
    },
    pushOption(option) {
      if (this.simpleArray) {
        this.valueSelected.push(option[this.labelValue]);
      } else {
        const opt = Object.assign({}, option);
        delete opt[this.labelSelected];
        delete opt.visible;
        this.valueSelected.push(opt);
      }
    },
    popOption(opt) {
      for (let i = 0; i < this.valueSelected.length; i += 1) {
        if (this.valueSelected[i][this.labelValue] === opt[this.labelValue]
          || (this.simpleArray && this.valueSelected[i] === opt[this.labelValue])) {
          this.valueSelected.splice(i, 1);
          return;
        }
      }
    },
    selectTab(id) {
      this.idSelectedTab = id;
      this.searchfn();
    },
    searchfn() {
      let allHide = true;
      for (let i = 0; i < this.globalModel[this.idSelectedTab][this.list].length;
        i += 1) {
        if (~this.globalModel[this.idSelectedTab][this.list][i][this.labelName]
          .toLowerCase().indexOf(
            this.searchInput.toLowerCase(),
          )) {
          allHide = false;
          this.globalModel[this.idSelectedTab][this.list][i].visible = true;
        } else {
          this.globalModel[this.idSelectedTab][this.list][i].visible = false;
        }
      }
      this.optionsAllHide = allHide;
      this.filter();
    },
    clearSearch() {
      this.searchInput = '';
      this.searchfn();
    },
    selectCurrent(option) {
      this.previousSelected.push(this.cloneData(this.valueSelected));
      for (let i = 0; i < this.globalModel[this.idSelectedTab][this.list].length;
        i += 1) {
        if (this.globalModel[this.idSelectedTab][this.list][i].visible
          && !this.globalModel[this.idSelectedTab][this.list][i][this.labelDisabled]
          && option.func(this.globalModel[this.idSelectedTab][this.list][i])) {
          if (!option.selectAll) {
            if (!this.globalModel[this.idSelectedTab][this.list][i][this.labelSelected]) {
              this.globalModel[this.idSelectedTab][this.list][i][this.labelSelected] = true;
              this.pushOption(this.globalModel[this.idSelectedTab][this.list][i]);
            }
          } else if (this.globalModel[this.idSelectedTab][this.list][i][this.labelSelected]) {
            this.globalModel[this.idSelectedTab][this.list][i][this.labelSelected] = false;
            this.popOption(this.globalModel[this.idSelectedTab][this.list][i]);
          }
        }
      }
      this.$emit('input', this.valueSelected.slice(0));
      this.$emit(this.eventName, this.valueSelected.slice(0));
      option.selectAll = !option.selectAll;
      this.filter();
    },
    filter() {
      for (let i = 0; i < this.filters.length; i += 1) {
        let allSelected = true;
        for (let j = 0; j < this.globalModel[this.idSelectedTab][this.list].length;
          j += 1) {
          if (this.globalModel[this.idSelectedTab][this.list][j].visible
            && this.filters[i].func(
              this.globalModel[this.idSelectedTab][this.list][j],
            )
              && !this.globalModel[this.idSelectedTab][this.list][j][this.labelDisabled]
              && !this.globalModel[this.idSelectedTab][this.list][j][this.labelSelected]) {
            allSelected = false;
            break;
          }
        }
        this.filters[i].selectAll = allSelected;
      }
    },
    deselctAll() {
      for (let i = 0; i < this.globalModel.length; i += 1) {
        for (let j = 0; j < this.globalModel[i][this.list].length; j += 1) {
          if (!this.globalModel[i][this.list][j][this.labelDisabled]) {
            this.globalModel[i][this.list][j][this.labelSelected] = false;
          }
        }
      }
    },
    prepareArray(value) {
      return value.map(elem => ({ [this.labelValue]: elem }));
    },
    cloneData(value) {
      if (Array.isArray(value)) {
        return value.map(this.cloneData);
      } if (value && typeof value === 'object') {
        const res = {};
        const keys = Object.keys(value);
        for (let i = 0; i < keys.length; i += 1) {
          res[keys[i]] = this.cloneData(value[keys[i]]);
        }
        return res;
      }
      return value;
    },
    historyBack() {
      const previousValues = this.previousSelected.pop();
      this.$emit('input', previousValues);
      this.$emit(this.eventName, previousValues);
    },
    openStatus(status) {
      const event = status ? 'open' : 'close';
      this.$emit(event);
    },
  },
  computed: {
    getBtnLabel() {
      return this.btnLabel(this.valueSelected);
    },
    getPosition() {
      if (this.multiSelect) {
        const btnHeight = this.multiSelect.offsetHeight;
        const positions = this.position.split('-');
        const style = {
          [positions[1]]: 0,
        };
        if (positions[0] === 'top') {
          style.bottom = `${btnHeight}px`;
        }
        return style;
      }
      return {};
    },
    getButtonList() {
      return !!this.filters && this.multi && this.filters;
    },
  },
  watch: {
    selectOptions: {
      handler() {
        this.setConfig();
      },
      deep: true,
    },
    reloadInit: {
      handler(value) {
        if (value) {
          this.initValues();
          this.$emit('vueMultiSelectInited');
        }
      },
    },
    value: {
      handler(newVal, oldval) {
        if (oldval && newVal && this.valueSelected) {
          if (this.simpleArray
            && !compareHelper.compareSimpleArray(newVal, this.valueSelected)) {
            this.initValues();
          } else if (!compareHelper.compareArrayObject(
            newVal, this.valueSelected, this.labelName,
          )) {
            this.initValues();
          }
        }
      },
      deep: true,
    },
  },
  directives: {
    'click-outside': {
      bind(el, binding) {
        const { bubble } = binding.modifiers;
        const ua = navigator.userAgent;
        const event = (ua.match(/iPad|iPhone/i)) ? 'touchstart' : 'click';
        const handler = (e) => {
          if (bubble || (!el.contains(e.target) && el !== e.target)) {
            binding.value(e);
          }
        };
        el.vueClickOutside = handler;
        document.addEventListener(event, handler);
      },
      unbind(el) {
        const ua = navigator.userAgent;
        const event = (ua.match(/iPad|iPhone/i)) ? 'touchstart' : 'click';
        document.removeEventListener(event, el.vueClickOutside);
        el.vueClickOutside = null;
      },
    },
  },
};
<commit_msg>Add 2 functions accessible by ref to manualy open<commit_after>import compareHelper from '../../helper/equals';

export default {
  name: 'multi-select',
  props: {
    options: {
      type: Object,
      default: () => ({}),
    },
    filters: {
      type: Array,
      default: () => [],
    },
    selectOptions: {
      type: Array,
      default: () => [],
    },
    eventName: {
      type: String,
      default: 'selectionChanged',
    },
    reloadInit: {
      type: Boolean,
      default: false,
    },
    value: {
      type: Array,
      default: () => ([]),
    },
    btnClass: {
      type: String,
      default: '',
    },
    popoverClass: {
      type: String,
      default: '',
    },
    btnLabel: {
      type: Function,
      default: () => ('multi-select'),
    },
    search: {
      type: Boolean,
      default: false,
    },
    searchPlaceholder: {
      type: String,
      default: 'Search...',
    },
    historyButton: {
      type: Boolean,
      default: false,
    },
    historyButtonText: {
      type: String,
      default: '↶',
    },
    position: {
      type: String,
      default: 'bottom-left',
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    disabledUnSelect: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      valueSelected: [],
      simpleArray: false,
      multiSelect: null,
      groups: null,
      isOpen: false,
      globalModel: [],
      idSelectedTab: 0,
      searchInput: '',
      optionsAllHide: false,
      previousSelected: [],
    };
  },
  created() {
    this.setConfig();
  },
  methods: {
    openMultiSelect() {
      this.manualClick = true;
      this.isOpen = true;
      this.openStatus(this.isOpen);
    },
    closeMultiSelect() {
      this.manualClick = true;
      this.isOpen = false;
      this.openStatus(this.isOpen);
    },
    setConfig() {
      this.multi = typeof (this.options.multi) !== 'undefined'
        ? this.options.multi : false;
      this.groups = typeof (this.options.groups) !== 'undefined'
        ? this.options.groups : false;
      this.list = this.options.labelList || 'list';
      this.labelName = this.options.labelName || 'name';
      this.labelValue = this.options.labelValue || this.labelName;
      this.groupName = this.options.groupName || 'name';
      this.labelSelected = this.options.labelSelected || 'selected';
      this.labelDisabled = this.options.labelDisabled || 'disabled';
      this.cssSelected = this.options.cssSelected || (
        option => (option[this.labelSelected]
          ? {
            'font-weight': 'bold',
            color: '#5755d9',
          } : ''));
      this.init();
    },
    init() {
      const clone = this.cloneData(this.selectOptions);
      if (!this.groups) {
        if (typeof this.selectOptions[0] === 'string'
          || typeof this.selectOptions[0] === 'number') {
          this.simpleArray = true;
          this.globalModel = [{ [this.list]: this.prepareArray(clone) }];
        } else {
          this.globalModel = [{ [this.list]: clone }];
        }
      } else {
        if (typeof clone[0][this.list][0] === 'string'
        || typeof clone[0][this.list][0] === 'number') {
          for (let i = 0; i < clone.length; i += 1) {
            clone[i][this.list] = this.prepareArray(clone[i][this.list]);
          }
          this.simpleArray = true;
        }
        this.globalModel = clone;
      }
      this.initValues();
    },
    initValues() {
      this.valueSelected = [];
      for (let i = 0; i < this.globalModel.length; i += 1) {
        for (let j = 0; j < this.globalModel[i][this.list].length; j += 1) {
          if (typeof this.globalModel[i][this.list][j][this.labelSelected]
            === 'boolean') {
            this.globalModel[i][this.list][j][this.labelSelected] = false;
          } else {
            this.$set(this.globalModel[i][this.list][j], this.labelSelected, false);
            this.$set(this.globalModel[i][this.list][j], 'visible', true);
          }
          for (let k = 0; k < this.value.length; k += 1) {
            if (this.simpleArray
              && this.globalModel[i][this.list][j][this.labelValue] === this.value[k]) {
              this.globalModel[i][this.list][j][this.labelSelected] = true;
              this.valueSelected.push(this.globalModel[i][
                this.list][j][this.labelValue]);
            } else if (!this.simpleArray
              && this.globalModel[i][this.list][j][this.labelValue]
              === this.value[k][this.labelValue]) {
              this.globalModel[i][this.list][j][this.labelSelected] = true;
              const opt = Object.assign({}, this.globalModel[i][this.list][j]);
              delete opt[this.labelSelected];
              delete opt.visible;
              this.valueSelected.push(opt);
            }
          }
        }
      }
      this.filter();
      this.$emit('input', this.valueSelected.slice(0));
      this.$emit(this.eventName, this.valueSelected.slice(0));
    },
    toggleCheckboxes(event) {
      this.multiSelect = event.target;
      if (this.multiSelect.className === 'buttonLabel') {
        this.multiSelect = this.multiSelect.parentNode;
      }
      this.isOpen = !this.isOpen;
      this.openStatus(this.isOpen);
    },
    externalClick(event) {
      if (this.isOpen && !this.manualClick) {
        let elem = event.target;
        if (!!elem && elem.className === 'buttonLabel') {
          elem = elem.parentNode;
        }
        if (!!elem && elem.isSameNode(this.multiSelect)) {
          return;
        }
        this.isOpen = false;
        this.openStatus(this.isOpen);
      }
      this.manualClick = false;
    },
    /* eslint no-param-reassign: ["error", { "props": false }] */
    selectOption(option) {
      if (option[this.labelDisabled]) {
        return;
      }
      if (!option[this.labelSelected]) {
        this.previousSelected.push(this.cloneData(this.valueSelected));
        if (!this.multi) {
          this.deselctAll();
          this.valueSelected = [];
          this.externalClick({ path: [] });
        }
        this.pushOption(option);
        this.$emit('input', this.valueSelected.slice(0));
        this.$emit(this.eventName, this.valueSelected.slice(0));
      } else {
        if (!this.multi && this.disabledUnSelect) {
          return;
        }
        this.previousSelected.push(this.cloneData(this.valueSelected));
        this.popOption(option);
        this.$emit('input', this.valueSelected.slice(0));
        this.$emit(this.eventName, this.valueSelected.slice(0));
      }
      option[this.labelSelected] = !option[this.labelSelected];
      this.filter();
    },
    pushOption(option) {
      if (this.simpleArray) {
        this.valueSelected.push(option[this.labelValue]);
      } else {
        const opt = Object.assign({}, option);
        delete opt[this.labelSelected];
        delete opt.visible;
        this.valueSelected.push(opt);
      }
    },
    popOption(opt) {
      for (let i = 0; i < this.valueSelected.length; i += 1) {
        if (this.valueSelected[i][this.labelValue] === opt[this.labelValue]
          || (this.simpleArray && this.valueSelected[i] === opt[this.labelValue])) {
          this.valueSelected.splice(i, 1);
          return;
        }
      }
    },
    selectTab(id) {
      this.idSelectedTab = id;
      this.searchfn();
    },
    searchfn() {
      let allHide = true;
      for (let i = 0; i < this.globalModel[this.idSelectedTab][this.list].length;
        i += 1) {
        if (~this.globalModel[this.idSelectedTab][this.list][i][this.labelName]
          .toLowerCase().indexOf(
            this.searchInput.toLowerCase(),
          )) {
          allHide = false;
          this.globalModel[this.idSelectedTab][this.list][i].visible = true;
        } else {
          this.globalModel[this.idSelectedTab][this.list][i].visible = false;
        }
      }
      this.optionsAllHide = allHide;
      this.filter();
    },
    clearSearch() {
      this.searchInput = '';
      this.searchfn();
    },
    selectCurrent(option) {
      this.previousSelected.push(this.cloneData(this.valueSelected));
      for (let i = 0; i < this.globalModel[this.idSelectedTab][this.list].length;
        i += 1) {
        if (this.globalModel[this.idSelectedTab][this.list][i].visible
          && !this.globalModel[this.idSelectedTab][this.list][i][this.labelDisabled]
          && option.func(this.globalModel[this.idSelectedTab][this.list][i])) {
          if (!option.selectAll) {
            if (!this.globalModel[this.idSelectedTab][this.list][i][this.labelSelected]) {
              this.globalModel[this.idSelectedTab][this.list][i][this.labelSelected] = true;
              this.pushOption(this.globalModel[this.idSelectedTab][this.list][i]);
            }
          } else if (this.globalModel[this.idSelectedTab][this.list][i][this.labelSelected]) {
            this.globalModel[this.idSelectedTab][this.list][i][this.labelSelected] = false;
            this.popOption(this.globalModel[this.idSelectedTab][this.list][i]);
          }
        }
      }
      this.$emit('input', this.valueSelected.slice(0));
      this.$emit(this.eventName, this.valueSelected.slice(0));
      option.selectAll = !option.selectAll;
      this.filter();
    },
    filter() {
      for (let i = 0; i < this.filters.length; i += 1) {
        let allSelected = true;
        for (let j = 0; j < this.globalModel[this.idSelectedTab][this.list].length;
          j += 1) {
          if (this.globalModel[this.idSelectedTab][this.list][j].visible
            && this.filters[i].func(
              this.globalModel[this.idSelectedTab][this.list][j],
            )
              && !this.globalModel[this.idSelectedTab][this.list][j][this.labelDisabled]
              && !this.globalModel[this.idSelectedTab][this.list][j][this.labelSelected]) {
            allSelected = false;
            break;
          }
        }
        this.filters[i].selectAll = allSelected;
      }
    },
    deselctAll() {
      for (let i = 0; i < this.globalModel.length; i += 1) {
        for (let j = 0; j < this.globalModel[i][this.list].length; j += 1) {
          if (!this.globalModel[i][this.list][j][this.labelDisabled]) {
            this.globalModel[i][this.list][j][this.labelSelected] = false;
          }
        }
      }
    },
    prepareArray(value) {
      return value.map(elem => ({ [this.labelValue]: elem }));
    },
    cloneData(value) {
      if (Array.isArray(value)) {
        return value.map(this.cloneData);
      } if (value && typeof value === 'object') {
        const res = {};
        const keys = Object.keys(value);
        for (let i = 0; i < keys.length; i += 1) {
          res[keys[i]] = this.cloneData(value[keys[i]]);
        }
        return res;
      }
      return value;
    },
    historyBack() {
      const previousValues = this.previousSelected.pop();
      this.$emit('input', previousValues);
      this.$emit(this.eventName, previousValues);
    },
    openStatus(status) {
      const event = status ? 'open' : 'close';
      this.$emit(event);
    },
  },
  computed: {
    getBtnLabel() {
      return this.btnLabel(this.valueSelected);
    },
    getPosition() {
      if (this.multiSelect) {
        const btnHeight = this.multiSelect.offsetHeight;
        const positions = this.position.split('-');
        const style = {
          [positions[1]]: 0,
        };
        if (positions[0] === 'top') {
          style.bottom = `${btnHeight}px`;
        }
        return style;
      }
      return {};
    },
    getButtonList() {
      return !!this.filters && this.multi && this.filters;
    },
  },
  watch: {
    selectOptions: {
      handler() {
        this.setConfig();
      },
      deep: true,
    },
    reloadInit: {
      handler(value) {
        if (value) {
          this.initValues();
          this.$emit('vueMultiSelectInited');
        }
      },
    },
    value: {
      handler(newVal, oldval) {
        if (oldval && newVal && this.valueSelected) {
          if (this.simpleArray
            && !compareHelper.compareSimpleArray(newVal, this.valueSelected)) {
            this.initValues();
          } else if (!compareHelper.compareArrayObject(
            newVal, this.valueSelected, this.labelName,
          )) {
            this.initValues();
          }
        }
      },
      deep: true,
    },
  },
  directives: {
    'click-outside': {
      bind(el, binding) {
        const { bubble } = binding.modifiers;
        const ua = navigator.userAgent;
        const event = (ua.match(/iPad|iPhone/i)) ? 'touchstart' : 'click';
        const handler = (e) => {
          if (bubble || (!el.contains(e.target) && el !== e.target)) {
            binding.value(e);
          }
        };
        el.vueClickOutside = handler;
        document.addEventListener(event, handler);
      },
      unbind(el) {
        const ua = navigator.userAgent;
        const event = (ua.match(/iPad|iPhone/i)) ? 'touchstart' : 'click';
        document.removeEventListener(event, el.vueClickOutside);
        el.vueClickOutside = null;
      },
    },
  },
};
<|endoftext|>


<commit_before>  /********************************************/
 /**				MARKERS					**/
/********************************************/

// Define marker icons
var ReachKeep_4 = L.icon({iconUrl: 'img/marker/Reach/keep.png',iconSize: [12, 36]})
var ReachKeep_3 = L.icon({iconUrl: 'img/marker/Reach/keep.png',iconSize: [6, 18]})
var ReachKeep_2 = L.icon({iconUrl: 'img/marker/Reach/keep.png',iconSize: [3, 9]})

var ReachVillage_4 = L.icon({iconUrl: 'img/marker/Reach/village.png',iconSize: [12, 12]})
var ReachVillage_3 = L.icon({iconUrl: 'img/marker/Reach/village.png',iconSize: [6, 6]})
var ReachVillage_2 = L.icon({iconUrl: 'img/marker/Reach/village.png',iconSize: [3, 3]})

var ReachCity_4 =  L.icon({iconUrl: 'img/marker/Reach/city.png',iconSize: [12, 36]})
var ReachCity_3 =  L.icon({iconUrl: 'img/marker/Reach/city.png',iconSize: [6, 18]})
var ReachCity_2 =  L.icon({iconUrl: 'img/marker/Reach/city.png',iconSize: [3, 9]})

var ReachTown_4 =  L.icon({iconUrl: 'img/marker/Reach/town.png',iconSize: [12, 36]})
var ReachTown_3 =  L.icon({iconUrl: 'img/marker/Reach/town.png',iconSize: [6, 18]})
var ReachTown_2 =  L.icon({iconUrl: 'img/marker/Reach/town.png',iconSize: [3, 9]})

var ReachCapital_4 =  L.icon({iconUrl: 'img/marker/Reach/capital.png',iconSize: [12, 36]})
var ReachCapital_3 =  L.icon({iconUrl: 'img/marker/Reach/capital.png',iconSize: [12, 18]})
var ReachCapital_2 =  L.icon({iconUrl: 'img/marker/Reach/capital.png',iconSize: [12, 9]})

var ReachLandResource_4 =  L.icon({iconUrl: 'img/marker/Reach/landresource.png',iconSize: [12, 12]})
var ReachLandResource_3 = L.icon({iconUrl: 'img/marker/Reach/landresource.png',iconSize: [6, 6]})
var ReachLandResource_2 =  L.icon({iconUrl: 'img/marker/Reach/village.png',iconSize: [3, 3]})

var ReachSeaResource_4 = L.icon({iconUrl: 'img/marker/Reach/seaesource.png',iconSize: [12, 12]})
var ReachSeaResource_3 = L.icon({iconUrl: 'img/marker/Reach/searesource.png',iconSize: [6, 6]})
var ReachSeaResource_2 = L.icon({iconUrl: 'img/marker/Reach/searesource.png',iconSize: [3, 3]})

var ReachPort_4 = L.icon({iconUrl: 'img/marker/Reach/seaesource.png',iconSize: [12, 12]})
var ReachPort_3 = L.icon({iconUrl: 'img/marker/Reach/searesource.png',iconSize: [6, 6]})
var ReachPort_2 = L.icon({iconUrl: 'img/marker/Reach/searesource.png',iconSize: [3, 3]})

var reachKeeps = [

]

var reachVillages = [

]

var reachResources = [

]

alert("REACH LOADED!");<commit_msg>ko<commit_after>  /********************************************/
 /**				MARKERS					**/
/********************************************/

// Define marker icons
var ReachKeep_4 = L.icon({iconUrl: 'img/marker/Reach/keep.png',iconSize: [12, 36]})
var ReachKeep_3 = L.icon({iconUrl: 'img/marker/Reach/keep.png',iconSize: [6, 18]})
var ReachKeep_2 = L.icon({iconUrl: 'img/marker/Reach/keep.png',iconSize: [3, 9]})

var ReachVillage_4 = L.icon({iconUrl: 'img/marker/Reach/village.png',iconSize: [12, 12]})
var ReachVillage_3 = L.icon({iconUrl: 'img/marker/Reach/village.png',iconSize: [6, 6]})
var ReachVillage_2 = L.icon({iconUrl: 'img/marker/Reach/village.png',iconSize: [3, 3]})

var ReachCity_4 =  L.icon({iconUrl: 'img/marker/Reach/city.png',iconSize: [12, 36]})
var ReachCity_3 =  L.icon({iconUrl: 'img/marker/Reach/city.png',iconSize: [6, 18]})
var ReachCity_2 =  L.icon({iconUrl: 'img/marker/Reach/city.png',iconSize: [3, 9]})

var ReachTown_4 =  L.icon({iconUrl: 'img/marker/Reach/town.png',iconSize: [12, 36]})
var ReachTown_3 =  L.icon({iconUrl: 'img/marker/Reach/town.png',iconSize: [6, 18]})
var ReachTown_2 =  L.icon({iconUrl: 'img/marker/Reach/town.png',iconSize: [3, 9]})

var ReachCapital_4 =  L.icon({iconUrl: 'img/marker/Reach/capital.png',iconSize: [12, 36]})
var ReachCapital_3 =  L.icon({iconUrl: 'img/marker/Reach/capital.png',iconSize: [12, 18]})
var ReachCapital_2 =  L.icon({iconUrl: 'img/marker/Reach/capital.png',iconSize: [12, 9]})

var ReachLandResource_4 =  L.icon({iconUrl: 'img/marker/Reach/landresource.png',iconSize: [12, 12]})
var ReachLandResource_3 = L.icon({iconUrl: 'img/marker/Reach/landresource.png',iconSize: [6, 6]})
var ReachLandResource_2 =  L.icon({iconUrl: 'img/marker/Reach/village.png',iconSize: [3, 3]})

var ReachSeaResource_4 = L.icon({iconUrl: 'img/marker/Reach/seaesource.png',iconSize: [12, 12]})
var ReachSeaResource_3 = L.icon({iconUrl: 'img/marker/Reach/searesource.png',iconSize: [6, 6]})
var ReachSeaResource_2 = L.icon({iconUrl: 'img/marker/Reach/searesource.png',iconSize: [3, 3]})

var ReachPort_4 = L.icon({iconUrl: 'img/marker/Reach/seaesource.png',iconSize: [12, 12]})
var ReachPort_3 = L.icon({iconUrl: 'img/marker/Reach/searesource.png',iconSize: [6, 6]})
var ReachPort_2 = L.icon({iconUrl: 'img/marker/Reach/searesource.png',iconSize: [3, 3]})

var reachKeeps = [

]

var reachVillages = [

]

var reachResources = [

]

alert("REACH LOADED !!!!");<|endoftext|>


<commit_before>
function escapeHTML( html ) {
    var trans = {
        '&': '&',
        '<': '<',
        '>': '>',
        '"': '"',
        "'": '''
    };
    return (html + '').replace(/[&<>\"\']/g, function(c) { return trans[c]; });
}

function handlekeys(field, state, e)
{
    var keycode;

    if (window.event) {
        keycode = window.event.keyCode;
    } else if (e) {
        keycode = e.which;
    } else {
        return true;
    }

    if (keycode == 13) {
       state.handle('SEND');
       return false;
    } else {
       return true;
    }
}

function display(text) {
    var div = document.createElement("div");
    div.innerHTML = text;
    var cl = document.getElementById("terminal");
    cl.appendChild(div);
    div.scrollIntoView();
}

function change_prompt(new_prompt) {
    var p = document.getElementById("prompt")
    p.scrollIntoView();
    p.focus();
}

function clear_prompt() {
    change_prompt("");
    var prompt = document.getElementById("prompt");
    prompt.value = "";
}

function prompt(text, pchar) {
    clear_prompt();
    display(text);
    change_prompt(pchar);
}

state = new FSM({
    start: function(fsm, event) {
        display("Connecting to the Mongrel2 BBS....");
        fsm.trans('connecting');
        BBS.init(fsm);
    },

    connecting: {
        CONNECT: function(fsm, event) {
            display("Connected to Mongrel2 BBS.");
            BBS.send("connect");
            fsm.trans('connected');
        },
    },

    connected: {
        PROMPT: function(fsm, event) {
            prompt(event.msg, event.pchar);
            fsm.last_pchar = event.pchar;
        },

        EXIT: function(fsm, event) {
            clear_prompt();
            display(event.msg);
        },

        SCREEN: function(fsm, event) {
            display(event.msg);
        },

        CLOSE: function(fsm, event) {
            addMessage('Disconnected, will reconnect...');
            fsm.trans('connecting');
        },

        SEND: function(fsm, event) {
            var input = document.getElementById("prompt");
            BBS.send(input.value);
            display(fsm.last_pchar + input.value);
            clear_prompt();
        }
    }
});

<commit_msg>Protect against some simple XSS.<commit_after>
function escapeHTML( html ) {
    var trans = {
        '&': '&',
        '<': '<',
        '>': '>',
        '"': '"',
        "'": '''
    };
    return (html + '').replace(/[&<>\"\']/g, function(c) { return trans[c]; });
}

function handlekeys(field, state, e)
{
    var keycode;

    if (window.event) {
        keycode = window.event.keyCode;
    } else if (e) {
        keycode = e.which;
    } else {
        return true;
    }

    if (keycode == 13) {
       state.handle('SEND');
       return false;
    } else {
       return true;
    }
}

function display(text) {
    var div = document.createElement("div");
    div.innerHTML = escapeHTML(text);
    var cl = document.getElementById("terminal");
    cl.appendChild(div);
    div.scrollIntoView();
}

function change_prompt() {
    var p = document.getElementById("prompt")
    p.scrollIntoView();
    p.focus();
}

function clear_prompt() {
    change_prompt();
    var prompt = document.getElementById("prompt");
    prompt.value = "";
}

function prompt(text) {
    clear_prompt();
    display(escapeHTML(text));
    change_prompt();
}

state = new FSM({
    start: function(fsm, event) {
        display("Connecting to the Mongrel2 BBS....");
        fsm.trans('connecting');
        BBS.init(fsm);
    },

    connecting: {
        CONNECT: function(fsm, event) {
            display("Connected to Mongrel2 BBS.");
            BBS.send("connect");
            fsm.trans('connected');
        },
    },

    connected: {
        PROMPT: function(fsm, event) {
            prompt(event.msg);
            fsm.last_pchar = escapeHTML(event.pchar);
        },

        EXIT: function(fsm, event) {
            clear_prompt();
            display(event.msg);
        },

        SCREEN: function(fsm, event) {
            display(event.msg);
        },

        CLOSE: function(fsm, event) {
            addMessage('Disconnected, will reconnect...');
            fsm.trans('connecting');
        },

        SEND: function(fsm, event) {
            var input = document.getElementById("prompt");
            BBS.send(input.value);
            display(fsm.last_pchar + input.value);
            clear_prompt();
        }
    }
});

<|endoftext|>


<commit_before>define(function(require) {

    'use strict';

    var _    = require('underscore');
    var PIXI = require('pixi');

                           require('common/v3/pixi/create-drop-shadow');
                           require('common/v3/pixi/draw-stick-arrow');
                           require('common/v3/pixi/draw-arrow');
    var AppView          = require('common/v3/app/app');
    var PixiView         = require('common/v3/pixi/view');
    var Colors           = require('common/colors/colors');
    var WavelengthColors = require('common/colors/wavelength');
    var Rectangle        = require('common/math/rectangle');
    var Functions        = require('common/math/functions');
    var PhysicsUtil      = require('common/quantum/models/physics-util');

    var EnergyLevelView = require('views/energy-level');

    var Constants = require('constants');
    var Assets    = require('assets');

    /**
     *
     */
    var EnergyLevelPanelView = PixiView.extend({

        width: 300,
        height: 200,

        /**
         * Initializes the new EnergyLevelPanelView.
         */
        initialize: function(options) {
            options = _.extend({
                padding: 15,
                bgColor: '#f5f5f5',
                bgAlpha: 0.75,
                axisLineColor: '#000',
                axisLineAlpha: 1
            }, options);

            // Required options
            this.simulation = options.simulation;

            // Optional options
            this.padding = options.padding;
            this.bgColor = Colors.parseHex(options.bgColor);
            this.bgAlpha = options.bgAlpha;
            this.axisLineColor = Colors.parseHex(options.axisLineColor);
            this.axisLineAlpha = options.axisLineAlpha;

            this.energyLevelViews = [];

            // Init graph parameters
            this.minY = this.padding + 16;
            this.maxY = this.height - this.padding - 10;
            this.atomDiameter = 10;
            this.squiggleAmplitude = this.atomDiameter; // Amplitude of the squiggle waves

            var groundStateEnergy = this.simulation.getGroundState().getEnergyLevel();
            this.energyToY = Functions.createLinearFunction(
                groundStateEnergy + PhysicsUtil.wavelengthToEnergy(WavelengthColors.MIN_WAVELENGTH),
                groundStateEnergy,
                this.minY,
                this.maxY
            );

            // Initialize the graphics
            this.initGraphics();

            this.listenTo(this.simulation, 'atomic-states-changed', this.energyLevelsChanged);
            this.listenTo(this.simulation.seedBeam,    'change:wavelength change:photonsPerSecond', this.beamChanged);
            this.listenTo(this.simulation.pumpingBeam, 'change:wavelength change:photonsPerSecond', this.beamChanged);
        },

        /**
         * Initializes everything for rendering graphics
         */
        initGraphics: function() {
            this.initPanel();
            this.initAxis();
            this.initSquiggles();
            this.drawSquiggles();

            this.energyLevelsLayer = new PIXI.Container();
            this.displayObject.addChild(this.energyLevelsLayer);

            this.createEnergyLevels();
        },

        initPanel: function() {
            // Draw the shadow
            var rectangle = new Rectangle(0, 0, this.width, this.height);
            var shadow = PIXI.createDropShadow(rectangle);
            this.displayObject.addChild(shadow);

            // Draw the panel
            var graphics = new PIXI.Graphics();
            graphics.beginFill(this.bgColor, this.bgAlpha);
            graphics.drawRect(0, 0, this.width, this.height);
            graphics.endFill();

            this.displayObject.addChild(graphics);
        },

        initAxis: function() {
            var labelWidth = 15;
            var x = this.padding + labelWidth;
            var y0 = this.height - this.padding;
            var y1 = this.padding;
            var graphics = new PIXI.Graphics();
            graphics.lineStyle(2, this.axisLineColor, this.axisLineAlpha);
            graphics.drawStickArrow(x, y0, x, y1, 12, 10);

            var text = new PIXI.Text('Energy (eV)', {
                font: 'bold 12px Helvetica Neue',
                fill: '#000'
            });
            text.resolution = this.getResolution();
            text.rotation = -Math.PI / 2;
            text.anchor.y = 0;
            text.anchor.x = 0.5;
            text.x = this.padding - 5;
            text.y = this.height / 2;

            this.displayObject.addChild(graphics);
            this.displayObject.addChild(text);

            this.axisOriginX = x;
        },

        initSquiggles: function() {
            this.seedSquiggle = new PIXI.Graphics();
            this.pumpSquiggle = new PIXI.Graphics();

            this.seedSquiggle.x = this.axisOriginX + this.squiggleAmplitude;
            this.pumpSquiggle.x = this.axisOriginX + this.squiggleAmplitude * 3;
            this.seedSquiggle.y = this.maxY;
            this.pumpSquiggle.y = this.maxY;
            this.seedSquiggle.rotation = -Math.PI / 2;
            this.pumpSquiggle.rotation = -Math.PI / 2;

            this.displayObject.addChild(this.seedSquiggle);
            this.displayObject.addChild(this.seedSquiggle);
        },

        drawSquiggles: function() {
            this.drawSquiggle(this.seedSquiggle, this.simulation.seedBeam);
            this.drawSquiggle(this.pumpSquiggle, this.simulation.pumpingBeam);
        },

        drawSquiggle: function(graphics, beam) {
            // Calculate all our rendering variables
            var wavelength = beam.get('wavelength')
            var color = Colors.parseHex(WavelengthColors.nmToHex(wavelength));
            var beamEnergy = PhysicsUtil.wavelengthToEnergy(wavelength);
            var groundStateEnergy = this.simulation.getGroundState().getEnergyLevel();
            var y0 = this.energyToY(groundStateEnergy);
            var y1 = this.energyToY(groundStateEnergy + beamEnergy);
            var length = y0 - y1;
            var amp = this.squiggleAmplitude;
            var intensity = beam.get('photonsPerSecond') / beam.get('maxPhotonsPerSecond');
            var alpha = Math.sqrt(intensity);
            var arrowHeight = amp;
            // So that the tip of the arrow will just touch an energy level line when it is supposed to
            //   match the line, we need to subtract 1 from the length of the squiggle
            var actualLength = length - 1;

            graphics.clear();
            graphics.lineStyle(1, color, alpha);

            // Draw squiggle
            var phaseAngle = 0;
            var freqFactor = 15 * wavelength / 680;

            for (var i = 0; i <= actualLength - arrowHeight * 2; i++) {
                var k = Math.floor(Math.sin(phaseAngle + i * Math.PI * 2 / freqFactor) * amp / 2 + amp / 2);
                for (var j = 0; j < amp; j++) {
                    if (j === k) {
                        if (i === 0)
                            graphics.moveTo(i + arrowHeight, k);
                        else
                            graphics.lineTo(i + arrowHeight, k);
                    }
                }
            }

            // Draw arrows
            graphics.lineStyle(0, 0, 0);
            graphics.beginFill(color, alpha);

            var tailWidth = 2;
            var headWidth = amp * 1.2;
            graphics.drawArrow(arrowHeight, amp / 2, 0, amp / 2, tailWidth, headWidth, arrowHeight);
            graphics.drawArrow(actualLength - arrowHeight, amp / 2, actualLength, amp / 2, tailWidth, headWidth, arrowHeight);

            graphics.endFill();
        },

        createEnergyLevels: function() {
            // Remove old ones
            for (var j = this.energyLevelViews.length - 1; j >= 0; j--) {
                this.energyLevelViews[j].remove();
                this.energyLevelViews.splice(j, 1);
            }

            var x = this.axisOriginX + 10;
            var width = this.width - x - this.padding;
            var groundStateEnergy = this.simulation.getGroundState().getEnergyLevel();

            var states = this.simulation.getStates();
            for (var i = 0; i < states.length; i++) {
                var energyLevelView = new EnergyLevelView({
                    simulation: this.simulation,
                    model: states[i],
                    energyToY: this.energyToY,
                    minY: this.minY,
                    maxY: this.maxY,
                    groundStateEnergy: groundStateEnergy,
                    width: width,
                    levelNumber: i + 1,
                    wavelengthChangeEnabled: (i > 0),
                    lifetimeChangeEnabled: (i > 0)
                });
                energyLevelView.displayObject.x = x;

                this.energyLevelViews.push(energyLevelView);
                this.energyLevelsLayer.addChild(energyLevelView.displayObject);
            }
        },

        energyLevelsChanged: function() {
            this.createEnergyLevels();
        },

        beamChanged: function(model, wavelength) {
            if (model === this.simulation.seedBeam)
                this.drawSquiggle(this.seedSquiggle, model);
            else
                this.drawSquiggle(this.pumpSquiggle, model);
        }

    }, Constants.EnergyLevelPanelView);

    return EnergyLevelPanelView;
});<commit_msg>Squiggles are shown and hidden along with the lamps<commit_after>define(function(require) {

    'use strict';

    var _    = require('underscore');
    var PIXI = require('pixi');

                           require('common/v3/pixi/create-drop-shadow');
                           require('common/v3/pixi/draw-stick-arrow');
                           require('common/v3/pixi/draw-arrow');
    var AppView          = require('common/v3/app/app');
    var PixiView         = require('common/v3/pixi/view');
    var Colors           = require('common/colors/colors');
    var WavelengthColors = require('common/colors/wavelength');
    var Rectangle        = require('common/math/rectangle');
    var Functions        = require('common/math/functions');
    var PhysicsUtil      = require('common/quantum/models/physics-util');

    var EnergyLevelView = require('views/energy-level');

    var Constants = require('constants');
    var Assets    = require('assets');

    /**
     *
     */
    var EnergyLevelPanelView = PixiView.extend({

        width: 300,
        height: 200,

        /**
         * Initializes the new EnergyLevelPanelView.
         */
        initialize: function(options) {
            options = _.extend({
                padding: 15,
                bgColor: '#f5f5f5',
                bgAlpha: 0.75,
                axisLineColor: '#000',
                axisLineAlpha: 1
            }, options);

            // Required options
            this.simulation = options.simulation;

            // Optional options
            this.padding = options.padding;
            this.bgColor = Colors.parseHex(options.bgColor);
            this.bgAlpha = options.bgAlpha;
            this.axisLineColor = Colors.parseHex(options.axisLineColor);
            this.axisLineAlpha = options.axisLineAlpha;

            this.energyLevelViews = [];

            // Init graph parameters
            this.minY = this.padding + 16;
            this.maxY = this.height - this.padding - 10;
            this.atomDiameter = 10;
            this.squiggleAmplitude = this.atomDiameter; // Amplitude of the squiggle waves

            var groundStateEnergy = this.simulation.getGroundState().getEnergyLevel();
            this.energyToY = Functions.createLinearFunction(
                groundStateEnergy + PhysicsUtil.wavelengthToEnergy(WavelengthColors.MIN_WAVELENGTH),
                groundStateEnergy,
                this.minY,
                this.maxY
            );

            // Initialize the graphics
            this.initGraphics();

            this.listenTo(this.simulation, 'atomic-states-changed', this.energyLevelsChanged);
            this.listenTo(this.simulation.seedBeam,    'change:wavelength change:photonsPerSecond', this.beamChanged);
            this.listenTo(this.simulation.pumpingBeam, 'change:wavelength change:photonsPerSecond', this.beamChanged);
            this.listenTo(this.simulation.seedBeam,    'change:enabled', this.seedBeamEnabledChanged);
            this.listenTo(this.simulation.pumpingBeam, 'change:enabled', this.pumpingBeamEnabledChanged);
        },

        /**
         * Initializes everything for rendering graphics
         */
        initGraphics: function() {
            this.initPanel();
            this.initAxis();
            this.initSquiggles();
            this.drawSquiggles();

            this.energyLevelsLayer = new PIXI.Container();
            this.displayObject.addChild(this.energyLevelsLayer);

            this.createEnergyLevels();
        },

        initPanel: function() {
            // Draw the shadow
            var rectangle = new Rectangle(0, 0, this.width, this.height);
            var shadow = PIXI.createDropShadow(rectangle);
            this.displayObject.addChild(shadow);

            // Draw the panel
            var graphics = new PIXI.Graphics();
            graphics.beginFill(this.bgColor, this.bgAlpha);
            graphics.drawRect(0, 0, this.width, this.height);
            graphics.endFill();

            this.displayObject.addChild(graphics);
        },

        initAxis: function() {
            var labelWidth = 15;
            var x = this.padding + labelWidth;
            var y0 = this.height - this.padding;
            var y1 = this.padding;
            var graphics = new PIXI.Graphics();
            graphics.lineStyle(2, this.axisLineColor, this.axisLineAlpha);
            graphics.drawStickArrow(x, y0, x, y1, 12, 10);

            var text = new PIXI.Text('Energy (eV)', {
                font: 'bold 12px Helvetica Neue',
                fill: '#000'
            });
            text.resolution = this.getResolution();
            text.rotation = -Math.PI / 2;
            text.anchor.y = 0;
            text.anchor.x = 0.5;
            text.x = this.padding - 5;
            text.y = this.height / 2;

            this.displayObject.addChild(graphics);
            this.displayObject.addChild(text);

            this.axisOriginX = x;
        },

        initSquiggles: function() {
            this.seedSquiggle = new PIXI.Graphics();
            this.pumpSquiggle = new PIXI.Graphics();

            this.seedSquiggle.x = this.axisOriginX + this.squiggleAmplitude;
            this.pumpSquiggle.x = this.axisOriginX + this.squiggleAmplitude * 3;
            this.seedSquiggle.y = this.maxY;
            this.pumpSquiggle.y = this.maxY;
            this.seedSquiggle.rotation = -Math.PI / 2;
            this.pumpSquiggle.rotation = -Math.PI / 2;

            this.displayObject.addChild(this.seedSquiggle);
            this.displayObject.addChild(this.pumpSquiggle);

            this.seedBeamEnabledChanged(null, this.simulation.seedBeam.get('enabled'));
            this.pumpingBeamEnabledChanged(null, this.simulation.pumpingBeam.get('enabled'));
        },

        drawSquiggles: function() {
            this.drawSquiggle(this.seedSquiggle, this.simulation.seedBeam);
            this.drawSquiggle(this.pumpSquiggle, this.simulation.pumpingBeam);
        },

        drawSquiggle: function(graphics, beam) {
            // Calculate all our rendering variables
            var wavelength = beam.get('wavelength')
            var color = Colors.parseHex(WavelengthColors.nmToHex(wavelength));
            var beamEnergy = PhysicsUtil.wavelengthToEnergy(wavelength);
            var groundStateEnergy = this.simulation.getGroundState().getEnergyLevel();
            var y0 = this.energyToY(groundStateEnergy);
            var y1 = this.energyToY(groundStateEnergy + beamEnergy);
            var length = y0 - y1;
            var amp = this.squiggleAmplitude;
            var intensity = beam.get('photonsPerSecond') / beam.get('maxPhotonsPerSecond');
            var alpha = Math.sqrt(intensity);
            var arrowHeight = amp;
            // So that the tip of the arrow will just touch an energy level line when it is supposed to
            //   match the line, we need to subtract 1 from the length of the squiggle
            var actualLength = length - 1;

            graphics.clear();
            graphics.lineStyle(1, color, alpha);

            // Draw squiggle
            var phaseAngle = 0;
            var freqFactor = 15 * wavelength / 680;

            for (var i = 0; i <= actualLength - arrowHeight * 2; i++) {
                var k = Math.floor(Math.sin(phaseAngle + i * Math.PI * 2 / freqFactor) * amp / 2 + amp / 2);
                for (var j = 0; j < amp; j++) {
                    if (j === k) {
                        if (i === 0)
                            graphics.moveTo(i + arrowHeight, k);
                        else
                            graphics.lineTo(i + arrowHeight, k);
                    }
                }
            }

            // Draw arrows
            graphics.lineStyle(0, 0, 0);
            graphics.beginFill(color, alpha);

            var tailWidth = 2;
            var headWidth = amp * 1.2;
            graphics.drawArrow(arrowHeight, amp / 2, 0, amp / 2, tailWidth, headWidth, arrowHeight);
            graphics.drawArrow(actualLength - arrowHeight, amp / 2, actualLength, amp / 2, tailWidth, headWidth, arrowHeight);

            graphics.endFill();
        },

        createEnergyLevels: function() {
            // Remove old ones
            for (var j = this.energyLevelViews.length - 1; j >= 0; j--) {
                this.energyLevelViews[j].remove();
                this.energyLevelViews.splice(j, 1);
            }

            var x = this.axisOriginX + 10;
            var width = this.width - x - this.padding;
            var groundStateEnergy = this.simulation.getGroundState().getEnergyLevel();

            var states = this.simulation.getStates();
            for (var i = 0; i < states.length; i++) {
                var energyLevelView = new EnergyLevelView({
                    simulation: this.simulation,
                    model: states[i],
                    energyToY: this.energyToY,
                    minY: this.minY,
                    maxY: this.maxY,
                    groundStateEnergy: groundStateEnergy,
                    width: width,
                    levelNumber: i + 1,
                    wavelengthChangeEnabled: (i > 0),
                    lifetimeChangeEnabled: (i > 0)
                });
                energyLevelView.displayObject.x = x;

                this.energyLevelViews.push(energyLevelView);
                this.energyLevelsLayer.addChild(energyLevelView.displayObject);
            }
        },

        energyLevelsChanged: function() {
            this.createEnergyLevels();
        },

        beamChanged: function(model, wavelength) {
            if (model === this.simulation.seedBeam)
                this.drawSquiggle(this.seedSquiggle, model);
            else
                this.drawSquiggle(this.pumpSquiggle, model);
        },

        seedBeamEnabledChanged: function(model, enabled) {
            this.seedSquiggle.visible = enabled;
        },

        pumpingBeamEnabledChanged: function(model, enabled) {
            this.pumpSquiggle.visible = enabled;
        }

    }, Constants.EnergyLevelPanelView);

    return EnergyLevelPanelView;
});<|endoftext|>


<commit_before>#!/usr/bin/env node
// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

// require('format-stack').set({
//   traces: 'short' // 'long' works too, maybe.. ;)
// });

/*global process */

// Usage: node bin/adhoc_multi.js <relay_count> <serviceName> <port>
// Creates relay_count services on localhost, connected to Autobahn on
// localhost. The services call each other to do echo.

var os = require('os');
var console = require('console');
var fs = require('fs');
var CountedReadySignal = require('ready-signal/counted');

var TChannel = require('../');
var AutobahnClient = require('../hyperbahn/');
var DebugLogger = require('debug-logtron');

if (require.main === module) {
    main();
}

var EP_NAME;

function main() {
    if (process.argv[2] === '-h' || process.argv[2] === '--help') {
        console.log('adhoc_multi [relay_count] [serviceName] [port]');
        return;
    }

    /*eslint no-console: 0*/
    var rcount = Math.abs(process.argv[2] || 1);
    var opts = {};
    opts.listenReady = CountedReadySignal(rcount);
    opts.registerReady = CountedReadySignal(rcount);
    opts.serviceName = process.argv[3] || 'service';
    opts.port = +process.argv[4] || 6000;
    opts.host = getHost();
    opts.autobahnList = getAutobahnHost();
    opts.logger = DebugLogger('adhocMulti');
    EP_NAME = 'echo';
    start(opts, rcount);
}

function start(opts, rcount) {
    var clients = [];
    for (var i = 0; i < rcount; i++) {
        opts.i = i;
        if (i === rcount - 1) {
            opts.isLast = true;
        }
        clients.push(createClient(opts));
    }

    opts.listenReady(function onListen() {
        console.log('All channel listen started.');
        for (i = 0; i < rcount; i++) {
            register(opts, clients[i]);
        }
    });

    opts.registerReady(function onRegister() {
        console.log('All clients registered.');
        var chan = createChannel(opts);
        var service = opts.serviceName + '_0';
        chan.makeSubChannel({
            serviceName: service,
            peers: opts.autobahnList
        }).request({
            headers: {
                cn: opts.serviceName,
                as: 'raw'
            },
            hasNoParent: true,
            serviceName: service
        }).send(
            EP_NAME + '_0',
            'aa2',
            'hello',
            function onRes(err, res) {
                if (err) {
                    console.log(err);
                } else {
                    console.log(String(res.arg3));
                }
            }
        );
    });
}

function createChannel(options) {
    var tchannel = new TChannel({
        trace: true,
        logger: options.logger
    });

    return tchannel;
}

function createClient(options) {
    var tchannel = createChannel(options);
    var onResponse = options.isLast ? finish : forwardChannel;
    var count = options.i;

    console.log('registering ' + enumerated(EP_NAME));
    tchannel.makeSubChannel({
        serviceName: enumerated(options.serviceName)
    }).register(enumerated(EP_NAME), onResponse);

    var autobahnClient = new AutobahnClient({
        tchannel: tchannel,
        serviceName: enumerated(options.serviceName),
        callerName: enumerated(options.serviceName, count - 1),
        hostPortList: options.autobahnList,
        forwardRetries: 5,
        checkForwardListInterval: 60000,
        registrationTimeout: 5000,
        logger: options.logger
    });

    console.log('Starting to listen service',
        options.serviceName, 'port', options.port + count);
    tchannel.listen(options.port + count, options.host, onListen);
    return {
        channel: tchannel,
        client: autobahnClient
    };

    function onListen(err) {
        if (err) {
            throw err;
        }

        console.log('listening', tchannel.address());
        options.listenReady.signal();
    }

    function enumerated(name, index) {
        index = index || count;
        return name + '_' + index;
    }

    function forwardChannel(req, res, arg2, arg3) {
        var fchan = createChannel(options);
        var service = enumerated(options.serviceName, count + 1);

        fchan.makeSubChannel({
            serviceName: service,
            peers: options.autobahnList
        }).request({
            headers: {
                cn: enumerated(options.serviceName, count),
                as: 'raw'
            },
            serviceName: service,
            parent: req
        }).send(
            enumerated(EP_NAME, count + 1),
            arg2,
            arg3,
            function onRet(e, r) {
                if (e) {
                    console.log(e);
                } else {
                    res.headers.as = 'raw';
                    res.sendOk(
                        r.arg2,
                        enumerated(options.serviceName)
                        + ' says "' + String(r.arg3)
                        + '"'
                    );
                }
            }
        );
    }

    function finish(req, res, arg2, arg3) {
        res.headers.as = 'raw';
        res.sendOk(
            arg2,
            enumerated(options.serviceName) + ' says "' + String(arg3) + '"');
    }
}

function register(options, pair) {
    var autobahnClient = pair.client;
    console.log('Registering at Hyperbahn', autobahnClient.hostPortList[0]);

    autobahnClient.on('registered', onRegister);
    autobahnClient.register();
    function onRegister(err2) {
        if (err2) {
            throw err2;
        }
        console.log('Registered at Hyperbahn', autobahnClient.hostPortList[0]);
        options.registerReady.signal();
    }
}

function getAutobahnHost() {
    try {
        var hostPortListString =
        fs.readFileSync('/etc/uber/autobahn/ringpop-v2.json', 'utf8');
        return JSON.parse(hostPortListString);
    } catch (err) {
        if (err.code !== 'ENOENT') {
            throw err;
        }
        var host = getHost();
        return [host + ':21300', host + ':21301'];
    }
}

function getHost() {
    var ifaces = os.networkInterfaces();
    var ifaceNames = Object.keys(ifaces);
    for (var index = 0; index < ifaceNames.length; index++) {
        var ifaceName = ifaceNames[index];
        var ports = ifaces[ifaceName];
        for (var portIndex = 0; portIndex < ports.length; portIndex++) {
            var port = ports[portIndex];
            if (!port.internal && port.family === 'IPv4') {
                return port.address;
            }
        }
    }
}
<commit_msg>bin/adhoc-multi: fix the linter<commit_after>#!/usr/bin/env node
// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

// require('format-stack').set({
//   traces: 'short' // 'long' works too, maybe.. ;)
// });

/*global process */

// Usage: node bin/adhoc_multi.js <relay_count> <serviceName> <port>
// Creates relay_count services on localhost, connected to Autobahn on
// localhost. The services call each other to do echo.

var os = require('os');
var console = require('console');
var fs = require('fs');
var CountedReadySignal = require('ready-signal/counted');

var TChannel = require('../');
var AutobahnClient = require('../hyperbahn/');
var DebugLogger = require('debug-logtron');

if (require.main === module) {
    main();
}

var EP_NAME;

function main() {
    if (process.argv[2] === '-h' || process.argv[2] === '--help') {
        console.log('adhoc_multi [relay_count] [serviceName] [port]');
        return;
    }

    /*eslint no-console: 0*/
    var rcount = Math.abs(process.argv[2] || 1);
    var opts = {};
    opts.listenReady = CountedReadySignal(rcount);
    opts.registerReady = CountedReadySignal(rcount);
    opts.serviceName = process.argv[3] || 'service';
    opts.port = +process.argv[4] || 6000;
    opts.host = getHost();
    opts.autobahnList = getAutobahnHost();
    opts.logger = DebugLogger('adhocMulti');
    EP_NAME = 'echo';
    start(opts, rcount);
}

function start(opts, rcount) {
    var clients = [];
    for (var i = 0; i < rcount; i++) {
        opts.i = i;
        if (i === rcount - 1) {
            opts.isLast = true;
        }
        clients.push(createClient(opts));
    }

    opts.listenReady(function onListen() {
        console.log('All channel listen started.');
        for (i = 0; i < rcount; i++) {
            register(opts, clients[i]);
        }
    });

    opts.registerReady(function onRegister() {
        console.log('All clients registered.');
        var chan = createChannel(opts);
        var service = opts.serviceName + '_0';
        chan.makeSubChannel({
            serviceName: service,
            peers: opts.autobahnList
        }).request({
            headers: {
                cn: opts.serviceName,
                as: 'raw'
            },
            hasNoParent: true,
            serviceName: service
        }).send(
            EP_NAME + '_0',
            'aa2',
            'hello',
            function onRes(err, res) {
                if (err) {
                    console.log(err);
                } else {
                    console.log(String(res.arg3));
                }
            }
        );
    });
}

function createChannel(options) {
    var tchannel = new TChannel({
        trace: true,
        logger: options.logger
    });

    return tchannel;
}

function createClient(options) {
    var tchannel = createChannel(options);
    var onResponse = options.isLast ? finish : forwardChannel;
    var count = options.i;

    console.log('registering ' + enumerated(EP_NAME));
    tchannel.makeSubChannel({
        serviceName: enumerated(options.serviceName)
    }).register(enumerated(EP_NAME), onResponse);

    var autobahnClient = new AutobahnClient({
        tchannel: tchannel,
        serviceName: enumerated(options.serviceName),
        callerName: enumerated(options.serviceName, count - 1),
        hostPortList: options.autobahnList,
        forwardRetries: 5,
        checkForwardListInterval: 60000,
        registrationTimeout: 5000,
        logger: options.logger
    });

    console.log('Starting to listen service',
        options.serviceName, 'port', options.port + count);
    tchannel.listen(options.port + count, options.host, onListen);
    return {
        channel: tchannel,
        client: autobahnClient
    };

    function onListen(err) {
        if (err) {
            throw err;
        }

        console.log('listening', tchannel.address());
        options.listenReady.signal();
    }

    function enumerated(name, index) {
        index = index || count;
        return name + '_' + index;
    }

    function forwardChannel(req, res, arg2, arg3) {
        var fchan = createChannel(options);
        var service = enumerated(options.serviceName, count + 1);

        fchan.makeSubChannel({
            serviceName: service,
            peers: options.autobahnList
        }).request({
            headers: {
                cn: enumerated(options.serviceName, count),
                as: 'raw'
            },
            serviceName: service,
            parent: req
        }).send(
            enumerated(EP_NAME, count + 1),
            arg2,
            arg3,
            function onRet(e, r) {
                if (e) {
                    console.log(e);
                } else {
                    res.headers.as = 'raw';
                    res.sendOk(
                        r.arg2,
                        enumerated(options.serviceName) +
                            ' says "' + String(r.arg3) + '"'
                    );
                }
            }
        );
    }

    function finish(req, res, arg2, arg3) {
        res.headers.as = 'raw';
        res.sendOk(
            arg2,
            enumerated(options.serviceName) + ' says "' + String(arg3) + '"');
    }
}

function register(options, pair) {
    var autobahnClient = pair.client;
    console.log('Registering at Hyperbahn', autobahnClient.hostPortList[0]);

    autobahnClient.on('registered', onRegister);
    autobahnClient.register();
    function onRegister(err2) {
        if (err2) {
            throw err2;
        }
        console.log('Registered at Hyperbahn', autobahnClient.hostPortList[0]);
        options.registerReady.signal();
    }
}

function getAutobahnHost() {
    try {
        var hostPortListString =
        fs.readFileSync('/etc/uber/autobahn/ringpop-v2.json', 'utf8');
        return JSON.parse(hostPortListString);
    } catch (err) {
        if (err.code !== 'ENOENT') {
            throw err;
        }
        var host = getHost();
        return [host + ':21300', host + ':21301'];
    }
}

function getHost() {
    var ifaces = os.networkInterfaces();
    var ifaceNames = Object.keys(ifaces);
    for (var index = 0; index < ifaceNames.length; index++) {
        var ifaceName = ifaceNames[index];
        var ports = ifaces[ifaceName];
        for (var portIndex = 0; portIndex < ports.length; portIndex++) {
            var port = ports[portIndex];
            if (!port.internal && port.family === 'IPv4') {
                return port.address;
            }
        }
    }
}
<|endoftext|>