<commit_before>var formatters = require('../../lib/formatters'),
	helper = require('./helper');

exports.options = {
  logoURL: 'https://pagar.me/assets/boleto/images/bradesco.jpg',
  codigo: '237'
}

exports.dvBarra = function(barra) {
  var resto2 = formatters.mod11(barra, 9, 1);
  return (resto2 == 0 || resto2 == 1 || resto2 == 10) ? 1 : 11 - resto2;
}

exports.barcodeData = function(boleto){
  var codigoBanco = this.options.codigo;
  var numMoeda = "9";
  var fixo = "9"; // Numero fixo para a posição 05-05

  var fatorVencimento = formatters.fatorVencimento(boleto['data_vencimento']);

  var agencia = formatters.addTrailingZeros(boleto['agencia'], 4);

  var valor = formatters.addTrailingZeros(boleto['valor'], 10);
  var carteira = boleto['carteira'];
  var codigoCedente = formatters.addTrailingZeros(boleto['codigo_cedente'], 7);

  var nossoNumero = carteira + formatters.addTrailingZeros(boleto['nosso_numero'], 11);

  var barra = codigoBanco + numMoeda + fatorVencimento + valor + agencia + nossoNumero + codigoCedente + '0';

  var dvBarra = this.dvBarra(barra);
  var lineData = barra.substring(0, 4) + dvBarra + barra.substring(4, barra.length);

  return lineData;
}

exports.linhaDigitavel = function(barcodeData) {
  // 01-03    -> Código do banco sem o digito
  // 04-04    -> Código da Moeda (9-Real)
  // 05-05    -> Dígito verificador do código de barras
  // 06-09    -> Fator de vencimento
  // 10-19    -> Valor Nominal do Título
  // 20-44    -> Campo Livre (Abaixo)
  // 20-23    -> Código da Agencia (sem dígito)
  // 24-05    -> Número da Carteira
  // 26-36    -> Nosso Número (sem dígito)
  // 37-43    -> Conta do Cedente (sem dígito)
  // 44-44    -> Zero (Fixo)

  var campos = new Array();

  // 1. Campo - composto pelo código do banco, código da moéda, as cinco primeiras posições
  // do campo livre e DV (modulo10) deste campo
  var campo = barcodeData.substring(0, 3) + barcodeData.substring(3, 4) + barcodeData.substring(19, 20) + barcodeData.substring(20, 24);
  campo = campo + formatters.mod10(campo);
  campo = campo.substring(0, 5) + '.' + campo.substring(5, campo.length);
  campos.push(campo);

  // 2. Campo - composto pelas posiçoes 6 a 15 do campo livre
  // e livre e DV (modulo10) deste campo
  var campo = barcodeData.substring(24, 34);
  campo = campo + formatters.mod10(campo);
  campo = campo.substring(0, 5) + '.' + campo.substring(5, campo.length);
  campos.push(campo);

  // 3. Campo composto pelas posicoes 16 a 25 do campo livre
  // e livre e DV (modulo10) deste campo
  var campo = barcodeData.substring(34, 44);
  campo = campo + formatters.mod10(campo);
  campo = campo.substring(0, 5) + '.' + campo.substring(5, campo.length);
  campos.push(campo);

  // 4. Campo - digito verificador do codigo de barras
  var campo = barcodeData.substring(4, 5);
  campos.push(campo);

  // 5. Campo composto pelo fator vencimento e valor nominal do documento, sem
  // indicacao de zeros a esquerda e sem edicao (sem ponto e virgula). Quando se
  // tratar de valor zerado, a representacao deve ser 000 (tres zeros).
  var campo = barcodeData.substring(5, 9) + barcodeData.substring(9, 19);
  campos.push(campo);

  return campos.join(" ");
}

exports.parseEDIFile = function(fileContent){
  try {
	var lines = fileContent.split("\n");
	var parsedFile = {
	  boletos: {}
	};

	var currentNossoNumero = null;
	var hasCompanyData = false;

	for(var i = 0; i < lines.length; i++) {
	  var line = lines[i];
	  var registro = line.substring(0, 1);

	  if(registro == '0') {
		parsedFile['razao_social'] = line.substring(46, 76);
		parsedFile['data_arquivo'] = helper.dateFromEdiDate(line.substring(94, 100));
	  } else if(registro == '1') {
		var boleto = {};

		parsedFile['cnpj'] = formatters.removeTrailingZeros(line.substring(3, 17));
		parsedFile['carteira'] = formatters.removeTrailingZeros(line.substring(22, 24));
		parsedFile['agencia_cedente'] = formatters.removeTrailingZeros(line.substring(24, 29));
		parsedFile['conta_cedente'] = formatters.removeTrailingZeros(line.substring(29, 37));

		boleto['codigo_ocorrencia'] = line.substring(108, 110);
		boleto['data_ocorrencia'] = helper.dateFromEdiDate(line.substring(110, 116));
		boleto['data_credito'] = helper.dateFromEdiDate(line.substring(295, 301));
		boleto['vencimento'] = helper.dateFromEdiDate(line.substring(110, 116));
		boleto['valor_pago'] = formatters.removeTrailingZeros(line.substring(253, 266));
		boleto['valor'] = formatters.removeTrailingZeros(line.substring(152, 165));
		boleto['banco_recebedor'] = formatters.removeTrailingZeros(line.substring(165, 168));
		boleto['agencia_recebedora'] = formatters.removeTrailingZeros(line.substring(168, 173));
		boleto['paid'] = (parseInt(boleto['valor_pago']) >= parseInt(boleto['valor']) || boleto['codigo_ocorrencia'] == '06');

		currentNossoNumero = formatters.removeTrailingZeros(line.substring(126, 145));
		parsedFile.boletos[currentNossoNumero] = boleto;
	  }
	}

	return parsedFile;
  } catch(e) {
	console.log(e);
	return null;
  }
};
<commit_msg>Get nosso_numero from the correct offset.<commit_after>var formatters = require('../../lib/formatters'),
	helper = require('./helper');

exports.options = {
  logoURL: 'https://pagar.me/assets/boleto/images/bradesco.jpg',
  codigo: '237'
}

exports.dvBarra = function(barra) {
  var resto2 = formatters.mod11(barra, 9, 1);
  return (resto2 == 0 || resto2 == 1 || resto2 == 10) ? 1 : 11 - resto2;
}

exports.barcodeData = function(boleto){
  var codigoBanco = this.options.codigo;
  var numMoeda = "9";
  var fixo = "9"; // Numero fixo para a posição 05-05

  var fatorVencimento = formatters.fatorVencimento(boleto['data_vencimento']);

  var agencia = formatters.addTrailingZeros(boleto['agencia'], 4);

  var valor = formatters.addTrailingZeros(boleto['valor'], 10);
  var carteira = boleto['carteira'];
  var codigoCedente = formatters.addTrailingZeros(boleto['codigo_cedente'], 7);

  var nossoNumero = carteira + formatters.addTrailingZeros(boleto['nosso_numero'], 11);

  var barra = codigoBanco + numMoeda + fatorVencimento + valor + agencia + nossoNumero + codigoCedente + '0';

  var dvBarra = this.dvBarra(barra);
  var lineData = barra.substring(0, 4) + dvBarra + barra.substring(4, barra.length);

  return lineData;
}

exports.linhaDigitavel = function(barcodeData) {
  // 01-03    -> Código do banco sem o digito
  // 04-04    -> Código da Moeda (9-Real)
  // 05-05    -> Dígito verificador do código de barras
  // 06-09    -> Fator de vencimento
  // 10-19    -> Valor Nominal do Título
  // 20-44    -> Campo Livre (Abaixo)
  // 20-23    -> Código da Agencia (sem dígito)
  // 24-05    -> Número da Carteira
  // 26-36    -> Nosso Número (sem dígito)
  // 37-43    -> Conta do Cedente (sem dígito)
  // 44-44    -> Zero (Fixo)

  var campos = new Array();

  // 1. Campo - composto pelo código do banco, código da moéda, as cinco primeiras posições
  // do campo livre e DV (modulo10) deste campo
  var campo = barcodeData.substring(0, 3) + barcodeData.substring(3, 4) + barcodeData.substring(19, 20) + barcodeData.substring(20, 24);
  campo = campo + formatters.mod10(campo);
  campo = campo.substring(0, 5) + '.' + campo.substring(5, campo.length);
  campos.push(campo);

  // 2. Campo - composto pelas posiçoes 6 a 15 do campo livre
  // e livre e DV (modulo10) deste campo
  var campo = barcodeData.substring(24, 34);
  campo = campo + formatters.mod10(campo);
  campo = campo.substring(0, 5) + '.' + campo.substring(5, campo.length);
  campos.push(campo);

  // 3. Campo composto pelas posicoes 16 a 25 do campo livre
  // e livre e DV (modulo10) deste campo
  var campo = barcodeData.substring(34, 44);
  campo = campo + formatters.mod10(campo);
  campo = campo.substring(0, 5) + '.' + campo.substring(5, campo.length);
  campos.push(campo);

  // 4. Campo - digito verificador do codigo de barras
  var campo = barcodeData.substring(4, 5);
  campos.push(campo);

  // 5. Campo composto pelo fator vencimento e valor nominal do documento, sem
  // indicacao de zeros a esquerda e sem edicao (sem ponto e virgula). Quando se
  // tratar de valor zerado, a representacao deve ser 000 (tres zeros).
  var campo = barcodeData.substring(5, 9) + barcodeData.substring(9, 19);
  campos.push(campo);

  return campos.join(" ");
}

exports.parseEDIFile = function(fileContent){
  try {
	var lines = fileContent.split("\n");
	var parsedFile = {
	  boletos: {}
	};

	var currentNossoNumero = null;
	var hasCompanyData = false;

	for(var i = 0; i < lines.length; i++) {
	  var line = lines[i];
	  var registro = line.substring(0, 1);

	  if(registro == '0') {
		parsedFile['razao_social'] = line.substring(46, 76);
		parsedFile['data_arquivo'] = helper.dateFromEdiDate(line.substring(94, 100));
	  } else if(registro == '1') {
		var boleto = {};

		parsedFile['cnpj'] = formatters.removeTrailingZeros(line.substring(3, 17));
		parsedFile['carteira'] = formatters.removeTrailingZeros(line.substring(22, 24));
		parsedFile['agencia_cedente'] = formatters.removeTrailingZeros(line.substring(24, 29));
		parsedFile['conta_cedente'] = formatters.removeTrailingZeros(line.substring(29, 37));

		boleto['codigo_ocorrencia'] = line.substring(108, 110);
		boleto['data_ocorrencia'] = helper.dateFromEdiDate(line.substring(110, 116));
		boleto['data_credito'] = helper.dateFromEdiDate(line.substring(295, 301));
		boleto['vencimento'] = helper.dateFromEdiDate(line.substring(110, 116));
		boleto['valor_pago'] = formatters.removeTrailingZeros(line.substring(253, 266));
		boleto['valor'] = formatters.removeTrailingZeros(line.substring(152, 165));
		boleto['banco_recebedor'] = formatters.removeTrailingZeros(line.substring(165, 168));
		boleto['agencia_recebedora'] = formatters.removeTrailingZeros(line.substring(168, 173));
		boleto['paid'] = (parseInt(boleto['valor_pago']) >= parseInt(boleto['valor']) || boleto['codigo_ocorrencia'] == '06');

		currentNossoNumero = formatters.removeTrailingZeros(line.substring(70, 81));
		parsedFile.boletos[currentNossoNumero] = boleto;
	  }
	}

	return parsedFile;
  } catch(e) {
	console.log(e);
	return null;
  }
};
<|endoftext|>


