<commit_before>/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * [description]
 *
 * @function Phaser.Actions.SetY
 * @since 3.0.0
 *
 * @param {array} items - An array of Game Objects. The contents of this array are updated by this Action.
 * @param {number} value - [description]
 * @param {number} [step=0] - [description]
 *
 * @return {array} The array of Game Objects that was passed to this Action.
 */
var SetY = function (items, value, step)
{
    if (step === undefined) { step = 0; }

    for (var i = 0; i < items.length; i++)
    {
        items[i].y = value + (i * step);
    }

    return items;
};

module.exports = SetY;
<commit_msg>Actions.SetY has 2 new arguments: `index` and `direction`.<commit_after>/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var PropertyValueSet = require('./PropertyValueSet');

/**
 * Takes an array of Game Objects, or any objects that have the public property `y`
 * and then sets it to the given value.
 *
 * The optional `step` property is applied incrementally, multiplied by each item in the array.
 *
 * To use this with a Group: `SetY(group.getChildren(), value, step)`
 *
 * @function Phaser.Actions.SetY
 * @since 3.0.0
 *
 * @param {array|Phaser.GameObjects.GameObject[]} items - The array of items to be updated by this action.
 * @param {number} value - The amount to set the property to.
 * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter.
 * @param {integer} [index=0] - An optional offset to start searching from within the items array.
 * @param {integer} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning.
 *
 * @return {array} The array of objects that were passed to this Action.
 */
var SetY = function (items, value, step, index, direction)
{
    return PropertyValueSet(items, 'y', value, step, index, direction);
};

module.exports = SetY;
<|endoftext|>


<commit_before>'use strict';

const DefaultRegistry = require('undertaker-registry');
const configParser = require('./config/configParser');
const gutil = require('gulp-util');

/**
 * Custom Gulp registry containing Drupal tasks.
 *
 * @class DrupalTaskRegistry
 * @extends {DefaultRegistry}
 */
class DrupalTaskRegistry extends DefaultRegistry {

  /**
   * Creates an instance of DrupalTaskRegistry.
   *
   * @param {object|ConfigParser} conf Configuration object.
   *
   * @memberOf DrupalTaskRegistry
   */
  constructor(conf) {
    super();

    // If we've got no config, then bomb out.
    if (typeof conf === 'undefined') {
      throw new Error('No config provided.');
    }

    // If we've got config, but it's just an object, then make it a configParser instance.
    if (conf.constructor.name !== 'configParser') {
      conf = new configParser(conf);
    }

    if (conf.productionMode) {
      gutil.log(gutil.colors.magenta('---------------------------'));
      gutil.log(gutil.colors.magenta('Running in production mode.'));
      gutil.log(gutil.colors.magenta('---------------------------'));
    }

    this.conf = conf;

  }

  /**
   * @inheritdoc
   *
   * @memberOf DrupalTaskRegistry
   */
  init(undertaker) {

    // SASS/CSS.
    undertaker.task(require('./styles/buildStyles'));
    undertaker.task(require('./styles/lintStyles'));
    undertaker.task(require('./styles/holograph'));

    // SCRIPTS.
    undertaker.task(require('./scripts/buildScripts'));
    undertaker.task(require('./scripts/lintScripts'));

    // OTHER ASSETS.
    undertaker.task(require('./assets/buildImages'));
    undertaker.task(require('./assets/buildFonts'));
    undertaker.task(require('./build/clean'));

    // ANCILLIARY.
    undertaker.task(require('./other/generateTheme'));
    undertaker.task(require('./other/watch'));

    // NAMED TASKS.
    // These are required as just passing undertaker.series means that you can't flag async completion.
    undertaker.task('build', function buildTask(conf, done) {
      return undertaker.series(
        'build:clean',
        'lint:scripts',
        undertaker.parallel(
          'build:scripts',
          'build:styles',
          'build:images',
          'build:fonts'
        )
      )(done);
    });

    undertaker.task('default', function defaultTask(conf, done) {
      return undertaker.series(
        'build',
        'watch'
      )(done);
    });

  }

  /**
   * @inheritdoc
   *
   * @memberOf DrupalTaskRegistry
   */
  set(name, fn) {
    const task = this._tasks[name] = fn.bind(null, this.conf);
    return task;
  }

}

module.exports = DrupalTaskRegistry;<commit_msg>Added Holograph to build task<commit_after>'use strict';

const DefaultRegistry = require('undertaker-registry');
const configParser = require('./config/configParser');
const gutil = require('gulp-util');

/**
 * Custom Gulp registry containing Drupal tasks.
 *
 * @class DrupalTaskRegistry
 * @extends {DefaultRegistry}
 */
class DrupalTaskRegistry extends DefaultRegistry {

  /**
   * Creates an instance of DrupalTaskRegistry.
   *
   * @param {object|ConfigParser} conf Configuration object.
   *
   * @memberOf DrupalTaskRegistry
   */
  constructor(conf) {
    super();

    // If we've got no config, then bomb out.
    if (typeof conf === 'undefined') {
      throw new Error('No config provided.');
    }

    // If we've got config, but it's just an object, then make it a configParser instance.
    if (conf.constructor.name !== 'configParser') {
      conf = new configParser(conf);
    }

    if (conf.productionMode) {
      gutil.log(gutil.colors.magenta('---------------------------'));
      gutil.log(gutil.colors.magenta('Running in production mode.'));
      gutil.log(gutil.colors.magenta('---------------------------'));
    }

    this.conf = conf;

  }

  /**
   * @inheritdoc
   *
   * @memberOf DrupalTaskRegistry
   */
  init(undertaker) {

    // SASS/CSS.
    undertaker.task(require('./styles/buildStyles'));
    undertaker.task(require('./styles/lintStyles'));
    undertaker.task(require('./styles/holograph'));

    // SCRIPTS.
    undertaker.task(require('./scripts/buildScripts'));
    undertaker.task(require('./scripts/lintScripts'));

    // OTHER ASSETS.
    undertaker.task(require('./assets/buildImages'));
    undertaker.task(require('./assets/buildFonts'));
    undertaker.task(require('./build/clean'));

    // ANCILLIARY.
    undertaker.task(require('./other/generateTheme'));
    undertaker.task(require('./other/watch'));

    // NAMED TASKS.
    // These are required as just passing undertaker.series means that you can't flag async completion.
    undertaker.task('build', function buildTask(conf, done) {
      return undertaker.series(
        'build:clean',
        'lint:scripts',
        undertaker.parallel(
          'build:scripts',
          'build:styles',
          'build:images',
          'build:fonts'
        ),
        'build:holograph'
      )(done);
    });

    undertaker.task('default', function defaultTask(conf, done) {
      return undertaker.series(
        'build',
        'watch'
      )(done);
    });

  }

  /**
   * @inheritdoc
   *
   * @memberOf DrupalTaskRegistry
   */
  set(name, fn) {
    const task = this._tasks[name] = fn.bind(null, this.conf);
    return task;
  }

}

module.exports = DrupalTaskRegistry;<|endoftext|>


<commit_before>import fetch from 'isomorphic-fetch';
import jwtDecode from 'jwt-decode';
import { browserHistory } from 'react-router';
import cookie from '../utils/cookie';
import handleErrors from '../utils/fetchErrorHandler';
import API_BASE from '../utils/APIBase';

export const POST_RICE_REQUEST = 'POST_RICE_REQUEST';
export const POST_RICE_SUCCESS = 'POST_RICE_SUCCESS';
export const POST_RICE_FAILURE = 'POST_RICE_FAILURE';

async function post(body) {
  const token = cookie.get('token');
  if (!jwtDecode(token).username) {
    throw new Error('invalid token');
  }
  return fetch(`${API_BASE}/api/v1/rice`, {
    method: 'post',
    headers: {
      'Content-Type': 'application/json',
      Accept: 'application/json',
      Authorization: `Bearer ${token}`,
    },
    body: JSON.stringify(body),
  })
  .then(handleErrors)
  .then(res => res.json());
}

export function submit(body) {
  return async dispatch => {
    try {
      dispatch({ type: POST_RICE_REQUEST });
      const submitted = await post(body);
      if (submitted.error) {
        dispatch({ type: POST_RICE_FAILURE, error: submitted.error });
      } else {
        dispatch({ type: POST_RICE_SUCCESS, submitted });
        browserHistory.push(`/rice/${submitted.id}`);
      }
    } catch (err) {
      dispatch({ type: POST_RICE_FAILURE, error: err });
    }
  };
}

export const SHOW_RICE_REQUEST = 'SHOW_RICE_REQUEST';
export const SHOW_RICE_SUCCESS = 'SHOW_RICE_SUCCESS';
export const SHOW_RICE_FAILURE = 'SHOW_RICE_FAILURE';

function get(id) {
  return fetch(`${API_BASE}/api/v1/rice/${id}`)
    .then(handleErrors)
    .then(res => res.json());
}

export function showRice(id) {
  return async dispatch => {
    try {
      dispatch({ type: SHOW_RICE_REQUEST });
      const detail = await get(id);
      dispatch({ type: SHOW_RICE_SUCCESS, detail });
    } catch (err) {
      dispatch({ type: SHOW_RICE_FAILURE, error: err });
    }
  };
}

export const LIST_RICE_REQUEST = 'LIST_RICE_REQUEST';
export const LIST_RICE_SUCCESS = 'LIST_RICE_SUCCESS';
export const LIST_RICE_FAILURE = 'LIST_RICE_FAILURE';

function list(queryParams = '') {
  return fetch(`${API_BASE}/api/v1/rice/${queryParams}`)
    .then(handleErrors)
    .then(res => res.json());
}

export function fetchList() {
  return async dispatch => {
    try {
      dispatch({ type: LIST_RICE_REQUEST });
      const riceList = await list();
      dispatch({ type: LIST_RICE_SUCCESS, list: riceList });
    } catch (err) {
      dispatch({ type: LIST_RICE_FAILURE, error: err });
    }
  };
}

export const LIKE_RICE_REQUEST = 'LIKE_RICE_REQUEST';
export const LIKE_RICE_SUCCESS = 'LIKE_RICE_SUCCESS';
export const LIKE_RICE_FAILURE = 'LIKE_RICE_FAILURE';

async function putLike(username, riceId) {
  return fetch(`${API_BASE}/api/v1/user/${username}`, {
    method: 'PUT',
    body: JSON.stringify({ riceId: +riceId }),
  })
  .then(handleErrors);
}

