<commit_before>"use strict";
let express = require("express");
let router = express.Router(); // eslint-disable-line new-cap
let cache = require("apicache");
let log = require("winston");
let { db, sql } = require("../helpers/db");

/**
 * @api {get} /user/:userId Retrieve a user
 * @apiGroup users
 * @apiVersion 0.1.0
 * @apiName getUserById
 * @apiParam {Number} userId user ID
 *
 * @apiSuccess {Boolean} OK true if call was successful
 * @apiSuccess {data} User object if call was successful
 * @apiSuccess {String[]} errors List of error strings (when `OK` is false)
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *        OK: true
 *     }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */
router.get("/:userId", async function getUserById(req, res) {
  try {
    const user = await db.one(sql("../sql/user_by_id.sql"), {
      userId: req.params.userId,
      language: req.params.language || "en"
    });
    res.status(200).json({ OK: true, data: user });
  } catch (error) {
    log.error("Exception in GET /user/%s => %s", req.params.userId, error);
    res.status(500).json({ OK: false, error: error });
  }
});

/**
 * @api {delete} /user/:userId Delete a user
 * @apiGroup users
 * @apiVersion 0.1.0
 * @apiName deleteuser
 * @apiParam {Number} userId user ID
 *
 * @apiSuccess {Boolean} OK true if call was successful
 * @apiSuccess {String[]} errors List of error strings (when `OK` is false)
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *        OK: true
 *     }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */

router.delete("/:userId", function edituserById(req, res) {
  cache.clear();
  // let userId = req.swagger.params.userId.value;
  // let userBody = req.body;
  res.status(200).json(req.body);
});

module.exports = router;
<commit_msg>refactoring and use ensureUser<commit_after>"use strict";
let express = require("express");
let router = express.Router(); // eslint-disable-line new-cap
let cache = require("apicache");
let log = require("winston");
let { db, sql } = require("../helpers/db");
let { ensureUser } = require("../helpers/user");

async function getUserById(req, userId, res) {
  try {
    const user = await db.oneOrNone(sql("../sql/user_by_id.sql"), {
      userId: userId,
      language: req.params.language || "en"
    });
    console.log("GOT USER", user);
    res.status(200).json({ OK: true, data: user });
  } catch (error) {
    log.error("Exception in GET /user/%s => %s", req.params.userId, error);
    res.status(500).json({ OK: false, error: error });
  }
}

/**
 * @api {get} /user/:userId Retrieve a user
 * @apiGroup users
 * @apiVersion 0.1.0
 * @apiName getUserById
 * @apiParam {Number} userId user ID
 *
 * @apiSuccess {Boolean} OK true if call was successful
 * @apiSuccess {data} User object if call was successful
 * @apiSuccess {String[]} errors List of error strings (when `OK` is false)
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *        OK: true
 *     }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */
router.get("/:userId", function(req, res) {
  return getUserById(req, req.params.userId, res);
});

router.get("/", async function(req, res) {
  await ensureUser(req, res);
  return getUserById(req, req.user.user_id, res);
});

/**
 * @api {delete} /user/:userId Delete a user
 * @apiGroup users
 * @apiVersion 0.1.0
 * @apiName deleteuser
 * @apiParam {Number} userId user ID
 *
 * @apiSuccess {Boolean} OK true if call was successful
 * @apiSuccess {String[]} errors List of error strings (when `OK` is false)
 *
 * @apiSuccessExample Success-Response:
 *     HTTP/1.1 200 OK
 *     {
 *        OK: true
 *     }
 *
 * @apiError NotAuthenticated The user is not authenticated
 * @apiError NotAuthorized The user doesn't have permission to perform this operation.
 *
 */

router.delete("/:userId", function edituserById(req, res) {
  cache.clear();
  // let userId = req.swagger.params.userId.value;
  // let userBody = req.body;
  res.status(200).json(req.body);
});

module.exports = router;
<|endoftext|>


<commit_before>const Promise = require('bluebird');
const _ = require('lodash');
const rp = require('request-promise');
const StellarSdk = require('stellar-sdk');
const niceRound = require('./utils/niceRound');
const tradeWalker = require('./utils/tradeWalker');

const PQueue = require('p-queue');
const queue = new PQueue({concurrency: 20});
const run = queue.add;

const directory = require('../directory.json');

Server = new StellarSdk.Server('https://horizon.stellar.org');
StellarSdk.Network.usePublicNetwork();

function tickerGenerator() {
  let finish;
  let ticker = {
    _meta: {
      start: Math.floor(Date.now()/1000),
      startISO: Date(),
      apiLicense: 'Apache-2.0',
    },
  };

  let tickerPromise = Promise.resolve()
    .then(() => phase1(ticker))
    .then(() => loadAssets(ticker))
    .then(() => phase3(ticker))
    .then(() => {
      return {
        'v1/ticker.json': JSON.stringify(ticker, null, 2)
      };
    })

  return tickerPromise;
}

function phase1(ticker) {
  return Promise.all([
    getHorizonMain()
      .then(main => {
        ticker._meta.horizon = {
          core_latest_ledger: main.core_latest_ledger,
          network_passphrase: main.network_passphrase,
        }
      })
    ,
    getExternalPrices()
      .then(externalPrices => {
        ticker._meta.externalPrices = externalPrices;
      })
  ])
}

function loadAssets(ticker) {
  ticker.assets = [];

  ticker.assets.push({
    id: 'XLM-native',
    code: 'XLM',
    issuer: null,
    domain: 'native',
    slug: 'XLM-native',
    website: 'https://www.stellar.org/lumens/',
    price_XLM: 1, // LOL 1 dogecoin = 1 dogecoin; 1 lumen = 1 lumen
    price_USD: ticker._meta.externalPrices.USD_XLM,
  })
  _.each(directory.assets, (asset, id) => {
    let r = {};
    r.id = id;
    r.code = asset.code;
    r.issuer = asset.issuer;
    r.domain = asset.domain;
    r.slug = asset.code + '-' + asset.domain;
    r.website = directory.anchors[asset.domain].website;
    ticker.assets.push(r)
  });
}

function phase3(ticker) {
  ticker.pairs = {};
  _.each(directory.pairs, (pairData, id) => {
    ticker.pairs[id] = {
      baseBuying: pairData.baseBuying,
      counterSelling: pairData.counterSelling,
    };
  });

  return Promise.all(_.map(ticker.pairs, pair => {
    let baseBuying     = new StellarSdk.Asset(pair.baseBuying.code, pair.baseBuying.issuer);
    let counterSelling = new StellarSdk.Asset(pair.counterSelling.code, pair.counterSelling.issuer);
    return Server.orderbook(baseBuying, counterSelling).call()
      .then((res) => {
        if (res.bids.length === 0 || res.asks.length === 0) {
          return;
        }
        pair.bid = _.round(res.bids[0].price, 7);
        pair.ask = _.round(res.asks[0].price, 7);
        // pair.spread = _.round(1 - pair.bid/pair.ask, 4);
        pair.price = _.round((parseFloat(pair.bid) + parseFloat(pair.ask))/2, 7);

        return tradeWalker.walkUntil(Server, pair.baseBuying, pair.counterSelling, 86400)
          .then(tradesList => {
            pair.numTrades24h = tradesList.length;

            if (baseBuying.isNative()) {
              asset = _.find(ticker.assets, {
                code: pair.counterSelling.code,
                issuer: pair.counterSelling.issuer,
              });
              asset.price_XLM = niceRound(1/pair.price);
              asset.price_USD = niceRound(1/pair.price * ticker._meta.externalPrices.USD_XLM);
              pair.volume24h_XLM = niceRound(_.sumBy(tradesList, 'baseAmount'));
              asset.volume24h_XLM = pair.volume24h_XLM;
              asset.volume24h_USD = niceRound(pair.volume24h_XLM * ticker._meta.externalPrices.USD_XLM);
            } else if (counterSelling.isNative()) {
              asset = _.find(ticker.assets, {
                code: pair.baseBuying.code,
                issuer: pair.baseBuying.issuer,
              });
              asset.price_XLM = niceRound(pair.price);
              asset.price_USD = niceRound(pair.price * ticker._meta.externalPrices.USD_XLM);
              pair.volume24h_XLM = niceRound(_.sumBy(tradesList, 'counterAmount'));
              asset.volume24h_XLM = pair.volume24h_XLM;
              asset.volume24h_USD = niceRound(pair.volume24h_XLM * ticker._meta.externalPrices.USD_XLM);
            }
          })
      })
  }));
}

function getExternalPrices() {
  return Promise.all([
    getBtcPrice(),
    getLumenPrice(),
  ])
  .then(externalData => {
    return {
      USD_BTC: externalData[0],
      BTC_XLM: externalData[1],
      USD_XLM: _.round(externalData[0]*externalData[1],6),
    }
  })
}

function getBtcPrice() {
  return Promise.all([
    rp('https://api.coindesk.com/v1/bpi/currentprice.json')
      .then(data => {
        return _.round(JSON.parse(data).bpi.USD.rate_float, 3);
      })
      .catch(() => {
        return null;
      })
    ,
    rp('https://api.bitfinex.com/v2/ticker/tBTCUSD')
      .then(data => {
        return _.round(JSON.parse(data)[2], 3);
      })
      .catch(() => {
        return null;
      })
    ,
    rp('https://api.coinbase.com/v2/prices/spot?currency=USD')
      .then(data => {
        return _.round(JSON.parse(data).data.amount, 3);
      })
      .catch(() => {
        return null;
      })
    ,
    rp('https://api.kraken.com/0/public/Ticker?pair=XBTUSD')
      .then(data => {
        return _.round(JSON.parse(data).result.XXBTZUSD.c[0], 3);
      })
      .catch(() => {
        return null;
      })
  ])
  .then(allPrices => {
    return _.round(_.mean(_.filter(allPrices, price => price !== null)), 2);
  })
}

// Get lumen price in terms of btc
function getLumenPrice() {
  return Promise.all([
    rp('https://poloniex.com/public?command=returnTicker')
      .then(data => {
        return parseFloat(JSON.parse(data).BTC_STR.last);
      })
      .catch(() => {
        return null;
      })
    ,
    rp('https://bittrex.com/api/v1.1/public/getticker?market=BTC-XLM')
      .then(data => {
        return parseFloat(JSON.parse(data).result.Last);
      })
      .catch(() => {
        return null;
      })
    ,
    rp('https://api.kraken.com/0/public/Ticker?pair=XLMXBT')
      .then(data => {
        return parseFloat(JSON.parse(data).result.XXLMXXBT.c[0]);
      })
      .catch(() => {
        return null;
      })
  ])
  .then(allPrices => {
    return _.round(_.mean(_.filter(allPrices, price => price !== null)), 8);
  })
}

function getHorizonMain() {
  return rp('https://horizon.stellar.org/')
    .then(horizonMain => {
      return JSON.parse(horizonMain);
    })
}

module.exports = tickerGenerator;
<commit_msg>Add scoring system to ticker assets<commit_after>const Promise = require('bluebird');
const _ = require('lodash');
const rp = require('request-promise');
const StellarSdk = require('stellar-sdk');
const niceRound = require('./utils/niceRound');
const tradeWalker = require('./utils/tradeWalker');

const PQueue = require('p-queue');
const queue = new PQueue({concurrency: 20});
const run = queue.add;

const directory = require('../directory.json');

Server = new StellarSdk.Server('https://horizon.stellar.org');
StellarSdk.Network.usePublicNetwork();

function tickerGenerator() {
  let finish;
  let ticker = {
    _meta: {
      start: Math.floor(Date.now()/1000),
      startISO: Date(),
      apiLicense: 'Apache-2.0',
    },
  };

  let tickerPromise = Promise.resolve()
    .then(() => phase1(ticker))
    .then(() => loadAssets(ticker))
    .then(() => phase3(ticker))
    .then(() => phase4(ticker))
    .then(() => {
      return {
        'v1/ticker.json': JSON.stringify(ticker, null, 2)
      };
    })

  return tickerPromise;
}

function phase1(ticker) {
  return Promise.all([
    getHorizonMain()
      .then(main => {
        ticker._meta.horizon = {
          core_latest_ledger: main.core_latest_ledger,
          network_passphrase: main.network_passphrase,
        }
      })
    ,
    getExternalPrices()
      .then(externalPrices => {
        ticker._meta.externalPrices = externalPrices;
      })
  ])
}