<commit_before>import execa from 'execa'
import puppeteer from 'puppeteer'

const percySnapshot = require('@percy/puppeteer')

const OTP_RR_TEST_CONFIG_PATH = '../percy/har-mock-config.yml'
const OTP_RR_TEST_JS_CONFIG_PATH = './percy/har-mock-config.js'

const MOCK_SERVER_PORT = 5000

// Puppeteer can take a long time to load, especially in some ci environments
jest.setTimeout(600000)

// How long to wait for each page to fully render before taking a screenshot
const PERCY_EXTRA_WAIT = 5000
const percySnapshotWithWait = async (page, name, enableJavaScript) => {
  await page.waitForTimeout(PERCY_EXTRA_WAIT)

  const namePrefix = process.env.PERCY_OTP_CONFIG_OVERRIDE || 'Mock OTP1 Server'
  await percySnapshot(page, `${namePrefix} - ${name}`, { enableJavaScript })
}

let browser
const serveAbortController = new AbortController()
const harAbortController = new AbortController()

/**
 * Loads a path
 */
async function loadPath(otpPath) {
  const page = await browser.newPage()
  const filePath = `http://localhost:${MOCK_SERVER_PORT}/#${otpPath}`
  await Promise.all([
    page.goto(filePath),
    page.waitForNavigation({ waitUntil: 'networkidle2' })
  ])

  return page
}

beforeAll(async () => {
  try {
    // Build OTP-RR main.js using new config file
    await execa('env', [
      `YAML_CONFIG=${
        process.env.PERCY_OTP_CONFIG_OVERRIDE || OTP_RR_TEST_CONFIG_PATH
      }`,
      `JS_CONFIG=${OTP_RR_TEST_JS_CONFIG_PATH}`,
      'yarn',
      'build'
    ])
    console.log('Built OTP-RR')

    // grab ATL har file to tmp
    if (process.env.HAR_URL) {
      await execa('curl', [process.env.HAR_URL, '-s', '--output', 'mock.har'])
      console.log('Downloaded HAR data')
    }
  } catch (error) {
    console.log(error)
  }
  console.log('Built OTP-RR and downloaded HAR data')

  try {
    execa('yarn', ['percy-serve', 'dist', '-p', MOCK_SERVER_PORT], {
      signal: serveAbortController.signal
    }).stdout.pipe(process.stdout)

    // Launch mock OTP server
    if (process.env.HAR_URL) {
      execa('yarn', ['percy-har-express', '-p', '9999', 'mock.har'], {
        signal: harAbortController.signal
      }).stdout.pipe(process.stdout)
    }

    // Web security is disabled to allow requests to the mock OTP server
    browser = await puppeteer.launch({
      args: ['--disable-web-security']
      // headless: false
    })

    // Fix time
    browser.on('targetchanged', async (target) => {
      const targetPage = await target.page()
      const client = await targetPage.target().createCDPSession()
      await client.send('Runtime.evaluate', {
        expression:
          'Date.now = function() { return 1646835742000; }; Date.getTime = function() { return 1646835742000; }'
      })
    })
  } catch (error) {
    console.log(error)
  }

  // Give servers time to start up
  await execa('sleep', ['5'])
})

afterAll(async () => {
  try {
    serveAbortController.abort()
    harAbortController.abort()
    await browser.close()
  } catch (error) {
    console.log(error)
  }
  console.log('Closed mock server and headless browser')
})

// Puppeteer can take a long time to load, espeically in some ci environments
jest.setTimeout(600000)

/* These fixed routes allow us to test features that the static html screenshots
 * don't allow us to test. This is disabled, as percy doesn't support transitive.js
 * out of the box, even with javascript enabled.
 *
 * TODO: make transitive.js work with Percy, then complete this test suite
 */
// eslint-disable-next-line jest/no-commented-out-tests
/*
test('OTP-RR Fixed Routes', async () => {
  const transitive = await loadPath(
    '/?ui_activeSearch=5rzujqghc&ui_activeItinerary=0&fromPlace=Opus Music Store%2C Decatur%2C GA%3A%3A33.77505%2C-84.300178&toPlace=Five Points Station (MARTA Stop ID 908981)%3A%3A33.753837%2C-84.391397&date=2022-03-09&time=09%3A58&arriveBy=false&mode=WALK%2CBUS%2CSUBWAY%2CTRAM%2CFLEX_EGRESS%2CFLEX_ACCESS%2CFLEX_DIRECT&showIntermediateStops=true&maxWalkDistance=1207&optimize=QUICK&walkSpeed=1.34&ignoreRealtimeUpdates=true&wheelchair=false&numItineraries=3&otherThanPreferredRoutesPenalty=900'
  )
  await percySnapshotWithWait(transitive, 'Itinerary (with transitive)', true)

  const routes = await loadPath('/route')
  await percySnapshotWithWait(routes, 'Route Viewer (with transitive)', true)
})
*/

// Percy screenshot is not an assertion, but that's ok
// eslint-disable-next-line jest/expect-expect
test('OTP-RR', async () => {
  const page = await loadPath('/')
  await page.setViewport({
    height: 1080,
    width: 1920
  })

  await percySnapshotWithWait(page, 'Main Page (without styling)')

  // Plan a trip
  await page.goto(
    `http://localhost:${MOCK_SERVER_PORT}/#/?ui_activeSearch=5rzujqghc&ui_activeItinerary=0&fromPlace=Opus Music Store%2C Decatur%2C GA%3A%3A33.77505%2C-84.300178&toPlace=Five Points Station (MARTA Stop ID 908981)%3A%3A33.753837%2C-84.391397&date=2022-03-09&time=09%3A58&arriveBy=false&mode=WALK%2CBUS%2CSUBWAY%2CTRAM%2CFLEX_EGRESS%2CFLEX_ACCESS%2CFLEX_DIRECT&showIntermediateStops=true&maxWalkDistance=1207&optimize=QUICK&walkSpeed=1.34&ignoreRealtimeUpdates=true&wheelchair=false&numItineraries=3&otherThanPreferredRoutesPenalty=900`
  )
  await page.waitForNavigation({ waitUntil: 'networkidle2' })
  await page.waitForSelector('.title')

  await percySnapshotWithWait(page, 'Batch Itinerary')

  // Select a trip
  await page.waitForSelector('.title:nth-of-type(1)')
  await page.click('.title:nth-of-type(1)')

  await percySnapshotWithWait(page, 'Batch Itinerary Selected')

  // Open Trip Viewer
  await page.waitForTimeout(2000)
  const [tripViewerButton] = await page.$x(
    "//button[contains(., 'Trip Viewer')]"
  )
  await tripViewerButton.click()
  await page.waitForSelector('div.trip-viewer-body')
  await page.waitForTimeout(1000)
  await percySnapshotWithWait(page, 'Trip Viewer')

  // Open stop viewer from trip viewer
  await page.click(
    'div.trip-viewer-body > div:nth-child(3) > div.stop-button-container > button'
  )
  await page.waitForSelector('.stop-viewer')

  await percySnapshotWithWait(page, 'Stop Viewer')

  // Open schedule view
  await page.waitForSelector('button.link-button.pull-right')
  await page.click('button.link-button.pull-right')
  await page.waitForTimeout(3000) // Slow animation
  await percySnapshotWithWait(page, 'Schedule Viewer')

  // Open route viewer
  const [routeViewerButton] = await page.$x(
    "//button[contains(., 'View Routes')]"
  )
  await routeViewerButton.click()
  await page.waitForSelector('.route-viewer')
  await page.waitForTimeout(5000)

  await percySnapshotWithWait(page, 'Route Viewer')

  // Open Specific Route`
  const [busRouteButton] = await page.$x(
    "//span[contains(., 'Sugarloaf Mills - Lindbergh Center')]"
  )
  await busRouteButton.click()
  await page.waitForSelector('#headsign-selector')

  await percySnapshotWithWait(page, 'Route Viewer Showing Route 410')

  // View multiple patterns
  // Click second option
  const secondPatternOption = await page.$$eval(
    'option',
    (options) => options.find((o) => o.innerText.includes('Sugarloaf'))?.value
  )
  await page.select('select#headsign-selector', secondPatternOption)

  await page.waitForSelector('#headsign-selector-label')
  await page.waitForTimeout(1000)

  // Click first option
  const firstPatternOption = await page.$$eval(
    'option',
    (options) => options.find((o) => o.innerText.includes('Lindbergh'))?.value
  )
  await page.select('select#headsign-selector', firstPatternOption)
  await page.waitForTimeout(1000)

  await percySnapshotWithWait(page, 'Pattern Viewer Showing Route 410')

  // Stop viewer from pattern viewer
  const [patternStopButton] = await page.$x(
    "//a[contains(., 'Sugarloaf Mills GCT Park and Ride')]"
  )
  await patternStopButton.click()
  await page.waitForSelector('.stop-viewer')

  // Activate all layers
  await page.$$eval('.leaflet-control-layers-selector', (checks) =>
    checks.forEach((c) => c.click())
  )
  await page.waitForTimeout(1000)

  // Go back to trip planner
  const [tripPlannerButton] = await page.$x(
    "//button[contains(., 'Plan Trip')]"
  )
  await tripPlannerButton.click()
  await page.waitForSelector('.batch-routing-panel')
  await page.waitForTimeout(3000)
  const [viewAllOptionsButton] = await page.$x(
    "//button[contains(., 'View all options')]"
  )
  await viewAllOptionsButton.click()
  await page.waitForTimeout(1000)

  await percySnapshotWithWait(page, 'Batch Itinerary Showing Bikes')
})
<commit_msg>test(percy): update itinerary date<commit_after>import execa from 'execa'
import puppeteer from 'puppeteer'

const percySnapshot = require('@percy/puppeteer')

const OTP_RR_TEST_CONFIG_PATH = '../percy/har-mock-config.yml'
const OTP_RR_TEST_JS_CONFIG_PATH = './percy/har-mock-config.js'

const MOCK_SERVER_PORT = 5000

// Puppeteer can take a long time to load, especially in some ci environments
jest.setTimeout(600000)

// How long to wait for each page to fully render before taking a screenshot
const PERCY_EXTRA_WAIT = 5000
const percySnapshotWithWait = async (page, name, enableJavaScript) => {
  await page.waitForTimeout(PERCY_EXTRA_WAIT)

  const namePrefix = process.env.PERCY_OTP_CONFIG_OVERRIDE || 'Mock OTP1 Server'
  await percySnapshot(page, `${namePrefix} - ${name}`, { enableJavaScript })
}

let browser
const serveAbortController = new AbortController()
const harAbortController = new AbortController()

/**
 * Loads a path
 */
async function loadPath(otpPath) {
  const page = await browser.newPage()
  const filePath = `http://localhost:${MOCK_SERVER_PORT}/#${otpPath}`
  await Promise.all([
    page.goto(filePath),
    page.waitForNavigation({ waitUntil: 'networkidle2' })
  ])

  return page
}

