<commit_before>/** @babel */
/** @jsx etch.dom */

import etch from 'etch'
const $ = etch.dom
import GeneratorPaneSectionView from './generator-pane-section-view'
import ValueInputView from './value-input-view'
import TextOnCore from './texton-core'

export default class GeneratorPaneView {
  constructor (props) {
    this.collapsedSections = props.collapsedSections ? new Set(props.collapsedSections) : new Set();
    this.inputs = [];
    this.sections = [];
    this.attributes = [];
    this.variables = [];
    this.output = [];
    this.props = props;
    etch.initialize(this);
    for (const section of this.sections) {
      if (this.collapsedSections.has(section.name)) {
        section.collapse();
      } else {
        section.expand();
      }
    }
  }

  destroy () {
    for (const input of this.inputs) {
      input.destroy();
    }
    for (const section of this.sections) {
      section.destroy();
    }
    this.inputs = null;
    this.sections = null;
  }

  serialize () {
    return {
      deserializer: this.constructor.name,
      collapsedSections: this.sections.filter((s) => s.collapsed).map((s) => s.name)
    }
  }

  update (props) {
    if (props.hasOwnProperty('attributes')) {
      this.props.attributes = props.attributes
    }
    if (props.hasOwnProperty('variables')) {
      this.props.variables = props.variables
    }
    if (props.hasOwnProperty('functionName')) {
      this.props.functionName = props.functionName
    }
    if (props.hasOwnProperty('fileName')) {
      this.props.fileName = props.fileName
    }
    if (props.hasOwnProperty('canGenerate')) {
      this.props.canGenerate = props.canGenerate
    }
    if (props.hasOwnProperty('output')) {
      this.props.output = props.output
    }
    this.attributes = this.props.attributes.map((item) => {
      return item;
    });
    this.variables = this.props.variables.map((item) => {
      return item;
    });
    this.output = this.props.output.map((item) => {
      return item;
    });
    return etch.update(this)
  }

  getTitle () {
    return 'TextOn Generator';
  }

  didInitializeSection (section) {
    this.sections.push(section);
  }

  didInitializeInput (input) {
    this.inputs.push(input);
  }

  didConfirmSelection (type, name, value) {
    this.props.onDidConfirmSelection (type, name, value)
  }

  isEqual (other) {
    return other instanceof GeneratorPaneView;
  }

  renderAttributes () {
    return $.div(
      {},
      ...this.attributes.map((att, index) => $(ValueInputView, {
            ref: 'attributes',
            type: 'Attribute',
            name: att.name,
            value: att.value,
            text: att.text,
            className: 'texton-sections-settable padded',
            permitsFreeValue: false,
            items: att.items,
            onDidInitialize: this.didInitializeInput.bind(this),
            onDidConfirmSelection: this.didConfirmSelection.bind(this),
            onDidClickLink: this.didClickAttributeLink.bind(this)
        })));
  }

  renderVariables () {
    return $.div(
      {},
      ...this.variables.map((att, index) => $(ValueInputView, {
            ref: 'variables',
            type: 'Variable',
            name: att.name,
            value: att.value,
            text: att.text,
            className: 'texton-sections-settable padded',
            permitsFreeValue: att.permitsFreeValue,
            items: att.items,
            onDidInitialize: this.didInitializeInput.bind(this),
            onDidConfirmSelection: this.didConfirmSelection.bind(this),
            onDidClickLink: this.didClickVariableLink.bind(this)
        })));
  }

  renderOutput () {
    return $.div(
      {
        className: 'texton-sections-output padded'
      },
      ...this.output.map((item, index) =>
        (item.IsParagraphBreak) ?
          $.br()
          : $.a(
              {
                onClick: () => this.didClickOutputLink(index)
              },
              item.Value
            )
        )
    );
  }

  didClickOutputLink(index) {
    if (this.props.output.length > index) {
      this.props.onDidClickSimpleLink(this.props.output[index])
    }
  }

  didClickCopyToClipboard() {
    atom.clipboard.write(this.props.output.map((item) => item.Value).join(''));
  }

  didClickGenerate() {
    this.props.onDidClickGenerate();
  }

  renderGenerator () {
    if (this.props.canGenerate) {
      if (this.props.output.length === 0) {
        return (

            <button class='btn btn' onClick={this.didClickGenerate.bind(this)}>Generate</button>

        );
      } else {
        return (

            <button class='btn btn' onClick={this.didClickGenerate.bind(this)}>Generate</button>
            {this.renderOutput()}
            <button class='btn' onClick={this.didClickCopyToClipboard.bind(this)}>Copy to clipboard</button>

        );
      }
    } else {
      return (

Nothing to generate.

      )
    }
  }

  didClickFunctionLink () {
    this.props.onDidClickSmartLink ('Function', this.props.fileName, this.props.functionName)
    return false
  }

  didClickVariableLink (variableName) {
    this.props.onDidClickSmartLink ('Variable', this.props.fileName, variableName)
    return false
  }

  didClickAttributeLink (attributeName) {
    this.props.onDidClickSmartLink ('Attribute', this.props.fileName, attributeName)
    return false
  }

  render () {
    return (

TextOn Generator for {this.props.functionName}

          <GeneratorPaneSectionView onDidInitialize={this.didInitializeSection.bind(this)} name='attributes' title='Attributes'>
            {this.renderAttributes()}
          </GeneratorPaneSectionView>
          <GeneratorPaneSectionView onDidInitialize={this.didInitializeSection.bind(this)} name='variables' title='Variables'>
            {this.renderVariables()}
          </GeneratorPaneSectionView>
          <GeneratorPaneSectionView onDidInitialize={this.didInitializeSection.bind(this)} name='generator' title='Generator'>
            {this.renderGenerator()}
          </GeneratorPaneSectionView>

    )
  }
}
<commit_msg>Not sure I can be bothered to serialize this<commit_after>/** @babel */
/** @jsx etch.dom */

import etch from 'etch'
const $ = etch.dom
import GeneratorPaneSectionView from './generator-pane-section-view'
import ValueInputView from './value-input-view'
import TextOnCore from './texton-core'

export default class GeneratorPaneView {
  constructor (props) {
    this.collapsedSections = props.collapsedSections ? new Set(props.collapsedSections) : new Set();
    this.inputs = [];
    this.sections = [];
    this.attributes = [];
    this.variables = [];
    this.output = [];
    this.props = props;
    etch.initialize(this);
    for (const section of this.sections) {
      if (this.collapsedSections.has(section.name)) {
        section.collapse();
      } else {
        section.expand();
      }
    }
  }

  destroy () {
    for (const input of this.inputs) {
      input.destroy();
    }
    for (const section of this.sections) {
      section.destroy();
    }
    this.inputs = null;
    this.sections = null;
  }

  update (props) {
    if (props.hasOwnProperty('attributes')) {
      this.props.attributes = props.attributes
    }
    if (props.hasOwnProperty('variables')) {
      this.props.variables = props.variables
    }
    if (props.hasOwnProperty('functionName')) {
      this.props.functionName = props.functionName
    }
    if (props.hasOwnProperty('fileName')) {
      this.props.fileName = props.fileName
    }
    if (props.hasOwnProperty('canGenerate')) {
      this.props.canGenerate = props.canGenerate
    }
    if (props.hasOwnProperty('output')) {
      this.props.output = props.output
    }
    this.attributes = this.props.attributes.map((item) => {
      return item;
    });
    this.variables = this.props.variables.map((item) => {
      return item;
    });
    this.output = this.props.output.map((item) => {
      return item;
    });
    return etch.update(this)
  }

  getTitle () {
    return 'TextOn Generator';
  }

  didInitializeSection (section) {
    this.sections.push(section);
  }

  didInitializeInput (input) {
    this.inputs.push(input);
  }

  didConfirmSelection (type, name, value) {
    this.props.onDidConfirmSelection (type, name, value)
  }

  isEqual (other) {
    return other instanceof GeneratorPaneView;
  }

  renderAttributes () {
    return $.div(
      {},
      ...this.attributes.map((att, index) => $(ValueInputView, {
            ref: 'attributes',
            type: 'Attribute',
            name: att.name,
            value: att.value,
            text: att.text,
            className: 'texton-sections-settable padded',
            permitsFreeValue: false,
            items: att.items,
            onDidInitialize: this.didInitializeInput.bind(this),
            onDidConfirmSelection: this.didConfirmSelection.bind(this),
            onDidClickLink: this.didClickAttributeLink.bind(this)
        })));
  }

  renderVariables () {
    return $.div(
      {},
      ...this.variables.map((att, index) => $(ValueInputView, {
            ref: 'variables',
            type: 'Variable',
            name: att.name,
            value: att.value,
            text: att.text,
            className: 'texton-sections-settable padded',
            permitsFreeValue: att.permitsFreeValue,
            items: att.items,
            onDidInitialize: this.didInitializeInput.bind(this),
            onDidConfirmSelection: this.didConfirmSelection.bind(this),
            onDidClickLink: this.didClickVariableLink.bind(this)
        })));
  }

  renderOutput () {
    return $.div(
      {
        className: 'texton-sections-output padded'
      },
      ...this.output.map((item, index) =>
        (item.IsParagraphBreak) ?
          $.br()
          : $.a(
              {
                onClick: () => this.didClickOutputLink(index)
              },
              item.Value
            )
        )
    );
  }

  didClickOutputLink(index) {
    if (this.props.output.length > index) {
      this.props.onDidClickSimpleLink(this.props.output[index])
    }
  }

  didClickCopyToClipboard() {
    atom.clipboard.write(this.props.output.map((item) => item.Value).join(''));
  }

  didClickGenerate() {
    this.props.onDidClickGenerate();
  }

  renderGenerator () {
    if (this.props.canGenerate) {
      if (this.props.output.length === 0) {
        return (

            <button class='btn btn' onClick={this.didClickGenerate.bind(this)}>Generate</button>

        );
      } else {
        return (

            <button class='btn btn' onClick={this.didClickGenerate.bind(this)}>Generate</button>
            {this.renderOutput()}
            <button class='btn' onClick={this.didClickCopyToClipboard.bind(this)}>Copy to clipboard</button>

        );
      }
    } else {
      return (

Nothing to generate.

      )
    }
  }

  didClickFunctionLink () {
    this.props.onDidClickSmartLink ('Function', this.props.fileName, this.props.functionName)
    return false
  }

  didClickVariableLink (variableName) {
    this.props.onDidClickSmartLink ('Variable', this.props.fileName, variableName)
    return false
  }

  didClickAttributeLink (attributeName) {
    this.props.onDidClickSmartLink ('Attribute', this.props.fileName, attributeName)
    return false
  }

  render () {
    return (

TextOn Generator for {this.props.functionName}

          <GeneratorPaneSectionView onDidInitialize={this.didInitializeSection.bind(this)} name='attributes' title='Attributes'>
            {this.renderAttributes()}
          </GeneratorPaneSectionView>
          <GeneratorPaneSectionView onDidInitialize={this.didInitializeSection.bind(this)} name='variables' title='Variables'>
            {this.renderVariables()}
          </GeneratorPaneSectionView>
          <GeneratorPaneSectionView onDidInitialize={this.didInitializeSection.bind(this)} name='generator' title='Generator'>
            {this.renderGenerator()}
          </GeneratorPaneSectionView>

    )
  }
}
<|endoftext|>