function loadAssets(ticker) {
  ticker.assets = [];

  ticker.assets.push({
    id: 'XLM-native',
    code: 'XLM',
    issuer: null,
    domain: 'native',
    slug: 'XLM-native',
    website: 'https://www.stellar.org/lumens/',
    price_XLM: 1, // LOL 1 dogecoin = 1 dogecoin; 1 lumen = 1 lumen
    price_USD: ticker._meta.externalPrices.USD_XLM,
  })
  _.each(directory.assets, (asset, id) => {
    let r = {};
    r.id = id;
    r.code = asset.code;
    r.issuer = asset.issuer;
    r.domain = asset.domain;
    r.slug = asset.code + '-' + asset.domain;
    r.website = directory.anchors[asset.domain].website;
    ticker.assets.push(r)
  });
}

function phase3(ticker) {
  ticker.pairs = {};
  _.each(directory.pairs, (pairData, id) => {
    ticker.pairs[id] = {
      baseBuying: pairData.baseBuying,
      counterSelling: pairData.counterSelling,
    };
  });

  return Promise.all(_.map(ticker.pairs, pair => {
    let baseBuying     = new StellarSdk.Asset(pair.baseBuying.code, pair.baseBuying.issuer);
    let counterSelling = new StellarSdk.Asset(pair.counterSelling.code, pair.counterSelling.issuer);
    return Server.orderbook(baseBuying, counterSelling).call()
      .then((res) => {
        if (res.bids.length === 0 || res.asks.length === 0) {
          return;
        }
        pair.bid = _.round(res.bids[0].price, 7);
        pair.ask = _.round(res.asks[0].price, 7);
        pair.spread = _.round(1 - pair.bid/pair.ask, 4);
        pair.price = _.round((parseFloat(pair.bid) + parseFloat(pair.ask))/2, 7);

        return tradeWalker.walkUntil(Server, pair.baseBuying, pair.counterSelling, 86400)
          .then(tradesList => {
            pair.numTrades24h = tradesList.length;

            if (baseBuying.isNative()) {
              asset = _.find(ticker.assets, {
                code: pair.counterSelling.code,
                issuer: pair.counterSelling.issuer,
              });
              // TODO: Add num trades for other trade pairs too
              asset.numTrades24h = pair.numTrades24h;
              asset.spread = pair.spread;
              asset.price_XLM = niceRound(1/pair.price);
              asset.price_USD = niceRound(1/pair.price * ticker._meta.externalPrices.USD_XLM);
              pair.volume24h_XLM = niceRound(_.sumBy(tradesList, 'baseAmount'));
              asset.volume24h_XLM = pair.volume24h_XLM;
              asset.volume24h_USD = niceRound(pair.volume24h_XLM * ticker._meta.externalPrices.USD_XLM);
            } else if (counterSelling.isNative()) {
              asset = _.find(ticker.assets, {
                code: pair.baseBuying.code,
                issuer: pair.baseBuying.issuer,
              });
              // TODO: Add num trades for other trade pairs too
              asset.numTrades24h = pair.numTrades24h;
              asset.spread = pair.spread;
              asset.price_XLM = niceRound(pair.price);
              asset.price_USD = niceRound(pair.price * ticker._meta.externalPrices.USD_XLM);
              pair.volume24h_XLM = niceRound(_.sumBy(tradesList, 'counterAmount'));
              asset.volume24h_XLM = pair.volume24h_XLM;
              asset.volume24h_USD = niceRound(pair.volume24h_XLM * ticker._meta.externalPrices.USD_XLM);
            }
          })
      })
  }));
}

function phase4(ticker) {
  // Assign a score to each asset
  _.each(ticker.assets, asset => {
    if (asset.id === 'XLM-native') {
      asset.score = 100;
      return;
    }
    // Has orderbook relating to XLM
    if (asset.price_XLM === undefined) {
      asset.score = 0;
    }
    asset.score = 1;

    if (asset.volume24h_USD === undefined || asset.volume24h_USD === 0 || asset.volume24h_USD <= 10) {
      return;
    }

    // We want the score to be slightly more stable, so just a little spread can negatively influence
    // It's also a easy fix for issuers
    let spreadMultiplier = (1-asset.spread)*(1-asset.spread)*(1-asset.spread); // range: [0,1]

    // Volume really helps!
    let volumeScore = Math.log10(10 + asset.volume24h_USD);

    // numTrades is helpful too. Especially the first few num trades are important!
    let numTradesScore = Math.log10(asset.numTrades24h+10);

    asset.score = asset.score + spreadMultiplier*volumeScore*numTradesScore;
  });

  ticker.assets.sort((a,b) => {
    return b.score - a.score;
  });
}

function getExternalPrices() {
  return Promise.all([
    getBtcPrice(),
    getLumenPrice(),
  ])
  .then(externalData => {
    return {
      USD_BTC: externalData[0],
      BTC_XLM: externalData[1],
      USD_XLM: _.round(externalData[0]*externalData[1],6),
    }
  })
}

function getBtcPrice() {
  return Promise.all([
    rp('https://api.coindesk.com/v1/bpi/currentprice.json')
      .then(data => {
        return _.round(JSON.parse(data).bpi.USD.rate_float, 3);
      })
      .catch(() => {
        return null;
      })
    ,
    rp('https://api.bitfinex.com/v2/ticker/tBTCUSD')
      .then(data => {
        return _.round(JSON.parse(data)[2], 3);
      })
      .catch(() => {
        return null;
      })
    ,
    rp('https://api.coinbase.com/v2/prices/spot?currency=USD')
      .then(data => {
        return _.round(JSON.parse(data).data.amount, 3);
      })
      .catch(() => {
        return null;
      })
    ,
    rp('https://api.kraken.com/0/public/Ticker?pair=XBTUSD')
      .then(data => {
        return _.round(JSON.parse(data).result.XXBTZUSD.c[0], 3);
      })
      .catch(() => {
        return null;
      })
  ])
  .then(allPrices => {
    return _.round(_.mean(_.filter(allPrices, price => price !== null)), 2);
  })
}

// Get lumen price in terms of btc
function getLumenPrice() {
  return Promise.all([
    rp('https://poloniex.com/public?command=returnTicker')
      .then(data => {
        return parseFloat(JSON.parse(data).BTC_STR.last);
      })
      .catch(() => {
        return null;
      })
    ,
    rp('https://bittrex.com/api/v1.1/public/getticker?market=BTC-XLM')
      .then(data => {
        return parseFloat(JSON.parse(data).result.Last);
      })
      .catch(() => {
        return null;
      })
    ,
    rp('https://api.kraken.com/0/public/Ticker?pair=XLMXBT')
      .then(data => {
        return parseFloat(JSON.parse(data).result.XXLMXXBT.c[0]);
      })
      .catch(() => {
        return null;
      })
  ])
  .then(allPrices => {
    return _.round(_.mean(_.filter(allPrices, price => price !== null)), 8);
  })
}

function getHorizonMain() {
  return rp('https://horizon.stellar.org/')
    .then(horizonMain => {
      return JSON.parse(horizonMain);
    })
}

module.exports = tickerGenerator;
<|endoftext|>


<commit_before>import BaseTool from './BaseTool.js';
import EVENTS from './../../events.js';
import external from './../../externalModules.js';
import { getToolState } from '../../stateManagement/toolState.js';
import { globalImageIdSpecificToolStateManager } from '../../stateManagement/imageIdSpecificStateManager.js';
import isToolActive from './../../store/isToolActive.js';
import store from './../../store/index.js';
import triggerEvent from './../../util/triggerEvent.js';
import { getLogger } from './../../util/logger.js';

const logger = getLogger('baseBrushTool');
const { state, setters } = store.modules.brush;

/**
 * @abstract
 * @memberof Tools.Base
 * @classdesc Abstract class for tools which manipulate the mask data to be displayed on
 * the cornerstone canvas.
 * @extends Tools.Base.BaseTool
 */
class BaseBrushTool extends BaseTool {
  constructor(props, defaultProps = {}) {
    if (!defaultProps.configuration) {
      defaultProps.configuration = {};
    }
    defaultProps.configuration.referencedToolData = 'brush';
    super(props, defaultProps);

    this.updateOnMouseMove = true;
    this.hideDefaultCursor = true;

    this._drawing = false;
    this._drawingMouseUpCallback = this._drawingMouseUpCallback.bind(this);
  }

  // ===================================================================
  // Abstract Methods - Must be implemented.
  // ===================================================================

  /**
   * Helper function for rendering the brush.
   *
   * @abstract
   * @param {Object} evt - The event.
   * @returns {void}
   */
  // eslint-disable-next-line no-unused-vars
  renderBrush(evt) {
    throw new Error(`Method renderBrush not implemented for ${this.name}.`);
  }

  /**
   * Paints the data to the canvas.
   *
   * @protected
   * @abstract
   * @param  {Object} evt The event.
   * @returns {void}
   */
  // eslint-disable-next-line no-unused-vars
  _paint(evt) {
    throw new Error(`Method _paint not implemented for ${this.name}.`);
  }

  // ===================================================================
  // Virtual Methods - Have default behavior but may be overriden.
  // ===================================================================

  /**
   * Event handler for MOUSE_DRAG event.
   *
   * @override
   * @event
   * @param {Object} evt - The event.
   */
  mouseDragCallback(evt) {
    this._startPainting(evt);
  }

  /**
   * Event handler for MOUSE_DOWN event.
   *
   * @override
   * @event
   * @param {Object} evt - The event.
   */
  preMouseDownCallback(evt) {
    this._startPainting(evt);

    return true;
  }

  /**
   * Initialise painting with baseBrushTool
   *
   * @protected
   * @event
   * @param {Object} evt - The event.
   * @returns {void}
   */
  _startPainting(evt) {
    const eventData = evt.detail;
    const element = eventData.element;

    this._paint(evt);
    this._drawing = true;
    this._startListeningForMouseUp(element);
    this._lastImageCoords = eventData.currentPoints.image;
  }

  /**
   * Event handler for MOUSE_MOVE event.
   *
   * @override
   * @event
   * @param {Object} evt - The event.
   */
  mouseMoveCallback(evt) {
    const { currentPoints } = evt.detail;

    this._lastImageCoords = currentPoints.image;
  }

  /**
   * Event handler for switching mode to passive;
   *
   * @override
   * @event
   * @param {Object} evt - The event.
   */
  // eslint-disable-next-line no-unused-vars
  passiveCallback(evt) {
    try {
      external.cornerstone.updateImage(this.element);
    } catch (error) {
      // It is possible that the image has not been loaded
      // when this is called.
      return;
    }
  }

  /**
   * Used to redraw the tool's annotation data per render.
   *
   * @override
   * @param {Object} evt - The event.
   */
  renderToolData(evt) {
    const eventData = evt.detail;
    const element = eventData.element;

    // Only brush needs to render.
    if (isToolActive(element, this.name)) {
      // Call the hover event for the brush
      this.renderBrush(evt);
    }
  }

  // ===================================================================
  // Implementation interface
  // ===================================================================

  /**
   * Get the draw color (segmentation) of the tool.
   *
   * @protected
   * @param  {Number} drawId The id of the color (segmentation) to switch to.
   * @returns {string} The brush color in rgba format
   */
  _getBrushColor(drawId) {
    const colormap = external.cornerstone.colors.getColormap(state.colorMapId);
    const colorArray = colormap.getColor(drawId);

    if (this._drawing) {
      return `rgba(${colorArray[[0]]}, ${colorArray[[1]]}, ${
        colorArray[[2]]
      }, 1.0 )`;
    }

    return `rgba(${colorArray[[0]]}, ${colorArray[[1]]}, ${
      colorArray[[2]]
    }, 0.8 )`;
  }