beforeAll(async () => {
  try {
    // Build OTP-RR main.js using new config file
    await execa('env', [
      `YAML_CONFIG=${
        process.env.PERCY_OTP_CONFIG_OVERRIDE || OTP_RR_TEST_CONFIG_PATH
      }`,
      `JS_CONFIG=${OTP_RR_TEST_JS_CONFIG_PATH}`,
      'yarn',
      'build'
    ])
    console.log('Built OTP-RR')

    // grab ATL har file to tmp
    if (process.env.HAR_URL) {
      await execa('curl', [process.env.HAR_URL, '-s', '--output', 'mock.har'])
      console.log('Downloaded HAR data')
    }
  } catch (error) {
    console.log(error)
  }
  console.log('Built OTP-RR and downloaded HAR data')

  try {
    execa('yarn', ['percy-serve', 'dist', '-p', MOCK_SERVER_PORT], {
      signal: serveAbortController.signal
    }).stdout.pipe(process.stdout)

    // Launch mock OTP server
    if (process.env.HAR_URL) {
      execa('yarn', ['percy-har-express', '-p', '9999', 'mock.har'], {
        signal: harAbortController.signal
      }).stdout.pipe(process.stdout)
    }

    // Web security is disabled to allow requests to the mock OTP server
    browser = await puppeteer.launch({
      args: ['--disable-web-security']
      // headless: false
    })

    // Fix time
    browser.on('targetchanged', async (target) => {
      const targetPage = await target.page()
      const client = await targetPage.target().createCDPSession()
      await client.send('Runtime.evaluate', {
        expression:
          'Date.now = function() { return 1646835742000; }; Date.getTime = function() { return 1646835742000; }'
      })
    })
  } catch (error) {
    console.log(error)
  }

  // Give servers time to start up
  await execa('sleep', ['5'])
})

afterAll(async () => {
  try {
    serveAbortController.abort()
    harAbortController.abort()
    await browser.close()
  } catch (error) {
    console.log(error)
  }
  console.log('Closed mock server and headless browser')
})

// Puppeteer can take a long time to load, espeically in some ci environments
jest.setTimeout(600000)

/* These fixed routes allow us to test features that the static html screenshots
 * don't allow us to test. This is disabled, as percy doesn't support transitive.js
 * out of the box, even with javascript enabled.
 *
 * TODO: make transitive.js work with Percy, then complete this test suite
 */
// eslint-disable-next-line jest/no-commented-out-tests
/*
test('OTP-RR Fixed Routes', async () => {
  const transitive = await loadPath(
    '/?ui_activeSearch=5rzujqghc&ui_activeItinerary=0&fromPlace=Opus Music Store%2C Decatur%2C GA%3A%3A33.77505%2C-84.300178&toPlace=Five Points Station (MARTA Stop ID 908981)%3A%3A33.753837%2C-84.391397&date=2022-03-09&time=09%3A58&arriveBy=false&mode=WALK%2CBUS%2CSUBWAY%2CTRAM%2CFLEX_EGRESS%2CFLEX_ACCESS%2CFLEX_DIRECT&showIntermediateStops=true&maxWalkDistance=1207&optimize=QUICK&walkSpeed=1.34&ignoreRealtimeUpdates=true&wheelchair=false&numItineraries=3&otherThanPreferredRoutesPenalty=900'
  )
  await percySnapshotWithWait(transitive, 'Itinerary (with transitive)', true)

  const routes = await loadPath('/route')
  await percySnapshotWithWait(routes, 'Route Viewer (with transitive)', true)
})
*/

// Percy screenshot is not an assertion, but that's ok
// eslint-disable-next-line jest/expect-expect
test('OTP-RR', async () => {
  const page = await loadPath('/')
  await page.setViewport({
    height: 1080,
    width: 1920
  })

  await percySnapshotWithWait(page, 'Main Page (without styling)')

  // Plan a trip
  await page.goto(
    `http://localhost:${MOCK_SERVER_PORT}/#/?ui_activeSearch=5rzujqghc&ui_activeItinerary=0&fromPlace=Opus Music Store%2C Decatur%2C GA%3A%3A33.77505%2C-84.300178&toPlace=Five Points Station (MARTA Stop ID 908981)%3A%3A33.753837%2C-84.391397&date=2022-05-09&time=09%3A58&arriveBy=false&mode=WALK%2CBUS%2CSUBWAY%2CTRAM%2CFLEX_EGRESS%2CFLEX_ACCESS%2CFLEX_DIRECT&showIntermediateStops=true&maxWalkDistance=1207&optimize=QUICK&walkSpeed=1.34&ignoreRealtimeUpdates=true&wheelchair=false&numItineraries=3&otherThanPreferredRoutesPenalty=900`
  )
  await page.waitForNavigation({ waitUntil: 'networkidle2' })
  await page.waitForSelector('.title')

  await percySnapshotWithWait(page, 'Batch Itinerary')

  // Select a trip
  await page.waitForSelector('.title:nth-of-type(1)')
  await page.click('.title:nth-of-type(1)')

  await percySnapshotWithWait(page, 'Batch Itinerary Selected')

  // Open Trip Viewer
  await page.waitForTimeout(2000)
  const [tripViewerButton] = await page.$x(
    "//button[contains(., 'Trip Viewer')]"
  )
  await tripViewerButton.click()
  await page.waitForSelector('div.trip-viewer-body')
  await page.waitForTimeout(1000)
  await percySnapshotWithWait(page, 'Trip Viewer')

  // Open stop viewer from trip viewer
  await page.click(
    'div.trip-viewer-body > div:nth-child(3) > div.stop-button-container > button'
  )
  await page.waitForSelector('.stop-viewer')

  await percySnapshotWithWait(page, 'Stop Viewer')

  // Open schedule view
  await page.waitForSelector('button.link-button.pull-right')
  await page.click('button.link-button.pull-right')
  await page.waitForTimeout(3000) // Slow animation
  await percySnapshotWithWait(page, 'Schedule Viewer')

  // Open route viewer
  const [routeViewerButton] = await page.$x(
    "//button[contains(., 'View Routes')]"
  )
  await routeViewerButton.click()
  await page.waitForSelector('.route-viewer')
  await page.waitForTimeout(5000)

  await percySnapshotWithWait(page, 'Route Viewer')

  // Open Specific Route`
  const [busRouteButton] = await page.$x(
    "//span[contains(., 'Sugarloaf Mills - Lindbergh Center')]"
  )
  await busRouteButton.click()
  await page.waitForSelector('#headsign-selector')

  await percySnapshotWithWait(page, 'Route Viewer Showing Route 410')

  // View multiple patterns
  // Click second option
  const secondPatternOption = await page.$$eval(
    'option',
    (options) => options.find((o) => o.innerText.includes('Sugarloaf'))?.value
  )
  await page.select('select#headsign-selector', secondPatternOption)

  await page.waitForSelector('#headsign-selector-label')
  await page.waitForTimeout(1000)

  // Click first option
  const firstPatternOption = await page.$$eval(
    'option',
    (options) => options.find((o) => o.innerText.includes('Lindbergh'))?.value
  )
  await page.select('select#headsign-selector', firstPatternOption)
  await page.waitForTimeout(1000)

  await percySnapshotWithWait(page, 'Pattern Viewer Showing Route 410')

  // Stop viewer from pattern viewer
  const [patternStopButton] = await page.$x(
    "//a[contains(., 'Sugarloaf Mills GCT Park and Ride')]"
  )
  await patternStopButton.click()
  await page.waitForSelector('.stop-viewer')

  // Activate all layers
  await page.$$eval('.leaflet-control-layers-selector', (checks) =>
    checks.forEach((c) => c.click())
  )
  await page.waitForTimeout(1000)

  // Go back to trip planner
  const [tripPlannerButton] = await page.$x(
    "//button[contains(., 'Plan Trip')]"
  )
  await tripPlannerButton.click()
  await page.waitForSelector('.batch-routing-panel')
  await page.waitForTimeout(3000)
  const [viewAllOptionsButton] = await page.$x(
    "//button[contains(., 'View all options')]"
  )
  await viewAllOptionsButton.click()
  await page.waitForTimeout(1000)

  await percySnapshotWithWait(page, 'Batch Itinerary Showing Bikes')
})
<|endoftext|>


<commit_before>import React from 'react';

export default () => (

      {this.props.children}

);
<commit_msg>Modal fix<commit_after>import React from 'react';

export default (props) => (

      {props.children}

);
<|endoftext|>


<commit_before>/* jshint -W097 */
// jshint strict:true
/*jslint node: true */
/*jslint esversion: 6 */
'use strict';

var { SerialPort } = require('serialport');

function SerialRequestResponseTransport(options, protocol) {
    this.options = options;
    this.protocol = protocol;
    this.serialConnected = false;
    this.serialComm = undefined;

    this.requestTimer = null;
    this.stopRequests = false;
    this.currentData = null;
    this.currentDataOffset = 0;
    this.messageTimeoutTimer = null;

    if (!this.options.transportSerialBaudrate) this.options.transportSerialBaudrate = 300;
    if (!this.options.transportSerialDataBits) this.options.transportSerialDataBits = 7;
    if (!this.options.transportSerialStopBits) this.options.transportSerialStopBits = 1;
    if (!this.options.transportSerialParity) this.options.transportSerialParity = 'even';
    if (!this.options.transportSerialMaxBufferSize) this.options.transportSerialMaxBufferSize = 300000;
    if (!this.options.transportSerialMessageTimeout) this.options.transportSerialMessageTimeout = 120000;
    if (!this.options.anotherQueryDelay) this.options.anotherQueryDelay = 1000;
    if (this.options.anotherQueryDelay < 500) this.options.anotherQueryDelay = 500;

    var self = this;
    this.protocol.setTransportResetCallback(function(res) {
        if (self.options.debug === 2) self.options.logger('Transport Reset!! Restart = ' + !self.stopRequests);
        if (!self.stopRequests) {
            self.stop(function() {
                self.stopRequests = false;
                self.scheduleNextRun();
            });
        }
    });
}