export function likeRice(riceId) {
  return async dispatch => {
    if (!riceId) {
      return;
    }
    let token = cookie.get('token');
    if (!token) {
      return;
    }
    let username = jwtDecode(token).username;
    if (!username) {
      return;
    }
    try {
      dispatch({
        type: LIKE_RICE_REQUEST,
        username,
        riceId,
      });
      const res = await putLike(username, riceId);
      if (res.status === 204) {
        dispatch({ type: LIKE_RICE_SUCCESS });
      } else {
        dispatch({
          type: LIKE_RICE_FAILURE,
          username,
          riceId,
          error: res.error,
        });
      }
    } catch (err) {
      dispatch({
        type: LIKE_RICE_FAILURE,
        username,
        riceId,
        error: err,
      });
    }
  };
}

export const UNLIKE_RICE_REQUEST = 'UNLIKE_RICE_REQUEST';
export const UNLIKE_RICE_SUCCESS = 'UNLIKE_RICE_SUCCESS';
export const UNLIKE_RICE_FAILURE = 'UNLIKE_RICE_FAILURE';

async function deleteLike(username, riceId) {
  return fetch(`${API_BASE}/api/v1/user/${username}`, {
    method: 'DELETE',
    body: JSON.stringify({ riceId: +riceId }),
  })
  .then(handleErrors);
}

export function unlikeRice(riceId) {
  return async dispatch => {
    if (!riceId) {
      return;
    }
    let token = cookie.get('token');
    if (!token) {
      return;
    }
    let username = jwtDecode(token).username;
    if (!username) {
      return;
    }
    try {
      dispatch({
        type: UNLIKE_RICE_REQUEST,
        username,
        riceId,
      });
      const res = await deleteLike(username, riceId);
      if (res.status === 204) {
        dispatch({ type: UNLIKE_RICE_SUCCESS });
      } else {
        dispatch({
          type: UNLIKE_RICE_FAILURE,
          username,
          riceId,
          error: res.error,
        });
      }
    } catch (err) {
      dispatch({
        type: UNLIKE_RICE_FAILURE,
        username,
        riceId,
        error: err,
      });
    }
  };
}
<commit_msg>add auth to like api<commit_after>import fetch from 'isomorphic-fetch';
import jwtDecode from 'jwt-decode';
import { browserHistory } from 'react-router';
import cookie from '../utils/cookie';
import handleErrors from '../utils/fetchErrorHandler';
import API_BASE from '../utils/APIBase';

export const POST_RICE_REQUEST = 'POST_RICE_REQUEST';
export const POST_RICE_SUCCESS = 'POST_RICE_SUCCESS';
export const POST_RICE_FAILURE = 'POST_RICE_FAILURE';

async function post(body) {
  const token = cookie.get('token');
  if (!jwtDecode(token).username) {
    throw new Error('invalid token');
  }
  return fetch(`${API_BASE}/api/v1/rice`, {
    method: 'post',
    headers: {
      'Content-Type': 'application/json',
      Accept: 'application/json',
      Authorization: `Bearer ${token}`,
    },
    body: JSON.stringify(body),
  })
  .then(handleErrors)
  .then(res => res.json());
}

export function submit(body) {
  return async dispatch => {
    try {
      dispatch({ type: POST_RICE_REQUEST });
      const submitted = await post(body);
      if (submitted.error) {
        dispatch({ type: POST_RICE_FAILURE, error: submitted.error });
      } else {
        dispatch({ type: POST_RICE_SUCCESS, submitted });
        browserHistory.push(`/rice/${submitted.id}`);
      }
    } catch (err) {
      dispatch({ type: POST_RICE_FAILURE, error: err });
    }
  };
}

export const SHOW_RICE_REQUEST = 'SHOW_RICE_REQUEST';
export const SHOW_RICE_SUCCESS = 'SHOW_RICE_SUCCESS';
export const SHOW_RICE_FAILURE = 'SHOW_RICE_FAILURE';

function get(id) {
  return fetch(`${API_BASE}/api/v1/rice/${id}`)
    .then(handleErrors)
    .then(res => res.json());
}

export function showRice(id) {
  return async dispatch => {
    try {
      dispatch({ type: SHOW_RICE_REQUEST });
      const detail = await get(id);
      dispatch({ type: SHOW_RICE_SUCCESS, detail });
    } catch (err) {
      dispatch({ type: SHOW_RICE_FAILURE, error: err });
    }
  };
}

export const LIST_RICE_REQUEST = 'LIST_RICE_REQUEST';
export const LIST_RICE_SUCCESS = 'LIST_RICE_SUCCESS';
export const LIST_RICE_FAILURE = 'LIST_RICE_FAILURE';

function list(queryParams = '') {
  return fetch(`${API_BASE}/api/v1/rice/${queryParams}`)
    .then(handleErrors)
    .then(res => res.json());
}

export function fetchList() {
  return async dispatch => {
    try {
      dispatch({ type: LIST_RICE_REQUEST });
      const riceList = await list();
      dispatch({ type: LIST_RICE_SUCCESS, list: riceList });
    } catch (err) {
      dispatch({ type: LIST_RICE_FAILURE, error: err });
    }
  };
}

export const LIKE_RICE_REQUEST = 'LIKE_RICE_REQUEST';
export const LIKE_RICE_SUCCESS = 'LIKE_RICE_SUCCESS';
export const LIKE_RICE_FAILURE = 'LIKE_RICE_FAILURE';

async function putLike(username, riceId, token) {
  return fetch(`${API_BASE}/api/v1/user/${username}`, {
    method: 'PUT',
    headers: {
      Authorization: `Bearer ${token}`,
    },
    body: JSON.stringify({ riceId: +riceId }),
  })
  .then(handleErrors);
}

export function likeRice(riceId) {
  return async dispatch => {
    if (!riceId) {
      return;
    }
    let token = cookie.get('token');
    if (!token) {
      return;
    }
    let username = jwtDecode(token).username;
    if (!username) {
      return;
    }
    try {
      dispatch({
        type: LIKE_RICE_REQUEST,
        username,
        riceId,
      });
      const res = await putLike(username, riceId, token);
      if (res.status === 204) {
        dispatch({ type: LIKE_RICE_SUCCESS });
      } else {
        dispatch({
          type: LIKE_RICE_FAILURE,
          username,
          riceId,
          error: res.error,
        });
      }
    } catch (err) {
      dispatch({
        type: LIKE_RICE_FAILURE,
        username,
        riceId,
        error: err,
      });
    }
  };
}

export const UNLIKE_RICE_REQUEST = 'UNLIKE_RICE_REQUEST';
export const UNLIKE_RICE_SUCCESS = 'UNLIKE_RICE_SUCCESS';
export const UNLIKE_RICE_FAILURE = 'UNLIKE_RICE_FAILURE';

async function deleteLike(username, riceId, token) {
  return fetch(`${API_BASE}/api/v1/user/${username}`, {
    method: 'DELETE',
    headers: {
      Authorization: `Bearer ${token}`,
    },
    body: JSON.stringify({ riceId: +riceId }),
  })
  .then(handleErrors);
}

export function unlikeRice(riceId) {
  return async dispatch => {
    if (!riceId) {
      return;
    }
    let token = cookie.get('token');
    if (!token) {
      return;
    }
    let username = jwtDecode(token).username;
    if (!username) {
      return;
    }
    try {
      dispatch({
        type: UNLIKE_RICE_REQUEST,
        username,
        riceId,
      });
      const res = await deleteLike(username, riceId, token);
      if (res.status === 204) {
        dispatch({ type: UNLIKE_RICE_SUCCESS });
      } else {
        dispatch({
          type: UNLIKE_RICE_FAILURE,
          username,
          riceId,
          error: res.error,
        });
      }
    } catch (err) {
      dispatch({
        type: UNLIKE_RICE_FAILURE,
        username,
        riceId,
        error: err,
      });
    }
  };
}
<|endoftext|>


<commit_before><commit_msg>Add french translation<commit_after>// French - root strings

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define */

define({
    "COMPARE_WITH" : "Comparer avec...",
    "CHOOSE_FILE" : "Parcourir...",
    "SAVE_FILES" : "Sauvegarder les fichiers comparés",
    "CLOSE_VIEWS" : "Fermer les comparaisons",
    "STICK" : "Synchroniser les comparaisons",
    "UNSTICK": "Désynchroniser les comparaisons"
});
<|endoftext|>


<commit_before>import React from 'react'
import { percentage, euro } from './formValueTypes.js'

let	today = new Date()