<commit_before>var Dominion = (function () {
  "use strict";

  var Cards = (function () {
    /**
     * IMPORTANT
     *
     * `play` and `end` will be called with
     * `apply` against the Player object
     */
    var Cards =  {
      "Copper": {
        name: "Copper",
        type: "Treasure",
        cost: 0,
        play: function () {
          this.addCoins(1);
        }
      },
      "Silver": {
        name: "Silver",
        type: "Treasure",
        cost: 3,
        play: function () {
          this.addCoins(2);
        }
      },
      "Gold": {
        name: "Gold",
        type: "Treasure",
        cost: 6,
        play: function () {
          this.addCoins(3);
        }
      },
      "Estate": {
        name: "Estate",
        type: "Victory",
        cost: 2,
        end:  function () {
          this.add_victory(1);
        }
      },
      "Duchy": {
        name: "Duchy",
        type: "Victory",
        cost: 5,
        end:  function () {
          this.add_victory(3);
        }
      },
      "Province": {
        name: "Province",
        type: "Victory",
        cost: 8,
        end:  function () {
          this.add_victory(6);
        }
      },
      "Curse": {
        name: "Curse",
        type: "Curse",
        cost: 0,
        end:  function () {
          this.add_victory(-1);
        }
      },
      "Cellar": {
        name: "Cellar",
        type: "Action",
        cost: 2,
        play: function () {
          this.add_actions(1);
          this.discard_any_cards();
          this.replace_discarded_cards();
        }
      },
      "Chapel":  {
        name: "Chapel",
        type: "Action",
        cost: 2,
        play: function () {
          this.trash_up_to(4);
        }
      },
      "Moat": {
        name:   "Moat",
        type:   "Action - Reaction",
        cost:   2,
        immune: true,
        play:   function () {
          this.draw_cards(2);
        }
      },
      "Chancellor": {
        name: "Chancellor",
        type: "Action",
        cost: 3,
        play: function () {
          this.add_coins(2);
          this.discard_deck();
        }
      },
      "Village": {
        name: "Village",
        type: "Action",
        cost: 3,
        play: function () {
          this.draw_cards(1);
          this.add_actions(2);
        }
      },
      "Woodcutter": {
        name: "Woodcutter",
        type: "Action",
        cost: 3,
        play: function () {
          this.add_buys(1);
          this.add_coins(2);
        }
      },
      "Workshop": {
        name: "Workshop",
        type: "Action",
        cost: 3,
        play: function () {
          this.gain_card_costing_up_to(4);
        }
      },
      "Bureaucrat": {
        name: "Bureaucrat",
        type: "Action - Attack",
        cost: 4,
        play: function () {
          this.bureaucrat();
        }
      },
      "Feast": {
        name: "Feast",
        type: "Action",
        cost: 4,
        play: function () {
          this.trash_this_card();
          this.gain_card_costing_up_to(5);
        }
      },
      "Gardens": {
        name: "Gardens",
        type: "Victory",
        cost: 4,
        end:  function () {
          this.gardens();
        }
      },
      "Militia": {
        name: "Militia",
        type: "Action - Attack",
        cost: 4,
        play: function () {
          this.add_coins(2);
          this.other_players_discard_down_to(3);
        }
      },
      "Moneylender": {
        name: "Moneylender",
        type: "Action",
        cost: 4,
        play: function () {
          this.trash_copper_for_coins(3);
        }
      },
      "Remodel": {
        name: "Remodel",
        type: "Action",
        cost: 4,
        play: function () {
          this.trash_card_for_card_costing_more(3);
        }
      },
      "Smithy": {
        name: "Smithy",
        type: "Action",
        cost: 4,
        play: function () {
          this.draw_cards(3);
        }
      },
      "Spy": {
        name: "Spy",
        type: "Action - Attack",
        cost: 4,
        play: function () {
          this.spy();
        }
      },
      "Thief": {
        name: "Thief",
        type: "Action - Attack",
        cost: 4,
        play: function () {
          this.thief();
        }
      },
      "ThroneRoom": {
        name: "ThroneRoom",
        type: "Action",
        cost: 4,
        play: function () {
          this.chose_card_play_it_twice();
        }
      },
      "CouncilRoom": {
        name: "CouncilRoom",
        type: "Action",
        cost: 5,
        play: function () {
          this.draw_cards(4);
          this.buy_points(1);
          this.other_players_draw_cards(1);
        }
      },
      "Festival": {
        name: "Festival",
        type: "Action",
        cost: 5,
        play: function () {
          this.add_actions(2);
          this.add_buys(1);
          this.add_coins(2);
        }
      },
      "Laboratory": {
        name: "Laboratory",
        type: "Action",
        cost: 5,
        play: function () {
          this.draw_cards(2);
          this.add_actions(1);
        }
      },
      "Library": {
        name: "Library",
        type: "Action",
        cost: 5,
        play: function () {
          this.library();
        }
      },
      "Market": {
        name: "Market",
        type: "Action",
        cost: 5,
        play: function () {
          this.draw_cards(1);
          this.add_actions(1);
          this.add_buys(1);
          this.add_coins(1);
        }
      },
      "Mine": {
        name: "Mine",
        type: "Action",
        cost: 5,
        play: function () {
          this.mine();
        }
      },
      "Witch": {
        name: "Witch",
        type: "Action - Attack",
        cost: 5,
        play: function () {
          this.draw_cards(2);
          this.other_players_get_curse_card();
        }
      },
      "Adventurer": {
        name: "Adventurer",
        type: "Action",
        cost: 6,
        play: function () {
          this.adventurer();
        }
      }
    };

    return Cards;
  }());

  // TODO: Rename board to Table
  var Board = (function () {
    var Board =  {
      kingdom: {}, // kingdom cards aka available cards
      trashed: [], // cards that are trashed
      onBoard: [], // visible cards that are placed on the board

      init: function (gamePreset) {
        this.reset();

        if (gamePreset === undefined || gamePreset === "firstGame") {
          this.pickFirstGameKingdomCards();
        }

        this.pickVictoryAndTreasureCards();

        return this;
      },
      reset: function () {
        this.onBoard = [];
        this.trashed = [];
        this.kingdom = {};
      },
      clear: function () {
        this.onBoard = [];
      },
      pickVictoryAndTreasureCards: function () {
        var infinity = 1.0/0;

        this.kingdom["Estate"]   = 8;
        this.kingdom["Duchy"]    = 8;
        this.kingdom["Province"] = 8;
        this.kingdom["Curse"]    = 10;

        this.kingdom["Copper"] = infinity;
        this.kingdom["Silver"] = infinity;
        this.kingdom["Gold"]   = infinity;
      },
      pickFirstGameKingdomCards: function () {
        var firstGameCards = [
          "Cellar", "Market", "Militia", "Mine", "Moat", "Remodel",
          "Smithy", "Village", "Woodcutter", "Workshop"
        ];

        for (var i = 0; i < firstGameCards.length; i++) {
          this.kingdom[firstGameCards[i]] = 25;
        }
      }
    };

    return Board;
  }());

  var Player = (function () {
    var Player = {
      drawPile:    [],
      discardPile: [],
      hand:        [],
      actions:     1,
      buys:        1,
      coins:       0,

      /**
       *  Initializers and resetters
       */
      init: function () {
        this.initialHand();

        return this;
      },
      clearHand: function () {
        this.actions = 1;
        this.buys    = 1;
        this.coins   = 0;
        this.hand    = [];
      },
      clearBoard: function () {
        Board.clear();
      },
      initialHand: function () {
        this.drawPile = [
          "Estate", "Estate", "Estate", "Copper", "Copper",
          "Copper", "Copper", "Copper", "Copper", "Copper"
        ];

        this.shuffleDrawPile();
        this.clearHand();
        this.drawNextHand();
      },

      /**
       *  Turn interactions
       */
      drawNextHand: function () {
        for (var i = 0; i < 5; i++) {
          this.drawCard();
        }
      },
      endOfTurn: function () {
        this.moveCardsToDiscardPile();
        this.drawNextHand();
      },
      shuffleDrawPile: function () {
        var counter = this.drawPile.length,
            temp,
            index;

        while (counter > 0) {
          index    = Math.floor(Math.random() * counter);
          counter -= 1;

          temp = this.drawPile[counter];

          this.drawPile[counter] = this.drawPile[index];
          this.drawPile[index]   = temp;
        }
      },
      moveDiscardPileToDrawPile: function () {
        this.drawPile    = this.discardPile;
        this.discardPile = [];

        this.shuffleDrawPile();
      },
      moveCardsToDiscardPile: function () {
        for (var i = 0; i < this.hand.length; i++) {
          this.discardPile.push(this.hand[i]);
        }

        this.clearHand();

        for (var i = 0; i < Board.onBoard.length; i++) {
          this.discardPile.push(Board.onBoard[i]);
        }

        this.clearBoard();
      },
      isDrawPileEmpty: function () {
        return this.drawPile.length === 0;
      },
      moveCardFromHandToBoard: function (cardIndex) {
        Board.onBoard.push(this.hand.splice(cardIndex, 1).pop());
      },
      drawCard: function () {
        if (this.isDrawPileEmpty()) {
          this.moveDiscardPileToDrawPile();
        }

        var card = this.drawPile.shift();
        if (card) {
          this.hand.push(card);
        }
      },
      playCard: function (card) {
        var cardIndex = this.hand.indexOf(card);

        if (cardIndex !== -1) {
          this.moveCardFromHandToBoard(cardIndex);
          if (Cards[card].play) {
            Cards[card].play.apply(this);
          }
        } else {
          throw card + " card cannot be played as it's not part of your hand";
        }
      },
      buyCard: function (card) {
        if (this.buys < 1) {
          throw "Not enough buy points";
        }

        if (this.coins < Cards[card].cost) {
          throw "Not enough treasure points"
        }

        if (Board.kingdom[card] <= 0) {
          throw "Card out of supply"
        }

        this.buys           -= 1;
        this.coins          -= Cards[card].cost;
        Board.kingdom[card] -= 1;

        this.discardPile.push(card);
      },

      /**
       * Card interactions
       */
      addCoins: function (n) {
        this.coins += n;
      },
      addActions: function (n) {
        this.actions += n;
      },
      addBuys: function (n) {
        this.buys += n;
      },

      /* Debug helpers */
      debug: function () {
        return {
          handCards:    Player.hand, //should be just hand = []
          drawPile:     Player.drawPile,
          discardPile:  Player.discardPile,
          kingdomCards: Board.kingdom,
          trashedCards: Board.trashed,
          onBoardCards: Board.onBoard
        };
      }
    };

    return Player;
  }());

  var Game = (function () {
    var Game = {
      state: null,
      context: function () {

      },
      start: function (cardListOrPresetName) {
        Board.init(cardListOrPresetName);
        Player.init();
      },
      play: function (card) {
        Player.playCard(card);
      },
      buy: function (card) {
        Player.buyCard(card);
      },
      endOfTurn: function () {
        Player.endOfTurn();
      },
      quit: function () {
      },
      debug: Player.debug
    };

    return Game;
  }());

  return Game;
}());<commit_msg>End of line char change<commit_after>var Dominion = (function () {
  "use strict";

  var Cards = (function () {
    /**
     * IMPORTANT
     *
     * `play` and `end` will be called with
     * `apply` against the Player object
     */
    var Cards =  {
      "Copper": {
        name: "Copper",
        type: "Treasure",
        cost: 0,
        play: function () {
          this.addCoins(1);
        }
      },
      "Silver": {
        name: "Silver",
        type: "Treasure",
        cost: 3,
        play: function () {
          this.addCoins(2);
        }
      },
      "Gold": {
        name: "Gold",
        type: "Treasure",
        cost: 6,
        play: function () {
          this.addCoins(3);
        }
      },
      "Estate": {
        name: "Estate",
        type: "Victory",
        cost: 2,
        end:  function () {
          this.add_victory(1);
        }
      },
      "Duchy": {
        name: "Duchy",
        type: "Victory",
        cost: 5,
        end:  function () {
          this.add_victory(3);
        }
      },
      "Province": {
        name: "Province",
        type: "Victory",
        cost: 8,
        end:  function () {
          this.add_victory(6);
        }
      },
      "Curse": {
        name: "Curse",
        type: "Curse",
        cost: 0,
        end:  function () {
          this.add_victory(-1);
        }
      },
      "Cellar": {
        name: "Cellar",
        type: "Action",
        cost: 2,
        play: function () {
          this.add_actions(1);
          this.discard_any_cards();
          this.replace_discarded_cards();
        }
      },
      "Chapel":  {
        name: "Chapel",
        type: "Action",
        cost: 2,
        play: function () {
          this.trash_up_to(4);
        }
      },
      "Moat": {
        name:   "Moat",
        type:   "Action - Reaction",
        cost:   2,
        immune: true,
        play:   function () {
          this.draw_cards(2);
        }
      },
      "Chancellor": {
        name: "Chancellor",
        type: "Action",
        cost: 3,
        play: function () {
          this.add_coins(2);
          this.discard_deck();
        }
      },
      "Village": {
        name: "Village",
        type: "Action",
        cost: 3,
        play: function () {
          this.draw_cards(1);
          this.add_actions(2);
        }
      },
      "Woodcutter": {
        name: "Woodcutter",
        type: "Action",
        cost: 3,
        play: function () {
          this.add_buys(1);
          this.add_coins(2);
        }
      },
      "Workshop": {
        name: "Workshop",
        type: "Action",
        cost: 3,
        play: function () {
          this.gain_card_costing_up_to(4);
        }
      },
      "Bureaucrat": {
        name: "Bureaucrat",
        type: "Action - Attack",
        cost: 4,
        play: function () {
          this.bureaucrat();
        }
      },
      "Feast": {
        name: "Feast",
        type: "Action",
        cost: 4,
        play: function () {
          this.trash_this_card();
          this.gain_card_costing_up_to(5);
        }
      },
      "Gardens": {
        name: "Gardens",
        type: "Victory",
        cost: 4,
        end:  function () {
          this.gardens();
        }
      },
      "Militia": {
        name: "Militia",
        type: "Action - Attack",
        cost: 4,
        play: function () {
          this.add_coins(2);
          this.other_players_discard_down_to(3);
        }
      },
      "Moneylender": {
        name: "Moneylender",
        type: "Action",
        cost: 4,
        play: function () {
          this.trash_copper_for_coins(3);
        }
      },
      "Remodel": {
        name: "Remodel",
        type: "Action",
        cost: 4,
        play: function () {
          this.trash_card_for_card_costing_more(3);
        }
      },
      "Smithy": {
        name: "Smithy",
        type: "Action",
        cost: 4,
        play: function () {
          this.draw_cards(3);
        }
      },
      "Spy": {
        name: "Spy",
        type: "Action - Attack",
        cost: 4,
        play: function () {
          this.spy();
        }
      },
      "Thief": {
        name: "Thief",
        type: "Action - Attack",
        cost: 4,
        play: function () {
          this.thief();
        }
      },
      "ThroneRoom": {
        name: "ThroneRoom",
        type: "Action",
        cost: 4,
        play: function () {
          this.chose_card_play_it_twice();
        }
      },
      "CouncilRoom": {
        name: "CouncilRoom",
        type: "Action",
        cost: 5,
        play: function () {
          this.draw_cards(4);
          this.buy_points(1);
          this.other_players_draw_cards(1);
        }
      },
      "Festival": {
        name: "Festival",
        type: "Action",
        cost: 5,
        play: function () {
          this.add_actions(2);
          this.add_buys(1);
          this.add_coins(2);
        }
      },
      "Laboratory": {
        name: "Laboratory",
        type: "Action",
        cost: 5,
        play: function () {
          this.draw_cards(2);
          this.add_actions(1);
        }
      },
      "Library": {
        name: "Library",
        type: "Action",
        cost: 5,
        play: function () {
          this.library();
        }
      },
      "Market": {
        name: "Market",
        type: "Action",
        cost: 5,
        play: function () {
          this.draw_cards(1);
          this.add_actions(1);
          this.add_buys(1);
          this.add_coins(1);
        }
      },
      "Mine": {
        name: "Mine",
        type: "Action",
        cost: 5,
        play: function () {
          this.mine();
        }
      },
      "Witch": {
        name: "Witch",
        type: "Action - Attack",
        cost: 5,
        play: function () {
          this.draw_cards(2);
          this.other_players_get_curse_card();
        }
      },
      "Adventurer": {
        name: "Adventurer",
        type: "Action",
        cost: 6,
        play: function () {
          this.adventurer();
        }
      }
    };

    return Cards;
  }());

  // TODO: Rename board to Table
  var Board = (function () {
    var Board =  {
      kingdom: {}, // kingdom cards aka available cards
      trashed: [], // cards that are trashed
      onBoard: [], // visible cards that are placed on the board

      init: function (gamePreset) {
        this.reset();

        if (gamePreset === undefined || gamePreset === "firstGame") {
          this.pickFirstGameKingdomCards();
        }

        this.pickVictoryAndTreasureCards();

        return this;
      },
      reset: function () {
        this.onBoard = [];
        this.trashed = [];
        this.kingdom = {};
      },
      clear: function () {
        this.onBoard = [];
      },
      pickVictoryAndTreasureCards: function () {
        var infinity = 1.0/0;

        this.kingdom["Estate"]   = 8;
        this.kingdom["Duchy"]    = 8;
        this.kingdom["Province"] = 8;
        this.kingdom["Curse"]    = 10;

        this.kingdom["Copper"] = infinity;
        this.kingdom["Silver"] = infinity;
        this.kingdom["Gold"]   = infinity;
      },
      pickFirstGameKingdomCards: function () {
        var firstGameCards = [
          "Cellar", "Market", "Militia", "Mine", "Moat", "Remodel",
          "Smithy", "Village", "Woodcutter", "Workshop"
        ];

        for (var i = 0; i < firstGameCards.length; i++) {
          this.kingdom[firstGameCards[i]] = 25;
        }
      }
    };

    return Board;
  }());

  var Player = (function () {
    var Player = {
      drawPile:    [],
      discardPile: [],
      hand:        [],
      actions:     1,
      buys:        1,
      coins:       0,

      /**
       *  Initializers and resetters
       */
      init: function () {
        this.initialHand();

        return this;
      },
      clearHand: function () {
        this.actions = 1;
        this.buys    = 1;
        this.coins   = 0;
        this.hand    = [];
      },
      clearBoard: function () {
        Board.clear();
      },
      initialHand: function () {
        this.drawPile = [
          "Estate", "Estate", "Estate", "Copper", "Copper",
          "Copper", "Copper", "Copper", "Copper", "Copper"
        ];

        this.shuffleDrawPile();
        this.clearHand();
        this.drawNextHand();
      },

      /**
       *  Turn interactions
       */
      drawNextHand: function () {
        for (var i = 0; i < 5; i++) {
          this.drawCard();
        }
      },
      endOfTurn: function () {
        this.moveCardsToDiscardPile();
        this.drawNextHand();
      },
      shuffleDrawPile: function () {
        var counter = this.drawPile.length,
            temp,
            index;

        while (counter > 0) {
          index    = Math.floor(Math.random() * counter);
          counter -= 1;

          temp = this.drawPile[counter];

          this.drawPile[counter] = this.drawPile[index];
          this.drawPile[index]   = temp;
        }
      },
      moveDiscardPileToDrawPile: function () {
        this.drawPile    = this.discardPile;
        this.discardPile = [];

        this.shuffleDrawPile();
      },
      moveCardsToDiscardPile: function () {
        for (var i = 0; i < this.hand.length; i++) {
          this.discardPile.push(this.hand[i]);
        }

        this.clearHand();

        for (var i = 0; i < Board.onBoard.length; i++) {
          this.discardPile.push(Board.onBoard[i]);
        }

        this.clearBoard();
      },
      isDrawPileEmpty: function () {
        return this.drawPile.length === 0;
      },
      moveCardFromHandToBoard: function (cardIndex) {
        Board.onBoard.push(this.hand.splice(cardIndex, 1).pop());
      },
      drawCard: function () {
        if (this.isDrawPileEmpty()) {
          this.moveDiscardPileToDrawPile();
        }

        var card = this.drawPile.shift();
        if (card) {
          this.hand.push(card);
        }
      },
      playCard: function (card) {
        var cardIndex = this.hand.indexOf(card);

        if (cardIndex !== -1) {
          this.moveCardFromHandToBoard(cardIndex);
          if (Cards[card].play) {
            Cards[card].play.apply(this);
          }
        } else {
          throw card + " card cannot be played as it's not part of your hand";
        }
      },
      buyCard: function (card) {
        if (this.buys < 1) {
          throw "Not enough buy points";
        }

        if (this.coins < Cards[card].cost) {
          throw "Not enough treasure points"
        }

        if (Board.kingdom[card] <= 0) {
          throw "Card out of supply"
        }

        this.buys           -= 1;
        this.coins          -= Cards[card].cost;
        Board.kingdom[card] -= 1;

        this.discardPile.push(card);
      },

      /**
       * Card interactions
       */
      addCoins: function (n) {
        this.coins += n;
      },
      addActions: function (n) {
        this.actions += n;
      },
      addBuys: function (n) {
        this.buys += n;
      },

      /* Debug helpers */
      debug: function () {
        return {
          handCards:    Player.hand, //should be just hand = []
          drawPile:     Player.drawPile,
          discardPile:  Player.discardPile,
          kingdomCards: Board.kingdom,
          trashedCards: Board.trashed,
          onBoardCards: Board.onBoard
        };
      }
    };

    return Player;
  }());

  var Game = (function () {
    var Game = {
      state: null,
      context: function () {

      },
      start: function (cardListOrPresetName) {
        Board.init(cardListOrPresetName);
        Player.init();
      },
      play: function (card) {
        Player.playCard(card);
      },
      buy: function (card) {
        Player.buyCard(card);
      },
      endOfTurn: function () {
        Player.endOfTurn();
      },
      quit: function () {
      },
      debug: Player.debug
    };

    return Game;
  }());

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


<commit_before>var net = require('net');

module.exports = function(RED) {

	function FritzboxCallmonitor(n) {
		RED.nodes.createNode(this,n);
		var node = this;
    node.topic = n.topic;
		node.config = RED.nodes.getNode(n.device);

    var client = new net.Socket();
    client.setKeepAlive(true, 118000);
    var connections = {};
    var timeout;
    var options = {
      port: 1012,
      host: node.config.host,
    };

		var reconnect = function() {
			node.log('Connecting to fritzbox...');
			if(timeout) clearTimeout(timeout);
			client.connect(options);
		};

    node.status({fill:"yellow",shape:"ring",text:"Initialization"});

    client.on('connect', function() {
			node.log('Connected to fritzbox');
      node.status({fill:"green",shape:"dot",text:"Connected"});
    });

    client.on('close', function(hadError) {
      if(hadError) {
				node.error("Disconnected with Error");
        node.status({fill:"red",shape:"ring",text:"Disconnected with Error"});
      } else {
				node.warn("Disconnected");
        node.status({fill:"red",shape:"ring",text:"Disconnected"});
      }
			node.log("Reconnecting in 30sec");
      timeout = setTimeout(reconnect, 30000);
    });

		client.on('error', function(e) {
			node.error(e);
		});

		client.on('timeout', function() {
			node.error('Connection to fritzbox timed out');
			client.end();
		});

    client.on('data', function(data) {
      const raw = data.toString();
      const array = raw.split(";");
      const type = array[1];
      const id = array[2];
      const timestamp = array[0];
      let message;

      if (connections[id] !== undefined) {
        message = connections[id]
      } else {
        message = {}
      }

      switch(type) {
        case "CALL":
          message.type = "OUTBOUND";
          message.id = id;
          message.timestamp = timestamp;
          message.caller = array[4];
          message.callee = array[5];
          message.extension = array[3];
          connections[id] = message;
          break;
        case "RING":
          message.type = "INBOUND";
          message.id = id;
          message.timestamp = timestamp;
          message.caller = array[3];
          message.callee = array[4];
          connections[id] = message;
          break;
        case "CONNECT":
          message.type = "CONNECT";
          message.id = id;
          message.timestamp = timestamp;
          message.extension = array[3];
          connections[id] = message;
          break;
        case "DISCONNECT":
          switch(message.type) {
            case "INBOUND":
              message.type = "MISSED";
              break;
            case "CONNECT":
              message.type = "DISCONNECT";
              break;
            case "OUTBOUND":
              message.type = "UNREACHED";
              break;
          }
          message.id = id;
          message.timestamp = timestamp;
          delete connections[id];
          break;
      }
      node.send({
        topic: node.topic ? node.topic : "",
        payload: message
      });
    });

    reconnect();

    node.on('close', function() {
      client.removeAllListeners();
      client.end();
      if(timeout) clearTimeout(timeout);
    });

	}
	RED.nodes.registerType("fritzbox-callmonitor", FritzboxCallmonitor);

};
<commit_msg>Print log when connection is closed.<commit_after>var net = require('net');

module.exports = function(RED) {

	function FritzboxCallmonitor(n) {
		RED.nodes.createNode(this,n);
		var node = this;
    node.topic = n.topic;
		node.config = RED.nodes.getNode(n.device);

    var client = new net.Socket();
    client.setKeepAlive(true, 118000);
    var connections = {};
    var timeout;
    var options = {
      port: 1012,
      host: node.config.host,
    };

		var reconnect = function() {
			node.log('Connecting to fritzbox...');
			if(timeout) clearTimeout(timeout);
			client.connect(options);
		};

    node.status({fill:"yellow",shape:"ring",text:"Initialization"});

    client.on('connect', function() {
			node.log('Connected to fritzbox');
      node.status({fill:"green",shape:"dot",text:"Connected"});
    });

    client.on('close', function(hadError) {
      if(hadError) {
				node.error("Disconnected with Error");
        node.status({fill:"red",shape:"ring",text:"Disconnected with Error"});
      } else {
				node.warn("Disconnected");
        node.status({fill:"red",shape:"ring",text:"Disconnected"});
      }
			node.log("Reconnecting in 30sec");
      timeout = setTimeout(reconnect, 30000);
    });

		client.on('error', function(e) {
			node.error(e);
		});

		client.on('timeout', function() {
			node.error('Connection to fritzbox timed out');
			client.end();
		});

    client.on('data', function(data) {
      const raw = data.toString();
      const array = raw.split(";");
      const type = array[1];
      const id = array[2];
      const timestamp = array[0];
      let message;

      if (connections[id] !== undefined) {
        message = connections[id]
      } else {
        message = {}
      }

      switch(type) {
        case "CALL":
          message.type = "OUTBOUND";
          message.id = id;
          message.timestamp = timestamp;
          message.caller = array[4];
          message.callee = array[5];
          message.extension = array[3];
          connections[id] = message;
          break;
        case "RING":
          message.type = "INBOUND";
          message.id = id;
          message.timestamp = timestamp;
          message.caller = array[3];
          message.callee = array[4];
          connections[id] = message;
          break;
        case "CONNECT":
          message.type = "CONNECT";
          message.id = id;
          message.timestamp = timestamp;
          message.extension = array[3];
          connections[id] = message;
          break;
        case "DISCONNECT":
          switch(message.type) {
            case "INBOUND":
              message.type = "MISSED";
              break;
            case "CONNECT":
              message.type = "DISCONNECT";
              break;
            case "OUTBOUND":
              message.type = "UNREACHED";
              break;
          }
          message.id = id;
          message.timestamp = timestamp;
          delete connections[id];
          break;
      }
      node.send({
        topic: node.topic ? node.topic : "",
        payload: message
      });
    });

    reconnect();

    node.on('close', function() {
      client.setKeepAlive(false, 118000);
      client.end(function() {
        client.removeAllListeners();
        node.log('Disconnected from fritzbox');
      });
      if(timeout) clearTimeout(timeout);
    });

	}
	RED.nodes.registerType("fritzbox-callmonitor", FritzboxCallmonitor);

};
<|endoftext|>


<commit_before>var miio = require('./lib');

const crypto = require('crypto');
// var vacuum = python.import('mirobot/protocol');

class MiHome {

  constructor (name, ip, port, token, model) {
    this.ip = ip;
    this.port = port
    this.token = token;
    this.name = name
    this.model = model
    this.device = null;
  }

  load () {
    var that = this;

    return that.loading = new Promise(function(resolve, reject){

      if (that.model == 'vacuum') {
        that.device = miio.createDevice({
          address: that.ip,
          token: that.token,
          model: 'rockrobo.vacuum.v1'
        });

        that.device.init()
        .then(() => {
          console.log(that.model + " init success");
          resolve(that);
        })
        .catch(err => {
          console.error(that.model + " init error: " + err);
          reject(err);
        });
      }
      else {

        if (that.token == null) {
          var para = { address: that.ip };
        }
        else {
          var para = { address: that.ip, token: that.token };
        };

        miio.device(para)
          .then(device => {
              that.device = device;
              console.log(that.name + " " + that.device.type + " init success");
              resolve(that);
            })
          .catch(err => {
          console.error(that.name + " init error: " + err);
          reject(err);
        });
      }
    });
  }

  exec(cmd) {
    var that = this;

    if (cmd == 'Stop') {
      cmd = 'Charge';
    }

    switch (cmd) {
      case 'Start':

        if (this.device.type == 'vacuum') {
          this.device.start()
            .then(res => console.log(this.name + " start result : " + res))
            .catch(err => console.error(this.name + " start error: " + err));
        }

        break;

      case 'Charge':

        if (this.device.type == 'vacuum') {
          this.device.charge()
            .then(res => console.log(this.name + " charge result : " + res))
            .catch(err => console.error(this.name + " charge error: " + err));
        }

        break;

      case 'Pause':

        if (this.device.type == 'vacuum') {
          this.device.pause()
            .then(res => console.log(this.name + " pause result : " + res))
            .catch(err => console.error(this.name + " pause error: " + err));
        }

        break;

      case 'List':
        if (this.device.type == 'gateway') {
          this.list();
        }

        break;

      case 'PowerOff':
        if (this.device.type == 'light') {
          this.device.setPower(false)
            .then(res => console.log(this.name + " PowerOff result : " + res))
            .catch(err => console.error(this.name + " PowerOff error: " + err));
        }
        else {
          this.powerSet(false);
        }

        break;
      case 'PowerOn':

        if (this.device.type == 'light') {
          this.device.setPower(true)
            .then(res => console.log(this.name + " PowerOn result : " + res))
            .catch(err => console.error(this.name + " PowerOn error: " + err));
        }
        else {
          this.powerSet(true);
        }
        break;

      case 'PowerStatus':
        this.powerStatus();
        break;

      case 'LightStatus':
        if (this.device.type == 'light') {
          console.log(this.name + " Color Temp: " + this.device.colorTemperature);
        }
        break;

      default:
        console.log('Invalid type:' + cmd);
    }

    return;

  }

  powerOn() {
    var that = this;

    if(this.device.hasCapability('power')) {
      this.device.setPower(true)
        .then(console.log(this.name + ":Power On"))
        .catch(console.error(this.name + "Failed to Power On"));
    }

  }

  _deviecPowerSet(inputDevice, cmd) {
    var that = this;

    for (var i=0; i<inputDevice.powerChannels.length; i++) {
      console.log("Chan " + i);
      inputDevice.setPower(i, cmd)
      .then(power => console.log(inputDevice.type + " Power " + power))
      .catch(err => console.error(inputDevice.type + " Failed: " + err));
    }
  }

  _deviecPowerStatus(inputDevice) {
    var that = this;

    for (var i=0; i<inputDevice.powerChannels.length; i++) {
      console.log(inputDevice.type + " power " + inputDevice.power(JSON.stringify(i)));
    }
  }

  powerSet(cmd) {
    var that = this;

    if(that.device.type == 'gateway') {
      that.device.on('deviceAvailable', subDevice => {
        if (subDevice.type == 'power-plug') {

          that._deviecPowerSet(subDevice,cmd);
        }

        return;
      });
    }
    else {
      that._deviecPowerSet(that.device,cmd);
    }
  }

  powerStatus() {
    var that = this;

    if(that.device.type == 'gateway') {
      that.device.on('deviceAvailable', subDevice => {
        if (subDevice.type == 'power-plug') {

          that._deviecPowerStatus(subDevice);
        }

        return;
      });
    }
    else {
      that._deviecPowerStatus(that.device);
    }
  }

  encryption (key, iv, data) {
    var cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
    var crypted = cipher.update(data, 'utf8', 'binary');
    crypted += cipher.final('binary');
    crypted = new Buffer(crypted, 'binary');
    return crypted;
  }

  list() {
    var that = this;
    console.log('All SubDevice:');

    that.device.on('deviceAvailable', subDevice => {
      console.log('ID: ' + subDevice.id + ' Model:' + subDevice.model + ' Type:' + subDevice.type );

      if (subDevice.model == 'lumi.switch') {
          console.log('Actions: ' + subDevice.actions );
          debugger;

          var key = that.device._developerKey;
          var token = that.device._lastToken;

          console.log('key ' + key + ' token ' + token)

          console.log('tokenkey ' + that.device.packet._tokenKey + ' IV ' + that.device.packet._tokenIV)

          var base64str = that.encryption(that.device.packet._tokenKey, that.device.packet._tokenIV, token.toString());

          console.log(' ciphertext: ' + base64str);

          var data = {"cmd":"write",
                "model":"switch",
                "sid":subDevice.id,
                "short_id":2014,
                "data":"{\"status\":\"click\",\"key\":\"" + base64str + "\"}" }
          that.device.devApi.send(data);
                 // 0: data = {"cmd":"read_ack","model":"switch","sid":"158d000155e11d","short_id":2014,"data":"{\"voltage\":3062}"}

        }

      return;

    });

    if(that.device.devices) {

      that.device.devices.forEach(function(item){
        console.log('-' + item);
      })
    }

  }

};

module.exports = MiHome;<commit_msg>update test<commit_after>var miio = require('./lib');

const crypto = require('crypto');
// var vacuum = python.import('mirobot/protocol');

class MiHome {

  constructor (name, ip, port, token, model) {
    this.ip = ip;
    this.port = port
    this.token = token;
    this.name = name
    this.model = model
    this.device = null;
  }

  load () {
    var that = this;

    return that.loading = new Promise(function(resolve, reject){

      if (that.model == 'vacuum') {
        that.device = miio.createDevice({
          address: that.ip,
          token: that.token,
          model: 'rockrobo.vacuum.v1'
        });

        that.device.init()
        .then(() => {
          console.log(that.model + " init success");
          resolve(that);
        })
        .catch(err => {
          console.error(that.model + " init error: " + err);
          reject(err);
        });
      }
      else {

        if (that.token == null) {
          var para = { address: that.ip };
        }
        else {
          var para = { address: that.ip, token: that.token };
        };

        miio.device(para)
          .then(device => {
              that.device = device;
              console.log(that.name + " " + that.device.type + " init success");
              resolve(that);
            })
          .catch(err => {
          console.error(that.name + " init error: " + err);
          reject(err);
        });
      }
    });
  }

  exec(cmd) {
    var that = this;

    if (cmd == 'Stop') {
      cmd = 'Charge';
    }

    switch (cmd) {
      case 'Start':

        if (this.device.type == 'vacuum') {
          this.device.start()
            .then(res => console.log(this.name + " start result : " + res))
            .catch(err => console.error(this.name + " start error: " + err));
        }

        break;

      case 'Charge':

        if (this.device.type == 'vacuum') {
          this.device.charge()
            .then(res => console.log(this.name + " charge result : " + res))
            .catch(err => console.error(this.name + " charge error: " + err));
        }

        break;

      case 'Pause':

        if (this.device.type == 'vacuum') {
          this.device.pause()
            .then(res => console.log(this.name + " pause result : " + res))
            .catch(err => console.error(this.name + " pause error: " + err));
        }

        break;

      case 'List':
        if (this.device.type == 'gateway') {
          this.list();
        }

        break;

      case 'PowerOff':
        if (this.device.type == 'light') {
          this.device.setPower(false)
            .then(res => console.log(this.name + " PowerOff result : " + res))
            .catch(err => console.error(this.name + " PowerOff error: " + err));
        }
        else {
          this.powerSet(false);
        }

        break;
      case 'PowerOn':

        if (this.device.type == 'light') {
          this.device.setPower(true)
            .then(res => console.log(this.name + " PowerOn result : " + res))
            .catch(err => console.error(this.name + " PowerOn error: " + err));
        }
        else {
          this.powerSet(true);
        }
        break;

      case 'PowerStatus':
        this.powerStatus();
        break;

      case 'LightStatus':
        if (this.device.type == 'light') {
          console.log(this.name + " Color Temp: " + this.device.colorTemperature);
        }
        break;

      default:
        console.log('Invalid type:' + cmd);
    }

    return;

  }

  powerOn() {
    var that = this;

    if(this.device.hasCapability('power')) {
      this.device.setPower(true)
        .then(console.log(this.name + ":Power On"))
        .catch(console.error(this.name + "Failed to Power On"));
    }

  }

  _deviecPowerSet(inputDevice, cmd) {
    var that = this;

    for (var i=0; i<inputDevice.powerChannels.length; i++) {
      console.log("Chan " + i);
      inputDevice.setPower(i, cmd)
      .then(power => console.log(inputDevice.type + " Power " + power))
      .catch(err => console.error(inputDevice.type + " Failed: " + err));
    }
  }

  _deviecPowerStatus(inputDevice) {
    var that = this;

    for (var i=0; i<inputDevice.powerChannels.length; i++) {
      console.log(inputDevice.type + " power " + inputDevice.power(JSON.stringify(i)));
    }
  }

  powerSet(cmd) {
    var that = this;

    if(that.device.type == 'gateway') {
      that.device.on('deviceAvailable', subDevice => {
        if (subDevice.type == 'power-plug') {

          that._deviecPowerSet(subDevice,cmd);
        }

        return;
      });
    }
    else {
      that._deviecPowerSet(that.device,cmd);
    }
  }

  powerStatus() {
    var that = this;

    if(that.device.type == 'gateway') {
      that.device.on('deviceAvailable', subDevice => {
        if (subDevice.type == 'power-plug') {

          that._deviecPowerStatus(subDevice);
        }

        return;
      });
    }
    else {
      that._deviecPowerStatus(that.device);
    }
  }

  encryption (key, iv, data) {
    var cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
    var crypted = cipher.update(data, 'utf8', 'binary');
    crypted += cipher.final('binary');
    crypted = new Buffer(crypted, 'binary');
    return crypted;
  }

  list() {
    var that = this;
    console.log('All SubDevice:');

    that.device.on('deviceAvailable', subDevice => {
      console.log('ID: ' + subDevice.id + ' Model:' + subDevice.model + ' Type:' + subDevice.type );

      if (subDevice.model == 'lumi.switch') {
          console.log('Actions: ' + subDevice.actions );
          debugger;

          var key = that.device._developerKey;
          var token = that.device._lastToken;

          console.log('key ' + key + ' token ' + token)

          console.log('tokenkey ' + that.device.packet._tokenKey + ' IV ' + that.device.packet._tokenIV)

          var base64str = that.encryption(that.device.packet._tokenKey, that.device.packet._tokenIV, token.toString());

          console.log(' ciphertext: ' + base64str.toString('hex'));

          var finalKey = base64str.toString('hex');

          var data = {"cmd":"write",
                "model":"switch",
                "sid":subDevice.id,
                "short_id":2014,
                "data":"{\"status\":\"click\",\"key\":\"" + finalKey + "\"}" }
          that.device.devApi.send(data);
                 // 0: data = {"cmd":"read_ack","model":"switch","sid":"158d000155e11d","short_id":2014,"data":"{\"voltage\":3062}"}

        }

      return;

    });

    if(that.device.devices) {

      that.device.devices.forEach(function(item){
        console.log('-' + item);
      })
    }

  }

};

module.exports = MiHome;<|endoftext|>


<commit_before>import React from 'react';

class DinoScene extends React.Component {
  constructor(props) {
    super(props);
  }

  render () {
    return (
      <a-scene>
      <a-assets>
        <a-asset-item id="asstronautDae" src="/assets/John_glenn/model.dae" />
        <a-asset-item id="stall" src="/assets/Toilet_Stall.dae" />
      </a-assets>
      <a-sky src='/assets/prehistoric.jpg'/>
      <a-entity position="0 0 0">

          <a-model src="/assets/dino.dae" sound="src: /assets/trex.mp3; autoplay: true; volume: 1;" position='35 12 0' rotation='0 90 0'>
          </a-model>
        <a-animation attribute="rotation"
                     dur="9000"
                     fill="forwards"
                     to="0 360 0"
                     repeat="indefinite"/>
      </a-entity>

      <a-plane id='ground' src='/assets/ground.jpg' position='0 0 0' rotation='-90 0 0' width='25' height='25' />
      <a-entity position='0 1.5 0'>
        <a-camera id='camera' wasd-controls-enabled='false'/>
      </a-entity>
      <a-entity position='0 10 -10'>
<<<<<<< HEAD
        <a-plane src='/assets/ptero.png' transparent='true' width='3' height='2' rotation='90 0 0'/>
        <a-animation
=======
        <a-plane src='/assets/ptero.png' sound="src: /assets/pter.mp3; autoplay: true; loop: true; volume: 10;" transparent='true' width='3' height='2' rotation='90 0 0'/>
        <a-animation
>>>>>>> 7f04869a155efcb90633b2d8e168a4e296aae5fa
          attribute='position'
          dur='15000'
          from='0 10 -100'
          to='0 10 100'
          repeat='indefinite'
        />
      </a-entity>
      <a-collada-model scale="2.3 1.2 1.6" src='#stall' position='1.2 0 1' rotation='0 180 0'/>
      </a-scene>
    );
  }
};

module.exports = DinoScene;
<commit_msg>Remove merge messages<commit_after>import React from 'react';

class DinoScene extends React.Component {
  constructor(props) {
    super(props);
  }

  render () {
    return (
      <a-scene>
      <a-assets>
        <a-asset-item id="asstronautDae" src="/assets/John_glenn/model.dae" />
        <a-asset-item id="stall" src="/assets/Toilet_Stall.dae" />
      </a-assets>
      <a-sky src='/assets/prehistoric.jpg'/>
      <a-entity position="0 0 0">

          <a-model src="/assets/dino.dae" sound="src: /assets/trex.mp3; autoplay: true; volume: 1;" position='35 12 0' rotation='0 90 0'>
          </a-model>
        <a-animation attribute="rotation"
                     dur="9000"
                     fill="forwards"
                     to="0 360 0"
                     repeat="indefinite"/>
      </a-entity>

      <a-plane id='ground' src='/assets/ground.jpg' position='0 0 0' rotation='-90 0 0' width='25' height='25' />
      <a-entity position='0 1.5 0'>
        <a-camera id='camera' wasd-controls-enabled='false'/>
      </a-entity>
      <a-entity position='0 10 -10'>
        <a-plane src='/assets/ptero.png' sound="src: /assets/pter.mp3; autoplay: true; loop: true; volume: 10;" transparent='true' width='3' height='2' rotation='90 0 0'/>
        <a-animation
          attribute='position'
          dur='15000'
          from='0 10 -100'
          to='0 10 100'
          repeat='indefinite'
        />
      </a-entity>
      <a-collada-model scale="2.3 1.2 1.6" src='#stall' position='1.2 0 1' rotation='0 180 0'/>
      </a-scene>
    );
  }
};

module.exports = DinoScene;
<|endoftext|>


<commit_before>import React from 'react';
import { Link } from 'react-router';
import { prefixLink } from 'gatsby-helpers';
import styled from 'styled-components';

const StyledFooter = styled.footer`
    background-color: #292b2c;
    color: #ddd;
    bottom: 0;
    left: 0;
    width: 100%;
    padding: 80px 0px;
    margin-top: 0px;

    .about > * {
        margin-bottom: 15px;
    }
`;

const SocialIcon = styled.a`
    font-size: 32px;
    line-height: 32px;
    padding-right: 10px;
`;

const FooterButton = styled.a`
    font-size: 12px;
    display: inline-block;
    padding: 10px;
    border: 1px solid #fff;
    text-transform: uppercase;
`;

class Footer extends React.Component {
    render() {
        const { projects } = this.props;
        return (

        );
    }
}

export default Footer;
<commit_msg>Accessibility improvements to footer icons.<commit_after>import React from 'react';
import { Link } from 'react-router';
import { prefixLink } from 'gatsby-helpers';
import styled from 'styled-components';

const StyledFooter = styled.footer`
    background-color: #292b2c;
    color: #ddd;
    bottom: 0;
    left: 0;
    width: 100%;
    padding: 80px 0px;
    margin-top: 0px;

    .about > * {
        margin-bottom: 15px;
    }
`;

const FooterButton = styled.a`
    font-size: 12px;
    display: inline-block;
    padding: 10px;
    border: 1px solid #fff;
    text-transform: uppercase;
`;

const StyledIcon = styled.a`
    font-size: 32px;
    line-height: 32px;
    padding-right: 10px;
`;

const SocialIcon = ({ link, icon, title }) => (

);

class Footer extends React.Component {
    render() {
        const { projects } = this.props;
        return (

        );
    }
}

export default Footer;
<|endoftext|>


<commit_before>import styled from 'styled-components';

import {device} from '../dimensions';
import {COLOR_BACKGROUND_GREY, COLOR_ORANGE} from '../colors';

export const StyledHelp = styled.div`
  display: ${({shown}) => (shown ? 'block' : 'none')};
  -webkit-overflow-scrolling: touch;
  box-sizing: border-box;
  padding: 0 8px;
  background: ${COLOR_BACKGROUND_GREY};

  h5 {
    color: ${COLOR_ORANGE};
    font-weight: 700;
    margin-bottom: 8px;
  }
`;

export const StyledHelpInner = styled.div`
  overflow-x: hidden;
  overflow-y: auto;

  > p {
    margin-top: 0;
  }
`;
<commit_msg>#250 #234 code cleanup<commit_after>import styled from 'styled-components';

import {COLOR_BACKGROUND_GREY, COLOR_ORANGE} from '../colors';

export const StyledHelp = styled.div`
  display: ${({shown}) => (shown ? 'block' : 'none')};
  -webkit-overflow-scrolling: touch;
  box-sizing: border-box;
  padding: 0 8px;
  background: ${COLOR_BACKGROUND_GREY};

  h5 {
    color: ${COLOR_ORANGE};
    font-weight: 700;
    margin-bottom: 8px;
  }
`;

export const StyledHelpInner = styled.div`
  overflow-x: hidden;
  overflow-y: auto;

  > p {
    margin-top: 0;
  }
`;
<|endoftext|>


<commit_before><commit_msg>terminal: show the button for opening the terminal if a jujushell URL is specified in settings.<commit_after><|endoftext|>


<commit_before>app.factory('amazonFactory', function($http, addProductFactory, $location){
  return {
    getAmazon : (value) => {
      console.log("value from Factory", value);
       return $http.post('/api/amazon',
        {params: value
                 })
      .then((things) => {
          console.log(things.data);
          let searchResults = [];
          for (var i = 0; i < things.data.length; i++) {
            let searchProduct = {};
            searchProduct.category = value.searchIndex;
            searchProduct.name = things.data[i].ItemAttributes[0].Title[0];
            console.log("title", searchProduct.name);
            searchProduct.company = things.data[i].ItemAttributes[0].Brand[0];
            console.log("company", searchProduct.company);

            if(things.data[i].ImageSets) {
              searchProduct.image = things.data[i].ImageSets[0].ImageSet[0].LargeImage[0].URL[0];
              console.log("productImage", searchProduct.image);
              if(things.data[i].ItemAttributes[0].ListPrice) {
                searchProduct.price = things.data[i].ItemAttributes[0].ListPrice[0].FormattedPrice[0];
              console.log("price", searchProduct.price);
              }
              searchProduct.descript = "";
            for (var j = 0; j < things.data[i].ItemAttributes[0].Feature.length; j++) {
              searchProduct.descript += things.data[i].ItemAttributes[0].Feature[j] + ". ";
              }
              console.log("description", searchProduct.descript);
            }
            searchProduct.link = things.data[i].DetailPageURL[0];
            console.log("link", searchProduct.link);
            searchProduct.amazonUniqueId = things.data[i].ASIN[0];
            console.log("ASIN", searchProduct.amazonUniqueId);
            searchProduct.addDate = new Date();
            console.log("date", searchProduct.addDate);
            searchResults.push(searchProduct);
          }
          console.log("searchResults", searchResults);
          return searchResults;

      });//end of then
    },//end of getAmazon()
    addAmazon : (value) => {
      let newProduct = value;

      if(newProduct.uscompany === undefined) {
        newProduct.uscompany = false;
      }
      if (newProduct.usassembled === undefined) {
        newProduct.usassembled = false;
      }
      if (newProduct.usmanufactured === undefined) {
        newProduct.usmanufactured = false;
      }
       if (newProduct.uscompany || newProduct.usassembled || newProduct.usmanufactured) {
        addProductFactory.addProductToFirebase(newProduct)
        .then(()=>{
        //thank them for entering a product
        Materialize.toast("Thanks for sharing your find with us!", 4000, 'round right'); // 4000 is the duration of the toast
        //wait 3 second, then return to homepage
        setTimeout(()=> {
          $location.url("/addProductThroughAmazon");
          }, 3000);

      });//end of then
     } else {
        //if not in our category, error message
      // Materialize.toast(message, displayLength, className, completeCallback);
      Materialize.toast("That product sounds awesome, but it doesn't fit in with our American made collection.", 4000, 'round right'); // 4000 is the duration of the toast
      }
      console.log("newProduct", newProduct);
    }//end of addAmazon()

  }; //end of factory object
});//end of factory
<commit_msg>if amazon search result doesn't list a brand, that item will not be included in searchresults<commit_after>app.factory('amazonFactory', function($http, addProductFactory, $location){
  return {
    getAmazon : (value) => {
      console.log("value from Factory", value);
       return $http.post('/api/amazon',
        {params: value
                 })
      .then((things) => {
          console.log(things.data);
          let searchResults = [];
          for (var i = 0; i < things.data.length; i++) {
            let searchProduct = {};
            //set the amazon search category to a largerlocal search category
            if (value.searchIndex === "ArtsAndCrafts" || value.searchIndex === "HomeGarden"){
              searchProduct.category = "Home";
            } else if (value.searchIndex === "Fashion") {
              searchProduct.category = "Clothing";
            } else if (value.searchIndex === "Grocery") {
              searchProduct.category = "Food";
            } else {
            searchProduct.category = value.searchIndex;
            }
            //parse the product name
            searchProduct.name = things.data[i].ItemAttributes[0].Title[0];
            console.log("title", searchProduct.name);
            //parse the company name
            if (things.data[i].ItemAttributes[0].Brand === undefined) {
              continue;
            } else {
              searchProduct.company = things.data[i].ItemAttributes[0].Brand[0];
              console.log("company", searchProduct.company);
            }
            //parse the amazon purchase link
            searchProduct.link = things.data[i].DetailPageURL[0];
            console.log("link", searchProduct.link);
            //parse the amazon unique product id
            searchProduct.amazonUniqueId = things.data[i].ASIN[0];
            console.log("ASIN", searchProduct.amazonUniqueId);
            //stamp the search date on the product object for later use
            searchProduct.addDate = new Date();
            console.log("date", searchProduct.addDate);
            //if the product has images, gather one
            if(things.data[i].ImageSets) {
              searchProduct.image = things.data[i].ImageSets[0].ImageSet[0].LargeImage[0].URL[0];
              console.log("productImage", searchProduct.image);
              if(things.data[i].ItemAttributes[0].ListPrice) {
                searchProduct.price = things.data[i].ItemAttributes[0].ListPrice[0].FormattedPrice[0];
              console.log("price", searchProduct.price);
              }
              searchProduct.descript = "";
            for (var j = 0; j < things.data[i].ItemAttributes[0].Feature.length; j++) {
              searchProduct.descript += things.data[i].ItemAttributes[0].Feature[j] + ". ";
              }
              console.log("description", searchProduct.descript);
            }
            // searchProduct.link = things.data[i].DetailPageURL[0];
            // console.log("link", searchProduct.link);
            // searchProduct.amazonUniqueId = things.data[i].ASIN[0];
            // console.log("ASIN", searchProduct.amazonUniqueId);
            // searchProduct.addDate = new Date();
            // console.log("date", searchProduct.addDate);
            searchResults.push(searchProduct);
          }
          console.log("searchResults", searchResults);
          return searchResults;

      });//end of then
    },//end of getAmazon()
    addAmazon : (value) => {
      let newProduct = value;

      if(newProduct.uscompany === undefined) {
        newProduct.uscompany = false;
      }
      if (newProduct.usassembled === undefined) {
        newProduct.usassembled = false;
      }
      if (newProduct.usmanufactured === undefined) {
        newProduct.usmanufactured = false;
      }
       if (newProduct.uscompany || newProduct.usassembled || newProduct.usmanufactured) {
        addProductFactory.addProductToFirebase(newProduct)
        .then(()=>{
        //thank them for entering a product
        Materialize.toast("Thanks for sharing your find with us!", 4000, 'round right'); // 4000 is the duration of the toast
        //wait 3 second, then return to homepage
        setTimeout(()=> {
          $location.url("/addProductThroughAmazon");
          }, 3000);

      });//end of then
     } else {
        //if not in our category, error message
      // Materialize.toast(message, displayLength, className, completeCallback);
      Materialize.toast("That product sounds awesome, but it doesn't fit in with our American made collection.", 4000, 'round right'); // 4000 is the duration of the toast
      }
      console.log("newProduct", newProduct);
    }//end of addAmazon()

  }; //end of factory object
});//end of factory
<|endoftext|>