SerialRequestResponseTransport.prototype.init = function init() {
    this.protocol.initState(); // init State from protocol instance

    var self = this;
    if (!this.serialComm) {
        this.serialComm = new SerialPort({
            path:       this.options.transportSerialPort
            autoOpen:   false,
            baudRate:   this.options.transportSerialBaudrate,
            dataBits:   this.options.transportSerialDataBits,
            stopBits:   this.options.transportSerialStopBits,
            parity:     this.options.transportSerialParity,
            highWaterMark: 2048
        });
        if (this.options.debug === 2) this.options.logger('CREATE SERIALPORT: ' + this.options.transportSerialBaudrate + ' '  + this.options.transportSerialDataBits + ' '  + this.options.transportSerialStopBits + ' '  + this.options.transportSerialParity);

        this.serialComm.on('data', function (data) {
            if (!data || !Buffer.isBuffer(data)) return;
            if (!self.serialComm) return;
            if (self.options.debug === 2) self.options.logger('NEW DATA');
            if (self.stopRequests) {
                if (self.options.debug === 2) self.options.logger('NEW DATA AFTER STOP ... ignore');
                return;
            }
            if (! self.currentData) {
                try {
                    self.currentData = Buffer.alloc(self.options.transportSerialMaxBufferSize);
                } catch (e) {
                    if (self.options.debug === 2) self.options.logger('CAN NOT ALLOCATE MEMORY! STOPPING');
                    self.stop();
                    return;
                }
            }
            if (data.length > 0) {
                data.copy(self.currentData, self.currentDataOffset);
                self.currentDataOffset += data.length;
            }
            var bufferOverrun = false;
            if (self.currentDataOffset > self.options.transportSerialMaxBufferSize) {
                if (self.options.debug === 2) self.options.logger('BUFFER OVERRUN DETECTED, Try to Process anyway (' + self.currentDataOffset + ' vs. ' + self.options.transportSerialMaxBufferSize + ')');
                self.currentDataOffset = self.options.transportSerialMaxBufferSize;
                bufferOverrun = true;
            }
            if (bufferOverrun && !self.protocol.checkMessageAfterBufferOverrun()) {
                if (self.options.debug === 2) self.options.logger('DELETE all data (' + self.currentDataOffset + ') because of Buffer overrun missed data');
                self.currentData = null;
                self.currentDataOffset = 0;
                return;
            }

            if (self.protocol.checkMessage(self.currentData.slice(0, self.currentDataOffset))) {
                if (self.options.debug === 2) self.options.logger('PAUSE READING SERIALPORT TO HANDLE MESSAGE');
                self.serialComm.pause();
                if (self.messageTimeoutTimer) {
                    clearTimeout(self.messageTimeoutTimer);
                    self.messageTimeoutTimer = null;
                }
                if (self.options.debug === 2) self.options.logger('CLEAR MESSAGE TIMEOUT TIMER');

                var addData = self.protocol.handleMessage(self.currentData.slice(0, self.currentDataOffset));
                if (self.options.debug === 2) self.options.logger('LEFT AFTER HANDLE-MESSAGE ' + (addData ? addData.length : 0));

                try {
                    self.currentData = Buffer.alloc(self.options.transportSerialMaxBufferSize);
                } catch (e) {
                    if (self.options.debug === 2) self.options.logger('CAN NOT ALLOCATE MEMORY! STOPPING');
                    self.stop();
                    return;
                }

                self.currentDataOffset = 0;
                if (addData && addData.length > 0) {
                    addData.copy(self.currentData, 0);
                    self.currentDataOffset = addData.length;
                }
                if (!self.protocol.isProcessComplete()) {
                    var messagesToSend = self.protocol.messagesToSend();
                    if (self.options.debug === 2) self.options.logger('ALL MESSAGES TO SEND: ' + messagesToSend);

                    setTimeout(function() {
                        sendOutMessages(messagesToSend);
                    }, 250);
                }
                else {
                    finalizeMessageHandling();
                }

                function sendOutMessages(messagesToSend) {
                    if (messagesToSend > 0) {
                        self.protocol.getNextMessage(self.serialComm, function(nextData) {
                            if (self.options.debug === 2) self.options.logger('TO SEND ' + messagesToSend + ': ' + nextData);
                            if (typeof nextData === 'string' || typeof nextData === 'object') {
                                if (self.serialComm && nextData.length > 0) {
                                    self.serialComm.write(nextData, function () {
                                        self.serialComm.drain(function() {
                                            if (self.options.debug === 2) self.options.logger('DONE SEND ' + messagesToSend);
                                            setTimeout(function() {
                                                sendOutMessages(--messagesToSend);
                                            }, 250);
                                        });
                                    });
                                    return;
                                }
                                else if (!self.serialComm) {
                                    self.protocol.callUserCallback(new Error('Serialport instance needed to write data'), null);
                                    finalizeMessageHandling();
                                    return;
                                }
                            }
                            sendOutMessages(--messagesToSend);
                        });
                    }
                    else {
                        if (self.options.debug === 2) self.options.logger('DONE SEND ' + messagesToSend);
                        finalizeMessageHandling();
                    }
                }

                function finalizeMessageHandling() {
                    if (self.options.debug === 2) self.options.logger('RESUME READING SERIALPORT IN FINALIZE');
                    if (self.serialComm && !self.stopRequests) self.serialComm.resume(); // we want to read continously

                    if (self.options.debug === 2) self.options.logger('SET MESSAGE TIMEOUT TIMER: ' + self.options.transportSerialMessageTimeout);
                    if (self.messageTimeoutTimer) {
                        clearTimeout(self.messageTimeoutTimer);
                        self.messageTimeoutTimer = null;
                    }
                    self.messageTimeoutTimer = setTimeout(function() {
                        self.messageTimeoutTimer = null;
                        self.handleSerialTimeout();
                    }, self.options.transportSerialMessageTimeout);
                    if (self.protocol.isProcessComplete()) {
                        if (self.messageTimeoutTimer) {
                            clearTimeout(self.messageTimeoutTimer);
                            self.messageTimeoutTimer = null;
                        }
                        if (self.options.debug === 2) self.options.logger('CLEAR MESSAGE TIMEOUT TIMER');
                        if (self.serialComm && self.serialComm.isOpen) {
                            self.serialComm.close(function(err) {
                                if (err) {
                                    self.options.logger('ERROR CLOSING SERIALPORT: ' + err);
                                }
                                self.scheduleNextRun();
                            });
                        }
                        else {
                            self.scheduleNextRun();
                        }
                    }
                    if (self.options.debug === 2 && self.currentData) self.options.logger('REMAINING DATA AFTER MESSAGE HANDLING: ' + self.currentData.slice(0, self.currentDataOffset).toString());
                    if (self.options.debug === 2) self.options.logger('END FINALIZE');
                }
            }
            else if (self.currentDataOffset === self.options.transportSerialMaxBufferSize) {
                self.protocol.callUserCallback(new Error('Maximal Buffer size reached without matching message : ' + self.currentData.toString()), null);
                if (self.options.debug === 2) self.options.logger('DELETE all data (' + self.currentDataOffset + ')');
                self.currentData = null;
                self.currentDataOffset = 0;
            }
            else if (bufferOverrun) {
                if (self.options.debug === 2) self.options.logger('DELETE all data (' + self.currentDataOffset + ') because of Buffer overrun missed data');
                self.currentData = null;
                self.currentDataOffset = 0;
            }

        });

        this.serialComm.on('error', function (msg) {
            if (self.options.debug !== 0) self.options.logger('SERIALPORT ERROR: ' + msg);
            self.serialConnected = false;
            self.currentData = null;
            self.currentDataOffset = 0;
        });

        this.serialComm.on('open', function () {
            if (self.options.debug === 2) self.options.logger('SERIALPORT OPEN');
            self.serialConnected = true;
            self.currentData = null;
            self.currentDataOffset = 0;
        });

        this.serialComm.on('disconnect', function (err) {
            if (self.options.debug !== 0) self.options.logger('SERIALPORT DISCONNECTED: ' + err);
            self.serialConnected = false;
            self.currentData = null;
            self.currentDataOffset = 0;
        });

        this.serialComm.on('close', function () {
            if (self.options.debug === 2) self.options.logger('SERIALPORT CLOSE');
            self.serialConnected = false;
            self.currentData = null;
            self.currentDataOffset = 0;
            if (self.stopRequests && self.serialComm) {
                if (self.options.debug === 2) self.options.logger('SERIALPORT REMOVE LISTENERS');
                self.serialComm.removeAllListeners();
            }
        });
    }

    this.currentData = null;
    this.currentDataOffset = 0;
};

SerialRequestResponseTransport.prototype.scheduleNextRun = function scheduleNextRun() {
    if (!this.stopRequests) {
        if (this.requestTimer) {
            clearTimeout(this.requestTimer);
            this.requestTimer = null;
        }
        var delay = this.options.requestInterval * 1000;
        if (this.protocol.anotherQueryAvailable()) {
            delay = this.options.anotherQueryDelay;
        }
        else if (this.options.requestInterval < 0) {
            if (this.options.debug === 2) this.options.logger('STOP because requestInterval < 0');
            this.stop();
            return;
        }
        if (this.options.debug === 2) this.options.logger('DELETE rest of data (' + this.currentDataOffset + ') because new Message start with a new Request Message');
        this.currentData = null;
        this.currentDataOffset = 0;

        if (this.options.debug === 2) this.options.logger('SCHEDULE NEXT RUN IN ' + delay + 's');
        var self = this;
        this.requestTimer = setTimeout(function() {
            self.requestTimer = null;
            if (!self.serialComm) self.init();
                else self.protocol.initState(); // reset Protocol instance because it will be a new session
            self.process(); // and open port again
        }, delay);
    }
};

SerialRequestResponseTransport.prototype.process = function process() {
    this.protocol.initState();
    this.currentData = null;
    this.currentDataOffset = 0;
    var self = this;
    this.serialComm.open(function() {
        if (self.stopRequests || !self.serialComm) return;
        self.serialComm.flush(function() {
            if (self.stopRequests || !self.serialComm) return;
            if (self.options.debug === 2) self.options.logger('SERIALPORT RESET BAUDRATE TO ' + self.options.transportSerialBaudrate);
            self.serialComm.update({baudRate: self.options.transportSerialBaudrate}, function(error) {
                if (error) {
                    self.protocol.callUserCallback(new Error('Error on Baudrate changeover: ' + error), null);
                }
                if (self.stopRequests || !self.serialComm) return;
                var messagesToSend = self.protocol.messagesToSend();
                if (self.options.debug === 2) self.options.logger('INITIAL MESSAGES TO SEND: ' + messagesToSend);

                sendOutMessages(messagesToSend);

                function sendOutMessages(messagesToSend) {
                    if (messagesToSend > 0) {
                        self.protocol.getNextMessage(self.serialComm, function(nextData) {
                            if (self.options.debug === 2) self.options.logger('TO SEND ' + messagesToSend + ': ' + nextData);
                            if (self.serialComm && (typeof nextData === 'string' || typeof nextData === 'object')) {
                                if (nextData.length > 0) {
                                    self.serialComm.write(nextData, function () {
                                        self.serialComm && self.serialComm.drain(function() {
                                            if (self.options.debug === 2) self.options.logger('DONE SEND ' + messagesToSend);
                                            setTimeout(function() {
                                                sendOutMessages(--messagesToSend);
                                            }, 250);
                                        });
                                    });
                                    return;
                                }
                            }
                            sendOutMessages(--messagesToSend);
                        });
                    }
                    else {
                        if (self.options.debug === 2) self.options.logger('DONE SEND ' + messagesToSend);
                        finalizeMessageHandling();
                    }
                }

                function finalizeMessageHandling() {
                    if (self.messageTimeoutTimer) {
                        clearTimeout(self.messageTimeoutTimer);
                        self.messageTimeoutTimer = null;
                    }
                    if (self.stopRequests || !self.serialComm) return;
                    if (self.options.debug === 2) self.options.logger('SET MESSAGE TIMEOUT TIMER2: ' + self.options.transportSerialMessageTimeout);
                    self.messageTimeoutTimer = setTimeout(function() {
                        self.messageTimeoutTimer = null;
                        self.handleSerialTimeout();
                    }, self.options.transportSerialMessageTimeout);
                }
            });
        });
    });
};

SerialRequestResponseTransport.prototype.stop = function stop(callback) {
    if (this.options.debug === 2) this.options.logger('STOP');
    this.stopRequests = true;
    if (this.requestTimer) {
        clearTimeout(this.requestTimer);
        this.requestTimer = null;
    }
    if (this.messageTimeoutTimer) {
        clearTimeout(this.messageTimeoutTimer);
        this.messageTimeoutTimer = null;
    }
    if (this.options.debug === 2) this.options.logger('CLEAR MESSAGE TIMEOUT TIMER');
    if (this.serialComm && this.serialComm.isOpen) {
        var self = this;
        this.serialComm.close(function(err) {
            if (err) {
                self.options.logger('ERROR CLOSING SERIALPORT: ' + err);
            }
            self.serialComm = null;
            if (callback) callback();
        });
    }
    else {
        this.serialComm = null;
        if (callback) callback();
    }
};

SerialRequestResponseTransport.prototype.handleSerialTimeout = function handleSerialTimeout() {
    if (this.options.debug === 2) this.options.logger('MESSAGE TIMEOUT TRIGGERED');
    this.protocol.callUserCallback(new Error('No or too long answer from Serial Device after last request.'), null);
};

module.exports = SerialRequestResponseTransport;
<commit_msg>* fix serialport usage<commit_after>/* jshint -W097 */
// jshint strict:true
/*jslint node: true */
/*jslint esversion: 6 */
'use strict';

var { SerialPort } = require('serialport');