export default {

	// DEFAULTS : These inputs do not exist, but the API needs them
	'defaults': {
		adapt: () => ({
			allegement_fillon_mode_recouvrement: 'anticipe_regularisation_fin_de_periode',
			allegement_cotisation_allocations_familiales_mode_recouvrement: 'anticipe_regularisation_fin_de_periode',
			contrat_de_travail_debut: today.getFullYear() + '-' + ('0' + (today.getMonth() + 1)).slice(-2),
		}),
	},

	/*****************************
	 BASIC INPUT FORM FIELDS */

	/* Le type d'entreprise association 190X n'est pas défini comme une catégorie dans OpenFisca,
	mais comme un booléen */
	'typeEntreprise': {
		initial: 'entreprise',
		adapt: raw => raw === 'entreprise_est_association_non_lucrative' && {
			'entreprise_est_association_non_lucrative': true,
		},
	},

	/* Nous simulons une embauche, donc nous incrémentons l'effectif */
	'effectifEntreprise': {
		initial: 0,
		adapt: raw => ({'effectif_entreprise': raw + 1}),
	},

	/* Nous voulons un ratio : on multiplie donc le nombre d'heures par semaine capté par
	 (la durée légale mensuelle divisée par la durée légale hebdomadaire) */
	'heuresParSemaine': {
		initial: 30,
		adapt: raw => ({ 'heures_remunerees_volume': raw * (151.66 / 35)}),
	},

	'typeSalaireEntré': {
		initial: 'brut',
		adapt: () => ({}),
	},

	'salaire': {
		initial: 2300,
		adapt: (raw, value, values) => ({
			// Use other values to determine the name of this key
			[values['typeSalaireEntré'] == 'brut' ?
				'salaire_de_base' :
				'salaire_net_a_payer'
			]: value }),
	},

	'tempsDeTravail': {
		initial: 'temps_plein',
		adapt: raw => ({'contrat_de_travail': raw}),
	},

	'categorieSalarié': {
		initial: 'prive_non_cadre',
		adapt: raw => ({'categorie_salarie': raw}),
	},

	/****************************
	 ADVANCED VIEW STEPS

	One step is a Question, and an Answer field for the user.
	The steps, called in Conversation.js, use these data.
	The value stored in the state is the raw user input.
	The value is validated (with a "pre" normalisation step) to be able to submit the step.
	It is then 'adapted' into an object fragment. Object fragments are merged to be sent to the API.
	*/

	'mutuelle': { // the name of the form field. Data is stored in state.form.advancedQuestions.mutuelle
		// The attributes of the HTML form field
		attributes: {
			/* We use 'text' inputs : browser behaviour with input=number
			doesn't quite work with our "update simulation on input change"... */
			inputMode: 'numeric',
			placeholder: 'votre réponse', // help for the first input
		},
		valueType: euro, /* Will give the input a suffix (€), a human representation
		that will be used in the form resume, and a validation function */
		defaultValue: '40', // The user can pass steps in the advanced view, this value is set
		helpText: // What will be displayed in the help box

				L'employeur a l'obligation en 2016 de proposer et financer à 50% une offre
				de complémentaire santé. Son montant est libre, tant qu'elle couvre un panier légal de soins.

					Voir les détails (service-public.fr)

,
		adapt: (raw, validated) => ({'complementaire_sante_montant': validated}),
	},

	'codeINSEE': {
		human: v => v.nomCommune,
		helpText:
Quelle est la commune du lieu de travail effectif du salarié ?
,
		adapt: (selectObject) => ({'depcom_entreprise': selectObject && selectObject.codeInsee || ''}),
	},

	'pourcentage_alternants': {
		attributes: {
			inputMode: 'numeric',
		},
		valueType: percentage,
		defaultValue: '0',
		helpText:
Ce pourcentage de l'ensemble de vos salariés nous permet de calculer le montant de la Contribution Supplémentaire à l'Apprentissage, destinée à encourager cette forme d'emploi.
,
		adapt: (raw, validated) => ({'ratio_alternants': validated / 100}),
	},

	'tauxRisqueConnu': {
		choices: [ 'Oui', 'Non' ],
		helpText:

			C'est le taux de la cotisation accidents du travail (AT) et maladies professionnelles (MP). Il est accessible sur net-entreprises.fr ou reçu par courrier.

,
	},

	'tauxRisque': {
		attributes: {
			inputMode: 'numeric',
			placeholder: 'Par ex. 1,1',
		},
		valueType: percentage,
		defaultValue: '1',
		adapt: validated => ({taux_accident_travail: validated / 100}),
	},

	'selectTauxRisque': {
		fields: [ 'resume' ],
		human: v => v.text,
		optionsURL: 'https://cdn.rawgit.com/sgmap/taux-collectifs-cotisation-atmp/master/taux-2016.json',
	},

	'jei': {
		choices: [ 'Oui', 'Non' ],
		defaultValue: 'Non',
		helpText:

			Votre entreprise doit être éligible à ce statut, et votre employé doit notamment être fortement impliqué dans le projet de R&D.

				Voir toutes les conditions (service-public.fr)

,
		adapt: raw => ({jeune_entreprise_innovante: raw === 'Oui' ? 1 : 0}),
	},

	'serviceUtile': {
		choices: [ ':-|', ':-)' ],
		defaultValue: null,
		helpText:

			Dites-nous si ce simulateur vous a été utile

,
	},

	'partage': {},

	'remarque': {
		attributes: {
			cols: 30,
			rows: 6,
			placeholder: 'Votre remarque',
		},
		validator: {
			test: v => v !== '',
			error: 'Entrez votre remarque',
		},
		human: v => v.substring(0,20) + '...',
	},

}
<commit_msg>Correct horrible addition to string<commit_after>import React from 'react'
import { percentage, euro } from './formValueTypes.js'

let	today = new Date()

export default {

	// DEFAULTS : These inputs do not exist, but the API needs them
	'defaults': {
		adapt: () => ({
			allegement_fillon_mode_recouvrement: 'anticipe_regularisation_fin_de_periode',
			allegement_cotisation_allocations_familiales_mode_recouvrement: 'anticipe_regularisation_fin_de_periode',
			contrat_de_travail_debut: today.getFullYear() + '-' + ('0' + (today.getMonth() + 1)).slice(-2),
		}),
	},

	/*****************************
	 BASIC INPUT FORM FIELDS */

	/* Le type d'entreprise association 190X n'est pas défini comme une catégorie dans OpenFisca,
	mais comme un booléen */
	'typeEntreprise': {
		initial: 'entreprise',
		adapt: raw => raw === 'entreprise_est_association_non_lucrative' && {
			'entreprise_est_association_non_lucrative': true,
		},
	},

	/* Nous simulons une embauche, donc nous incrémentons l'effectif */
	'effectifEntreprise': {
		initial: 0,
		adapt: raw => ({'effectif_entreprise': +raw + 1}),
	},

	/* Nous voulons un ratio : on multiplie donc le nombre d'heures par semaine capté par
	 (la durée légale mensuelle divisée par la durée légale hebdomadaire) */
	'heuresParSemaine': {
		initial: 30,
		adapt: raw => ({ 'heures_remunerees_volume': raw * (151.66 / 35)}),
	},

	'typeSalaireEntré': {
		initial: 'brut',
		adapt: () => ({}),
	},

	'salaire': {
		initial: 2300,
		adapt: (raw, value, values) => ({
			// Use other values to determine the name of this key
			[values['typeSalaireEntré'] == 'brut' ?
				'salaire_de_base' :
				'salaire_net_a_payer'
			]: value }),
	},

	'tempsDeTravail': {
		initial: 'temps_plein',
		adapt: raw => ({'contrat_de_travail': raw}),
	},

	'categorieSalarié': {
		initial: 'prive_non_cadre',
		adapt: raw => ({'categorie_salarie': raw}),
	},

	/****************************
	 ADVANCED VIEW STEPS

	One step is a Question, and an Answer field for the user.
	The steps, called in Conversation.js, use these data.
	The value stored in the state is the raw user input.
	The value is validated (with a "pre" normalisation step) to be able to submit the step.
	It is then 'adapted' into an object fragment. Object fragments are merged to be sent to the API.
	*/

	'mutuelle': { // the name of the form field. Data is stored in state.form.advancedQuestions.mutuelle
		// The attributes of the HTML form field
		attributes: {
			/* We use 'text' inputs : browser behaviour with input=number
			doesn't quite work with our "update simulation on input change"... */
			inputMode: 'numeric',
			placeholder: 'votre réponse', // help for the first input
		},
		valueType: euro, /* Will give the input a suffix (€), a human representation
		that will be used in the form resume, and a validation function */
		defaultValue: '40', // The user can pass steps in the advanced view, this value is set
		helpText: // What will be displayed in the help box

				L'employeur a l'obligation en 2016 de proposer et financer à 50% une offre
				de complémentaire santé. Son montant est libre, tant qu'elle couvre un panier légal de soins.

					Voir les détails (service-public.fr)

,
		adapt: (raw, validated) => ({'complementaire_sante_montant': validated}),
	},

	'codeINSEE': {
		human: v => v.nomCommune,
		helpText:
Quelle est la commune du lieu de travail effectif du salarié ?
,
		adapt: (selectObject) => ({'depcom_entreprise': selectObject && selectObject.codeInsee || ''}),
	},

	'pourcentage_alternants': {
		attributes: {
			inputMode: 'numeric',
		},
		valueType: percentage,
		defaultValue: '0',
		helpText:
Ce pourcentage de l'ensemble de vos salariés nous permet de calculer le montant de la Contribution Supplémentaire à l'Apprentissage, destinée à encourager cette forme d'emploi.
,
		adapt: (raw, validated) => ({'ratio_alternants': validated / 100}),
	},

	'tauxRisqueConnu': {
		choices: [ 'Oui', 'Non' ],
		helpText:

			C'est le taux de la cotisation accidents du travail (AT) et maladies professionnelles (MP). Il est accessible sur net-entreprises.fr ou reçu par courrier.

,
	},

	'tauxRisque': {
		attributes: {
			inputMode: 'numeric',
			placeholder: 'Par ex. 1,1',
		},
		valueType: percentage,
		defaultValue: '1',
		adapt: validated => ({taux_accident_travail: validated / 100}),
	},

	'selectTauxRisque': {
		fields: [ 'resume' ],
		human: v => v.text,
		optionsURL: 'https://cdn.rawgit.com/sgmap/taux-collectifs-cotisation-atmp/master/taux-2016.json',
	},

	'jei': {
		choices: [ 'Oui', 'Non' ],
		defaultValue: 'Non',
		helpText:

			Votre entreprise doit être éligible à ce statut, et votre employé doit notamment être fortement impliqué dans le projet de R&D.

				Voir toutes les conditions (service-public.fr)

,
		adapt: raw => ({jeune_entreprise_innovante: raw === 'Oui' ? 1 : 0}),
	},

	'serviceUtile': {
		choices: [ ':-|', ':-)' ],
		defaultValue: null,
		helpText:

			Dites-nous si ce simulateur vous a été utile

,
	},

	'partage': {},

	'remarque': {
		attributes: {
			cols: 30,
			rows: 6,
			placeholder: 'Votre remarque',
		},
		validator: {
			test: v => v !== '',
			error: 'Entrez votre remarque',
		},
		human: v => v.substring(0,20) + '...',
	},

}
<|endoftext|>


<commit_before>const Promise = require('bluebird')
const readFile = Promise.promisify(require('fs').readFile)
const showdown = require('showdown')

class MarkdownRenderer {
  constructor (callback) {
    this.callback = callback
    this.converter = new showdown.Converter()
  }

  loadFile (fileName) {
    return readFile(fileName, 'utf8').then((markdown) => {
      return this.load(markdown)
    })
  }

  load (markdown) {
    return this.convert(markdown).then((html) => {
      return this.callback(html)
    }).catch((error) => {
      throw error
    })
  }

  convert (markdown) {
    return Promise.promisify((markdown, callback) => {
      var html = this.converter.makeHtml(markdown)
      html = '
' + html + '
'
      callback(null, html)
    })(markdown)
  }
}