<commit_before>/*
    Framework for building object relational database apps
    Copyright (C) 2021  John Rogelstad

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    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
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
/*jslint this, browser*/
/*global f, m*/
/**
    @module ResourceLinkRelation
*/

const resourceLinkRelation = {};

/**
    @class ContactRelation
    @extends ViewModels.ResourceLinkRelationWidget
    @constructor
    @namespace ViewModels
    @param {Object} options Options
    @param {Object} options.parentViewModel Parent view-model. Requires
    property `relations` returning javascript object to attach relation
    view model to.
    @param {String} options.parentProperty Name of the relation
    in view model to attached to
    @param {String} options.valueProperty Value property
    @param {Object} [options.form] Form configuration
    @param {Object} [options.list] (Search) List configuration
    @param {Boolean} [options.isCell] Use style for cell in table
    @param {Object} [options.filter] Filter object used for search
*/
resourceLinkRelation.viewModel = function (options) {
    let vm = f.createViewModel("RelationWidget", options);

    vm.labels = function () {
        let resource;
        let label;
        let icon;
        let elements = [];
        let parentModel = options.parentViewModel.model();
        let model = parentModel.data[options.parentProperty]();

        if (model) {

            resource = (
                model.data.resource
                ? model.data.resource()
                : ""
            );
            icon = (
                model.data.icon
                ? model.data.icon()
                : ""
            );

            label = (
                model.data.label
                ? model.data.label()
                : ""
            );

            if (resource) {

                elements.push(
                        m("a", {
                            href: resource,
                            target: "_blank"
                        }, [
                            m("i", {
                                class: (
                                    "material-icons " +
                                    (icon || "") +
                                    " fb-icon-button"
                                )
                            }, "resource")
                        ], resource)
                );
            }

        }
        return elements;
/*
        return m("ul", {
            class: "pure-menu-list"
        }, elements);
*/
    };

    return vm;
};