function SerialRequestResponseTransport(options, protocol) {
    this.options = options;
    this.protocol = protocol;
    this.serialConnected = false;
    this.serialComm = undefined;

    this.requestTimer = null;
    this.stopRequests = false;
    this.currentData = null;
    this.currentDataOffset = 0;
    this.messageTimeoutTimer = null;

    if (!this.options.transportSerialBaudrate) this.options.transportSerialBaudrate = 300;
    if (!this.options.transportSerialDataBits) this.options.transportSerialDataBits = 7;
    if (!this.options.transportSerialStopBits) this.options.transportSerialStopBits = 1;
    if (!this.options.transportSerialParity) this.options.transportSerialParity = 'even';
    if (!this.options.transportSerialMaxBufferSize) this.options.transportSerialMaxBufferSize = 300000;
    if (!this.options.transportSerialMessageTimeout) this.options.transportSerialMessageTimeout = 120000;
    if (!this.options.anotherQueryDelay) this.options.anotherQueryDelay = 1000;
    if (this.options.anotherQueryDelay < 500) this.options.anotherQueryDelay = 500;

    var self = this;
    this.protocol.setTransportResetCallback(function(res) {
        if (self.options.debug === 2) self.options.logger('Transport Reset!! Restart = ' + !self.stopRequests);
        if (!self.stopRequests) {
            self.stop(function() {
                self.stopRequests = false;
                self.scheduleNextRun();
            });
        }
    });
}

SerialRequestResponseTransport.prototype.init = function init() {
    this.protocol.initState(); // init State from protocol instance

    var self = this;
    if (!this.serialComm) {
        this.serialComm = new SerialPort({
            path:       this.options.transportSerialPort,
            autoOpen:   false,
            baudRate:   this.options.transportSerialBaudrate,
            dataBits:   this.options.transportSerialDataBits,
            stopBits:   this.options.transportSerialStopBits,
            parity:     this.options.transportSerialParity,
            highWaterMark: 2048
        });
        if (this.options.debug === 2) this.options.logger('CREATE SERIALPORT: ' + this.options.transportSerialBaudrate + ' '  + this.options.transportSerialDataBits + ' '  + this.options.transportSerialStopBits + ' '  + this.options.transportSerialParity);

        this.serialComm.on('data', function (data) {
            if (!data || !Buffer.isBuffer(data)) return;
            if (!self.serialComm) return;
            if (self.options.debug === 2) self.options.logger('NEW DATA');
            if (self.stopRequests) {
                if (self.options.debug === 2) self.options.logger('NEW DATA AFTER STOP ... ignore');
                return;
            }
            if (! self.currentData) {
                try {
                    self.currentData = Buffer.alloc(self.options.transportSerialMaxBufferSize);
                } catch (e) {
                    if (self.options.debug === 2) self.options.logger('CAN NOT ALLOCATE MEMORY! STOPPING');
                    self.stop();
                    return;
                }
            }
            if (data.length > 0) {
                data.copy(self.currentData, self.currentDataOffset);
                self.currentDataOffset += data.length;
            }
            var bufferOverrun = false;
            if (self.currentDataOffset > self.options.transportSerialMaxBufferSize) {
                if (self.options.debug === 2) self.options.logger('BUFFER OVERRUN DETECTED, Try to Process anyway (' + self.currentDataOffset + ' vs. ' + self.options.transportSerialMaxBufferSize + ')');
                self.currentDataOffset = self.options.transportSerialMaxBufferSize;
                bufferOverrun = true;
            }
            if (bufferOverrun && !self.protocol.checkMessageAfterBufferOverrun()) {
                if (self.options.debug === 2) self.options.logger('DELETE all data (' + self.currentDataOffset + ') because of Buffer overrun missed data');
                self.currentData = null;
                self.currentDataOffset = 0;
                return;
            }

            if (self.protocol.checkMessage(self.currentData.slice(0, self.currentDataOffset))) {
                if (self.options.debug === 2) self.options.logger('PAUSE READING SERIALPORT TO HANDLE MESSAGE');
                self.serialComm.pause();
                if (self.messageTimeoutTimer) {
                    clearTimeout(self.messageTimeoutTimer);
                    self.messageTimeoutTimer = null;
                }
                if (self.options.debug === 2) self.options.logger('CLEAR MESSAGE TIMEOUT TIMER');

                var addData = self.protocol.handleMessage(self.currentData.slice(0, self.currentDataOffset));
                if (self.options.debug === 2) self.options.logger('LEFT AFTER HANDLE-MESSAGE ' + (addData ? addData.length : 0));

                try {
                    self.currentData = Buffer.alloc(self.options.transportSerialMaxBufferSize);
                } catch (e) {
                    if (self.options.debug === 2) self.options.logger('CAN NOT ALLOCATE MEMORY! STOPPING');
                    self.stop();
                    return;
                }

                self.currentDataOffset = 0;
                if (addData && addData.length > 0) {
                    addData.copy(self.currentData, 0);
                    self.currentDataOffset = addData.length;
                }
                if (!self.protocol.isProcessComplete()) {
                    var messagesToSend = self.protocol.messagesToSend();
                    if (self.options.debug === 2) self.options.logger('ALL MESSAGES TO SEND: ' + messagesToSend);

                    setTimeout(function() {
                        sendOutMessages(messagesToSend);
                    }, 250);
                }
                else {
                    finalizeMessageHandling();
                }

                function sendOutMessages(messagesToSend) {
                    if (messagesToSend > 0) {
                        self.protocol.getNextMessage(self.serialComm, function(nextData) {
                            if (self.options.debug === 2) self.options.logger('TO SEND ' + messagesToSend + ': ' + nextData);
                            if (typeof nextData === 'string' || typeof nextData === 'object') {
                                if (self.serialComm && nextData.length > 0) {
                                    self.serialComm.write(nextData, function () {
                                        self.serialComm.drain(function() {
                                            if (self.options.debug === 2) self.options.logger('DONE SEND ' + messagesToSend);
                                            setTimeout(function() {
                                                sendOutMessages(--messagesToSend);
                                            }, 250);
                                        });
                                    });
                                    return;
                                }
                                else if (!self.serialComm) {
                                    self.protocol.callUserCallback(new Error('Serialport instance needed to write data'), null);
                                    finalizeMessageHandling();
                                    return;
                                }
                            }
                            sendOutMessages(--messagesToSend);
                        });
                    }
                    else {
                        if (self.options.debug === 2) self.options.logger('DONE SEND ' + messagesToSend);
                        finalizeMessageHandling();
                    }
                }

                function finalizeMessageHandling() {
                    if (self.options.debug === 2) self.options.logger('RESUME READING SERIALPORT IN FINALIZE');
                    if (self.serialComm && !self.stopRequests) self.serialComm.resume(); // we want to read continously

                    if (self.options.debug === 2) self.options.logger('SET MESSAGE TIMEOUT TIMER: ' + self.options.transportSerialMessageTimeout);
                    if (self.messageTimeoutTimer) {
                        clearTimeout(self.messageTimeoutTimer);
                        self.messageTimeoutTimer = null;
                    }
                    self.messageTimeoutTimer = setTimeout(function() {
                        self.messageTimeoutTimer = null;
                        self.handleSerialTimeout();
                    }, self.options.transportSerialMessageTimeout);
                    if (self.protocol.isProcessComplete()) {
                        if (self.messageTimeoutTimer) {
                            clearTimeout(self.messageTimeoutTimer);
                            self.messageTimeoutTimer = null;
                        }
                        if (self.options.debug === 2) self.options.logger('CLEAR MESSAGE TIMEOUT TIMER');
                        if (self.serialComm && self.serialComm.isOpen) {
                            self.serialComm.close(function(err) {
                                if (err) {
                                    self.options.logger('ERROR CLOSING SERIALPORT: ' + err);
                                }
                                self.scheduleNextRun();
                            });
                        }
                        else {
                            self.scheduleNextRun();
                        }
                    }
                    if (self.options.debug === 2 && self.currentData) self.options.logger('REMAINING DATA AFTER MESSAGE HANDLING: ' + self.currentData.slice(0, self.currentDataOffset).toString());
                    if (self.options.debug === 2) self.options.logger('END FINALIZE');
                }
            }
            else if (self.currentDataOffset === self.options.transportSerialMaxBufferSize) {
                self.protocol.callUserCallback(new Error('Maximal Buffer size reached without matching message : ' + self.currentData.toString()), null);
                if (self.options.debug === 2) self.options.logger('DELETE all data (' + self.currentDataOffset + ')');
                self.currentData = null;
                self.currentDataOffset = 0;
            }
            else if (bufferOverrun) {
                if (self.options.debug === 2) self.options.logger('DELETE all data (' + self.currentDataOffset + ') because of Buffer overrun missed data');
                self.currentData = null;
                self.currentDataOffset = 0;
            }

        });

        this.serialComm.on('error', function (msg) {
            if (self.options.debug !== 0) self.options.logger('SERIALPORT ERROR: ' + msg);
            self.serialConnected = false;
            self.currentData = null;
            self.currentDataOffset = 0;
        });

        this.serialComm.on('open', function () {
            if (self.options.debug === 2) self.options.logger('SERIALPORT OPEN');
            self.serialConnected = true;
            self.currentData = null;
            self.currentDataOffset = 0;
        });

        this.serialComm.on('disconnect', function (err) {
            if (self.options.debug !== 0) self.options.logger('SERIALPORT DISCONNECTED: ' + err);
            self.serialConnected = false;
            self.currentData = null;
            self.currentDataOffset = 0;
        });

        this.serialComm.on('close', function () {
            if (self.options.debug === 2) self.options.logger('SERIALPORT CLOSE');
            self.serialConnected = false;
            self.currentData = null;
            self.currentDataOffset = 0;
            if (self.stopRequests && self.serialComm) {
                if (self.options.debug === 2) self.options.logger('SERIALPORT REMOVE LISTENERS');
                self.serialComm.removeAllListeners();
            }
        });
    }

    this.currentData = null;
    this.currentDataOffset = 0;
};

SerialRequestResponseTransport.prototype.scheduleNextRun = function scheduleNextRun() {
    if (!this.stopRequests) {
        if (this.requestTimer) {
            clearTimeout(this.requestTimer);
            this.requestTimer = null;
        }
        var delay = this.options.requestInterval * 1000;
        if (this.protocol.anotherQueryAvailable()) {
            delay = this.options.anotherQueryDelay;
        }
        else if (this.options.requestInterval < 0) {
            if (this.options.debug === 2) this.options.logger('STOP because requestInterval < 0');
            this.stop();
            return;
        }
        if (this.options.debug === 2) this.options.logger('DELETE rest of data (' + this.currentDataOffset + ') because new Message start with a new Request Message');
        this.currentData = null;
        this.currentDataOffset = 0;

        if (this.options.debug === 2) this.options.logger('SCHEDULE NEXT RUN IN ' + delay + 's');
        var self = this;
        this.requestTimer = setTimeout(function() {
            self.requestTimer = null;
            if (!self.serialComm) self.init();
                else self.protocol.initState(); // reset Protocol instance because it will be a new session
            self.process(); // and open port again
        }, delay);
    }
};