exports.MarkdownRenderer = MarkdownRenderer
<commit_msg>Remove promises from fs, watch loaded files<commit_after>const { promisify } = require('util')
const fs = require('fs')
const showdown = require('showdown')

class MarkdownRenderer {
  constructor (callback) {
    this.callback = callback
    this.converter = new showdown.Converter()
  }

  loadFile (fileName) {
    fs.watch(fileName, () => {
      const markdown = fs.readFileSync(fileName, 'utf8')
      Promise.resolve(this.load(markdown))
    })

    const markdown = fs.readFileSync(fileName, 'utf8')
    return this.load(markdown)
  }

  load (markdown) {
    return this.convert(markdown).then((html) => {
      return this.callback(html)
    }).catch((error) => {
      throw error
    })
  }

  convert (markdown) {
    return promisify((markdown, callback) => {
      var html = this.converter.makeHtml(markdown)
      html = '
' + html + '
'
      callback(null, html)
    })(markdown)
  }
}

exports.MarkdownRenderer = MarkdownRenderer
<|endoftext|>


<commit_before>function lazy(run, time = false) {
    return function () {
        var fire = function () {
            if (fire.ing === true) run.apply(that, arguments);
            fire.ing = false;
        };
        var that = this;
        if (arguments.length) {
            var args = arguments;
            return requestAnimationFrame(function () {
                run.apply(that, args);
            });
        }
        if (fire.ing) return fire.ing = true;
        time = +time;
        if (time > 0) {
            setTimeout(fire, time);
            fire.ing = true;
        } else {
            fire.ing = requestAnimationFrame(fire);
            if (time === false || time === 0) fire.ing = true;
            else run();
        }
    };
}<commit_msg>修复防抖功能<commit_after>function lazy(run, time = false) {
    var fireing;
    return function () {
        var fire = function () {
            if (fireing === true) run.apply(that, arguments);
            fireing = false;
        };
        var that = this;
        if (arguments.length) {
            var args = arguments;
            return requestAnimationFrame(function () {
                run.apply(that, args);
            });
        }
        if (fireing) return fireing = true;
        if (time > 0) {
            setTimeout(fire, +time);
            fireing = true;
        } else {
            fireing = requestAnimationFrame(fire);
            if (time === false || time === 0) fireing = true;
            else run();
        }
    };
}<|endoftext|>


<commit_before>/**
 * Created by larry on 8/28/16.
 */

function countBs(aString) {
    var result = 0;
    for (var i = 0; i < aString.length; i++) {
        if (aString.charAt(i) === 'B') {
            result++;
        }
    }
    return result;
}

console.log("B's in 'BBB' ", countBs('BBB'));
console.log("B's in 'bbbB' ", countBs('bbbB'));
console.log("B's in 'bbbb' ", countBs('bbbb'));

function countChar(inText, toCount) {
    var result = 0;
    for (var i = 0; i < inText.length; i++) {
        if (inText.charAt(i) === toCount) {
            result++;
        }
    }
    return result;
}

console.log("z's in 'zzz' ", countChar('zzz', 'z'));
console.log("Q's in 'qqQ' ", countChar('qqQ', 'Q'));
console.log("a's in 'AAA' ", countChar('AAA', 'a'));<commit_msg>Change implementation of `countBs()`<commit_after>/**
 * Created by larry on 8/28/16.
 */

function countBs(aString) {
    return countChar(aString, 'B');
}

console.log("B's in 'BBB' ", countBs('BBB'));
console.log("B's in 'bbbB' ", countBs('bbbB'));
console.log("B's in 'bbbb' ", countBs('bbbb'));

function countChar(inText, toCount) {
    var result = 0;
    for (var i = 0; i < inText.length; i++) {
        if (inText.charAt(i) === toCount) {
            result++;
        }
    }
    return result;
}

console.log("z's in 'zzz' ", countChar('zzz', 'z'));
console.log("Q's in 'qqQ' ", countChar('qqQ', 'Q'));
console.log("a's in 'AAA' ", countChar('AAA', 'a'));<|endoftext|>


<commit_before>module.exports = function (gulp) {
	require('./gulp-hint')(gulp);
	var browserify = require('browserify');
	var tsify = require('tsify');
	var source = require('vinyl-source-stream');
	var buffer = require('vinyl-buffer');
	var uglify = require('gulp-uglify');
	var sourcemaps = require('gulp-sourcemaps');
	var gutil = require('gulp-util');
	var ngAnnotate = require('gulp-ng-annotate');
	var assign = require('lodash.assign');
	var watchify = require('watchify');

	var customOpts = {
  		entries: ['src/ts/main.ts'],
  		debug: true
	};
	var opts = assign({}, watchify.args, customOpts);
	var b = watchify(browserify(opts).plugin('tsify'));

	gulp.task(':browserify', [':tslint', ':clean-js'], bundle); // so you can run `gulp :browserify` to build the file
	b.on('update', bundle); // on any dep update, runs the bundler
	b.on('log', gutil.log); // output build logs to terminal

	function bundle () {
		return b.bundle()
		    .pipe(source('bundled.js'))
		    .pipe(ngAnnotate())
		    .pipe(buffer())
		    .pipe(sourcemaps.init({loadMaps: true}))
		        // Add transformation tasks to the pipeline here.
		        .pipe(uglify())
		        .on('error', gutil.log)
		    .pipe(sourcemaps.write('./'))
		    .pipe(gulp.dest('./src/prod/js/'));
	}
};<commit_msg>logging browserify error<commit_after>module.exports = function (gulp) {
	require('./gulp-hint')(gulp);
	var browserify = require('browserify');
	var tsify = require('tsify');
	var source = require('vinyl-source-stream');
	var buffer = require('vinyl-buffer');
	var uglify = require('gulp-uglify');
	var sourcemaps = require('gulp-sourcemaps');
	var gutil = require('gulp-util');
	var ngAnnotate = require('gulp-ng-annotate');
	var assign = require('lodash.assign');
	var watchify = require('watchify');

	var customOpts = {
  		entries: ['src/ts/main.ts'],
  		debug: true
	};
	var opts = assign({}, watchify.args, customOpts);
	var b = watchify(browserify(opts).plugin('tsify'));

	gulp.task(':browserify', [':tslint', ':clean-js'], bundle); // so you can run `gulp :browserify` to build the file
	b.on('update', bundle); // on any dep update, runs the bundler
	b.on('log', gutil.log); // output build logs to terminal

	function bundle () {
		return b.bundle()
			.on('error', gutil.log.bind(gutil, 'Browserify Error'))
		    .pipe(source('bundled.js'))
		    .pipe(ngAnnotate())
		    .pipe(buffer())
		    .pipe(sourcemaps.init({loadMaps: true}))
		        // Add transformation tasks to the pipeline here.
		        .pipe(uglify())
		        .on('error', gutil.log)
		    .pipe(sourcemaps.write('./'))
		    .pipe(gulp.dest('./src/prod/js/'));
	}
};<|endoftext|>