f.catalog().register(
    "viewModels",
    "resourceLinkRelation",
    resourceLinkRelation.viewModel
);

/**
    @class ContactRelation
    @uses Components.RelationWidget
    @namespace Components
*/
resourceLinkRelation.component = {
    oninit: function (vnode) {
        let list;
        let theForm;
        let options = vnode.attrs;
        let id = vnode.attrs.form || "scotelinkable";
        let relations = options.parentViewModel.relations();

        theForm = f.catalog().store().data().forms().find(
            (row) => id === row.id
        );

        if (theForm) {
            theForm = theForm.toJSON();
        }

        list = {
            columns: [{
                "attr": "icon"
            }, {
                "attr": "label"
            }, {
                "attr": "resource"
            }, {
                "attr": "displayValue"
            }]
        };

        options.isCell = (
            options.isCell === undefined
            ? false
            : options.isCell
        );

        // Set up viewModel if required
        if (!relations[options.parentProperty]) {
            relations[options.parentProperty] = resourceLinkRelation.viewModel({
                parentViewModel: options.parentViewModel,
                parentProperty: options.parentProperty,
                valueProperty: options.valueProperty || "displayValue",
                form: theForm,
                list: options.list || list,
                filter: options.filter,
                isCell: options.isCell,
                id: options.id,
                isReadOnly: options.isReadOnly,
                style: options.style || {}
            });
        }
        this.viewModel = relations[options.parentProperty];
    },

   view:f.getComponent("RelationWidget").view,
    labelProperty:f.prop("displayValue"),
    valueProperty:f.prop("displayValue")

};