  /**
   * Event handler for MOUSE_UP during the drawing event loop.
   *
   * @protected
   * @event
   * @param {Object} evt - The event.
   * @returns {void}
   */
  _drawingMouseUpCallback(evt) {
    const element = evt.detail.element;
    const imageId = evt.detail.image.imageId;

    this._drawing = false;
    this._mouseUpRender = true;

    let measurementData;
    const toolState = getToolState(element, this.name);

    logger.log(toolState);

    if (
      toolState[imageId] &&
      toolState[imageId].brush &&
      toolState[imageId].brush.data[0].pixelData
    ) {
      logger.log(toolState[imageId].brush);
      logger.log(toolState[imageId].brush.data[0]);
      measurementData = toolState;
    }

    const eventData = {
      toolType: this.name,
      element,
      measurementData,
      evtDetail: evt.detail,
    };

    triggerEvent(element, EVENTS.MEASUREMENT_COMPLETED, eventData);

    this._stopListeningForMouseUp(element);
  }

  /**
   * Adds modify loop event listeners.
   *
   * @protected
   * @param {Object} element - The viewport element to add event listeners to.
   * @modifies {element}
   * @returns {void}
   */
  _startListeningForMouseUp(element) {
    element.removeEventListener(EVENTS.MOUSE_UP, this._drawingMouseUpCallback);
    element.removeEventListener(
      EVENTS.MOUSE_CLICK,
      this._drawingMouseUpCallback
    );

    element.addEventListener(EVENTS.MOUSE_UP, this._drawingMouseUpCallback);
    element.addEventListener(EVENTS.MOUSE_CLICK, this._drawingMouseUpCallback);

    external.cornerstone.updateImage(element);
  }

  /**
   * Adds modify loop event listeners.
   *
   * @protected
   * @param {Object} element - The viewport element to add event listeners to.
   * @modifies {element}
   * @returns {void}
   */
  _stopListeningForMouseUp(element) {
    element.removeEventListener(EVENTS.MOUSE_UP, this._drawingMouseUpCallback);
    element.removeEventListener(
      EVENTS.MOUSE_CLICK,
      this._drawingMouseUpCallback
    );

    external.cornerstone.updateImage(element);
  }

  // ===================================================================
  // Segmentation API. This is effectively a wrapper around the store.
  // ===================================================================

  /**
   * Switches to the next segmentation color.
   *
   * @public
   * @api
   * @returns {void}
   */
  nextSegmentation() {
    const numberOfColors = this.constructor.getNumberOfColors();

    let drawId = state.drawColorId + 1;

    if (drawId === numberOfColors) {
      drawId = 0;
    }

    state.drawColorId = drawId;
  }

  /**
   * Switches to the previous segmentation color.
   *
   * @public
   * @api
   * @returns {void}
   */
  previousSegmentation() {
    const numberOfColors = this.constructor.getNumberOfColors();

    let drawId = state.drawColorId - 1;

    if (drawId < 0) {
      drawId = numberOfColors - 1;
    }

    state.drawColorId = drawId;
  }

  /**
   * Increases the brush size
   *
   * @public
   * @api
   * @returns {void}
   */
  increaseBrushSize() {
    const oldRadius = state.radius;
    let newRadius = Math.floor(oldRadius * 1.2);

    // If e.g. only 2 pixels big. Math.floor(2*1.2) = 2.
    // Hence, have minimum increment of 1 pixel.
    if (newRadius === oldRadius) {
      newRadius += 1;
    }

    setters.radius(newRadius);
  }

  /**
   * Decreases the brush size
   *
   * @public
   * @api
   * @returns {void}
   */
  decreaseBrushSize() {
    const oldRadius = state.radius;
    const newRadius = Math.floor(oldRadius * 0.8);

    setters.radius(newRadius);
  }

  /**
   * Displays a segmentation on the element.
   *
   * @public
   * @api
   * @param  {Number} segIndex        The index of the segmentation.
   * @returns {void}
   */
  showSegmentationOnElement(segIndex) {
    const enabledElement = this._getEnabledElement();
    const enabledElementUID = enabledElement.uuid;

    setters.brushVisibilityForElement(enabledElementUID, segIndex, true);

    external.cornerstone.updateImage(enabledElement.element);
  }

  /**
   * Hides a segmentation on an element.
   *
   * @public
   * @api
   * @param  {Number} segIndex        The index of the segmentation.
   * @returns {void}
   */
  hideSegmentationOnElement(segIndex) {
    const enabledElement = this._getEnabledElement();
    const enabledElementUID = enabledElement.uuid;

    setters.brushVisibilityForElement(enabledElementUID, segIndex, false);
    external.cornerstone.updateImage(enabledElement.element);
  }

  /**
   * Displays all segmentations on an element.
   *
   * @public
   * @api
   * @returns {void}
   */
  showAllSegmentationsOnElement() {
    const enabledElement = this._getEnabledElement();
    const enabledElementUID = enabledElement.uuid;
    const colormap = external.cornerstone.colors.getColormap(state.colorMapId);
    const numberOfColors = colormap.getNumberOfColors();

    for (let segIndex = 0; segIndex < numberOfColors; segIndex++) {
      setters.brushVisibilityForElement(enabledElementUID, segIndex, true);
    }

    external.cornerstone.updateImage(enabledElement.element);
  }

  /**
   * Hides all segmentations on an element.
   *
   * @public
   * @api
   * @returns {void}
   */
  hideAllSegmentationsOnElement() {
    const enabledElement = this._getEnabledElement();
    const enabledElementUID = enabledElement.uuid;
    const colormap = external.cornerstone.colors.getColormap(state.colorMapId);
    const numberOfColors = colormap.getNumberOfColors();

    for (let segIndex = 0; segIndex < numberOfColors; segIndex++) {
      setters.brushVisibilityForElement(enabledElementUID, segIndex, false);
    }

    external.cornerstone.updateImage(enabledElement.element);
  }

  /**
   * Returns the number of colors in the colormap.
   *
   * @static
   * @public
   * @api
   * @returns {Number} The number of colors in the color map.
   */
  static getNumberOfColors() {
    const colormap = external.cornerstone.colors.getColormap(state.colorMapId);

    return colormap.getNumberOfColors();
  }

  get alpha() {
    return state.alpha;
  }

  set alpha(value) {
    const enabledElement = this._getEnabledElement();

    state.alpha = value;
    external.cornerstone.updateImage(enabledElement.element);
  }

  get hiddenButActiveAlpha() {
    return state.hiddenButActiveAlpha;
  }

  set hiddenButActiveAlpha(value) {
    const enabledElement = this._getEnabledElement();

    state.hiddenButActiveAlpha = value;
    external.cornerstone.updateImage(enabledElement.element);
  }

  _getEnabledElement() {
    return external.cornerstone.getEnabledElement(this.element);
  }

  /**
   * Returns the toolData type assoicated with this type of tool.
   *
   * @static
   * @public
   * @returns {String} The number of colors in the color map.
   */
  static getReferencedToolDataName() {
    return 'brush';
  }

  /**
   * Invalidate all the brush data.
   *
   * @static
   * @public
   * @param {string} enabledElementUID - This identifier for the enabled element.
   * @returns {void}
   */
  static invalidateBrushOnEnabledElement(enabledElementUID) {
    /** WIP **/
    const element = store.getters.enabledElementByUID(enabledElementUID);

    const stackToolState = getToolState(element, 'stack');

    if (!stackToolState) {
      return;
    }

    const imageIds = stackToolState.data[0].imageIds;

    const toolState = globalImageIdSpecificToolStateManager.saveToolState();

    for (let i = 0; i < imageIds.length; i++) {
      const imageId = imageIds[i];

      if (toolState[imageId] && toolState[imageId].brush) {
        const brushData = toolState[imageId].brush.data;

        for (let j = 0; j < brushData.length; j++) {
          if (brushData[j].pixelData) {
            brushData[j].invalidated = true;
          }
        }
      }
    }

    external.cornerstone.updateImage(element, true);
  }

  /**
   * Returns a datacube for the segmentation.
   *
   * @static
   * @param {string} enabledElementUID - This identifier for the enabled element.
   * @returns {type}  description
   */
  static getDataAsVolume(enabledElementUID) {
    /** WIP **/
    const element = store.getters.enabledElementByUID(enabledElementUID);

    const stackToolState = getToolState(element, 'stack');

    if (!stackToolState) {
      return;
    }

    const imageIds = stackToolState.data[0].imageIds;

    const enabledElement = external.cornerstone.getEnabledElement(element);

    const image = enabledElement.image;

    const dim = {
      xy: image.columns * image.rows,
      z: image.rows,
      xyz: image.columns * image.rows * imageIds.length,
    };

    const toolState = globalImageIdSpecificToolStateManager.saveToolState();

    const buffer = new ArrayBuffer(dim.xyz);

    const uint8View = new Uint8Array(buffer);

    for (let i = 0; i < imageIds.length; i++) {
      const imageId = imageIds[i];

      // TODO -> Workout HTF we will do this for multiple colors etc.
      if (
        toolState[imageId] &&
        toolState[imageId].brush &&
        toolState[imageId].brush.data[0].pixelData
      ) {
        // ADD brush data to the location of that slice.
      }
    }
  }
}

export default BaseBrushTool;
<commit_msg>Use name, fallback to brush<commit_after>import BaseTool from './BaseTool.js';
import EVENTS from './../../events.js';
import external from './../../externalModules.js';
import { getToolState } from '../../stateManagement/toolState.js';
import { globalImageIdSpecificToolStateManager } from '../../stateManagement/imageIdSpecificStateManager.js';
import isToolActive from './../../store/isToolActive.js';
import store from './../../store/index.js';
import triggerEvent from './../../util/triggerEvent.js';
import { getLogger } from './../../util/logger.js';

const logger = getLogger('baseBrushTool');
const { state, setters } = store.modules.brush;

/**
 * @abstract
 * @memberof Tools.Base
 * @classdesc Abstract class for tools which manipulate the mask data to be displayed on
 * the cornerstone canvas.
 * @extends Tools.Base.BaseTool
 */
class BaseBrushTool extends BaseTool {
  constructor(props, defaultProps = {}) {
    if (!defaultProps.configuration) {
      defaultProps.configuration = {};
    }
    defaultProps.configuration.referencedToolData = 'brush';
    super(props, defaultProps);

    this.updateOnMouseMove = true;
    this.hideDefaultCursor = true;

    this._drawing = false;
    this._drawingMouseUpCallback = this._drawingMouseUpCallback.bind(this);
  }

  // ===================================================================
  // Abstract Methods - Must be implemented.
  // ===================================================================

  /**
   * Helper function for rendering the brush.
   *
   * @abstract
   * @param {Object} evt - The event.
   * @returns {void}
   */
  // eslint-disable-next-line no-unused-vars
  renderBrush(evt) {
    throw new Error(`Method renderBrush not implemented for ${this.name}.`);
  }

  /**
   * Paints the data to the canvas.
   *
   * @protected
   * @abstract
   * @param  {Object} evt The event.
   * @returns {void}
   */
  // eslint-disable-next-line no-unused-vars
  _paint(evt) {
    throw new Error(`Method _paint not implemented for ${this.name}.`);
  }

  // ===================================================================
  // Virtual Methods - Have default behavior but may be overriden.
  // ===================================================================

  /**
   * Event handler for MOUSE_DRAG event.
   *
   * @override
   * @event
   * @param {Object} evt - The event.
   */
  mouseDragCallback(evt) {
    this._startPainting(evt);
  }

  /**
   * Event handler for MOUSE_DOWN event.
   *
   * @override
   * @event
   * @param {Object} evt - The event.
   */
  preMouseDownCallback(evt) {
    this._startPainting(evt);

    return true;
  }

  /**
   * Initialise painting with baseBrushTool
   *
   * @protected
   * @event
   * @param {Object} evt - The event.
   * @returns {void}
   */
  _startPainting(evt) {
    const eventData = evt.detail;
    const element = eventData.element;

    this._paint(evt);
    this._drawing = true;
    this._startListeningForMouseUp(element);
    this._lastImageCoords = eventData.currentPoints.image;
  }

  /**
   * Event handler for MOUSE_MOVE event.
   *
   * @override
   * @event
   * @param {Object} evt - The event.
   */
  mouseMoveCallback(evt) {
    const { currentPoints } = evt.detail;

    this._lastImageCoords = currentPoints.image;
  }