<commit_before>javascript: (function() { var themes = {}; themes.dark = { font: 'Monaco', bMainBackground: 'hsl(0, 0%, 0%)', pageHeader: { tReviewTitle: 'hsl( 0, 0%, 100%)', bReviewTitleHover: 'hsl(60, 100%, 20%)', tReviewState: 'hsl( 0, 0%, 50%)', tReviewStateOverdue: 'hsl( 0, 100%, 40%)', tReviewMembers: 'hsl( 0, 0%, 50%)' }, toolbars: { bBackground: 'hsl(0, 0%, 20%)', tText: 'hsl(0, 0%, 100%)', oBorder: '1px solid hsl(0, 0%, 40%)' }, lowerToolbar: { tFileChangedName: 'hsl(210, 50%, 85%)', tFileChangedTag: 'hsl(210, 100%, 40%)', tFileAddedName: 'hsl(120, 100%, 45%)', tFileAddedTag: 'hsl(120, 100%, 30%)', tFileDeletedName: 'hsl( 0, 100%, 55%)', tFileDeletedTag: 'hsl( 0, 100%, 40%)', tDropdownMenuFileOutdated: 'hsl(0, 100%, 66%) !important' }, bHighlightedLine: 'hsl(0, 0%, 25%)', bFileCommentsSeparator: 'hsl(0, 0%, 66%)', oColumnVerticalBorder: '1px solid hsl(0, 0%, 38%)', revision: { bBackground: 'hsl(0, 0%, 20%)', tText: 'hsl(0, 0%, 63%)' }, lineNumbers: { normal: { tText: 'hsl(0, 0%, 40%)' }, old: { tText: 'hsl(0, 100%, 50%)', bBackground: 'hsl(0, 100%, 30%)' }, new: { tText: 'hsl(120, 100%, 40%)', bBackground: 'hsl(120, 100%, 25%)' } }, tCodeTextDefault: 'hsl(0, 0%, 100%)', token: { tKeyword: 'hsl(210, 100%, 80%)', tStartTag: 'hsl(210, 100%, 80%)', tEndTag: 'hsl(210, 100%, 80%)', tString: 'hsl(290, 100%, 80%)', tCharLiteral: 'hsl(290, 100%, 80%)', tNumeric: 'hsl(290, 100%, 80%)', tComment: 'hsl(22, 100%, 60%)', tTodo: 'hsl(22, 100%, 60%)', tIdentifier: 'hsl(45, 100%, 66%)', tAttrib: 'hsl(45, 100%, 66%)' }, diff: { completeBlock: { bOldBackground: 'hsl( 0, 100%, 30%)', bNewBackground: 'hsl(120, 100%, 25%)' }, partialBlock: { identical: { bOldBackground: 'hsl( 0, 100%, 12%)', bNewBackground: 'hsl(120, 100%, 10%)' }, changed: { bOldBackground: 'hsl( 0, 100%, 30%)', bNewBackground: 'hsl(120, 100%, 25%)' } }, bNonExistentBlockBackground: 'hsl(0, 0%, 20%)', bContextSeparatorBackground: 'hsl(0, 0%, 20%)' }, userComment: { bDefault: 'hsl(60, 25%, 60%)', bRead: 'hsl(60, 25%, 60%)', bUnread: 'hsl(60, 35%, 80%)', bLeaveUnread: 'hsl(60, 35%, 80%)', bReadDefect: 'hsl( 0, 25%, 60%)', bUnreadDefect: 'hsl( 0, 35%, 80%)', bLeaveUnreadDefect: 'hsl( 0, 35%, 80%)' } }; var theme = themes.dark; var css = "" + "body { background-color: " + theme.bMainBackground + "; } " + ".source { background-color: " + theme.bMainBackground + "; } " + ".revision_comments_frxinner { background-color: " + theme.bMainBackground + "; } " + "#reviewHead { color: " + theme.pageHeader.tReviewTitle + "; } " + "#reviewHead span.title a { color: " + theme.pageHeader.tReviewTitle + "; } " + "#reviewHead.editable:hover { background-color: " + theme.pageHeader.bReviewTitleHover + "; } " + "#review-state { color: " + theme.pageHeader.tReviewState + "; } " + "#review-state span { color: " + theme.pageHeader.tReviewState + " !important; } " + "#review-state em { color: " + theme.pageHeader.tReviewStateOverdue + "; } " + ".review-members h5 { color: " + theme.pageHeader.tReviewMembers + "; } " + "#status { -webkit-filter: invert(100%); } " + "#review-meta h3 { background-color: " + theme.toolbars.bBackground + "; color: " + theme.toolbars.tText + "; border: " + theme.toolbars.oBorder + "; } " + "#content-column .toolbar { color: " + theme.toolbars.tText + "; background-color: " + theme.toolbars.bBackground + "; } " + "#reviewpage #review-info-container .toolbar { border: " + theme.toolbars.oBorder + "; } " + "#time-spent-input { color: " + theme.toolbars.tText + "; } " + "#reviewpage .toolbar .toolbar-keyboard-shortcuts { color: " + theme.toolbars.tText + "; } " + ".frx-header-container .frx-header { background-color: " + theme.toolbars.bBackground + "; border-bottom: " + theme.toolbars.oBorder + "; } " + ".frx-header-container { border-left: " + theme.toolbars.oBorder + "; } " + ".path-truncated .path-prefix { color: " + theme.toolbars.tText + "; } " + ".frx-actions-primary .stats { color: " + theme.toolbars.tText + "; } " + "#content-column span.frx-changed { color: " + theme.lowerToolbar.tFileChangedName + "; } " + "#content-column span.operation-text.frx-changed { color: " + theme.lowerToolbar.tFileChangedTag + "; } " + "#content-column span.frx-added { color: " + theme.lowerToolbar.tFileAddedName + "; } " + "#content-column span.operation-text.frx-added { color: " + theme.lowerToolbar.tFileAddedTag + "; } " + "#content-column span.frx-deleted { color: " + theme.lowerToolbar.tFileDeletedName + "; } " + "#content-column span.operation-text.frx-deleted { color: " + theme.lowerToolbar.tFileDeletedTag + "; } " + ".frx-outdated a.aui-dd-link { color: " + theme.lowerToolbar.tDropdownMenuFileOutdated + "; } " + ".toolbar-frame .aui-dd-parent a.aui-dd-link { color: " + theme.toolbars.tText + "; } " + "#frx-pane { background-color: " + theme.bMainBackground + "; border-left: " + theme.toolbars.oBorder + "; } " + ".lineHighlighted { background-color: " + theme.bHighlightedLine + "; } " + ".inline-comment-tip { background-color: " + theme.bFileCommentsSeparator + "; } " + ".tetrisColumn { background-color: " + theme.bMainBackground + "; font-size: 1pt; } " + ".diffNav { background-color: " + theme.bMainBackground + "; border-right: " + theme.oColumnVerticalBorder + "; font-size: 1pt; } " + ".diffNav img { -webkit-filter: invert(100%); } " + ".inlineSource td.author { background-color: " + theme.bMainBackground + "; } " + "td.revision { background-color: " + theme.revision.bBackground + "; color: " + theme.revision.tText + "; } " + ".diffLineNumbers { font-family: " + theme.font + "; color: " + theme.lineNumbers.normal.tText + "; } " + ".diffLineNumbersA { font-family: " + theme.font + "; color: " + theme.lineNumbers.old.tText + "; background-color: " + theme.lineNumbers.old.bBackground + "; } " + ".diffLineNumbersB { font-family: " + theme.font + "; color: " + theme.lineNumbers.new.tText + "; background-color: " + theme.lineNumbers.new.bBackground + "; } " + ".lineContent { font-family: " + theme.font + "; color: " + theme.tCodeTextDefault + "; } " + ".diffContent { border-left: " + theme.oColumnVerticalBorder + "; border-right: " + theme.oColumnVerticalBorder + "; } " + ".hl_keyword { color: " + theme.token.tKeyword + "; font-weight: normal; } " + ".hl_starttag { color: " + theme.token.tStartTag + "; font-weight: normal; } " + ".hl_endtag { color: " + theme.token.tEndTag + "; font-weight: normal; } " + ".hl_string { color: " + theme.token.tString + "; font-weight: normal; } " + ".hl_char_literal { color: " + theme.token.tCharLiteral + "; font-weight: normal; } " + ".hl_numeric { color: " + theme.token.tNumeric + "; } " + ".hl_comment { color: " + theme.token.tComment + "; font-style: normal; } " + ".hl_todo { color: " + theme.token.tTodo + "; font-weight: normal; } " + ".hl_identifier { color: " + theme.token.tIdentifier + "; } " + ".hl_attrib { color: " + theme.token.tAttrib + "; } " + "td.diffContentA { background-color: " + theme.diff.completeBlock.bOldBackground + "; border-left: " + theme.oColumnVerticalBorder + "; border-right: " + theme.oColumnVerticalBorder + "; } " + "td.diffContentB { background-color: " + theme.diff.completeBlock.bNewBackground + "; border-left: " + theme.oColumnVerticalBorder + "; border-right: " + theme.oColumnVerticalBorder + "; } " + ".ediffContentA { background-color: " + theme.diff.partialBlock.identical.bOldBackground + "; border-left: " + theme.oColumnVerticalBorder + "; border-right: " + theme.oColumnVerticalBorder + "; } " + ".ediffContentB { background-color: " + theme.diff.partialBlock.identical.bNewBackground + "; border-left: " + theme.oColumnVerticalBorder + "; border-right: " + theme.oColumnVerticalBorder + "; } " + ".ediffChangedA { background-color: " + theme.diff.partialBlock.changed.bOldBackground + "; padding: 1px 0px; } " + ".ediffChangedB { background-color: " + theme.diff.partialBlock.changed.bNewBackground + "; padding: 1px 0px; } " + ".cells-empty .cell-empty { background-color: " + theme.diff.bNonExistentBlockBackground + "; } " + ".inlineSource td.author.cell-empty { background-color: " + theme.diff.bNonExistentBlockBackground + "; } " + ".inlineSource td.revision.cell-empty { background-color: " + theme.diff.bNonExistentBlockBackground + "; } " + ".activeFrx .diffSkipped td { background-image: none; background-color: " + theme.diff.bContextSeparatorBackground + "; } " + ".comment { border: 0; background-color: " + theme.userComment.bDefault + "; } " + ".comment.read { border: 0; background-color: " + theme.userComment.bRead + "; } " + ".comment.unread { border: 0; background-color: " + theme.userComment.bUnread + "; } " + ".comment.leaveUnread { border: 0; background-color: " + theme.userComment.bLeaveUnread + "; } " + ".comment.read.defect { border: 0; background-color: " + theme.userComment.bReadDefect + "; } " + ".comment.unread.defect { border: 0; background-color: " + theme.userComment.bUnreadDefect + "; } " + ".comment.leaveUnread.defect { border: 0; background-color: " + theme.userComment.bLeaveUnreadDefect + "; } "; var styleElement = document.createElement('style'); styleElement.type = 'text/css'; styleElement.appendChild(document.createTextNode(css)); document.getElementsByTagName('head')[0].appendChild(styleElement); })();<commit_msg>Update minified file<commit_after>javascript: (function() { var themes = {}; var palettes = {}; palettes.dark = { brightText: 'hsl(0, 0%, 100%)', dimText: 'hsl(0, 0%, 50%)', darkGreyBackground: 'hsl(0, 0%, 20%)', commonBorders: '1px solid hsl(0, 0%, 40%)', tokenBlue: 'hsl(210, 100%, 80%)', tokenPurple: 'hsl(290, 100%, 80%)', tokenOrange: 'hsl( 22, 100%, 60%)', tokenYellow: 'hsl( 45, 100%, 66%)' }; themes.dark = { font: 'Monaco', bMainBackground: 'hsl(0, 0%, 0%)', pageHeader: { tReviewTitle: palettes.dark.brightText, bReviewTitleHover: 'hsl(60, 100%, 20%)', tReviewState: palettes.dark.dimText, tReviewStateOverdue: 'hsl( 0, 100%, 40%)', tReviewMembers: palettes.dark.dimText }, toolbars: { bBackground: palettes.dark.darkGreyBackground, tText: palettes.dark.brightText, oBorder: palettes.dark.commonBorders }, oUpperToolbarSeparatorBorder: palettes.dark.commonBorders, lowerToolbar: { tFileChangedName: 'hsl(210, 50%, 85%)', tFileChangedTag: 'hsl(210, 100%, 40%)', tFileAddedName: 'hsl(120, 100%, 45%)', tFileAddedTag: 'hsl(120, 100%, 30%)', tFileDeletedName: 'hsl( 0, 100%, 55%)', tFileDeletedTag: 'hsl( 0, 100%, 40%)', tDropdownMenuFileOutdated: 'hsl(0, 100%, 66%) !important' }, bFileCommentsSeparator: 'hsl(0, 0%, 66%)', oColumnVerticalBorder: palettes.dark.commonBorders, author: { bBackground: palettes.dark.darkGreyBackground }, revision: { bBackground: palettes.dark.darkGreyBackground, tText: 'hsl(0, 0%, 63%)' }, lineNumbers: { normal: { tText: 'hsl(0, 0%, 40%)' }, old: { tText: 'hsl(0, 100%, 50%)', bBackground: 'hsl(0, 100%, 30%) !important' }, new: { tText: 'hsl(120, 100%, 40%)', bBackground: 'hsl(120, 100%, 25%) !important' } }, tCodeTextDefault: palettes.dark.brightText, token: { tKeyword: palettes.dark.tokenBlue, tStartTag: palettes.dark.tokenBlue, tEndTag: palettes.dark.tokenBlue, tString: palettes.dark.tokenPurple, tCharLiteral: palettes.dark.tokenPurple, tNumeric: palettes.dark.tokenPurple, tComment: palettes.dark.tokenOrange, tTodo: palettes.dark.tokenOrange, tIdentifier: palettes.dark.tokenYellow, tAttrib: palettes.dark.tokenYellow }, diff: { verticalBorder: { oOld: '1px solid hsl( 0, 100%, 50%)', oNew: '1px solid hsl(120, 100%, 40%)' }, completeBlock: { bOldBackground: 'hsl( 0, 100%, 30%) !important', bNewBackground: 'hsl(120, 100%, 25%) !important' }, partialBlock: { identical: { bOldBackground: 'hsl( 0, 100%, 12%) !important', bNewBackground: 'hsl(120, 100%, 10%) !important' }, changed: { bOldBackground: 'hsl( 0, 100%, 30%) !important', bNewBackground: 'hsl(120, 100%, 25%) !important' } }, contextSeparator: { dBackground: "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAATElEQVQYV4XQAQoAMAQFUM7k/kdwpg01YUEp6pUfBIAj7UVEcbWZmQEj7JBihxNyuCGDglLGl6kG/aAGr6UXE+xQOj0hhxtK79mefgG0Rif++GpEPQAAAABJRU5ErkJggg==') repeat", sHeight: '50px' } }, userComment: { bDefault: 'hsl(60, 25%, 60%)', bRead: 'hsl(60, 25%, 60%)', bUnread: 'hsl(60, 35%, 80%)', bLeaveUnread: 'hsl(60, 35%, 80%)', bReadDefect: 'hsl( 0, 25%, 60%)', bUnreadDefect: 'hsl( 0, 35%, 80%)', bLeaveUnreadDefect: 'hsl( 0, 35%, 80%)' } }; var theme = themes.dark; var css = "" + "body { background-color: " + theme.bMainBackground + "; } " + "#reviewHead { color: " + theme.pageHeader.tReviewTitle + "; } " + "#reviewHead span.title a { color: " + theme.pageHeader.tReviewTitle + "; } " + "#reviewHead.editable:hover { background-color: " + theme.pageHeader.bReviewTitleHover + "; } " + "#review-state { color: " + theme.pageHeader.tReviewState + "; } " + "#review-state span { color: " + theme.pageHeader.tReviewState + " !important; } " + "#review-state em { color: " + theme.pageHeader.tReviewStateOverdue + "; } " + ".review-members h5 { color: " + theme.pageHeader.tReviewMembers + "; } " + "#status { -webkit-filter: invert(100%); } " + "#review-meta h3 { background-color: " + theme.toolbars.bBackground + "; color: " + theme.toolbars.tText + "; border: " + theme.toolbars.oBorder + "; } " + "#content-column .toolbar { color: " + theme.toolbars.tText + "; background-color: " + theme.toolbars.bBackground + "; } " + "#reviewpage #review-info-container .toolbar { border: " + theme.toolbars.oBorder + "; } " + "#time-spent-input { color: " + theme.toolbars.tText + "; } " + "#reviewpage .toolbar .toolbar-keyboard-shortcuts { color: " + theme.toolbars.tText + "; } " + ".toolbar .tb_left { border-right: " + theme.oUpperToolbarSeparatorBorder + "; } " + ".frx-header-container .frx-header { background-color: " + theme.toolbars.bBackground + "; border-bottom: " + theme.toolbars.oBorder + "; } " + ".frx-header-container { border-left: " + theme.toolbars.oBorder + "; } " + ".path-truncated .path-prefix { color: " + theme.toolbars.tText + "; } " + ".frx-actions-primary .stats { color: " + theme.toolbars.tText + "; } " + "#content-column span.frx-changed { color: " + theme.lowerToolbar.tFileChangedName + "; } " + "#content-column span.operation-text.frx-changed { color: " + theme.lowerToolbar.tFileChangedTag + "; } " + "#content-column span.frx-added { color: " + theme.lowerToolbar.tFileAddedName + "; } " + "#content-column span.operation-text.frx-added { color: " + theme.lowerToolbar.tFileAddedTag + "; } " + "#content-column span.frx-deleted { color: " + theme.lowerToolbar.tFileDeletedName + "; } " + "#content-column span.operation-text.frx-deleted { color: " + theme.lowerToolbar.tFileDeletedTag + "; } " + ".frx-outdated a.aui-dd-link { color: " + theme.lowerToolbar.tDropdownMenuFileOutdated + "; } " + ".toolbar-frame .aui-dd-parent a.aui-dd-link { color: " + theme.toolbars.tText + "; } " + "#frx-pane { background-color: " + theme.bMainBackground + "; border-left: " + theme.toolbars.oBorder + "; } " + ".revision_comments_frxinner { background-color: " + theme.bMainBackground + "; } " + ".source { background-color: " + theme.bMainBackground + "; } " + ".inline-comment-tip { background-color: " + theme.bFileCommentsSeparator + "; } " + ".tetrisColumn { background-color: " + theme.bMainBackground + "; font-size: 1pt; } " + ".diffNav { background-color: " + theme.bMainBackground + "; border-right: " + theme.oColumnVerticalBorder + "; font-size: 1pt; } " + ".diffNav img { -webkit-filter: invert(100%); } " + ".inlineSource td.author { background-color: " + theme.author.bBackground + "; } " + "td.revision { background-color: " + theme.revision.bBackground + "; color: " + theme.revision.tText + "; } " + "td.diffLineNumbers { font-family: " + theme.font + "; color: " + theme.lineNumbers.normal.tText + "; background-color: " + theme.bMainBackground + "; } " + "td.diffLineNumbersA { font-family: " + theme.font + "; color: " + theme.lineNumbers.old.tText + "; background-color: " + theme.lineNumbers.old.bBackground + "; } " + "td.diffLineNumbersB { font-family: " + theme.font + "; color: " + theme.lineNumbers.new.tText + "; background-color: " + theme.lineNumbers.new.bBackground + "; } " + ".lineContent { font-family: " + theme.font + "; color: " + theme.tCodeTextDefault + "; } " + ".diffContent { border-left: " + theme.oColumnVerticalBorder + "; border-right: " + theme.oColumnVerticalBorder + "; background-color: " + theme.bMainBackground + "; } " + ".hl_keyword { color: " + theme.token.tKeyword + "; font-weight: normal; } " + ".hl_starttag { color: " + theme.token.tStartTag + "; font-weight: normal; } " + ".hl_endtag { color: " + theme.token.tEndTag + "; font-weight: normal; } " + ".hl_string { color: " + theme.token.tString + "; font-weight: normal; } " + ".hl_char_literal { color: " + theme.token.tCharLiteral + "; font-weight: normal; } " + ".hl_numeric { color: " + theme.token.tNumeric + "; } " + ".hl_comment { color: " + theme.token.tComment + "; font-style: normal; } " + ".hl_todo { color: " + theme.token.tTodo + "; font-weight: normal; } " + ".hl_identifier { color: " + theme.token.tIdentifier + "; } " + ".hl_attrib { color: " + theme.token.tAttrib + "; } " + "table td.lineContent.diffContentA { background-color: " + theme.diff.completeBlock.bOldBackground + "; border-left: " + theme.diff.verticalBorder.oOld + "; border-right: " + theme.diff.verticalBorder.oOld + "; } " + "table td.lineContent.diffContentB { background-color: " + theme.diff.completeBlock.bNewBackground + "; border-left: " + theme.diff.verticalBorder.oNew + "; border-right: " + theme.diff.verticalBorder.oNew + "; } " + "table td.lineContent.ediffContentA { background-color: " + theme.diff.partialBlock.identical.bOldBackground + "; border-left: " + theme.diff.verticalBorder.oOld + "; border-right: " + theme.diff.verticalBorder.oOld + "; } " + "table td.lineContent.ediffContentB { background-color: " + theme.diff.partialBlock.identical.bNewBackground + "; border-left: " + theme.diff.verticalBorder.oNew + "; border-right: " + theme.diff.verticalBorder.oNew + "; } " + ".ediffChangedA { background-color: " + theme.diff.partialBlock.changed.bOldBackground + "; padding: 1px 0px; } " + ".ediffChangedB { background-color: " + theme.diff.partialBlock.changed.bNewBackground + "; padding: 1px 0px; } " + ".cells-empty .cell-empty { background-color: " + theme.bMainBackground + "; } " + ".inlineSource td.author.cell-empty { background-color: " + theme.author.bBackground + "; } " + ".inlineSource td.revision.cell-empty { background-color: " + theme.revision.bBackground + "; } " + ".activeFrx .diffSkipped { border: 0; } " + ".activeFrx .diffSkipped td { background: " + theme.diff.contextSeparator.dBackground + "; height: " + theme.diff.contextSeparator.sHeight + "; } " + ".inlineSource .lineHighlighted .diffLineNumbers { background-color: " + theme.bMainBackground + "; } " + ".inlineSource .lineHighlighted .diffContent { background-color: " + theme.bMainBackground + "; } " + ".comment { border: 0; background-color: " + theme.userComment.bDefault + "; } " + ".comment.read { border: 0; background-color: " + theme.userComment.bRead + "; } " + ".comment.unread { border: 0; background-color: " + theme.userComment.bUnread + "; } " + ".comment.leaveUnread { border: 0; background-color: " + theme.userComment.bLeaveUnread + "; } " + ".comment.read.defect { border: 0; background-color: " + theme.userComment.bReadDefect + "; } " + ".comment.unread.defect { border: 0; background-color: " + theme.userComment.bUnreadDefect + "; } " + ".comment.leaveUnread.defect { border: 0; background-color: " + theme.userComment.bLeaveUnreadDefect + "; } "; var styleElement = document.createElement('style'); styleElement.type = 'text/css'; styleElement.appendChild(document.createTextNode(css)); document.getElementsByTagName('head')[0].appendChild(styleElement); })();<|endoftext|>