f.catalog().register(
    "components",
    "resourceLinkRelation",
    resourceLinkRelation.component
);
<commit_msg>Lint cleanup, adjust CSS classname<commit_after>/*
    Framework for building object relational database apps
    Copyright (C) 2021  John Rogelstad

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    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
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
/*jslint this, browser*/
/*global f, m*/
/**
    @module ResourceLinkRelation
*/

const resourceLinkRelation = {};

/**
    @class ResourceLinkRelation
    @extends ViewModels.ResourceLinkRelationWidget
    @constructor
    @namespace ViewModels
    @param {Object} options Options
    @param {Object} options.parentViewModel Parent view-model. Requires
    property `relations` returning javascript object to attach relation
    view model to.
    @param {String} options.parentProperty Name of the relation
    in view model to attached to
    @param {String} options.valueProperty Value property
    @param {Object} [options.form] Form configuration
    @param {Object} [options.list] (Search) List configuration
    @param {Boolean} [options.isCell] Use style for cell in table
    @param {Object} [options.filter] Filter object used for search
*/
resourceLinkRelation.viewModel = function (options) {
    let vm = f.createViewModel("RelationWidget", options);

    vm.labels = function () {
        let resource;
        let label;
        let icon;
        let elements = [];
        let parentModel = options.parentViewModel.model();
        let model = parentModel.data[options.parentProperty]();

        if (model) {

            resource = (
                model.data.resource
                ? model.data.resource()
                : ""
            );
            icon = (
                model.data.icon
                ? model.data.icon()
                : ""
            );

            label = (
                model.data.label
                ? model.data.label()
                : ""
            );

            if (resource) {

                elements.push(
                        m("a", {
                            href: resource,
                            target: "_blank"
                        }, [
                            m("i", {
                                class: (
                                    "material-icons " +
                                    (icon || "") +
                                    " fb-menu-list-icon"
                                )
                            }, "resource")
                        ], (label || resource))
                );
            }

        }
        return elements;
    };

    return vm;
};