SerialRequestResponseTransport.prototype.process = function process() {
    this.protocol.initState();
    this.currentData = null;
    this.currentDataOffset = 0;
    var self = this;
    this.serialComm.open(function() {
        if (self.stopRequests || !self.serialComm) return;
        self.serialComm.flush(function() {
            if (self.stopRequests || !self.serialComm) return;
            if (self.options.debug === 2) self.options.logger('SERIALPORT RESET BAUDRATE TO ' + self.options.transportSerialBaudrate);
            self.serialComm.update({baudRate: self.options.transportSerialBaudrate}, function(error) {
                if (error) {
                    self.protocol.callUserCallback(new Error('Error on Baudrate changeover: ' + error), null);
                }
                if (self.stopRequests || !self.serialComm) return;
                var messagesToSend = self.protocol.messagesToSend();
                if (self.options.debug === 2) self.options.logger('INITIAL MESSAGES TO SEND: ' + messagesToSend);

                sendOutMessages(messagesToSend);

                function sendOutMessages(messagesToSend) {
                    if (messagesToSend > 0) {
                        self.protocol.getNextMessage(self.serialComm, function(nextData) {
                            if (self.options.debug === 2) self.options.logger('TO SEND ' + messagesToSend + ': ' + nextData);
                            if (self.serialComm && (typeof nextData === 'string' || typeof nextData === 'object')) {
                                if (nextData.length > 0) {
                                    self.serialComm.write(nextData, function () {
                                        self.serialComm && self.serialComm.drain(function() {
                                            if (self.options.debug === 2) self.options.logger('DONE SEND ' + messagesToSend);
                                            setTimeout(function() {
                                                sendOutMessages(--messagesToSend);
                                            }, 250);
                                        });
                                    });
                                    return;
                                }
                            }
                            sendOutMessages(--messagesToSend);
                        });
                    }
                    else {
                        if (self.options.debug === 2) self.options.logger('DONE SEND ' + messagesToSend);
                        finalizeMessageHandling();
                    }
                }

                function finalizeMessageHandling() {
                    if (self.messageTimeoutTimer) {
                        clearTimeout(self.messageTimeoutTimer);
                        self.messageTimeoutTimer = null;
                    }
                    if (self.stopRequests || !self.serialComm) return;
                    if (self.options.debug === 2) self.options.logger('SET MESSAGE TIMEOUT TIMER2: ' + self.options.transportSerialMessageTimeout);
                    self.messageTimeoutTimer = setTimeout(function() {
                        self.messageTimeoutTimer = null;
                        self.handleSerialTimeout();
                    }, self.options.transportSerialMessageTimeout);
                }
            });
        });
    });
};

SerialRequestResponseTransport.prototype.stop = function stop(callback) {
    if (this.options.debug === 2) this.options.logger('STOP');
    this.stopRequests = true;
    if (this.requestTimer) {
        clearTimeout(this.requestTimer);
        this.requestTimer = null;
    }
    if (this.messageTimeoutTimer) {
        clearTimeout(this.messageTimeoutTimer);
        this.messageTimeoutTimer = null;
    }
    if (this.options.debug === 2) this.options.logger('CLEAR MESSAGE TIMEOUT TIMER');
    if (this.serialComm && this.serialComm.isOpen) {
        var self = this;
        this.serialComm.close(function(err) {
            if (err) {
                self.options.logger('ERROR CLOSING SERIALPORT: ' + err);
            }
            self.serialComm = null;
            if (callback) callback();
        });
    }
    else {
        this.serialComm = null;
        if (callback) callback();
    }
};

SerialRequestResponseTransport.prototype.handleSerialTimeout = function handleSerialTimeout() {
    if (this.options.debug === 2) this.options.logger('MESSAGE TIMEOUT TRIGGERED');
    this.protocol.callUserCallback(new Error('No or too long answer from Serial Device after last request.'), null);
};

module.exports = SerialRequestResponseTransport;
<|endoftext|>


<commit_before>/**
 * @module Ink.UI.Sticky_1
 * @author inkdev AT sapo.pt
 * @version 1
 */
Ink.createModule('Ink.UI.Sticky', '1', ['Ink.UI.Common_1','Ink.Dom.Event_1','Ink.Dom.Css_1','Ink.Dom.Element_1','Ink.Dom.Selector_1'], function(Common, Event, Css, Element, Selector ) {
    'use strict';

    /**
     * The Sticky component takes an element and transforms it's behavior in order to, when the user scrolls he sets its position
     * to fixed and maintain it until the user scrolls back to the same place.
     *
     * @class Ink.UI.Sticky
     * @constructor
     * @version 1
     * @param {String|DOMElement} selector
     * @param {Object} [options] Options
     *     @param {Number}     options.offsetBottom       Number of pixels of distance from the bottomElement.
     *     @param {Number}     options.offsetTop          Number of pixels of distance from the topElement.
     *     @param {String}     options.topElement         CSS Selector that specifies a top element with which the component could collide.
     *     @param {String}     options.bottomElement      CSS Selector that specifies a bottom element with which the component could collide.
     * @example
     *      <script>
     *          Ink.requireModules( ['Ink.Dom.Selector_1','Ink.UI.Sticky_1'], function( Selector, Sticky ){
     *              var menuElement = Ink.s('#menu');
     *              var stickyObj = new Sticky( menuElement );
     *          });
     *      </script>
     */
    var Sticky = function( selector, options ){

        if( typeof selector !== 'object' && typeof selector !== 'string'){
            throw '[Sticky] :: Invalid selector defined';
        }

        this._rootElement = Common.elOrSelector(selector,
            "[Sticky] :: Can't find any element with the specified selector");

        /**
         * Setting default options and - if needed - overriding it with the data attributes and given options
         */
        this._options = Ink.extendObj({
            offsetBottom: 0,
            offsetTop: 0,
            topElement: null,
            bottomElement: null
        }, options || {},  InkElement.data( this._rootElement ) );

        if( this._options.topElement ){
            this._topElement = Common.elOrSelector( this._options.topElement, 'Top Element');
        }

        if( this._options.bottomElement ){
            this._bottomElement = Common.elOrSelector( this._options.bottomElement, 'Bottom Element');
        }

        this._init();
    };

    Sticky.prototype = {

        /**
         * Init function called by the constructor
         *
         * @method _init
         * @private
         */
        _init: function(){
            InkEvent.observe( document, 'scroll', Ink.bindEvent(this._onScroll,this) );
            InkEvent.observe( window, 'resize', Ink.bindEvent(this._onResize,this) );
        },

        /**
         * Scroll handler.
         *
         * @method _onScroll
         * @private
         */
        _onScroll: InkEvent.throttle(function(){
            var viewport = (document.compatMode === "CSS1Compat") ?  document.documentElement : document.body;
            var elm = this._rootElement;

            if(
                ( ( (InkElement.elementWidth(this._rootElement)*100)/viewport.clientWidth ) > 90 ) ||
                ( viewport.clientWidth<=649 )
            ){
                if( InkElement.hasAttribute(elm,'style') ){
                    elm.removeAttribute('style');
                }
                return;  // Do not do anything for mobile
            }

            var elementRect = elm.getBoundingClientRect();
            var topRect = this._topElement && this._topElement.getBoundingClientRect();
            var bottomRect = this._bottomElement && this._bottomElement.getBoundingClientRect();

            var offsetTop = this._options.offsetTop ? parseInt(this._options.offsetTop, 10) : 0;
            var offsetBottom = this._options.offsetBottom ? parseInt(this._options.offsetBottom, 10) : 0;

            var elementHeight = elementRect.bottom - elementRect.top;

            var elMargins =
                (parseInt(Css.getStyle(elm, 'margin-top'), 10) || 0) +
                (parseInt(Css.getStyle(elm, 'margin-bottom'), 10) || 0);

            var stickingTo = this._lastStickingTo;

            if (bottomRect && bottomRect.top < elementHeight + offsetTop + offsetBottom + elMargins) {
                stickingTo = 'bottom';
                elm.style.position = 'fixed';
                elm.style.top = bottomRect.top - elementHeight - offsetBottom - elMargins + 'px';
            } else if (!topRect || topRect.bottom > offsetTop) {
                stickingTo = '[normal]';
                elm.style.position = 'static';
                elm.style.top = 'auto';
            } else if (topRect && topRect.bottom <= offsetTop) {
                stickingTo = 'top';
                elm.style.position = 'fixed';
                elm.style.top = offsetTop + 'px';
            }

            if (stickingTo !== this._lastStickingTo) {
                Css.addRemoveClassName(elm, 'ink-sticky-top', stickingTo === 'top');
                Css.addRemoveClassName(elm, 'ink-sticky-bottom', stickingTo === 'bottom');
            }
        }, 80),

        /**
         * Resize handler
         *
         * @method _onResize
         * @private
         */
        _onResize: InkEvent.throttle(function(){
            this._onScroll();
        }, 80),

    };

    return Sticky;

});
<commit_msg>Adding the Ink- prefix to Element and Event<commit_after>/**
 * @module Ink.UI.Sticky_1
 * @author inkdev AT sapo.pt
 * @version 1
 */
Ink.createModule('Ink.UI.Sticky', '1', ['Ink.UI.Common_1','Ink.Dom.Event_1','Ink.Dom.Css_1','Ink.Dom.Element_1','Ink.Dom.Selector_1'], function(Common, InkEvent, Css, InkElement, Selector ) {
    'use strict';

    /**
     * The Sticky component takes an element and transforms it's behavior in order to, when the user scrolls he sets its position
     * to fixed and maintain it until the user scrolls back to the same place.
     *
     * @class Ink.UI.Sticky
     * @constructor
     * @version 1
     * @param {String|DOMElement} selector
     * @param {Object} [options] Options
     *     @param {Number}     options.offsetBottom       Number of pixels of distance from the bottomElement.
     *     @param {Number}     options.offsetTop          Number of pixels of distance from the topElement.
     *     @param {String}     options.topElement         CSS Selector that specifies a top element with which the component could collide.
     *     @param {String}     options.bottomElement      CSS Selector that specifies a bottom element with which the component could collide.
     * @example
     *      <script>
     *          Ink.requireModules( ['Ink.Dom.Selector_1','Ink.UI.Sticky_1'], function( Selector, Sticky ){
     *              var menuElement = Ink.s('#menu');
     *              var stickyObj = new Sticky( menuElement );
     *          });
     *      </script>
     */
    var Sticky = function( selector, options ){

        if( typeof selector !== 'object' && typeof selector !== 'string'){
            throw '[Sticky] :: Invalid selector defined';
        }

        this._rootElement = Common.elOrSelector(selector,
            "[Sticky] :: Can't find any element with the specified selector");

        /**
         * Setting default options and - if needed - overriding it with the data attributes and given options
         */
        this._options = Ink.extendObj({
            offsetBottom: 0,
            offsetTop: 0,
            topElement: null,
            bottomElement: null
        }, options || {},  InkElement.data( this._rootElement ) );

        if( this._options.topElement ){
            this._topElement = Common.elOrSelector( this._options.topElement, 'Top Element');
        }

        if( this._options.bottomElement ){
            this._bottomElement = Common.elOrSelector( this._options.bottomElement, 'Bottom Element');
        }

        this._init();
    };

    Sticky.prototype = {

        /**
         * Init function called by the constructor
         *
         * @method _init
         * @private
         */
        _init: function(){
            InkEvent.observe( document, 'scroll', Ink.bindEvent(this._onScroll,this) );
            InkEvent.observe( window, 'resize', Ink.bindEvent(this._onResize,this) );
        },

        /**
         * Scroll handler.
         *
         * @method _onScroll
         * @private
         */
        _onScroll: InkEvent.throttle(function(){
            var viewport = (document.compatMode === "CSS1Compat") ?  document.documentElement : document.body;
            var elm = this._rootElement;

            if(
                ( ( (InkElement.elementWidth(this._rootElement)*100)/viewport.clientWidth ) > 90 ) ||
                ( viewport.clientWidth<=649 )
            ){
                if( InkElement.hasAttribute(elm,'style') ){
                    elm.removeAttribute('style');
                }
                return;  // Do not do anything for mobile
            }

            var elementRect = elm.getBoundingClientRect();
            var topRect = this._topElement && this._topElement.getBoundingClientRect();
            var bottomRect = this._bottomElement && this._bottomElement.getBoundingClientRect();

            var offsetTop = this._options.offsetTop ? parseInt(this._options.offsetTop, 10) : 0;
            var offsetBottom = this._options.offsetBottom ? parseInt(this._options.offsetBottom, 10) : 0;

            var elementHeight = elementRect.bottom - elementRect.top;

            var elMargins =
                (parseInt(Css.getStyle(elm, 'margin-top'), 10) || 0) +
                (parseInt(Css.getStyle(elm, 'margin-bottom'), 10) || 0);

            var stickingTo = this._lastStickingTo;

            if (bottomRect && bottomRect.top < elementHeight + offsetTop + offsetBottom + elMargins) {
                stickingTo = 'bottom';
                elm.style.position = 'fixed';
                elm.style.top = bottomRect.top - elementHeight - offsetBottom - elMargins + 'px';
            } else if (!topRect || topRect.bottom > offsetTop) {
                stickingTo = '[normal]';
                elm.style.position = 'static';
                elm.style.top = 'auto';
            } else if (topRect && topRect.bottom <= offsetTop) {
                stickingTo = 'top';
                elm.style.position = 'fixed';
                elm.style.top = offsetTop + 'px';
            }

            if (stickingTo !== this._lastStickingTo) {
                Css.addRemoveClassName(elm, 'ink-sticky-top', stickingTo === 'top');
                Css.addRemoveClassName(elm, 'ink-sticky-bottom', stickingTo === 'bottom');
            }
        }, 80),

        /**
         * Resize handler
         *
         * @method _onResize
         * @private
         */
        _onResize: InkEvent.throttle(function(){
            this._onScroll();
        }, 80),

    };

    return Sticky;

});
<|endoftext|>