  /**
   * Event handler for switching mode to passive;
   *
   * @override
   * @event
   * @param {Object} evt - The event.
   */
  // eslint-disable-next-line no-unused-vars
  passiveCallback(evt) {
    try {
      external.cornerstone.updateImage(this.element);
    } catch (error) {
      // It is possible that the image has not been loaded
      // when this is called.
      return;
    }
  }

  /**
   * Used to redraw the tool's annotation data per render.
   *
   * @override
   * @param {Object} evt - The event.
   */
  renderToolData(evt) {
    const eventData = evt.detail;
    const element = eventData.element;

    // Only brush needs to render.
    if (isToolActive(element, this.name)) {
      // Call the hover event for the brush
      this.renderBrush(evt);
    }
  }

  // ===================================================================
  // Implementation interface
  // ===================================================================

  /**
   * Get the draw color (segmentation) of the tool.
   *
   * @protected
   * @param  {Number} drawId The id of the color (segmentation) to switch to.
   * @returns {string} The brush color in rgba format
   */
  _getBrushColor(drawId) {
    const colormap = external.cornerstone.colors.getColormap(state.colorMapId);
    const colorArray = colormap.getColor(drawId);

    if (this._drawing) {
      return `rgba(${colorArray[[0]]}, ${colorArray[[1]]}, ${
        colorArray[[2]]
      }, 1.0 )`;
    }

    return `rgba(${colorArray[[0]]}, ${colorArray[[1]]}, ${
      colorArray[[2]]
    }, 0.8 )`;
  }

  /**
   * Event handler for MOUSE_UP during the drawing event loop.
   *
   * @protected
   * @event
   * @param {Object} evt - The event.
   * @returns {void}
   */
  _drawingMouseUpCallback(evt) {
    const element = evt.detail.element;
    const imageId = evt.detail.image.imageId;

    this._drawing = false;
    this._mouseUpRender = true;

    let measurementData;
    const toolState =
      getToolState(element, this.name) || getToolState(element, 'brush');

    logger.log(toolState);

    if (
      toolState[imageId] &&
      toolState[imageId].brush &&
      toolState[imageId].brush.data[0].pixelData
    ) {
      logger.log(toolState[imageId].brush);
      logger.log(toolState[imageId].brush.data[0]);
      measurementData = toolState;
    }

    const eventData = {
      toolType: this.name,
      element,
      measurementData,
      evtDetail: evt.detail,
    };

    triggerEvent(element, EVENTS.MEASUREMENT_COMPLETED, eventData);

    this._stopListeningForMouseUp(element);
  }

  /**
   * Adds modify loop event listeners.
   *
   * @protected
   * @param {Object} element - The viewport element to add event listeners to.
   * @modifies {element}
   * @returns {void}
   */
  _startListeningForMouseUp(element) {
    element.removeEventListener(EVENTS.MOUSE_UP, this._drawingMouseUpCallback);
    element.removeEventListener(
      EVENTS.MOUSE_CLICK,
      this._drawingMouseUpCallback
    );

    element.addEventListener(EVENTS.MOUSE_UP, this._drawingMouseUpCallback);
    element.addEventListener(EVENTS.MOUSE_CLICK, this._drawingMouseUpCallback);

    external.cornerstone.updateImage(element);
  }

  /**
   * Adds modify loop event listeners.
   *
   * @protected
   * @param {Object} element - The viewport element to add event listeners to.
   * @modifies {element}
   * @returns {void}
   */
  _stopListeningForMouseUp(element) {
    element.removeEventListener(EVENTS.MOUSE_UP, this._drawingMouseUpCallback);
    element.removeEventListener(
      EVENTS.MOUSE_CLICK,
      this._drawingMouseUpCallback
    );

    external.cornerstone.updateImage(element);
  }

  // ===================================================================
  // Segmentation API. This is effectively a wrapper around the store.
  // ===================================================================

  /**
   * Switches to the next segmentation color.
   *
   * @public
   * @api
   * @returns {void}
   */
  nextSegmentation() {
    const numberOfColors = this.constructor.getNumberOfColors();

    let drawId = state.drawColorId + 1;

    if (drawId === numberOfColors) {
      drawId = 0;
    }

    state.drawColorId = drawId;
  }

  /**
   * Switches to the previous segmentation color.
   *
   * @public
   * @api
   * @returns {void}
   */
  previousSegmentation() {
    const numberOfColors = this.constructor.getNumberOfColors();

    let drawId = state.drawColorId - 1;

    if (drawId < 0) {
      drawId = numberOfColors - 1;
    }

    state.drawColorId = drawId;
  }

  /**
   * Increases the brush size
   *
   * @public
   * @api
   * @returns {void}
   */
  increaseBrushSize() {
    const oldRadius = state.radius;
    let newRadius = Math.floor(oldRadius * 1.2);

    // If e.g. only 2 pixels big. Math.floor(2*1.2) = 2.
    // Hence, have minimum increment of 1 pixel.
    if (newRadius === oldRadius) {
      newRadius += 1;
    }

    setters.radius(newRadius);
  }

  /**
   * Decreases the brush size
   *
   * @public
   * @api
   * @returns {void}
   */
  decreaseBrushSize() {
    const oldRadius = state.radius;
    const newRadius = Math.floor(oldRadius * 0.8);

    setters.radius(newRadius);
  }

  /**
   * Displays a segmentation on the element.
   *
   * @public
   * @api
   * @param  {Number} segIndex        The index of the segmentation.
   * @returns {void}
   */
  showSegmentationOnElement(segIndex) {
    const enabledElement = this._getEnabledElement();
    const enabledElementUID = enabledElement.uuid;

    setters.brushVisibilityForElement(enabledElementUID, segIndex, true);

    external.cornerstone.updateImage(enabledElement.element);
  }

  /**
   * Hides a segmentation on an element.
   *
   * @public
   * @api
   * @param  {Number} segIndex        The index of the segmentation.
   * @returns {void}
   */
  hideSegmentationOnElement(segIndex) {
    const enabledElement = this._getEnabledElement();
    const enabledElementUID = enabledElement.uuid;

    setters.brushVisibilityForElement(enabledElementUID, segIndex, false);
    external.cornerstone.updateImage(enabledElement.element);
  }

  /**
   * Displays all segmentations on an element.
   *
   * @public
   * @api
   * @returns {void}
   */
  showAllSegmentationsOnElement() {
    const enabledElement = this._getEnabledElement();
    const enabledElementUID = enabledElement.uuid;
    const colormap = external.cornerstone.colors.getColormap(state.colorMapId);
    const numberOfColors = colormap.getNumberOfColors();

    for (let segIndex = 0; segIndex < numberOfColors; segIndex++) {
      setters.brushVisibilityForElement(enabledElementUID, segIndex, true);
    }

    external.cornerstone.updateImage(enabledElement.element);
  }

  /**
   * Hides all segmentations on an element.
   *
   * @public
   * @api
   * @returns {void}
   */
  hideAllSegmentationsOnElement() {
    const enabledElement = this._getEnabledElement();
    const enabledElementUID = enabledElement.uuid;
    const colormap = external.cornerstone.colors.getColormap(state.colorMapId);
    const numberOfColors = colormap.getNumberOfColors();

    for (let segIndex = 0; segIndex < numberOfColors; segIndex++) {
      setters.brushVisibilityForElement(enabledElementUID, segIndex, false);
    }

    external.cornerstone.updateImage(enabledElement.element);
  }

  /**
   * Returns the number of colors in the colormap.
   *
   * @static
   * @public
   * @api
   * @returns {Number} The number of colors in the color map.
   */
  static getNumberOfColors() {
    const colormap = external.cornerstone.colors.getColormap(state.colorMapId);

    return colormap.getNumberOfColors();
  }

  get alpha() {
    return state.alpha;
  }

  set alpha(value) {
    const enabledElement = this._getEnabledElement();

    state.alpha = value;
    external.cornerstone.updateImage(enabledElement.element);
  }

  get hiddenButActiveAlpha() {
    return state.hiddenButActiveAlpha;
  }

  set hiddenButActiveAlpha(value) {
    const enabledElement = this._getEnabledElement();

    state.hiddenButActiveAlpha = value;
    external.cornerstone.updateImage(enabledElement.element);
  }

  _getEnabledElement() {
    return external.cornerstone.getEnabledElement(this.element);
  }

  /**
   * Returns the toolData type assoicated with this type of tool.
   *
   * @static
   * @public
   * @returns {String} The number of colors in the color map.
   */
  static getReferencedToolDataName() {
    return 'brush';
  }

  /**
   * Invalidate all the brush data.
   *
   * @static
   * @public
   * @param {string} enabledElementUID - This identifier for the enabled element.
   * @returns {void}
   */
  static invalidateBrushOnEnabledElement(enabledElementUID) {
    /** WIP **/
    const element = store.getters.enabledElementByUID(enabledElementUID);

    const stackToolState = getToolState(element, 'stack');

    if (!stackToolState) {
      return;
    }

    const imageIds = stackToolState.data[0].imageIds;

    const toolState = globalImageIdSpecificToolStateManager.saveToolState();

    for (let i = 0; i < imageIds.length; i++) {
      const imageId = imageIds[i];

      if (toolState[imageId] && toolState[imageId].brush) {
        const brushData = toolState[imageId].brush.data;

        for (let j = 0; j < brushData.length; j++) {
          if (brushData[j].pixelData) {
            brushData[j].invalidated = true;
          }
        }
      }
    }

    external.cornerstone.updateImage(element, true);
  }

  /**
   * Returns a datacube for the segmentation.
   *
   * @static
   * @param {string} enabledElementUID - This identifier for the enabled element.
   * @returns {type}  description
   */
  static getDataAsVolume(enabledElementUID) {
    /** WIP **/
    const element = store.getters.enabledElementByUID(enabledElementUID);

    const stackToolState = getToolState(element, 'stack');

    if (!stackToolState) {
      return;
    }

    const imageIds = stackToolState.data[0].imageIds;

    const enabledElement = external.cornerstone.getEnabledElement(element);

    const image = enabledElement.image;

    const dim = {
      xy: image.columns * image.rows,
      z: image.rows,
      xyz: image.columns * image.rows * imageIds.length,
    };

    const toolState = globalImageIdSpecificToolStateManager.saveToolState();

    const buffer = new ArrayBuffer(dim.xyz);

    const uint8View = new Uint8Array(buffer);

    for (let i = 0; i < imageIds.length; i++) {
      const imageId = imageIds[i];

      // TODO -> Workout HTF we will do this for multiple colors etc.
      if (
        toolState[imageId] &&
        toolState[imageId].brush &&
        toolState[imageId].brush.data[0].pixelData
      ) {
        // ADD brush data to the location of that slice.
      }
    }
  }
}

export default BaseBrushTool;
<|endoftext|>


<commit_before>'use strict';

const { checkObject } = require('./validate');
const { assignObject } = require('./reduce');

// Similar to Lodash mapValues(), but with vanilla JavaScript
const mapValues = function (obj, mapperFunc) {
  return generalMap({ obj, mapperFunc, iterationFunc: mapValuesFunc });
};

const mapValuesFunc = function ({ key, obj, newValue }) {
  obj[key] = newValue;
  return obj;
};

// Similar to map() for keys
const mapKeys = function (obj, mapperFunc) {
  return generalMap({ obj, mapperFunc, iterationFunc: mapKeysFunc });
};

const mapKeysFunc = function ({ value, obj, newValue }) {
  obj[newValue] = value;
  return obj;
};

const generalMap = function ({ obj, mapperFunc, iterationFunc }) {
  checkObject(obj);

  return Object.entries(obj).reduce((newObj, [key, value]) => {
    const newValue = mapperFunc(value, key, obj);
    return iterationFunc({ value, key, obj: newObj, newValue });
  }, {});
};

// Same but async
const mapAsync = async function (obj, mapperFunc) {
  checkObject(obj);

  const promises = Object.entries(obj).map(([key, value]) => {
    const mappedVal = mapperFunc(value, key, obj);
    const promise = Promise.resolve(mappedVal);
    // eslint-disable-next-line promise/prefer-await-to-then
    return promise.then(val => ({ [key]: val }));
  });

  // Run in parallel
  const valuesArray = await Promise.all(promises);
  const valuesObj = valuesArray.reduce(assignObject, {});

  return valuesObj;
};