f.catalog().register(
    "viewModels",
    "resourceLinkRelation",
    resourceLinkRelation.viewModel
);

/**
    @class ResourceLinkRelation
    @uses Components.RelationWidget
    @namespace Components
*/
resourceLinkRelation.component = {
    oninit: function (vnode) {
        let list;
        let theForm;
        let options = vnode.attrs;
        let id = vnode.attrs.form || "scotelinkable";
        let relations = options.parentViewModel.relations();

        theForm = f.catalog().store().data().forms().find(
            (row) => id === row.id
        );

        if (theForm) {
            theForm = theForm.toJSON();
        }

        list = {
            columns: [{
                "attr": "icon"
            }, {
                "attr": "label"
            }, {
                "attr": "resource"
            }, {
                "attr": "displayValue"
            }]
        };

        options.isCell = (
            options.isCell === undefined
            ? false
            : options.isCell
        );

        // Set up viewModel if required
        if (!relations[options.parentProperty]) {
            relations[options.parentProperty] = resourceLinkRelation.viewModel({
                parentViewModel: options.parentViewModel,
                parentProperty: options.parentProperty,
                valueProperty: options.valueProperty || "displayValue",
                form: theForm,
                list: options.list || list,
                filter: options.filter,
                isCell: options.isCell,
                id: options.id,
                isReadOnly: options.isReadOnly,
                style: options.style || {}
            });
        }
        this.viewModel = relations[options.parentProperty];
    },

   view:f.getComponent("RelationWidget").view,
    labelProperty:f.prop("displayValue"),
    valueProperty:f.prop("displayValue")

};