<commit_before>/**
 * Copyright 2013,2014 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

module.exports = function(RED) {
    'use strict';
    require('events').EventEmitter.prototype._maxListeners = 100;
    var util  = require('util');
    var utils = require(__dirname + '/../lib/utils');
    //var redis = require("redis");
    //var hashFieldRE = /^([^=]+)=(.*)$/;
	// Get the redis address

	var settings = require(process.env.NODE_RED_HOME + '/red/red').settings;
    var instance = settings.get('iobrokerInstance') || 0;
    var config   = settings.get('iobrokerConfig');
	var valueConvert = settings.get('valueConvert');
    if (typeof config == 'string') {
        config = JSON.parse(config);
    }

    try {
        var adapter = utils.adapter({name: 'node-red', instance: instance, config: config});
    } catch(e) {
        console.log(e);
    }
    var nodes = [];
    var ready = false;
    var log = adapter && adapter.log && adapter.log.warn ? adapter.log.warn : console.log;

    adapter.on('ready', function () {
        ready = true;
        adapter.subscribeForeignStates('*');
        while (nodes.length) {
            var node = nodes.pop();
            if (node instanceof IOBrokerInNode) {
                adapter.on('stateChange', node.stateChange);
            }
            node.status({fill: 'green', shape: 'dot', text: 'connected'});
        }
    });

    // name is like system.state, pattern is like "*.state" or "*" or "*system*"
    function getRegex(pattern) {
        if (!pattern || pattern === '*') return null;
        if (pattern.indexOf('*') === -1) return null;
        if (pattern[pattern.length - 1] !== '*') pattern = pattern + '$';
        if (pattern[0] !== '*') pattern = '^' + pattern;
        pattern = pattern.replace(/\*/g, '[a-zA-Z0-9.\s]');
        pattern = pattern.replace(/\./g, '\\.');
        return new RegExp(pattern);
    }

    function checkState(node, id, val, callback) {
        if (node.idChecked) {
            return callback && callback();
        }
        node.idChecked = true;

        adapter.getObject(node.topic, function (err, obj) {
            if (!obj) {
                adapter.getForeignObject(node.topic, function (err, obj) {
                    if (!obj) {
                        log('State "' + id + '" was created in the ioBroker as ' + adapter._fixId(id));
                        // Create object
                        adapter.setObject(id, {
                            common: {
                                name: id,
                                role: 'info',
                                type: 'state',
                                desc: 'Created by MQTT'
                            },
                            native: {},
                            type: 'state'
                        }, function (err) {
                            if (val !== undefined && val !== null && val !== '__create__') {
                                adapter.setState(id, val, function () {
                                    callback && callback();
                                });
                            } else {
                                adapter.setState(id, undefined, function () {
                                    callback && callback();
                                });
                            }
                        });
                    } else {
                        node._id = obj._id;
                        if (val !== undefined && val !== null && val !== '__create__') {
                            adapter.setForeignState(obj._id, val, function () {
                                callback && callback();
                            });
                        } else {
                            callback && callback();
                        }
                    }
                });
            } else {
                if (val !== undefined && val !== null && val !== '__create__') {
                    adapter.setForeignState(obj._id, val, function () {
                        callback && callback();
                    });
                } else {
                    callback && callback();
                }
            }
        });
    }

    function IOBrokerInNode(n) {
        var node = this;
        RED.nodes.createNode(node,n);
        node.topic = (n.topic || '*').replace(/\//g, '.');
        node.regex = new RegExp('^node-red\\.' + instance + '\\.');

        // If no adapter prefix, add own adapter prefix
        if (node.topic && node.topic.indexOf('.') === -1) {
            node.topic = adapter.namespace + '.' + node.topic;
        }

        node.regexTopic  = getRegex(this.topic);
        node.payloadType = n.payloadType;
        node.onlyack     = (n.onlyack == true || false);
        node.func        = n.func || 'all';
        node.gap         = n.gap || '0';
        node.pc          = false;

		if (node.gap.substr(-1) === '%') {
            node.pc = true;
            node.gap = parseFloat(node.gap);
        }
        node.g = node.gap;

        node.previous = {};

        if (node.topic) {
            var id = node.topic;
            // If no wildchars and belongs to this adapter
            if (id.indexOf('*') === -1 && (node.regex.test(id) || id.indexOf('.') !== -1)) {
                checkState(node, id);
            }
        }

        if (ready) {
            node.status({fill: 'green', shape: 'dot', text: 'connected'});
        } else {
            node.status({fill: 'red', shape: 'ring', text: 'disconnected'}, true);
        }

        node.stateChange = function(topic, obj) {
            if (node.regexTopic) {
                if (!node.regexTopic.test(topic)) return;
            } else if (node.topic !== '*' && node.topic !== topic) {
                return;
            }

			if (node.onlyack && obj.ack != true) return;

            var t = topic.replace(/\./g, '/') || '_no_topic';
            //node.log ("Function: " + node.func);

			if (node.func === 'rbe') {
                if (obj.val === node.previous[t]) {
                    return;
                }
            } else if (node.func === 'deadband') {
                var n = parseFloat(obj.val.toString());
                if (!isNaN(n)) {
                    //node.log('Old Value: ' + node.previous[t] + ' New Value: ' + n);
                    if (node.pc) { node.gap = (node.previous[t] * node.g / 100) || 0; }
                    if (!node.previous.hasOwnProperty(t)) {
                        node.previous[t] = n - node.gap;
                    }
                    if (!Math.abs(n - node.previous[t]) >= node.gap) {
                        return;
                    }
                } else {
                    node.warn('no number found in value');
                    return;
                }
            }
            node.previous[t] = obj.val;

            node.send({
                topic:       t,
                payload:     (node.payloadType === 'object') ? obj : ((obj.val === null || obj.val === undefined) ? '' : (valueConvert ? obj.val.toString() : obj.val)),
                acknowledged:obj.ack,
                timestamp:   obj.ts,
                lastchange:  obj.lc,
                from:        obj.from
            });
        };

        node.on('close', function() {
            adapter.removeListener('stateChange', node.stateChange);
        });

        if (ready) {
            adapter.on('stateChange', node.stateChange);
        } else {
            nodes.push(node);
        }
    }
    RED.nodes.registerType('ioBroker in', IOBrokerInNode);

    function IOBrokerOutNode(n) {
        var node = this;
        RED.nodes.createNode(node,n);
        node.topic = n.topic;

        node.ack = (n.ack === 'true' || n.ack === true);
        node.autoCreate = (n.autoCreate === 'true' || n.autoCreate === true);
        node.regex = new RegExp('^node-red\\.' + instance + '\\.');

        // Create variable if not exists
        if (node.autoCreate && node.topic) {
            var id = node.topic.replace(/\//g, '.');
            // If no wildchars and belongs to this adapter
            if (id.indexOf('*') === -1 && (node.regex.test(id) || id.indexOf('.') !== -1)) {
                checkState(node, node.topic);
            }
        }

        if (ready) {
            node.status({fill: 'green', shape: 'dot', text: 'connected'});
        } else {
            node.status({fill: 'red', shape: 'ring', text: 'disconnected'}, true);
        }

        function setState(id, val, ack) {
            if (id === node.topic && node.idChecked) {
                if (val !== '__create__') {
                    adapter.setState(id, {val: val, ack: ack});
                }
            } else if (!node.idChecked) {
                checkState(node, node.topic, {val: val, ack: ack});
            }
        }

        node.on('input', function(msg) {
            var id = node.topic || msg.topic;
            if (id) {
                id = id.replace(/\//g, '.');
                // If not this adapter state
                if (!node.regex.test(id) && id.indexOf('.') !== -1) {
                    // Check if state exists
                    adapter.getForeignState(id, function (err, state) {
                        if (!err && state) {
                            adapter.setForeignState(id, {val: msg.payload, ack: node.ack});
                        } else {
                            log('State "' + id + '" does not exist in the ioBroker');
                        }
                    });
                } else {
                    if (id.indexOf('*') !== -1) {
                        log('Invalid topic name "' + id + '" for ioBroker');
                    } else {
                        setState(id, msg.payload, node.ack);
                    }
                }
            } else {
                node.warn('No key or topic set');
            }
        });

        if (!ready) {
            nodes.push(node);
        }

        //node.on("close", function() {
//
//        });

    }
    RED.nodes.registerType('ioBroker out', IOBrokerOutNode);

    function IOBrokerGetNode(n) {
        var node = this;
        RED.nodes.createNode(node,n);
        node.topic =  (typeof n.topic=== 'string' && n.topic.length > 0 ?  n.topic.replace(/\//g, '.') : null) ;

        // If no adapter prefix, add own adapter prefix
        if (node.topic && node.topic.indexOf('.') === -1) {
            node.topic = adapter.namespace + '.' + node.topic;
        }

        node.regex = new RegExp('^node-red\\.' + instance + '\\.');
        //node.regex = getRegex(this.topic);
        node.payloadType = n.payloadType;
        node.attrname = n.attrname;

        if (node.topic) {
            var id = node.topic;
            // If no wildchars and belongs to this adapter
            if (id.indexOf('*') === -1 && (node.regex.test(id) || id.indexOf('.') !== -1)) {
                checkState(node, id);
            }
        }

        if (ready) {
            node.status({fill: 'green', shape: 'dot', text: 'connected'});
        } else {
            node.status({fill: 'red', shape: 'ring', text: 'disconnected'}, true);
        }

        node.getStateValue = function (msg) {
            return function (err, state) {
                if (!err && state) {
                    msg[node.attrname] = (node.payloadType === 'object') ? state : ((state.val === null || state.val === undefined) ? '' : (valueConvert ? state.val.toString() : state.val));
                    msg.acknowledged   = state.ack;
                    msg.timestamp      = state.ts;
                    msg.lastchange     = state.lc;
                    node.send(msg);
                } else {
                    log('State "' + id + '" does not exist in the ioBroker');
                }
            };
        };

        node.on('input', function(msg) {
            var id = node.topic || msg.topic;
            if (id) {
                id = id.replace(/\//g, '.');
                // If not this adapter state
                if (!node.regex.test(id) && id.indexOf('.') !== -1) {
                    // Check if state exists
                    adapter.getForeignState(id, node.getStateValue(msg));
                } else {
                    if (id.indexOf('*') !== -1) {
                        log('Invalid topic name "' + id + '" for ioBroker');
                    } else {
                        adapter.getState(id, node.getStateValue(msg));
                    }
                }
            } else {
                node.warn('No key or topic set');
            }
        });

        if (!ready) {
            nodes.push(node);
        }

    }
    RED.nodes.registerType('ioBroker get', IOBrokerGetNode);
};

<commit_msg>fix blank topic<commit_after>/**
 * Copyright 2013,2014 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

module.exports = function(RED) {
    'use strict';
    require('events').EventEmitter.prototype._maxListeners = 100;
    var util  = require('util');
    var utils = require(__dirname + '/../lib/utils');
    //var redis = require("redis");
    //var hashFieldRE = /^([^=]+)=(.*)$/;
	// Get the redis address

	var settings = require(process.env.NODE_RED_HOME + '/red/red').settings;
    var instance = settings.get('iobrokerInstance') || 0;
    var config   = settings.get('iobrokerConfig');
	var valueConvert = settings.get('valueConvert');
    if (typeof config == 'string') {
        config = JSON.parse(config);
    }

    try {
        var adapter = utils.adapter({name: 'node-red', instance: instance, config: config});
    } catch(e) {
        console.log(e);
    }
    var nodes = [];
    var ready = false;
    var log = adapter && adapter.log && adapter.log.warn ? adapter.log.warn : console.log;

    adapter.on('ready', function () {
        ready = true;
        adapter.subscribeForeignStates('*');
        while (nodes.length) {
            var node = nodes.pop();
            if (node instanceof IOBrokerInNode) {
                adapter.on('stateChange', node.stateChange);
            }
            node.status({fill: 'green', shape: 'dot', text: 'connected'});
        }
    });

    // name is like system.state, pattern is like "*.state" or "*" or "*system*"
    function getRegex(pattern) {
        if (!pattern || pattern === '*') return null;
        if (pattern.indexOf('*') === -1) return null;
        if (pattern[pattern.length - 1] !== '*') pattern = pattern + '$';
        if (pattern[0] !== '*') pattern = '^' + pattern;
        pattern = pattern.replace(/\*/g, '[a-zA-Z0-9.\s]');
        pattern = pattern.replace(/\./g, '\\.');
        return new RegExp(pattern);
    }

    function checkState(node, id, val, callback) {
        if (node.idChecked) {
            return callback && callback();
        }
        if(node.topic) {
            node.idChecked = true;
        }

        adapter.getObject(id, function (err, obj) {
            if (!obj) {
                adapter.getForeignObject(id, function (err, obj) {
                    if (!obj) {
                        log('State "' + id + '" was created in the ioBroker as ' + adapter._fixId(id));
                        // Create object
                        adapter.setObject(id, {
                            common: {
                                name: id,
                                role: 'info',
                                type: 'state',
                                desc: 'Created by MQTT'
                            },
                            native: {},
                            type: 'state'
                        }, function (err) {
                            if (val !== undefined && val !== null && val !== '__create__') {
                                adapter.setState(id, val, function () {
                                    callback && callback();
                                });
                            } else {
                                adapter.setState(id, undefined, function () {
                                    callback && callback();
                                });
                            }
                        });
                    } else {
                        node._id = obj._id;
                        if (val !== undefined && val !== null && val !== '__create__') {
                            adapter.setForeignState(obj._id, val, function () {
                                callback && callback();
                            });
                        } else {
                            callback && callback();
                        }
                    }
                });
            } else {
                if (val !== undefined && val !== null && val !== '__create__') {
                    adapter.setForeignState(obj._id, val, function () {
                        callback && callback();
                    });
                } else {
                    callback && callback();
                }
            }
        });
    }

    function IOBrokerInNode(n) {
        var node = this;
        RED.nodes.createNode(node,n);
        node.topic = (n.topic || '*').replace(/\//g, '.');
        node.regex = new RegExp('^node-red\\.' + instance + '\\.');

        // If no adapter prefix, add own adapter prefix
        if (node.topic && node.topic.indexOf('.') === -1) {
            node.topic = adapter.namespace + '.' + node.topic;
        }

        node.regexTopic  = getRegex(this.topic);
        node.payloadType = n.payloadType;
        node.onlyack     = (n.onlyack == true || false);
        node.func        = n.func || 'all';
        node.gap         = n.gap || '0';
        node.pc          = false;

		if (node.gap.substr(-1) === '%') {
            node.pc = true;
            node.gap = parseFloat(node.gap);
        }
        node.g = node.gap;

        node.previous = {};

        if (node.topic) {
            var id = node.topic;
            // If no wildchars and belongs to this adapter
            if (id.indexOf('*') === -1 && (node.regex.test(id) || id.indexOf('.') !== -1)) {
                checkState(node, id);
            }
        }

        if (ready) {
            node.status({fill: 'green', shape: 'dot', text: 'connected'});
        } else {
            node.status({fill: 'red', shape: 'ring', text: 'disconnected'}, true);
        }

        node.stateChange = function(topic, obj) {
            if (node.regexTopic) {
                if (!node.regexTopic.test(topic)) return;
            } else if (node.topic !== '*' && node.topic !== topic) {
                return;
            }

			if (node.onlyack && obj.ack != true) return;

            var t = topic.replace(/\./g, '/') || '_no_topic';
            //node.log ("Function: " + node.func);

			if (node.func === 'rbe') {
                if (obj.val === node.previous[t]) {
                    return;
                }
            } else if (node.func === 'deadband') {
                var n = parseFloat(obj.val.toString());
                if (!isNaN(n)) {
                    //node.log('Old Value: ' + node.previous[t] + ' New Value: ' + n);
                    if (node.pc) { node.gap = (node.previous[t] * node.g / 100) || 0; }
                    if (!node.previous.hasOwnProperty(t)) {
                        node.previous[t] = n - node.gap;
                    }
                    if (!Math.abs(n - node.previous[t]) >= node.gap) {
                        return;
                    }
                } else {
                    node.warn('no number found in value');
                    return;
                }
            }
            node.previous[t] = obj.val;

            node.send({
                topic:       t,
                payload:     (node.payloadType === 'object') ? obj : ((obj.val === null || obj.val === undefined) ? '' : (valueConvert ? obj.val.toString() : obj.val)),
                acknowledged:obj.ack,
                timestamp:   obj.ts,
                lastchange:  obj.lc,
                from:        obj.from
            });
        };

        node.on('close', function() {
            adapter.removeListener('stateChange', node.stateChange);
        });

        if (ready) {
            adapter.on('stateChange', node.stateChange);
        } else {
            nodes.push(node);
        }
    }
    RED.nodes.registerType('ioBroker in', IOBrokerInNode);

    function IOBrokerOutNode(n) {
        var node = this;
        RED.nodes.createNode(node,n);
        node.topic = n.topic;

        node.ack = (n.ack === 'true' || n.ack === true);
        node.autoCreate = (n.autoCreate === 'true' || n.autoCreate === true);
        node.regex = new RegExp('^node-red\\.' + instance + '\\.');

        if (ready) {
            node.status({fill: 'green', shape: 'dot', text: 'connected'});
        } else {
            node.status({fill: 'red', shape: 'ring', text: 'disconnected'}, true);
        }

        function setState(id, val, ack) {
            if (node.idChecked) {
                if (val !== '__create__') {
                    adapter.setState(id, {val: val, ack: ack});
                }
            } else {
                checkState(node, id, {val: val, ack: ack});
            }
        }

        node.on('input', function(msg) {
            var id = node.topic || msg.topic;
            if (id) {
                id = id.replace(/\//g, '.');

                // Create variable if not exists
                if (node.autoCreate && !node.idChecked) {
                    id = id.replace(/\//g, '.');
                    // If no wildchars and belongs to this adapter
                    if (id.indexOf('*') === -1 && (node.regex.test(id) || id.indexOf('.') !== -1)) {
                        checkState(node, id);
                    }
                }

                // If not this adapter state
                if (!node.regex.test(id) && id.indexOf('.') !== -1) {
                    // Check if state exists
                    adapter.getForeignState(id, function (err, state) {
                        if (!err && state) {
                            adapter.setForeignState(id, {val: msg.payload, ack: node.ack});
                        } else {
                            log('State "' + id + '" does not exist in the ioBroker');
                        }
                    });
                } else {
                    if (id.indexOf('*') !== -1) {
                        log('Invalid topic name "' + id + '" for ioBroker');
                    } else {
                        setState(id, msg.payload, node.ack);
                    }
                }
            } else {
                node.warn('No key or topic set');
            }
        });

        if (!ready) {
            nodes.push(node);
        }

        //node.on("close", function() {
//
//        });

    }
    RED.nodes.registerType('ioBroker out', IOBrokerOutNode);

    function IOBrokerGetNode(n) {
        var node = this;
        RED.nodes.createNode(node,n);
        node.topic =  (typeof n.topic=== 'string' && n.topic.length > 0 ?  n.topic.replace(/\//g, '.') : null) ;

        // If no adapter prefix, add own adapter prefix
        if (node.topic && node.topic.indexOf('.') === -1) {
            node.topic = adapter.namespace + '.' + node.topic;
        }

        node.regex = new RegExp('^node-red\\.' + instance + '\\.');
        //node.regex = getRegex(this.topic);
        node.payloadType = n.payloadType;
        node.attrname = n.attrname;

        if (node.topic) {
            var id = node.topic;
            // If no wildchars and belongs to this adapter
            if (id.indexOf('*') === -1 && (node.regex.test(id) || id.indexOf('.') !== -1)) {
                checkState(node, id);
            }
        }

        if (ready) {
            node.status({fill: 'green', shape: 'dot', text: 'connected'});
        } else {
            node.status({fill: 'red', shape: 'ring', text: 'disconnected'}, true);
        }

        node.getStateValue = function (msg) {
            return function (err, state) {
                if (!err && state) {
                    msg[node.attrname] = (node.payloadType === 'object') ? state : ((state.val === null || state.val === undefined) ? '' : (valueConvert ? state.val.toString() : state.val));
                    msg.acknowledged   = state.ack;
                    msg.timestamp      = state.ts;
                    msg.lastchange     = state.lc;
                    node.send(msg);
                } else {
                    log('State "' + id + '" does not exist in the ioBroker');
                }
            };
        };

        node.on('input', function(msg) {
            var id = node.topic || msg.topic;
            if (id) {
                id = id.replace(/\//g, '.');
                // If not this adapter state
                if (!node.regex.test(id) && id.indexOf('.') !== -1) {
                    // Check if state exists
                    adapter.getForeignState(id, node.getStateValue(msg));
                } else {
                    if (id.indexOf('*') !== -1) {
                        log('Invalid topic name "' + id + '" for ioBroker');
                    } else {
                        adapter.getState(id, node.getStateValue(msg));
                    }
                }
            } else {
                node.warn('No key or topic set');
            }
        });

        if (!ready) {
            nodes.push(node);
        }

    }
    RED.nodes.registerType('ioBroker get', IOBrokerGetNode);
};

<|endoftext|>