// Apply map() recursively
const recurseMap = function ({ value, mapperFunc, onlyLeaves = true }) {
  const isObject = value && value.constructor === Object;
  const isArray = Array.isArray(value);
  if (!isObject && !isArray) { return mapperFunc(value); }

  const nextValue = isObject
    ? mapValues(value, child => recurseMap({
      value: child,
      mapperFunc,
      onlyLeaves,
    }))
    : value.map(child => recurseMap({
      value: child,
      mapperFunc,
      onlyLeaves,
    }));
  if (onlyLeaves) { return nextValue; }

  return mapperFunc(nextValue);
};

// Like lodash mapValues(), but recursive and by reference
const recurseMapByRef = function ({ value: val, mapFunc }) {
  const cache = new WeakMap();

  const recurse = function ({ value, key, parent, parents, depth }) {
    // Avoids infinite recursions
    if (cache.has(value)) { return cache.get(value); }

    const nextParents = parents.concat(value);
    const mapVal = mapFunc({ value, key, parent, parents: nextParents, depth });

    if (mapVal && typeof mapVal === 'object') {
      cache.set(value, mapVal);
    }

    const nextDepth = depth + 1;

    if (mapVal && (mapVal.constructor === Object || Array.isArray(mapVal))) {
      for (const [childKey, child] of Object.entries(mapVal)) {
        mapVal[childKey] = recurse({
          value: child,
          key: childKey,
          parent: mapVal,
          parents: nextParents,
          depth: nextDepth,
        });
      }
    }

    return mapVal;
  };

  return recurse({
    value: val,
    key: null,
    parent: null,
    parents: [],
    depth: 0,
  });
};

module.exports = {
  mapValues,
  mapAsync,
  mapKeys,
  recurseMap,
  recurseMapByRef,
};
<commit_msg>Small refactoring<commit_after>'use strict';

const { checkObject } = require('./validate');
const { assignObject } = require('./reduce');

// Similar to Lodash mapValues(), but with vanilla JavaScript
const mapValues = function (obj, mapperFunc) {
  return generalMap({ obj, mapperFunc, iterationFunc: mapValuesFunc });
};

const mapValuesFunc = function ({ key, obj, newValue }) {
  obj[key] = newValue;
  return obj;
};

// Similar to map() for keys
const mapKeys = function (obj, mapperFunc) {
  return generalMap({ obj, mapperFunc, iterationFunc: mapKeysFunc });
};

const mapKeysFunc = function ({ value, obj, newValue }) {
  obj[newValue] = value;
  return obj;
};

const generalMap = function ({ obj, mapperFunc, iterationFunc }) {
  checkObject(obj);

  return Object.entries(obj).reduce((newObj, [key, value]) => {
    const newValue = mapperFunc(value, key, obj);
    return iterationFunc({ value, key, obj: newObj, newValue });
  }, {});
};

// Same but async
const mapAsync = async function (obj, mapperFunc) {
  checkObject(obj);

  const promises = Object.entries(obj).map(([key, value]) => {
    const mappedVal = mapperFunc(value, key, obj);
    const promise = Promise.resolve(mappedVal);
    // eslint-disable-next-line promise/prefer-await-to-then
    return promise.then(val => ({ [key]: val }));
  });

  // Run in parallel
  const valuesArray = await Promise.all(promises);
  const valuesObj = valuesArray.reduce(assignObject, {});

  return valuesObj;
};

// Apply map() recursively
const recurseMap = function ({ value, mapperFunc, onlyLeaves = true }) {
  const isObject = value && value.constructor === Object;
  const isArray = Array.isArray(value);
  if (!isObject && !isArray) { return mapperFunc(value); }

  const nextValue = isObject
    ? mapValues(value, child => recurseMap({
      value: child,
      mapperFunc,
      onlyLeaves,
    }))
    : value.map(child => recurseMap({
      value: child,
      mapperFunc,
      onlyLeaves,
    }));
  if (onlyLeaves) { return nextValue; }

  return mapperFunc(nextValue);
};

// Like lodash mapValues(), but recursive and by reference
const recurseMapByRef = function ({ value: val, mapFunc }) {
  const cache = new WeakMap();

  const recurse = function ({ value, key, parent, parents, depth }) {
    // Avoids infinite recursions
    if (cache.has(value)) { return cache.get(value); }

    const nextParents = parents.concat(value);
    const mapVal = mapFunc({ value, key, parent, parents: nextParents, depth });

    if (mapVal && typeof mapVal === 'object') {
      cache.set(value, mapVal);
    }

    if (mapVal && (mapVal.constructor === Object || Array.isArray(mapVal))) {
      for (const [childKey, child] of Object.entries(mapVal)) {
        mapVal[childKey] = recurse({
          value: child,
          key: childKey,
          parent: mapVal,
          parents: nextParents,
          depth: depth + 1,
        });
      }
    }

    return mapVal;
  };

  return recurse({
    value: val,
    key: null,
    parent: null,
    parents: [],
    depth: 0,
  });
};

module.exports = {
  mapValues,
  mapAsync,
  mapKeys,
  recurseMap,
  recurseMapByRef,
};
<|endoftext|>


<commit_before>/*
 Copyright (c) 2015, Per Bernhardsson
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following disclaimer in the documentation
 and/or other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
angular.module('lavan-cfs-image', ['angular-meteor'])
	.controller('CfsImageController', ['$scope', '$meteor', 'cfsImage',
		function ($scope, $meteor, cfsImage) {
			var self = $scope;
			$meteor.subscribe(cfsImage.subscription).then(function () {
				$meteor.autorun(self, function () {
					var imageId = self.getReactively('imageId');
					if (_.isEmpty(imageId))
						return;
					var store = self.getReactively('store');
					var query = _.isEmpty(store) ? {} : {store: store};
					var image = cfsImage.collection.findOne(imageId);
					if (_.isUndefined(image))
						self.imageUrl = "";
					else
						self.imageUrl = image.url(query);
				});
			});
		}
	])
	.directive('cfsImage', function () {
		return {
			scope: {
				imageId: '=',
				store: '@'
			},
			restrict: 'E',
			replace: true,
			template: '',
			controller: 'CfsImageController'
		}
	})
	.controller('CfsBackgroundController', ['$scope', '$meteor', 'cfsImage',
		function ($scope, $meteor, cfsImage) {
			var self = $scope;
			$meteor.subscribe(cfsImage.subscription).then(function () {
				$meteor.autorun(self, function () {
					var element = self.getReactively('element');
					if (_.isUndefined(element))
						return;
					var imageId = self.getReactively('cfsBackground');
					if (_.isEmpty(imageId))
						return;
					var store = self.getReactively('cfsStore');
					var position = self.getReactively('cfsPosition');
					var size = self.getReactively('cfsSize');
					var repeat = self.getReactively('cfsRepeat');
					var query = _.isEmpty(store) ? {} : {store: store};
					var image = cfsImage.collection.findOne(imageId);
					if (_.isUndefined(image))
						element.style.backgroundImage = '';
					else
						element.style.backgroundImage = 'url(' + image.url(query) + ')';
					if (!_.isUndefined(position))
						element.style.backgroundPosition = position;
					if (!_.isUndefined(size))
						element.style.backgroundSize = size;
					element.style.backgroundRepeat = repeat || 'no-repeat';
				});
			});
		}
	])
	.directive('cfsBackground', function () {
		return {
			scope: {
				cfsBackground: '=',
				cfsStore: '@',
				cfsPosition: '@',
				cfsSize: '@',
				cfsRepeat: '@'
			},
			restrict: 'A',
			controller: 'CfsBackgroundController',
			link: function (scope, element, attrs) {
				scope.element = element[0];
			}
		}
	})
	.provider('cfsImage', function () {
		// Default collection 'Images'.
		if (!_.isUndefined(Images)) {
			this.collection = Images;
		}
		// Default subscription 'images'.
		this.subscription = 'images';

		this.setCollection = function (collection) {
			this.collection = collection;
		};
		this.setSubscription = function (subscription) {
			this.subscription = subscription;
		};
		this.$get = function () {
			return this;
		};
	});
<commit_msg>Initial work for collection attribute.<commit_after>/*
 Copyright (c) 2015, Per Bernhardsson
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following disclaimer in the documentation
 and/or other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
angular.module('lavan-cfs-image', ['angular-meteor'])
	.controller('CfsImageController', ['$scope', '$meteor', 'cfsImage',
		function ($scope, $meteor, cfsImage) {
			var self = $scope;
			$meteor.subscribe(cfsImage.subscription).then(function () {
				$meteor.autorun(self, function () {
					var imageId = self.getReactively('imageId');
					if (_.isEmpty(imageId))
						return;
					var store = self.getReactively('store');
					var query = _.isEmpty(store) ? {} : {store: store};
					var image = cfsImage.collection.findOne(imageId);
					if (_.isUndefined(image))
						self.imageUrl = "";
					else
						self.imageUrl = image.url(query);
				});
			});
		}
	])
	.directive('cfsImage', function () {
		return {
			scope: {
				imageId: '=',
				store: '@',
				collection: '@'
			},
			restrict: 'E',
			replace: true,
			template: '',
			controller: 'CfsImageController'
		}
	})
	.controller('CfsBackgroundController', ['$scope', '$meteor', 'cfsImage',
		function ($scope, $meteor, cfsImage) {
			var self = $scope;
			$meteor.subscribe(cfsImage.subscription).then(function () {
				$meteor.autorun(self, function () {
					var element = self.getReactively('element');
					if (_.isUndefined(element))
						return;
					var imageId = self.getReactively('cfsBackground');
					if (_.isEmpty(imageId))
						return;
					var store = self.getReactively('cfsStore');
					var position = self.getReactively('cfsPosition');
					var size = self.getReactively('cfsSize');
					var repeat = self.getReactively('cfsRepeat');
					var query = _.isEmpty(store) ? {} : {store: store};
					var image = cfsImage.collection.findOne(imageId);
					if (_.isUndefined(image))
						element.style.backgroundImage = '';
					else
						element.style.backgroundImage = 'url(' + image.url(query) + ')';
					if (!_.isUndefined(position))
						element.style.backgroundPosition = position;
					if (!_.isUndefined(size))
						element.style.backgroundSize = size;
					element.style.backgroundRepeat = repeat || 'no-repeat';
				});
			});
		}
	])
	.directive('cfsBackground', function () {
		return {
			scope: {
				cfsBackground: '=',
				cfsStore: '@',
				cfsPosition: '@',
				cfsSize: '@',
				cfsRepeat: '@',
				cfsCollection: '@'
			},
			restrict: 'A',
			controller: 'CfsBackgroundController',
			link: function (scope, element, attrs) {
				scope.element = element[0];
			}
		}
	})
	.provider('cfsImage', function () {
		// Default collection 'Images'.
		if (!_.isUndefined(Images)) {
			this.collection = Images;
		}
		// Default subscription 'images'.
		this.subscription = 'images';

		this.setCollection = function (collection) {
			this.collection = collection;
		};
		this.setSubscription = function (subscription) {
			this.subscription = subscription;
		};
		this.$get = function () {
			return this;
		};
	});
<|endoftext|>


<commit_before>/*!
 * ${copyright}
 */