f.catalog().register(
    "components",
    "resourceLinkRelation",
    resourceLinkRelation.component
);
<|endoftext|>


<commit_before>/*jshint node:true*/
module.exports = {
  "framework": "qunit",
  "test_page": "tests/index.html?hidepassed",
  "disable_watching": true,
  "launch_in_ci": [
    "Chrome"
  ],
  "launch_in_dev": [
    "Chrome"
  ]
};
<commit_msg>testem update for ember cli<commit_after>/* eslint-env node */
module.exports = {
  test_page: 'tests/index.html?hidepassed',
  disable_watching: true,
  launch_in_ci: [
    'Chrome'
  ],
  launch_in_dev: [
    'Chrome'
  ],
  browser_args: {
    Chrome: [
      '--headless',
      '--disable-gpu',
      '--remote-debugging-port=9222',
      '--window-size=1440,900'
    ]
  }
};
<|endoftext|>


<commit_before>// Create reply form and load data from server

'use strict';

var _          = require('lodash');
var remarked   = require('remarked');
var medialinks = require('nodeca.core/lib/parser/medialinks');

var $form;
var pageParams;
var parentPostId;
var $preview;
var parseRules;

function removeEditor() {
  if (!$form) {
    return;
  }

  // TODO: save draft
  $form.remove();
  $form = null;
  $preview = null;
}

function updatePreview() {
  if (!$preview) {
    return;
  }

  remarked.setOptions({
    gfm: false,
    tables: false,
    breaks: false,
    pedantic: false,
    sanitize: true,
    smartLists: true,
    smartypants: false
  });

  // TODO: generate real preview
  var Parser = require('ndparser');
  var parser = new Parser();

  var parserData = {
    input: remarked($form.find('textarea').val()),
    output: null,
    options: parseRules
  };

  parser.src2ast(parserData, function () {
    $preview.html(parserData.output.html());
  });
}

///////////////////////////////////////////////////////////////////////////////
// Init on page load
//
N.wire.on('navigate.done:forum.topic', function init_forum_post_reply(data) {
  pageParams = data.params;
});

// Free resources on page exit
//
N.wire.before('navigate.exit:forum.topic', function tear_down_forum_post_reply() {
  removeEditor();
});

// terminate editor if user tries to edit post on the same page
//
N.wire.on('forum.topic.post_edit', function click_edit() {
  removeEditor();
});

///////////////////////////////////////////////////////////////////////////////
// Fetch parse rules
//
N.wire.before('forum.topic.post_reply', function fetch_parse_rules(event, callback) {
  if (parseRules) {
    callback();
    return;
  }

  N.io.rpc('forum.topic.parse_rules').done(function (res) {
    parseRules = res.parse_rules;
    parseRules.medialinkProviders = medialinks(parseRules.medialinks.providers, parseRules.medialinks.content, true);
    callback();
  });
});

// Load parser
//
N.wire.before('forum.topic.post_reply', function load_parser(event, callback) {
  N.loader.loadAssets('parser', callback);
});

// Click on post reply link or toolbar reply button
//
N.wire.on('forum.topic.post_reply', function click_reply(event) {
  removeEditor();

  // TODO: load draft

  parentPostId = $(event.target).data('post-id');

  $form = $(N.runtime.render('forum.topic.post_reply'));
  $form.hide();

  $preview = $form.find('.forum-reply__preview');

  // Find parent, to attach editor after. For new reply - last child
  if (parentPostId) {
    $('#post' + parentPostId).after($form);
  } else {
    $('#postlist > :last').after($form);
  }

  $form.fadeIn();

  $form.find('textarea').on('input propertychange', _.debounce(updatePreview, 500));
});

///////////////////////////////////////////////////////////////////////////////
// Event handler on Save button click
//
N.wire.on('forum.topic.post_reply:save', function save() {
  // Save reply on server

  remarked.setOptions({
    gfm: false,
    tables: false,
    breaks: false,
    pedantic: false,
    sanitize: true,
    smartLists: true,
    smartypants: false
  });

  var data = {
    section_hid: pageParams.section_hid,
    topic_hid:   pageParams.hid,
    post_text:   remarked($form.find('textarea').val())
  };

  if (parentPostId) {
    data.parent_post_id = parentPostId;
  }

  N.io.rpc('forum.topic.post_reply.save', data).done(function (res) {
    removeEditor();
    // TODO: remove draft

    // TODO: append new posts
    window.location = res.redirect_url;
  });
});

N.wire.on('forum.topic.post_reply:preview_toggle', function preview_toggle() {
  $preview.fadeToggle();
  // TODO: save preview visibility
});

// on Cancel button remove editor and store draft
//
N.wire.on('forum.topic.post_reply:cancel', function cancel() {
  $form.fadeOut(function () {
    removeEditor();
  });
});
<commit_msg>Added parser 'md2src' instead 'remarked'<commit_after>// Create reply form and load data from server

'use strict';

var _          = require('lodash');
var medialinks = require('nodeca.core/lib/parser/medialinks');

var $form;
var pageParams;
var parentPostId;
var $preview;
var parseRules;
var parser;

function removeEditor() {
  if (!$form) {
    return;
  }

  // TODO: save draft
  $form.remove();
  $form = null;
  $preview = null;
}

function updatePreview() {
  if (!$preview) {
    return;
  }

  var mdData = { input: $form.find('textarea').val(), output: null };

  parser.md2src(mdData, function () {
    var parserData = {
      input: mdData.output,
      output: null,
      options: parseRules
    };

    parser.src2ast(parserData, function () {
      $preview.html(parserData.output.html());
    });
  });
}

///////////////////////////////////////////////////////////////////////////////
// Init on page load
//
N.wire.on('navigate.done:forum.topic', function init_forum_post_reply(data) {
  pageParams = data.params;
});

// Free resources on page exit
//
N.wire.before('navigate.exit:forum.topic', function tear_down_forum_post_reply() {
  removeEditor();
});

// terminate editor if user tries to edit post on the same page
//
N.wire.on('forum.topic.post_edit', function click_edit() {
  removeEditor();
});

///////////////////////////////////////////////////////////////////////////////
// Fetch parse rules
//
N.wire.before('forum.topic.post_reply', function fetch_parse_rules(event, callback) {
  if (parseRules) {
    callback();
    return;
  }

  N.io.rpc('forum.topic.parse_rules').done(function (res) {
    parseRules = res.parse_rules;
    parseRules.medialinkProviders = medialinks(parseRules.medialinks.providers, parseRules.medialinks.content, true);
    callback();
  });
});

// Load parser
//
N.wire.before('forum.topic.post_reply', function load_parser(event, callback) {
  N.loader.loadAssets('parser', callback);
});