<commit_before>'use strict';

import { combineReducers } from 'redux';
import tweetReducer from './tweet';
import authReducer from './auth';

export default combineReducers({
  tweetReducer,
  authReducer
});
<commit_msg>updated reducers<commit_after>'use strict';

import { combineReducers } from 'redux';
import authReducer from './auth';
import forms from './forms';

export default combineReducers({
	forms,
  authReducer
});
<|endoftext|>


<commit_before>//
// Functions
//

openOptions = function(info, tab) {

  chrome.runtime.openOptionsPage();
};

createSignatureMenuItem = function(parentMenu, signature) {

    chrome.contextMenus.create(
        {
            title: "Insert \"" + signature.name + "\"",
            parentId: parentMenu,
            contexts: ["editable"],
            onclick: function (info, tab) {

                chrome.tabs.query(
                    { active: true, currentWindow: true },
                    function (tabs) {

                        chrome.tabs.sendMessage( tabs[0].id, {action: "insertSig", signature: signature} );
                    }
                );
            }
        }
    );
};

createContextMenu = function() {

    //Remove all menus
    chrome.contextMenus.removeAll();

    var parentMenu = chrome.contextMenus.create( { title: "SigJar", contexts: ["all"] } );

    //For each signature: add
    chrome.storage.sync.get(
        { data: {} },
        function( items ) {

            var signatures = items.data.signatures;

            for(var i = 0; i < signatures.length; i++) {

                var sig = signatures[i];

                createSignatureMenuItem( parentMenu, sig );
            }

            //Now add separator and options
            chrome.contextMenus.create( { type: "separator", parentId: parentMenu, contexts: ["editable"] } );
            chrome.contextMenus.create( { title: "Options", parentId: parentMenu, contexts: ["all"], onclick: openOptions } );
        }
    );
};

initializeOptions = function() {

    //
    // Initialize default signatures, if needed
    //

    chrome.storage.sync.get(
        { data: {} },
        function( items ) {

            if (!items.data || !items.data.signatures || !items.data.userInfo) {

                chrome.storage.sync.set(
                    {
                        data:
                        {
                            signatures: [],
                            userInfo: {}
                        }
                    },
                    function() {

                        console.log( 'Default data created!' );
                    }
                );
            }
        }
    );
};

//
// Initiate app
//

initializeOptions();
createContextMenu();

chrome.storage.onChanged.addListener(
    function(changes, namespace) {

        createContextMenu();
    }
);<commit_msg>Open options upon installation<commit_after>//
// Functions
//

openOptions = function(info, tab) {

  chrome.runtime.openOptionsPage();
};

createSignatureMenuItem = function(parentMenu, signature) {

    chrome.contextMenus.create(
        {
            title: "Insert \"" + signature.name + "\"",
            parentId: parentMenu,
            contexts: ["editable"],
            onclick: function (info, tab) {

                chrome.tabs.query(
                    { active: true, currentWindow: true },
                    function (tabs) {

                        chrome.tabs.sendMessage( tabs[0].id, {action: "insertSig", signature: signature} );
                    }
                );
            }
        }
    );
};

createContextMenu = function() {

    //Remove all menus
    chrome.contextMenus.removeAll();

    var parentMenu = chrome.contextMenus.create( { title: "SigJar", contexts: ["all"] } );

    //For each signature: add
    chrome.storage.sync.get(
        { data: {} },
        function( items ) {

            var signatures = items.data.signatures;

            for(var i = 0; i < signatures.length; i++) {

                var sig = signatures[i];

                createSignatureMenuItem( parentMenu, sig );
            }

            //Now add separator and options
            chrome.contextMenus.create( { type: "separator", parentId: parentMenu, contexts: ["editable"] } );
            chrome.contextMenus.create( { title: "Options", parentId: parentMenu, contexts: ["all"], onclick: openOptions } );
        }
    );
};

initializeOptions = function() {

    //
    // Initialize default signatures, if needed
    //

    chrome.storage.sync.get(
        { data: {} },
        function( items ) {

            if (!items.data || !items.data.signatures || !items.data.userInfo) {

                chrome.storage.sync.set(
                    {
                        data:
                        {
                            signatures: [],
                            userInfo: {}
                        }
                    },
                    function() {

                        console.log( 'Default data created!' );

                        //And open first run wizard!
                        openOptions();
                    }
                );
            }
        }
    );
};

//
// Initiate app
//

initializeOptions();
createContextMenu();