sap.ui.define(['jquery.sap.global'],
	function(jQuery) {
	"use strict";

	/**
	 * @class Slider renderer.
	 * @static
	 */
	var SliderRenderer = {};

	/**
	 * CSS class to be applied to the HTML root element of the Slider control.
	 *
	 * @type {string}
	 */
	SliderRenderer.CSS_CLASS = "sapMSlider";

	/**
	 * Renders the HTML for the given control, using the provided {@link sap.ui.core.RenderManager}.
	 *
	 * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the render output buffer.
	 * @param {sap.ui.core.Control} oSlider An object representation of the slider that should be rendered.
	 */
	SliderRenderer.render = function(oRm, oSlider) {
		var bEnabled = oSlider.getEnabled(),
			sTooltip = oSlider.getTooltip_AsString(),
			CSS_CLASS = SliderRenderer.CSS_CLASS;

		// avoid render when not visible
		if (!oSlider.getVisible()) {
			return;
		}

		oRm.write("
");
		oRm.write('
");

		if (oSlider.getProgress()) {
			this.renderProgressIndicator(oRm, oSlider);
		}

		this.renderHandle(oRm, oSlider);
		oRm.write("
");

		if (oSlider.getName()) {
			this.renderInput(oRm, oSlider);
		}

		oRm.write("
");
	};

	SliderRenderer.renderProgressIndicator = function(oRm, oSlider) {
		oRm.write("

");
	};

	SliderRenderer.renderHandle = function(oRm, oSlider) {
		var bEnabled = oSlider.getEnabled(),
			fValue = oSlider.getValue();

		oRm.write("<span");
		oRm.writeAttribute("id", oSlider.getId() + "-handle");
		oRm.writeAttribute("title", fValue);
		oRm.addClass(SliderRenderer.CSS_CLASS + "Handle");
		oRm.addStyle(sap.ui.getCore().getConfiguration().getRTL() ? "right" : "left", oSlider._sProgressValue);

		// WAI-ARIA
		oRm.writeAccessibilityState(oSlider, {
			role: "slider",
			orientation: "horizontal",
			valuemin: oSlider.getMin(),
			valuemax: oSlider.getMax(),
			valuenow: fValue,
			valuetext: fValue,
			live: "assertive",
			disabled: !bEnabled
		});

		oRm.writeClasses();
		oRm.writeStyles();

		if (bEnabled) {
			oRm.writeAttribute("tabindex", "0");
		}

		oRm.write(">");
	};

	SliderRenderer.renderInput = function(oRm, oSlider) {
		oRm.write('<input type="text"');
		oRm.writeAttribute("id", oSlider.getId() + "-input");
		oRm.addClass(SliderRenderer.CSS_CLASS + "Input");

		if (!oSlider.getEnabled()) {
			oRm.write("disabled");
		}

		oRm.writeClasses();
		oRm.writeAttributeEscaped("name", oSlider.getName());
		oRm.writeAttribute("value", oSlider.getValue());
		oRm.write("/>");
	};

	return SliderRenderer;

}, /* bExport= */ true);
<commit_msg>[INTERNAL] sap.m.SliderRenderer: initial commit<commit_after>/*!
 * ${copyright}
 */

sap.ui.define(['jquery.sap.global'],
	function(jQuery) {
		"use strict";

		/**
		 * @class Slider renderer.
		 * @static
		 */
		var SliderRenderer = {};

		/**
		 * CSS class to be applied to the HTML root element of the Slider control.
		 *
		 * @type {string}
		 */
		SliderRenderer.CSS_CLASS = "sapMSlider";

		/**
		 * Renders the HTML for the given control, using the provided {@link sap.ui.core.RenderManager}.
		 *
		 * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the render output buffer.
		 * @param {sap.ui.core.Control} oSlider An object representation of the slider that should be rendered.
		 */
		SliderRenderer.render = function(oRm, oSlider) {
			var bEnabled = oSlider.getEnabled(),
				sTooltip = oSlider.getTooltip_AsString(),
				CSS_CLASS = SliderRenderer.CSS_CLASS;

			// avoid render when not visible
			if (!oSlider.getVisible()) {
				return;
			}

			oRm.write("
");
			oRm.write('
");

			if (oSlider.getProgress()) {
				this.renderProgressIndicator(oRm, oSlider);
			}

			this.renderHandle(oRm, oSlider);
			oRm.write("
");

			if (oSlider.getName()) {
				this.renderInput(oRm, oSlider);
			}

			oRm.write("
");
		};

		SliderRenderer.renderProgressIndicator = function(oRm, oSlider) {
			oRm.write("

");
		};

		SliderRenderer.renderHandle = function(oRm, oSlider) {
			var bEnabled = oSlider.getEnabled(),
				fValue = oSlider.getValue();

			oRm.write("<span");
			oRm.writeAttribute("id", oSlider.getId() + "-handle");
			oRm.writeAttribute("title", fValue);
			oRm.addClass(SliderRenderer.CSS_CLASS + "Handle");
			oRm.addStyle(sap.ui.getCore().getConfiguration().getRTL() ? "right" : "left", oSlider._sProgressValue);

			// WAI-ARIA
			oRm.writeAccessibilityState(oSlider, {
				role: "slider",
				orientation: "horizontal",
				valuemin: oSlider.getMin(),
				valuemax: oSlider.getMax(),
				valuenow: fValue,
				valuetext: fValue,
				live: "assertive",
				disabled: !bEnabled
			});

			oRm.writeClasses();
			oRm.writeStyles();

			if (bEnabled) {
				oRm.writeAttribute("tabindex", "0");
			}

			oRm.write(">");
		};

		SliderRenderer.renderInput = function(oRm, oSlider) {
			oRm.write('<input type="text"');
			oRm.writeAttribute("id", oSlider.getId() + "-input");
			oRm.addClass(SliderRenderer.CSS_CLASS + "Input");

			if (!oSlider.getEnabled()) {
				oRm.write("disabled");
			}

			oRm.writeClasses();
			oRm.writeAttributeEscaped("name", oSlider.getName());
			oRm.writeAttribute("value", oSlider.getValue());
			oRm.write("/>");
		};

		return SliderRenderer;

	}, /* bExport= */ true);<|endoftext|>


<commit_before>var groebner = require('../groebner')
var helper = require('./algebrite')

function reduce_basis(generating){
	var variables = [];

	// do initial traversal to fill out variables list
	// note that it includes expressions which aren't
	// necessarily plain symbols
	for(var i = 0; i < generating.length; i++){
		var polynomial = generating[i];

		polynomial.forEach(term => {
			var monomial = term[0],
				coeff = term[1];
			monomial.forEach(bases => {
				var expr = bases[0],
					degree = bases[1];
				// check if expr exists in variables
				var index = helper.find_index(expr, variables);
				if(index == -1){
					generating = generating.concat(helper.generate_from_expr(expr))
					variables.push(expr);
				}
			})
		})
	}

	// console.log('with additional:')
	// generating.forEach(print_polynomial)

	// format it how groebner.js expects it
	// as an array of arrays of arrays of arrays

	var simple = generating.map(polynomial => {
		return polynomial.map(term => {
			var monomial = term[0],
				coeff = term[1];

			// initialize an empty array of same length as variables
			for(var base = [], i = 0; i < variables.length; i++)
				base[i] = 0;

			monomial.forEach(bases => {
				var expr = bases[0],
					degree = bases[1],
					index = helper.find_index(expr, variables);
				console.assert(typeof degree == 'number')
				base[index] = degree;
			})
			return [base, helper.rat2grob(coeff)];
		})
	})

	// console.log(JSON.stringify(simple))
	var gb = groebner.naive_buchberger(simple)
	// var gb = groebner.normal_strategy(simple)
	// console.log(JSON.stringify(gb))
	// console.log('check basis', groebner.is_groebner(gb))
	// console.log(JSON.stringify(gb))
	var gb_red = groebner.reduce_groebner(gb)
	// console.log(JSON.stringify(gb))
	// console.log('check post reduce', groebner.is_groebner(gb_red))
	// console.log('check is reduced', groebner.is_reduced(gb_red))
	// console.log(gb)

	// now that we've done the reduction, lets assemble
	// it back into the original form
	var reconstituted = gb_red.filter(nonzero_polynomial).map(polynomial => {
		return polynomial.map(term => {
			var base = term[0],
				coeff = term[1],
				monomial = [];
			for(var i = 0; i < base.length; i++){
				if(base[i] == 0) continue;
				monomial.push([variables[i], base[i]])
			}
			return [monomial, helper.grob2rat(coeff)]
		})
	})

	reconstituted.forEach(print_polynomial)

	return reconstituted
}

function check_basis(generating, expression){
	var variables = [];

	// do initial traversal to fill out variables list
	// note that it includes expressions which aren't
	// necessarily plain symbols
	for(var i = 0; i < generating.length; i++){
		var polynomial = generating[i];

		polynomial.forEach(term => {
			var monomial = term[0],
				coeff = term[1];
			monomial.forEach(bases => {
				var expr = bases[0],
					degree = bases[1];
				// check if expr exists in variables
				var index = helper.find_index(expr, variables);
				if(index == -1){
					variables.push(expr);
				}
			})
		})
	}

	var simple = generating.map(polynomial => {
		return polynomial.map(term => {
			var monomial = term[0],
				coeff = term[1];

			// initialize an empty array of same length as variables
			for(var base = [], i = 0; i < variables.length; i++)
				base[i] = 0;

			monomial.forEach(bases => {
				var expr = bases[0],
					degree = bases[1],
					index = helper.find_index(expr, variables);
				console.assert(typeof degree == 'number')
				console.assert(index != -1)
				base[index] = degree;
			})
			return [base, helper.rat2grob(coeff)];
		})
	})

	var poly = expression.map(term => {
		var monomial = term[0],
			coeff = term[1];

		// initialize an empty array of same length as variables
		for(var base = [], i = 0; i < variables.length; i++)
			base[i] = 0;

		monomial.forEach(bases => {
			var expr = bases[0],
				degree = bases[1],
				index = helper.find_index(expr, variables);
			console.assert(typeof degree == 'number')
			console.assert(index != -1)
			base[index] = degree;
		})
		return [base, helper.rat2grob(coeff)];
	})

	// console.log(JSON.stringify(poly))
	// console.log(JSON.stringify(simple))
	return groebner.check_polynomial(simple, poly)
}

function nonzero_polynomial(polynomial){

	return !(polynomial.length == 1 && polynomial[0][0].length == 0 && helper.is_zero(polynomial[0][1]))
}

function print_polynomial(polynomial){
	console.log(polynomial.map(term => {
		var monomial = term[0],
			coeff = term[1];

		return coeff + ' ' + monomial.map(bases => {
			var expr = bases[0],
				degree = bases[1];

			return '[' + expr + ']' + (degree == 1 ? '' : ('^' + degree))
		}).join(' ')
	}).join(' + '))
}

function is_inconsistent(basis){
	return basis.some(terms =>
		terms.length == 1 &&
			terms[0][0].length == 0)
}

function compare_basis(a, b){
	if(a.length != b.length) return false;
	for(var i = 0; i < a.length; i++){
		var pa = a[i],
			pb = b[i];

		if(pa.length != pb.length) return false;
		for(var j = 0; j < pa.length; j++){
			var ta = pa[j],
				tb = pb[j];

			// compare variables/monomials/expressions ta[0], tb[0]
			if(!helper.is_equal(ta[0], tb[0])) return false;

			// compare coefficients ta[1], tb[1]
			if(!helper.is_equal(ta[1], tb[1])) return false;

		}
	}
	return true
}

exports.extract_polynomial = helper.extract_polynomial
exports.check_basis = check_basis
exports.extract_terms = extract_terms
exports.compare_basis = compare_basis
exports.is_inconsistent = is_inconsistent
exports.print_polynomial = print_polynomial
exports.parse_polynomial = helper.parse_polynomial
exports.reduce_basis = reduce_basis<commit_msg>fixes<commit_after>var groebner = require('../groebner')
var helper = require('./algebrite')

function reduce_basis(generating){
	var variables = [];

	// do initial traversal to fill out variables list
	// note that it includes expressions which aren't
	// necessarily plain symbols
	for(var i = 0; i < generating.length; i++){
		var polynomial = generating[i];

		polynomial.forEach(term => {
			var monomial = term[0],
				coeff = term[1];
			monomial.forEach(bases => {
				var expr = bases[0],
					degree = bases[1];
				// check if expr exists in variables
				var index = helper.find_index(expr, variables);
				if(index == -1){
					generating = generating.concat(helper.generate_from_expr(expr))
					variables.push(expr);
				}
			})
		})
	}

	// console.log('with additional:')
	// generating.forEach(print_polynomial)

	// format it how groebner.js expects it
	// as an array of arrays of arrays of arrays

	var simple = generating.map(polynomial => {
		return polynomial.map(term => {
			var monomial = term[0],
				coeff = term[1];

			// initialize an empty array of same length as variables
			for(var base = [], i = 0; i < variables.length; i++)
				base[i] = 0;

			monomial.forEach(bases => {
				var expr = bases[0],
					degree = bases[1],
					index = helper.find_index(expr, variables);
				console.assert(typeof degree == 'number')
				base[index] = degree;
			})
			return [base, helper.rat2grob(coeff)];
		})
	})

	// console.log(JSON.stringify(simple))
	var gb = groebner.naive_buchberger(simple)
	// var gb = groebner.normal_strategy(simple)
	// console.log(JSON.stringify(gb))
	// console.log('check basis', groebner.is_groebner(gb))
	// console.log(JSON.stringify(gb))
	var gb_red = groebner.reduce_groebner(gb)
	// console.log(JSON.stringify(gb))
	// console.log('check post reduce', groebner.is_groebner(gb_red))
	// console.log('check is reduced', groebner.is_reduced(gb_red))
	// console.log(gb)

	// now that we've done the reduction, lets assemble
	// it back into the original form
	var reconstituted = gb_red.filter(nonzero_polynomial).map(polynomial => {
		return polynomial.map(term => {
			var base = term[0],
				coeff = term[1],
				monomial = [];
			for(var i = 0; i < base.length; i++){
				if(base[i] == 0) continue;
				monomial.push([variables[i], base[i]])
			}
			return [monomial, helper.grob2rat(coeff)]
		})
	})

	reconstituted.forEach(print_polynomial)

	return reconstituted
}

function check_basis(generating, expression){
	var variables = [];

	// do initial traversal to fill out variables list
	// note that it includes expressions which aren't
	// necessarily plain symbols
	for(var i = 0; i < generating.length; i++){
		var polynomial = generating[i];

		polynomial.forEach(term => {
			var monomial = term[0],
				coeff = term[1];
			monomial.forEach(bases => {
				var expr = bases[0],
					degree = bases[1];
				// check if expr exists in variables
				var index = helper.find_index(expr, variables);
				if(index == -1){
					variables.push(expr);
				}
			})
		})
	}

	var simple = generating.map(polynomial => {
		return polynomial.map(term => {
			var monomial = term[0],
				coeff = term[1];

			// initialize an empty array of same length as variables
			for(var base = [], i = 0; i < variables.length; i++)
				base[i] = 0;

			monomial.forEach(bases => {
				var expr = bases[0],
					degree = bases[1],
					index = helper.find_index(expr, variables);
				console.assert(typeof degree == 'number')
				console.assert(index != -1)
				base[index] = degree;
			})
			return [base, helper.rat2grob(coeff)];
		})
	})

	var poly = expression.map(term => {
		var monomial = term[0],
			coeff = term[1];

		// initialize an empty array of same length as variables
		for(var base = [], i = 0; i < variables.length; i++)
			base[i] = 0;

		monomial.forEach(bases => {
			var expr = bases[0],
				degree = bases[1],
				index = helper.find_index(expr, variables);
			console.assert(typeof degree == 'number')
			console.assert(index != -1)
			base[index] = degree;
		})
		return [base, helper.rat2grob(coeff)];
	})

	// console.log(JSON.stringify(poly))
	// console.log(JSON.stringify(simple))
	return groebner.check_polynomial(simple, poly)
}

function nonzero_polynomial(polynomial){

	return !(polynomial.length == 1 && polynomial[0][0].length == 0 && helper.is_zero(polynomial[0][1]))
}

function print_polynomial(polynomial){
	console.log(polynomial.map(term => {
		var monomial = term[0],
			coeff = term[1];

		return coeff + ' ' + monomial.map(bases => {
			var expr = bases[0],
				degree = bases[1];

			return '[' + expr + ']' + (degree == 1 ? '' : ('^' + degree))
		}).join(' ')
	}).join(' + '))
}

function is_inconsistent(basis){
	return basis.some(terms =>
		terms.length == 1 &&
			terms[0][0].length == 0)
}

function compare_basis(a, b){
	if(a.length != b.length) return false;
	for(var i = 0; i < a.length; i++){
		var pa = a[i],
			pb = b[i];

		if(pa.length != pb.length) return false;
		for(var j = 0; j < pa.length; j++){
			var ta = pa[j],
				tb = pb[j];

			// compare variables/monomials/expressions ta[0], tb[0]
			if(!helper.is_equal(ta[0], tb[0])) return false;

			// compare coefficients ta[1], tb[1]
			if(!helper.is_equal(ta[1], tb[1])) return false;

		}
	}
	return true
}

exports.extract_polynomial = helper.extract_polynomial
exports.check_basis = check_basis
exports.extract_terms = helper.extract_terms
exports.compare_basis = compare_basis
exports.is_inconsistent = is_inconsistent
exports.print_polynomial = print_polynomial
exports.parse_polynomial = helper.parse_polynomial
exports.reduce_basis = reduce_basis<|endoftext|>


<commit_before>$(document).ready(function(){

  get_consultas();
  function get_consultas(){
    $.ajax({
            type:"GET",
            url:"/ceup/Cconsultas/get_consultas/",
            dataType: 'json',
            success:function(res){
              $('#contenedor_tabla').empty();
              var contenido="";
              if (res) {
                for (i = 0; i < res.length; i++){
                  contenido+="
"+
                          ""+res[i]['con_id']+"	"+
                          ""+res[i]['fecha']+"	"+
                          " Dr(a). "+res[i]['med_ape']+" "+res[i]['med_nom']+"	"+
                          " Sr(a). "+res[i]['pac_ape']+" "+res[i]['pac_nom']+"	"+
                          ""+res[i]['bri_des']+"	"+
                          ""+
                              "
"+
                                "<button type='button' class='btn btn-default' data-conid='"+res[i]['con_id']+"'  data-pacnom='"+res[i]['pac_nom']+"' data-pacape='"+res[i]['pac_ape']+"' data-pacsex='"+res[i]['pac_sex']+"'  data-pacid='"+res[i]['pac_id']+"' onclick=carga_consulta_id($(this))>"+
                                ""+
                                "</button>"+

                                "<button type='button' data-target='#modalObservacion' data-toggle='modal' class='btn btn-default' onclick=$.verObservacion($(this).parent())>"+
                                ""+
                                "</button>"+

                              "
"+
                          "	"+
                        "
";
                };
              }
              var tabla="
"+
                        "
"+
                          "
"+
                            "Identificador	"+
                            "Fecha	"+
                            "Medico	"+
                            "Paciente	"+
                            "Brigada	"+
                            "Accion	"+
                          "
"+
                        "
"+
                        "
"+contenido
                        "
"+
                        "
";
              $('#contenedor_tabla').append(tabla);
              $('table').DataTable({"order": [[ 0, "desc" ]]} );
              limp_form_consulta();

            }
    });
  }

  function limp_form_consulta(){
    $('#cod_consulta').val('');
  }

  $('#btn_salir_gen').click(function(){
    $(location).attr('href','/ceup/cconsultas/start');

  });

	consultar_Brigadas();
	$('#divExamenes').hide();

	function consultar_Brigadas(){
	$('#sel_medico').empty();
	$.ajax({
		url:"/ceup/Cbrigada/get/",
		success:function(res){

			for(i=0;i<res.datos.length; i++){
				$('#sel_brigada').append($('<option>',
			     {
			        value: ""+res.datos[i]['bri_id'],
			        text : ""+res.datos[i]['bri_des']
			    }));
			}
			$('#sel_brigada').selectpicker('refresh');
			consultar_Especialidad();

		}
	});
}

function consultar_Especialidad(){
	$('#sel_especialidad').empty();
	$('#sel_medico').empty();
	$.ajax({
  			type:"GET",
  			data: {"id": $('#sel_brigada').val()},
			url:"/ceup/Cconsultas/get_especialidad/",
			dataType: 'json',
			success: function(res){
			if(res.datos.length>0){
				for(i=0;i<res.datos.length; i++){
				$('#sel_especialidad').append($('<option>',
			     {
			        value: ""+res.datos[i]['esp_cod'],
			        text : ""+res.datos[i]['esp_des']
			    }));
			}
			}else {
				$('#sel_medico').empty();
				$('#dbm_id').val("");
				toastr.options={"progressBar": true}
                toastr.error('No se encontraron medicos Disponibles','Estado');

			}
			$('#sel_especialidad').selectpicker('refresh');
			$('#sel_medico').selectpicker('refresh');
			consultar_Medico();

			}
		});
}

$.verObservacion = function(td){
    var tr = $(td).parent().parent();
    $('#con_obs').val($(tr).attr('data-observacion'));
    $('#con_id').val($(tr).attr('data-id'));

  }

$('#guardarObservacion').on('click',function(){
   $.ajax({
      type:'POST',
      data:{'observacion':$('#con_obs').val(),'id_consulta':$('#con_id').val()},
      dataType:'json',
      url:'/ceup/Cconsultas/save_observacion/',
      success:function(data){
        toastr.options={"progressBar": true}
        toastr.success('Observcion Editada ','Estado');
        $('#modalObservacion').modal('hide');
        get_consultas();
      },error:function(textStatus){
        toastr.options={"progressBar": true}
        toastr.error('Error al Editar Observacion ','Estado');
      }
  });
});

function consultar_Medico(){
	$('#sel_medico').empty();
  		$.ajax({
  			type:"GET",
  			data: {"id": $('#sel_brigada').val(),"id_es":$('#sel_especialidad').val()},
			url:"/ceup/Cconsultas/get_medico/",
			dataType: 'json',
			success: function(res){
			if(res.datos.length>0){
				for(i=0;i<res.datos.length; i++){
				$('#sel_medico').append($('<option>',
			     {
			        value: ""+res.datos[i]['med_cod'],
			        text : ""+res.datos[i]['med_nom'] +" "+res.datos[i]['med_ape']
			    }));
			}
			}else {
				$('#sel_medico').empty();
				toastr.options={"progressBar": true}
                toastr.error('No se encontraron medicos Disponibles','Estado');
			}
			$('#sel_medico').selectpicker('refresh');
			consultar_dmb();
			}
		});
}

function consultar_dmb(){
	$('#dbm_id').val("");
  		$.ajax({
  			type:"GET",
  			data: {"bri_id": $('#sel_brigada').val(),"med_id":$('#sel_medico').val()},
			url:"/ceup/Cconsultas/get_dbm/",
			dataType: 'json',
			success: function(res){
			if(res.datos.length>0){
				for(i=0;i<res.datos.length; i++){
				$('#dbm_id').val(res.datos[i]['dbm_id']);
			}
			}else {

				        toastr.options={"progressBar": true}
                toastr.error('No se encontraron ','Estado');
			}
			}
		});
}

	$('#sel_brigada').on('change', function() {

  		consultar_Especialidad();

	});

	$('#dat_paci').hide();

  $('#btn_buscar').click(function(){
		buscar_paciente();
	});

		$('#sel_especialidad').on('change', function() {
  			consultar_Medico();
		});

		$('#sel_medico').on('change', function() {
  			consultar_dmb();
		});

$(function(){
        $("#frmConsulta").validate({
                rules: {
                    sel_brigada: { required: true},
                    sel_especialidad: { required: true},
                    sel_medico: { required: true},
                    id_pac:{required: true}
                },
                messages: {
                    input: { required: "required" },
                    sel_brigada: { required: "seleccione una brigada"},
                    sel_especialidad: { required: "seleccione una especialidad"},
                    sel_medico: { required: "seleccione un medico"},
                    id_pac:{required: "seleccione un paciente"}
                },
                ignore:      "",
                errorClass:  'fieldError',
                onkeyup:     false,
                onblur:      false,
                errorElement:'label',
                submitHandler: function() {

    				$.ajax({
    					url:"/ceup/Cconsultas/add/",
    					type: "POST",
              			data: {'dbm_id':$('#dbm_id').val(),
              					'pac_id':$('#pac_cod').val(),
              					'con_observacion':$('#con_observacion').val()},
              			dataType:"json",
              			success:function(res){
              				$('#dat_paci').append("
Datos de Consulta

codigo de Consulta :"+res+"
")
              				$('#cod_consulta').val(res);
              				$('#divFrmEsp').hide("slow");
              				$('#divExamenes').show();
              				$('#btn_salir').removeClass("hidden");
                      toastr.options={"progressBar": true}
							        toastr.success('Nueva Consulta Generada','Estado');
                      $('#btn_salir_gen').removeClass("hidden");

              			},
              			error: function(response){
							//$.notify("Error al editar paciente","error");
						toastr.options={"progressBar": true}
						toastr.error('Error al Guardar la Consulta','Estado');
			}

    				});
                }
            });

        $("#sub_boton").click(function(){
            $("#frmConsulta").submit();
            return false;
        });
    });

function buscar_paciente () {
  $('#pac_cod').val("");
    $.ajax({
        type:"GET",
        data: {"ced_pac": $('#input_ced_pac').val()},
      url:"/ceup/Cpaciente/get_one/",
      dataType: 'json',
      success: function(res){
      if(res.datos.length>0){
        $('#dat_paci').empty();
        $('#dat_paci').show();
        for(i=0;i<res.datos.length; i++){
        $('#dat_pac').empty();
        $('#dat_paci').append("
Datos de paciente

nombres :"+res.datos[i]['pac_nom']+"

Apellidos :"+res.datos[i]['pac_ape']+"

 sexo :"+res.datos[i]['pac_sex']+"
");
        $('#pac_cod').val(res.datos[i]['pac_id'])
        $('#dat_paci').show(3000);
        toastr.options={"progressBar": true}
                toastr.success('Datos de paciente cargados','Estado');
      }
      }else {
        $("#dat_paci").empty();
        $('#dat_paci').hide("slow");
        $('#pac_cod').val("");
        toastr.options={"progressBar": true}
                toastr.error('No se encuentra registrado el paciente','Estado');
      }
      }
    });
}

});

  function carga_consulta_id(boton) {
    $('#dat_paci').empty();
    $('#dat_paci').show();
    $('#dat_pac').empty();
    $('#dat_paci').append("
Datos de paciente

nombres :"+$(boton).attr("data-pacnom")+"

Apellidos :"+$(boton).attr("data-pacape")+"

 sexo :"+$(boton).attr("data-pacsex")+"
");
    $('#pac_cod').val($(boton).attr("data-pacid"));
    $('#dat_paci').show(3000);
    $('#dat_paci').append("
Datos de Consulta

codigo de Consulta :"+$(boton).attr("data-conid")+"
");
    $('#cod_consulta').val($(boton).attr("data-conid"));
    $('#divFrmEsp').hide("slow");
    $('#divExamenes').show();
    $('#btn_salir').removeClass("hidden");
    $('#btn_salir_gen').removeClass("hidden");

  }<commit_msg>Ultimo commit consultas on top accordion<commit_after>$(document).ready(function(){

  get_consultas();
  function get_consultas(){
    $.ajax({
            type:"GET",
            url:"/ceup/Cconsultas/get_consultas/",
            dataType: 'json',
            success:function(res){
              $('#contenedor_tabla').empty();
              var contenido="";
              if (res) {
                for (i = 0; i < res.length; i++){
                  contenido+="
"+
                          ""+res[i]['con_id']+"	"+
                          ""+res[i]['fecha']+"	"+
                          " Dr(a). "+res[i]['med_ape']+" "+res[i]['med_nom']+"	"+
                          " Sr(a). "+res[i]['pac_ape']+" "+res[i]['pac_nom']+"	"+
                          ""+res[i]['bri_des']+"	"+
                          ""+
                              "
"+
                                "<button type='button' class='btn btn-default' data-conid='"+res[i]['con_id']+"'  data-pacnom='"+res[i]['pac_nom']+"' data-pacape='"+res[i]['pac_ape']+"' data-pacsex='"+res[i]['pac_sex']+"'  data-pacid='"+res[i]['pac_id']+"' onclick=carga_consulta_id($(this))>"+
                                ""+
                                "</button>"+

                                "<button type='button' data-target='#modalObservacion' data-toggle='modal' class='btn btn-default' onclick=$.verObservacion($(this).parent())>"+
                                ""+
                                "</button>"+

                              "
"+
                          "	"+
                        "
";
                };
              }
              var tabla="
"+
                        "
"+
                          "
"+
                            "Identificador	"+
                            "Fecha	"+
                            "Medico	"+
                            "Paciente	"+
                            "Brigada	"+
                            "Accion	"+
                          "
"+
                        "
"+
                        "
"+contenido
                        "
"+
                        "
";
              $('#contenedor_tabla').append(tabla);
              $('table').DataTable({"order": [[ 0, "desc" ]]} );
              limp_form_consulta();

            }
    });
  }

  function limp_form_consulta(){
    $('#cod_consulta').val('');
  }

  $('#btn_salir_gen').click(function(){
    $(location).attr('href','/ceup/cconsultas/start');

  });

	consultar_Brigadas();
	$('#divExamenes').hide();

	function consultar_Brigadas(){
	$('#sel_medico').empty();
	$.ajax({
		url:"/ceup/Cbrigada/get/",
		success:function(res){

			for(i=0;i<res.datos.length; i++){
				$('#sel_brigada').append($('<option>',
			     {
			        value: ""+res.datos[i]['bri_id'],
			        text : ""+res.datos[i]['bri_des']
			    }));
			}
			$('#sel_brigada').selectpicker('refresh');
			consultar_Especialidad();

		}
	});
}

function consultar_Especialidad(){
	$('#sel_especialidad').empty();
	$('#sel_medico').empty();
	$.ajax({
  			type:"GET",
  			data: {"id": $('#sel_brigada').val()},
			url:"/ceup/Cconsultas/get_especialidad/",
			dataType: 'json',
			success: function(res){
			if(res.datos.length>0){
				for(i=0;i<res.datos.length; i++){
				$('#sel_especialidad').append($('<option>',
			     {
			        value: ""+res.datos[i]['esp_cod'],
			        text : ""+res.datos[i]['esp_des']
			    }));
			}
			}else {
				$('#sel_medico').empty();
				$('#dbm_id').val("");
				toastr.options={"progressBar": true}
                toastr.error('No se encontraron medicos Disponibles','Estado');

			}
			$('#sel_especialidad').selectpicker('refresh');
			$('#sel_medico').selectpicker('refresh');
			consultar_Medico();

			}
		});
}

$.verObservacion = function(td){
    var tr = $(td).parent().parent();
    $('#con_obs').val($(tr).attr('data-observacion'));
    $('#con_id').val($(tr).attr('data-id'));

  }

$('#guardarObservacion').on('click',function(){
   $.ajax({
      type:'POST',
      data:{'observacion':$('#con_obs').val(),'id_consulta':$('#con_id').val()},
      dataType:'json',
      url:'/ceup/Cconsultas/save_observacion/',
      success:function(data){
        toastr.options={"progressBar": true}
        toastr.success('Observcion Editada ','Estado');
        $('#modalObservacion').modal('hide');
        get_consultas();
      },error:function(textStatus){
        toastr.options={"progressBar": true}
        toastr.error('Error al Editar Observacion ','Estado');
      }
  });
});

function consultar_Medico(){
	$('#sel_medico').empty();
  		$.ajax({
  			type:"GET",
  			data: {"id": $('#sel_brigada').val(),"id_es":$('#sel_especialidad').val()},
			url:"/ceup/Cconsultas/get_medico/",
			dataType: 'json',
			success: function(res){
			if(res.datos.length>0){
				for(i=0;i<res.datos.length; i++){
				$('#sel_medico').append($('<option>',
			     {
			        value: ""+res.datos[i]['med_cod'],
			        text : ""+res.datos[i]['med_nom'] +" "+res.datos[i]['med_ape']
			    }));
			}
			}else {
				$('#sel_medico').empty();
				toastr.options={"progressBar": true}
                toastr.error('No se encontraron medicos Disponibles','Estado');
			}
			$('#sel_medico').selectpicker('refresh');
			consultar_dmb();
			}
		});
}

function consultar_dmb(){
	$('#dbm_id').val("");
  		$.ajax({
  			type:"GET",
  			data: {"bri_id": $('#sel_brigada').val(),"med_id":$('#sel_medico').val()},
			url:"/ceup/Cconsultas/get_dbm/",
			dataType: 'json',
			success: function(res){
			if(res.datos.length>0){
				for(i=0;i<res.datos.length; i++){
				$('#dbm_id').val(res.datos[i]['dbm_id']);
			}
			}else {

				        toastr.options={"progressBar": true}
                toastr.error('No se encontraron ','Estado');
			}
			}
		});
}

	$('#sel_brigada').on('change', function() {

  		consultar_Especialidad();

	});

	$('#dat_paci').hide();

  $('#btn_buscar').click(function(){
		buscar_paciente();
	});

		$('#sel_especialidad').on('change', function() {
  			consultar_Medico();
		});

		$('#sel_medico').on('change', function() {
  			consultar_dmb();
		});

$(function(){
        $("#frmConsulta").validate({
                rules: {
                    sel_brigada: { required: true},
                    sel_especialidad: { required: true},
                    sel_medico: { required: true},
                    id_pac:{required: true}
                },
                messages: {
                    input: { required: "required" },
                    sel_brigada: { required: "seleccione una brigada"},
                    sel_especialidad: { required: "seleccione una especialidad"},
                    sel_medico: { required: "seleccione un medico"},
                    id_pac:{required: "seleccione un paciente"}
                },
                ignore:      "",
                errorClass:  'fieldError',
                onkeyup:     false,
                onblur:      false,
                errorElement:'label',
                submitHandler: function() {

    				$.ajax({
    					url:"/ceup/Cconsultas/add/",
    					type: "POST",
              			data: {'dbm_id':$('#dbm_id').val(),
              					'pac_id':$('#pac_cod').val(),
              					'con_observacion':$('#con_observacion').val()},
              			dataType:"json",
              			success:function(res){
              				$('#dat_paci').append("
Datos de Consulta

codigo de Consulta :"+res+"
")
              				$('#cod_consulta').val(res);
              				$('#divFrmEsp').hide("slow");
              				$('#divExamenes').show();
              				$('#btn_salir').removeClass("hidden");
                      toastr.options={"progressBar": true}
							        toastr.success('Nueva Consulta Generada','Estado');
                      $('#btn_salir_gen').removeClass("hidden");

              			},
              			error: function(response){
							//$.notify("Error al editar paciente","error");
						toastr.options={"progressBar": true}
						toastr.error('Error al Guardar la Consulta','Estado');
			}

    				});
                }
            });

        $("#sub_boton").click(function(){
            $("#frmConsulta").submit();
            return false;
        });
    });

function buscar_paciente () {
  $('#pac_cod').val("");
    $.ajax({
        type:"GET",
        data: {"ced_pac": $('#input_ced_pac').val()},
      url:"/ceup/Cpaciente/get_one/",
      dataType: 'json',
      success: function(res){
      if(res.datos.length>0){
        $('#dat_paci').empty();
        $('#dat_paci').show();
        for(i=0;i<res.datos.length; i++){
        $('#dat_pac').empty();
        $('#dat_paci').append("
Datos de paciente

nombres :"+res.datos[i]['pac_nom']+"

Apellidos :"+res.datos[i]['pac_ape']+"

 sexo :"+res.datos[i]['pac_sex']+"
");
        $('#pac_cod').val(res.datos[i]['pac_id'])
        $('#dat_paci').show(3000);
        toastr.options={"progressBar": true}
                toastr.success('Datos de paciente cargados','Estado');
      }
      }else {
        $("#dat_paci").empty();
        $('#dat_paci').hide("slow");
        $('#pac_cod').val("");
        toastr.options={"progressBar": true}
                toastr.error('No se encuentra registrado el paciente','Estado');
      }
      }
    });
}

});

  function carga_consulta_id(boton) {
    $('#dat_paci').empty();
    $('#dat_paci').show();
    $('#dat_pac').empty();
    $('#dat_paci').append("
Datos de paciente

nombres :"+$(boton).attr("data-pacnom")+"

Apellidos :"+$(boton).attr("data-pacape")+"

 sexo :"+$(boton).attr("data-pacsex")+"
");
    $('#pac_cod').val($(boton).attr("data-pacid"));
    $('#dat_paci').show(3000);
    $('#dat_paci').append("
Datos de Consulta

codigo de Consulta :"+$(boton).attr("data-conid")+"
");
    $('#cod_consulta').val($(boton).attr("data-conid"));
    $('#divFrmEsp').hide("slow");
    $('#divExamenes').show();
    $('#btn_salir').removeClass("hidden");
    $('#btn_salir_gen').removeClass("hidden");
    $('html,body').animate({
                 scrollTop: $("#accordion2").offset().top
                 }, 2000);

  }<|endoftext|>