// Click on post reply link or toolbar reply button
//
N.wire.on('forum.topic.post_reply', function click_reply(event) {
  removeEditor();

  var Parser = require('ndparser');
  parser = new Parser();

  // TODO: load draft

  parentPostId = $(event.target).data('post-id');

  $form = $(N.runtime.render('forum.topic.post_reply'));
  $form.hide();

  $preview = $form.find('.forum-reply__preview');

  // Find parent, to attach editor after. For new reply - last child
  if (parentPostId) {
    $('#post' + parentPostId).after($form);
  } else {
    $('#postlist > :last').after($form);
  }

  $form.fadeIn();

  $form.find('textarea').on('input propertychange', _.debounce(updatePreview, 500));
});

///////////////////////////////////////////////////////////////////////////////
// Event handler on Save button click
//
N.wire.on('forum.topic.post_reply:save', function save() {
  // Save reply on server

  var mdData = { input: $form.find('textarea').val(), output: null };

  parser.md2src(mdData, function () {
    var data = {
      section_hid: pageParams.section_hid,
      topic_hid:   pageParams.hid,
      post_text:   mdData.output
    };

    if (parentPostId) {
      data.parent_post_id = parentPostId;
    }

    N.io.rpc('forum.topic.post_reply.save', data).done(function (res) {
      removeEditor();
      // TODO: remove draft

      // TODO: append new posts
      window.location = res.redirect_url;
    });
  });
});

N.wire.on('forum.topic.post_reply:preview_toggle', function preview_toggle() {
  $preview.fadeToggle();
  // TODO: save preview visibility
});

// on Cancel button remove editor and store draft
//
N.wire.on('forum.topic.post_reply:cancel', function cancel() {
  $form.fadeOut(function () {
    removeEditor();
  });
});
<|endoftext|>


<commit_before>/**This module searches for new ip addresses and tests them for validity**/
//Main process tells you to stop searching
//you return -1 for no tested ip found but search is still on
//you return -2 for no tested ip found and all untested ips have been tested and search has stopped
//Exports important functions to calling program
module.exports = function() {
	console.log('Search and test started');

	var request = require('request');
	var LineByLineReader = require('line-by-line');
    var tunnel = require('tunnel');
    var https = require('https');
    var EventEmitter = require('events').EventEmitter;
    var moduleEvents = new EventEmitter;
	var goodIps = [];
	var goodIpIndex = 0;

	var untestedIps = [];
	var untestedIpIndex=0;

	//
	var STOP_SEARCH =false;

	//Alternatives to gimmeproxy are
    //http://proxy.tekbreak.com/
    //https://happy-proxy.com/en
    //https://incloak.com/proxy-list/
    //https://kingproxies.com/register
    //http://www.getproxy.jp/en/api
    //https://getproxy.net/en/api/

    //gip = 41-45
    //gip1 = 36-40
    //gip2 = 21-25
    //gip3 = 1-5
    //gip4 = 6-10
    //gip5 = 11-15
    //gip6 = 16-20
    //gip7 = 26-30
    //gip8 = 31-35
    //gip9 = 46-50
    //gip10 = 51-55

	function getIp(){
		if(!STOP_SEARCH){
			 request.get('http://gimmeproxy.com/api/getProxy' , function(err , response , body){
				 if(err){
					 //console.log('cannot get ip address');
					 getIp();
				 }
				 else {
					 if(untestedIps.length > 2500){
						 STOP_SEARCH = true;
					 }
	                 try {
						 var rawIp = JSON.parse(body);

						 //only http proxies allowed//
						 if(rawIp.curl.indexOf('socks')<0){
						 	 untestedIps.push(rawIp.ip);
						 }

						 setTimeout(function(){
						 	getIp();
						 } ,500)
					 }
					 catch (err) {
						   // Handle the error here.
						   //console.log(body);
						   setTimeout(function(){
						 	  getIp();
						   } ,500)
					 }

				 }
			 });
		}
		else{
			console.log('ip searching stopped');
			return;
		}
	};
    getIp();

	//
	var testIp = function(){
		if(untestedIpIndex<untestedIps.length){
			var ip = untestedIps[untestedIpIndex]+'';
            untestedIpIndex++;
            var ipPort = ip.split(':');
            console.log(ipPort);

            var tunnelingAgent = tunnel.httpsOverHttp({
                proxy: {
                    host: ipPort[0],
                    port: ipPort[1]
                }
            });

            var req = https.request({
                host: 'www.google.com',
                port: 80,
                agent: tunnelingAgent
            });

            req.on('data' , function(data){
                console.log(data);
            });

            req.on('error' , function(err){
                //console.log(err);
                if(err.toString().indexOf('Parse')>=0){
                    moduleEvents.emit('ip' , 'http://'+ip);
                    testIp();
                }
                else{
                    moduleEvents.emit('notify' , 'ip not alive');
                    testIp();
                }
            });
		}
        else{
		    if(STOP_SEARCH && (untestedIpIndex==untestedIps.length)){
		    	 console.log('All ips have been tested stopping testing phase');
                 moduleEvents.emit('done' , '');
			}
			else{
				return setTimeout(function(){
                    console.log('No ip yet');
					return testIp();
				} , 5000);
			}

		}

	}
	//Kick start the testing process
	testIp();

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//

	return moduleEvents;
};<commit_msg>updated<commit_after>/**This module searches for new ip addresses and tests them for validity**/
//Main process tells you to stop searching
//you return -1 for no tested ip found but search is still on
//you return -2 for no tested ip found and all untested ips have been tested and search has stopped
//Exports important functions to calling program
module.exports = function() {
	console.log('Search and test started');

	var request = require('request');
	var LineByLineReader = require('line-by-line');
    var tunnel = require('tunnel');
    var https = require('https');
    var EventEmitter = require('events').EventEmitter;
    var moduleEvents = new EventEmitter;
	var goodIps = [];
	var goodIpIndex = 0;

	var untestedIps = [];
	var untestedIpIndex=0;

	//
	var STOP_SEARCH =false;

	//Alternatives to gimmeproxy are
    //http://proxy.tekbreak.com/
    //https://happy-proxy.com/en
    //https://incloak.com/proxy-list/
    //https://kingproxies.com/register
    //http://www.getproxy.jp/en/api
    //https://getproxy.net/en/api/

    //gip = 41-45
    //gip1 = 36-40
    //gip2 = 21-25
    //gip3 = 1-5
    //gip4 = 6-10
    //gip5 = 11-15
    //gip6 = 16-20
    //gip7 = 26-30
    //gip8 = 31-35
    //gip9 = 46-50
    //gip10 = 51-55

	function getIp(){
		if(!STOP_SEARCH){
			 request.get('http://gimmeproxy.com/api/getProxy' , function(err , response , body){
				 if(err){
					 //console.log('cannot get ip address');
					 getIp();
				 }
				 else {
					 if(untestedIps.length > 2500){
						 STOP_SEARCH = true;
					 }
	                 try {
						 var rawIp = JSON.parse(body);

						 //
						 untestedIps.push(rawIp.ip);

						 setTimeout(function(){
						 	getIp();
						 } ,500)
					 }
					 catch (err) {
						   // Handle the error here.
						   //console.log(body);
						   setTimeout(function(){
						 	  getIp();
						   } ,500)
					 }

				 }
			 });
		}
		else{
			console.log('ip searching stopped');
			return;
		}
	};
    getIp();

	//
	var testIp = function(){
		if(untestedIpIndex<untestedIps.length){
			var ip = untestedIps[untestedIpIndex]+'';
            untestedIpIndex++;
            var ipPort = ip.split(':');
            console.log(ipPort);

            var tunnelingAgent = tunnel.httpsOverHttp({
                proxy: {
                    host: ipPort[0],
                    port: ipPort[1]
                }
            });

            var req = https.request({
                host: 'www.google.com',
                port: 80,
                agent: tunnelingAgent
            });

            req.on('data' , function(data){
                console.log(data);
            });

            req.on('error' , function(err){
                //console.log(err);
                if(err.toString().indexOf('Parse')>=0){
                    moduleEvents.emit('ip' , 'http://'+ip);
                    testIp();
                }
                else{
                    moduleEvents.emit('notify' , 'ip not alive');
                    testIp();
                }
            });
		}
        else{
		    if(STOP_SEARCH && (untestedIpIndex==untestedIps.length)){
		    	 console.log('All ips have been tested stopping testing phase');
                 moduleEvents.emit('done' , '');
			}
			else{
				return setTimeout(function(){
                    console.log('No ip yet');
					return testIp();
				} , 5000);
			}

		}

	}
	//Kick start the testing process
	testIp();

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//

	return moduleEvents;
};<|endoftext|>


<commit_before>import PostList from '../components/postlist.jsx';
import {useDeps, composeWithTracker, composeAll} from 'mantra-core';

export const composer = ({context}, onData) => {

  const fields = {
    posts: {
      _id: true,
      title: true,
      description: true,
      likecount: true,
      commentcount: true,
      username: true,
      created: true,
      owner: true,
    },
    postComments: {
      _id: true,
      created: true,
      username: true,
      description: true,
      post: true,
    }
  }
  let recordCount = {posts: 5}

  const {Meteor, Collections} = context();
  if (Meteor.subscribe('feed', fields, recordCount, null).ready()) {
    const posts = Collections.Posts.find().fetch();
    onData(null, {posts});
  }
};

export default composeAll(
  composeWithTracker(composer),
  useDeps()
)(PostList);
<commit_msg>posts module from Mantra sample working with new publication<commit_after>import PostList from '../components/postlist.jsx'
//import FeedList from '../../../core/components/FeedList.jsx';
import {useDeps, composeWithTracker, composeAll} from 'mantra-core';
import FeedDomain from '../../../core/actions/feed_domain.jsx'

export const composer = ({context}, onData) => {
  const {Meteor, Collections} = context();
  sweetAlert("title", "test")
  const fields = {
    posts: {
      _id: true,
      title: true,
      likecount: true,
      commentcount: true,
      username: true,
      created: true,
      owner: true,
    },
    postComments: {
      _id: true,
      created: true,
      username: true,
      description: true,
      post: true,
    }
  }
  let recordCount = {posts: 5}
  sweetAlert("fields.posts", Object.keys(fields.posts))
  sweetAlert("FeedDomain", Object.keys(FeedDomain))
  const feedposts = FeedDomain.getAllFeedPosts()
  sweetAlert("feedposts", feedposts)
  const postIds = FeedDomain.getPostCommentIds()
  sweetAlert("postIds", postIds)
  if (Meteor.subscribe("feed", fields, recordCount, postIds).ready()) {
    const posts = Collections.Posts.find().fetch();
    sweetAlert("success", Object.keys(posts[1]))
    onData(null, {posts});
  }

/*
  const fields = {
    posts: {
      _id: true,
      title: true,
      description: true,
      likecount: true,
      commentcount: true,
      username: true,
      created: true,
      owner: true,
    },
    postComments: {
      _id: true,
      created: true,
      username: true,
      description: true,
      post: true,
    }
  }
  let recordCount = {posts: 5}

  const {Meteor, Collections} = context();
  if (Meteor.subscribe('feed', fields, recordCount, null).ready()) {
    const posts = Collections.Posts.find().fetch();
    onData(null, {posts});
  }
*/
};

export default composeAll(
  composeWithTracker(composer),
  useDeps()
)(PostList);
<|endoftext|>