chrome.storage.onChanged.addListener(
    function(changes, namespace) {

        createContextMenu();
    }
);<|endoftext|>


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

	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	/* # Variables globales */
	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	lastNumberAssigned = 0;
	playerName = "";

	pipePlayers = { "actions" :
			[
				{
					"kind" : "drinks",
					"prepare" : [],
					"price" : []
				}
			]
		}

	/* # Initialisation de la partie */
	gameInit();

	/* # Synchronisations */
	//setInterval(getMetrology, 12000);
	//setInterval(getPlayers, 30000);

	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	/* # Gestionnaires d'événements */
	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

	/* # Rejoindre une partie */
	$( "#formGameJoin" ).submit(function( event ) {
	  event.preventDefault();

	  /* # le joueur rejoin la partie */
	  var name = $('#name').val();
	  gameRejoin(name);

	  /* # liste de joueur */
	  getPlayers();

	});

	/* # Ajouter une recette dans le panier du joueur */
	$( "#formproduction" ).submit(function( event ) {
	  event.preventDefault();

	  getInfoRecette()

	});

	/* # raffraichir les données */
	$('#btnRefreshGameInfo').click(function() {
		getMetrology();
	})

	/* # Choix d'une recette */
	if($('#recettadd') != undefined){
		$('#recettadd').change(function() {
			getRepiceByName($(this).val())
		})
	}

	/* # supprimer une recette dans le pipe */
	callbackDelPlayerPipe()

	/* # Valider les actions : achat des recettes,... */
	$('#valideracions').click(function() {
		sendAction()
	})

	/* # Quitter la partie en cours */
	$('#btnexitgame').click(function() {
		exitGameByName()
	})

	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	/* # Les fonctions */
	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

	var rand = function() {
	    return Math.random().toString(36).substr(2); // remove `0.`
	};

	var token = function() {
	    return rand() + rand(); // to make it longer
	};

	function getInfoRecette(){
		var recette = $('#recettadd').val();
		  var prixu = $('#prixunitaire').text()
		  var quantite = parseInt($('#quantity').val());
		  var prixvente = parseFloat($('#prixvente').val());

		  if(Number.isInteger(quantite)){
		  	addPlayerPipe(recette,prixu,quantite,prixvente);
		  }
	}

	/**
	*
	*/
	function addPlayerPipe(recette,prixu,quantite,prixvente) {
		$.ajax({
			url: "/recipe/"+recette,
			type: "GET",
			contentType: 'application/json',
			success: function(result){
				var token = lastNumberAssigned++;

				var itemRecette = $('

'+result.recipe[0].rec_nom+'

'+quantite+'

'+prixvente+'

'+quantite*prixvente+'

');
				$('#additemrecette').before(itemRecette);

				/* # Event : supprimer une recette dans le pipe */
				callbackDelPlayerPipe()

				/* # Ajout dans la liste pipePlayers */
				// {"actions" : [{"kind" : "drinks","prepare" : [{"1":50},{"3":20}],"price" : [{"1":8},{"3":2}]} ]}

				var tmp1 = {};
				var tmp2 = {};
				recette = (result.recipe[0].rec_nom).toString();
				tmp1[recette] = quantite;
				tmp2[recette] = prixvente;

				pipePlayers.actions[0].prepare.push(tmp1);
				pipePlayers.actions[0].price.push(tmp2);

				//console.log(JSON.stringify(pipePlayers))
	    	}
		});

	}

	/**
	*
	*/
	function getMetrology () {
		$.ajax({
			url: "/metrology",
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				$('#timer').html(result.timestamp);
				$.each(result.weather, function( index, value ) {
					if(value['dfn'] == 0)
						$('#weatherToday').html(value['weather']);
	        		else
	        			$('#weatherTomorrow').html(value['weather']);
				});
	    	}
		});
	}

	function loadTime() {

	}
	loadTime();

	/**
	*
	*/
	function getPlayers() {
		$.ajax({
			url: "/players",
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				if(result.players.length > 0){
					var item = $('

');

					$('#playerList').html("");
					for (var i = 0; i < result.players.length; i++) {
						item.append($('
'+ result.players[i].pl_pseudo +'
'))
					};
					$('#playerList').append(item);
				}else{
					$('#playerList').html("Liste vide :(");
				}
	    	}
		});
	}

	function getRepices() {
		$.ajax({
			url: "/recipes",
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				$.each(result.recipes, function( index, value ) {

					$('#recettadd').append($('<option value="'+ value['rec_id'] +'">'+ value['rec_nom'] +'</option>'))
				});
	    	}
		});
	}

	function getRepiceByName(rc_id) {
		$.ajax({
			url: "/recipe/"+rc_id,
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				var totalCost = 0;
				$.each(result.ingredients, function( index, value ) {
					totalCost += value['ing_prix'];
				});
				$('#prixunitaire').html(totalCost)
	    	}
		});
	}

	function exitGameByName(rc_id) {
			$.ajax({
				url: "/players/"+playerName,
				type: "DELETE",
				contentType: 'application/json',
				success: function(result){

		    	}
			});
		}

	/**
	*
	*/
	function gameRejoin(name) {
		var data = {"name": name}
		$.ajax({
			url: "/players",
			data : JSON.stringify(data),
			type: "POST",
			contentType: 'application/json',
			success: function(result){
	        	resetFormGameJoin();

	        	/* Supprimer le bloque rejoindre la partie */
	        	$('#inscriptionbloc').remove();

	        	/* Mise à jour des informations relatives au player */
	        	$('#username').html(result.name);
	        	playerName = result.name
	        	$('#budgetplayer').html(result.info.cash)

	        	/* Affichage d'un message de bienvenue */
	        	var title = 'Coucou '+playerName+'. ';
	        	var msg = 'Toujours aussi BD ?';
	        	var status = 'success';
	        	showMessage(title,msg,status);

	        	/*console.log(result.info.profit)
	        	console.log(result.info.sales)
	        	console.log(result.info.drinksOffered)
	        	console.log(result.info.longitude)
	        	console.log(result.info.latitude)*/

	        	/* Afficher l'interface de simulation */
	        	$('#infogamebloc').removeClass("hidden");

	    	}
		});
	}

	/**
	*
	*/
	function resetFormGameJoin () {
		$('#name').val("");
	}

	/**
	*
	*/
	function gameInit () {

		if(playerName.length > 0){
			$('#infogamebloc').removeClass("hidden");

			/* # Confirmation du player pour quitter une partie */
			exitGame();
		}else{
			$('#infogamebloc').addClass("hidden");
		}

	  	/* # Liste de joueurs */
	  	getPlayers();

	  	if($('#blocSimul') != undefined)
	 		getRepices();

	}

	function exitGame () {
		window.onbeforeunload = function() {
		    return "Etes-vous sûr de quitter la partie ?";
		}
	}

	function callbackDelPlayerPipe () {
		/* # supprimer une recette dans le pipe */
		$('.btnSuppRecette').click(function (event) {
			var tmp  = '#'+event.target.id.split("-")[0];

			$.each(pipePlayers.actions[0].prepare, function( index, value ) {
				if (parseInt(index) == parseInt(event.target.id.split("-")[0]))
					pipePlayers.actions[0].prepare.splice(index, 1);
			});

			$.each(pipePlayers.actions[0].price, function( index, value ) {
				if (parseInt(index) == parseInt(event.target.id.split("-")[0]))
					pipePlayers.actions[0].price.splice(index, 1);
			});

			$(tmp).remove()

			//console.log(pipePlayers)

		})
	}

	/**
	*
	*/
	function sendAction() {
		console.log(pipePlayers)

		$.ajax({
			url: "/actions/"+playerName,
			pipePlayers : $.parseJSON(pipePlayers),
			type: "POST",
			contentType: 'application/json',
			success: function(result){
				var title, msg, status;

				if(result.sufficientFunds == "false"){
					title = 'Solde insuffisant';
					msg = 'Nous ne pouvez pas acheter ces boissons !';
					status = 'danger';
					showMessage(title,msg,status)
				}else if(result.sufficientFunds == "true"){
					title = 'Félicitation';
					msg = 'Vos boissons ont été ajoutés avec succès !';
					status = 'success';
					showMessage(title,msg,status)
				}
	    	}
		});
	}

	function showMessage (title,msg,status) {
		$.notify({
					title: title,
					message: msg
				},{
					type: status
				});
	}

})<commit_msg>test 15<commit_after>$(document).ready(function () {

	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	/* # Variables globales */
	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	lastNumberAssigned = 0;
	playerName = "";

	pipePlayers = { "actions" : []}

	/* # Initialisation de la partie */
	gameInit();

	/* # Synchronisations */
	//setInterval(getMetrology, 12000);
	//setInterval(getPlayers, 30000);

	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	/* # Gestionnaires d'événements */
	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

	/* # Rejoindre une partie */
	$( "#formGameJoin" ).submit(function( event ) {
	  event.preventDefault();

	  /* # le joueur rejoin la partie */
	  var name = $('#name').val();
	  gameRejoin(name);

	  /* # liste de joueur */
	  getPlayers();

	});

	/* # Ajouter une recette dans le panier du joueur */
	$( "#formproduction" ).submit(function( event ) {
	  event.preventDefault();

	  getInfoRecette()

	});

	/* # raffraichir les données */
	$('#btnRefreshGameInfo').click(function() {
		getMetrology();
	})

	/* # Choix d'une recette */
	if($('#recettadd') != undefined){
		$('#recettadd').change(function() {
			getRepiceByName($(this).val())
		})
	}

	/* # supprimer une recette dans le pipe */
	callbackDelPlayerPipe()

	/* # Valider les actions : achat des recettes,... */
	$('#valideracions').click(function() {
		sendAction()
	})

	/* # Quitter la partie en cours */
	$('#btnexitgame').click(function() {
		exitGameByName()
	})

	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
	/* # Les fonctions */
	/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

	var rand = function() {
	    return Math.random().toString(36).substr(2); // remove `0.`
	};

	var token = function() {
	    return rand() + rand(); // to make it longer
	};

	function getInfoRecette(){
		var recette = $('#recettadd').val();
		  var prixu = $('#prixunitaire').text()
		  var quantite = parseInt($('#quantity').val());
		  var prixvente = parseFloat($('#prixvente').val());

		  if(Number.isInteger(quantite)){
		  	addPlayerPipe(recette,prixu,quantite,prixvente);
		  }
	}

	/**
	*
	*/
	function addPlayerPipe(recette,prixu,quantite,prixvente) {
		$.ajax({
			url: "/recipe/"+recette,
			type: "GET",
			contentType: 'application/json',
			success: function(result){
				var token = lastNumberAssigned++;

				var itemRecette = $('

'+result.recipe[0].rec_nom+'

'+quantite+'

'+prixvente+'

'+quantite*prixvente+'

');
				$('#additemrecette').before(itemRecette);

				/* # Event : supprimer une recette dans le pipe */
				callbackDelPlayerPipe()

				/* # Ajout dans la liste pipePlayers */
				// {"actions" : [{"kind" : "drinks","prepare" : [{"1":50},{"3":20}],"price" : [{"1":8},{"3":2}]} ]}

				var tmp1 = [];
				var tmp2 = [];
				recette = (result.recipe[0].rec_nom).toString();
				tmp1[recette] = quantite;
				tmp2[recette] = prixvente;

				if(pipePlayers.actions != undefined && pipePlayers.actions.length > 0){
					if(pipePlayers.actions[0].prepare != undefined){
						pipePlayers.actions[0].prepare.push(tmp1);
					}

					if(pipePlayers.actions[0].price != undefined){
						pipePlayers.actions[0].price.push(tmp2);
					}
				}else{
					pipePlayers["actions"] = {}
					var drinksAction = {
						"kind" : "drinks",
						"prepare" : [],
						"price" : []
					};

					pipePlayers.actions.push(
						drinksAction.prepare.push(pipePlayers.actions.prepare.push(tmp1);)
						drinksAction.price.push(pipePlayers.actions.price.push(tmp2);)
					)
				}

				console.log(pipePlayers)

				//console.log(JSON.stringify(pipePlayers))
	    	}
		});

	}

	/**
	*
	*/
	function getMetrology () {
		$.ajax({
			url: "/metrology",
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				$('#timer').html(result.timestamp);
				$.each(result.weather, function( index, value ) {
					if(value['dfn'] == 0)
						$('#weatherToday').html(value['weather']);
	        		else
	        			$('#weatherTomorrow').html(value['weather']);
				});
	    	}
		});
	}

	function loadTime() {

	}
	loadTime();

	/**
	*
	*/
	function getPlayers() {
		$.ajax({
			url: "/players",
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				if(result.players.length > 0){
					var item = $('

');

					$('#playerList').html("");
					for (var i = 0; i < result.players.length; i++) {
						item.append($('
'+ result.players[i].pl_pseudo +'
'))
					};
					$('#playerList').append(item);
				}else{
					$('#playerList').html("Liste vide :(");
				}
	    	}
		});
	}

	function getRepices() {
		$.ajax({
			url: "/recipes",
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				$.each(result.recipes, function( index, value ) {

					$('#recettadd').append($('<option value="'+ value['rec_id'] +'">'+ value['rec_nom'] +'</option>'))
				});
	    	}
		});
	}

	function getRepiceByName(rc_id) {
		$.ajax({
			url: "/recipe/"+rc_id,
			type: "GET",
			contentType: 'application/json',
			success: function(result){

				var totalCost = 0;
				$.each(result.ingredients, function( index, value ) {
					totalCost += value['ing_prix'];
				});
				$('#prixunitaire').html(totalCost)
	    	}
		});
	}

	function exitGameByName(rc_id) {
			$.ajax({
				url: "/players/"+playerName,
				type: "DELETE",
				contentType: 'application/json',
				success: function(result){

		    	}
			});
		}

	/**
	*
	*/
	function gameRejoin(name) {
		var data = {"name": name}
		$.ajax({
			url: "/players",
			data : JSON.stringify(data),
			type: "POST",
			contentType: 'application/json',
			success: function(result){
	        	resetFormGameJoin();

	        	/* Supprimer le bloque rejoindre la partie */
	        	$('#inscriptionbloc').remove();

	        	/* Mise à jour des informations relatives au player */
	        	$('#username').html(result.name);
	        	playerName = result.name
	        	$('#budgetplayer').html(result.info.cash)

	        	/* Affichage d'un message de bienvenue */
	        	var title = 'Coucou '+playerName+'. ';
	        	var msg = 'Toujours aussi BD ?';
	        	var status = 'success';
	        	showMessage(title,msg,status);

	        	/*console.log(result.info.profit)
	        	console.log(result.info.sales)
	        	console.log(result.info.drinksOffered)
	        	console.log(result.info.longitude)
	        	console.log(result.info.latitude)*/

	        	/* Afficher l'interface de simulation */
	        	$('#infogamebloc').removeClass("hidden");

	    	}
		});
	}

	/**
	*
	*/
	function resetFormGameJoin () {
		$('#name').val("");
	}

	/**
	*
	*/
	function gameInit () {

		if(playerName.length > 0){
			$('#infogamebloc').removeClass("hidden");

			/* # Confirmation du player pour quitter une partie */
			exitGame();
		}else{
			$('#infogamebloc').addClass("hidden");
		}

	  	/* # Liste de joueurs */
	  	getPlayers();

	  	if($('#blocSimul') != undefined)
	 		getRepices();

	}

	function exitGame () {
		window.onbeforeunload = function() {
		    return "Etes-vous sûr de quitter la partie ?";
		}
	}

	function callbackDelPlayerPipe () {
		/* # supprimer une recette dans le pipe */
		$('.btnSuppRecette').click(function (event) {
			var tmp  = '#'+event.target.id.split("-")[0];

			$.each(pipePlayers.actions[0].prepare, function( index, value ) {
				if (parseInt(index) == parseInt(event.target.id.split("-")[0]))
					pipePlayers.actions[0].prepare.splice(index, 1);
			});

			$.each(pipePlayers.actions[0].price, function( index, value ) {
				if (parseInt(index) == parseInt(event.target.id.split("-")[0]))
					pipePlayers.actions[0].price.splice(index, 1);
			});

			$(tmp).remove()

			//console.log(pipePlayers)

		})
	}

	/**
	*
	*/
	function sendAction() {
		console.log(pipePlayers)

		$.ajax({
			url: "/actions/"+playerName,
			pipePlayers : $.parseJSON(pipePlayers),
			type: "POST",
			contentType: 'application/json',
			success: function(result){
				var title, msg, status;

				if(result.sufficientFunds == "false"){
					title = 'Solde insuffisant';
					msg = 'Nous ne pouvez pas acheter ces boissons !';
					status = 'danger';
					showMessage(title,msg,status)
				}else if(result.sufficientFunds == "true"){
					title = 'Félicitation';
					msg = 'Vos boissons ont été ajoutés avec succès !';
					status = 'success';
					showMessage(title,msg,status)
				}
	    	}
		});
	}

	function showMessage (title,msg,status) {
		$.notify({
					title: title,
					message: msg
				},{
					type: status
				});
	}

})<|endoftext|>