<commit_before>'use strict'

var async = require('async')
var sizlate = require('sizlate')
var getFile = require('./read-file')

var speclate = require('speclate')
var doSizlate = speclate.site.doSizlate
var loadComponents = speclate.components.load

/**
 * used for client side render.
 */
module.exports = function (page, callback) {
  async.parallel({
    pageLayout: function (next) {
      var pageLayoutPath = '/pages/' + page.page + '/' + page.page + '.html'
      getFile(pageLayoutPath, next)
    },
    components: function (next) {
      if (page.spec) {
        loadComponents(page.spec, next)
      } else {
        next()
      }
    }
  }, function (err, data) {

    if (err) {
      return callback(err)
    }
    $('nav a.active').removeClass('active')

    sizlate.render($('html'), {
      '#container': data.pageLayout
    })

    // components have not been renedered here, we just throwing in json
    console.log('--.>', data.components);
    var markup = doSizlate(page, $('html'), data.components)
    $('body').scrollTop($('#container'))
    callback(null, markup)
  })
}
<commit_msg>removing log<commit_after>'use strict'

var async = require('async')
var sizlate = require('sizlate')
var getFile = require('./read-file')

var speclate = require('speclate')
var doSizlate = speclate.site.doSizlate
var loadComponents = speclate.components.load

/**
 * used for client side render.
 */
module.exports = function (page, callback) {
  async.parallel({
    pageLayout: function (next) {
      var pageLayoutPath = '/pages/' + page.page + '/' + page.page + '.html'
      getFile(pageLayoutPath, next)
    },
    components: function (next) {
      if (page.spec) {
        loadComponents(page.spec, next)
      } else {
        next()
      }
    }
  }, function (err, data) {

    if (err) {
      return callback(err)
    }
    $('nav a.active').removeClass('active')

    sizlate.render($('html'), {
      '#container': data.pageLayout
    })
    var markup = doSizlate(page, $('html'), data.components)
    $('body').scrollTop($('#container'))
    callback(null, markup)
  })
}
<|endoftext|>


<commit_before>import React, { useState, useEffect } from "react";
import getConfig from "next/config";

import withErrors from "../components/hoc/with-errors";

import { getAllAPIs } from "../utils/api";

import Page from "../layouts/page";

import ApiCard from "../components/api-card";
import APISearchBar from "../components/api-search-bar";

import colors from "../styles/colors";

import { normaliseStr } from "../utils/normalize";

const { publicRuntimeConfig } = getConfig();
const SITE_DESCRIPTION =
  publicRuntimeConfig.SITE_DESCRIPTION || "Le site qui simplifie le partage et la circulation des données administratives";

function Home({ q, filter, apiList }) {
  const [filteredList, setFilteredList] = useState(apiList);

  useEffect(() => {
    if (filter) {
      const filteredList = apiList.filter(api => {
        const normalizeKeywords = api.keywords.map(k => normaliseStr(k));
        return normalizeKeywords.includes(normaliseStr(filter));
      });

      setFilteredList(filteredList);
    }
  }, [filter]);

  return (
    <Page>

{SITE_DESCRIPTION}

            <APISearchBar q={q} list={apiList} />

            {filteredList.length > 0 ? (
              filteredList.map(api => <ApiCard key={api.title} {...api} />)
            ) : (

Aucune API n’a pu être trouvée

                Aucun résultat avec le filter: {filter}

            )}

    </Page>
  );
}

Home.getInitialProps = async req => {
  const { q, filter } = req.query;
  const apiList = await getAllAPIs();

  return {
    q,
    filter,
    apiList
  };
};

export default withErrors(Home);
<commit_msg>Add externals links to home bottom<commit_after>import React, { useState, useEffect } from "react";
import getConfig from "next/config";

import withErrors from "../components/hoc/with-errors";

import { getAllAPIs } from "../utils/api";

import Page from "../layouts/page";

import ApiCard from "../components/api-card";
import APISearchBar from "../components/api-search-bar";
import ButtonLink from "../components/ui/button-link";

import colors from "../styles/colors";

import { normaliseStr } from "../utils/normalize";

const { publicRuntimeConfig } = getConfig();
const SITE_DESCRIPTION =
  publicRuntimeConfig.SITE_DESCRIPTION ||
  "Le site qui simplifie le partage et la circulation des données administratives";

function Home({ q, filter, apiList }) {
  const [filteredList, setFilteredList] = useState(apiList);

  useEffect(() => {
    if (filter) {
      const filteredList = apiList.filter(api => {
        const normalizeKeywords = api.keywords.map(k => normaliseStr(k));
        return normalizeKeywords.includes(normaliseStr(filter));
      });

      setFilteredList(filteredList);
    }
  }, [filter]);

  return (
    <Page>

{SITE_DESCRIPTION}

            <APISearchBar q={q} list={apiList} />

            {filteredList.length > 0 ? (
              filteredList.map(api => <ApiCard key={api.title} {...api} />)
            ) : (

Aucune API n’a pu être trouvée

                Aucun résultat avec le filter: {filter}

            )}

Vous ne trouvez pas l’API dont vous avez besoin ?

            <ButtonLink href="mailto:contact@api.gouv.fr?subject=Demande%20d%27une%20nouvelle%20API">
              Demander une API
            </ButtonLink>

Vous voulez partager une API ?

            <ButtonLink
              href="https://github.com/betagouv/api.gouv.fr/blob/master/CONTRIBUTING.md#ajouter-une-api"
              alt
            >
              Partager votre API
            </ButtonLink>

    </Page>
  );
}

Home.getInitialProps = async req => {
  const { q, filter } = req.query;
  const apiList = await getAllAPIs();

  return {
    q,
    filter,
    apiList
  };
};

export default withErrors(Home);
<|endoftext|>


<commit_before>// @flow

import React from 'react'

export default () =>

These aren't the Droids your looking for.

<commit_msg>Fix typo.<commit_after>// @flow

import React from 'react'

export default () =>

These aren't the Droids you're looking for.

<|endoftext|>


<commit_before>// external
import React from "react";

// internal
import Link from "../components/Link";
import Page from "../components/Page";
import Title from "../components/Title";
import Subtitle from "../components/Subtitle";
import Chart from "../components/Chart";
import { Card, CardTitle } from "../components/Card";
import { light, dark } from "../lib/themes";
import { ThemeProvider } from "../providers/Theme";

const Index = () => (
  <ThemeProvider theme={dark}>
    <Page title="analogic.al">

        <Title>Hello!</Title>

        <Subtitle>
          I'm Ricardo, a creative{" "}
          software developer.
        </Subtitle>

          With over +10 years experience building on the web, I
          move around as a fullstack developer, but nowadays I specialize in
          building UI components.

        <Chart
          title={"Methodologies"}
          data={[
            { label: "Kanban", value: 80 },
            { label: "Scrum", value: 50 },
            { label: "Waterfall", value: 25 }
          ]}
        />

        <Chart
          title={"Languages"}
          data={[
            { label: "JavaScript", value: 80 },
            { label: "PHP", value: 50 },
            { label: "TypeScript", value: 70 },
            { label: "HTML", value: 100 },
            { label: "CSS", value: 90 },
            { label: "SASS", value: 90 }
          ]}
        />

        <Chart
          title={"Frameworks"}
          data={[
            { label: "AngularJS", value: 80 },
            { label: "Angular", value: 50 },
            { label: "React", value: 80 },
            { label: "Hyperapp", value: 50 }
          ]}
        />

        <Chart
          title={"Tools"}
          data={[
            { label: "JIRA", value: 100 },
            { label: "Bamboo CI", value: 50 },
            { label: "Jenkins", value: 25 },
            { label: "Git", value: 80 }
          ]}
        />

        <Chart
          title={"Miscellaneous"}
          data={[
            { label: "CCNA", value: 100 },
            { label: "Cisco IOS", value: 100 },
            { label: "Mikrotik", value: 80 }
          ]}
        />

        <Chart
          title={"Work experience"}
          data={[
            { label: "Lead", value: 20 },
            { label: "Senior", value: 50 },
            { label: "Junior", value: 30 }
          ]}
        />

    </Page>
  </ThemeProvider>
);

export default Index;
<commit_msg>Remove unused components<commit_after>// external
import React from "react";

// internal
import Page from "../components/Page";
import Title from "../components/Title";
import Subtitle from "../components/Subtitle";
import Chart from "../components/Chart";
import { dark } from "../lib/themes";
import { ThemeProvider } from "../providers/Theme";

const Index = () => (
  <ThemeProvider theme={dark}>
    <Page title="analogic.al">

        <Title>Hello!</Title>

        <Subtitle>
          I'm Ricardo, a creative{" "}
          software developer.
        </Subtitle>

          With over +10 years experience building on the web, I
          move around as a fullstack developer, but nowadays I specialize in
          building UI components.

        <Chart
          title={"Methodologies"}
          data={[
            { label: "Kanban", value: 80 },
            { label: "Scrum", value: 50 },
            { label: "Waterfall", value: 25 }
          ]}
        />

        <Chart
          title={"Languages"}
          data={[
            { label: "JavaScript", value: 80 },
            { label: "PHP", value: 50 },
            { label: "TypeScript", value: 70 },
            { label: "HTML", value: 100 },
            { label: "CSS", value: 90 },
            { label: "SASS", value: 90 }
          ]}
        />

        <Chart
          title={"Frameworks"}
          data={[
            { label: "AngularJS", value: 80 },
            { label: "Angular", value: 50 },
            { label: "React", value: 80 },
            { label: "Hyperapp", value: 50 }
          ]}
        />

        <Chart
          title={"Tools"}
          data={[
            { label: "JIRA", value: 100 },
            { label: "Bamboo CI", value: 50 },
            { label: "Jenkins", value: 25 },
            { label: "Git", value: 80 }
          ]}
        />

        <Chart
          title={"Miscellaneous"}
          data={[
            { label: "CCNA", value: 100 },
            { label: "Cisco IOS", value: 100 },
            { label: "Mikrotik", value: 80 }
          ]}
        />

        <Chart
          title={"Work experience"}
          data={[
            { label: "Lead", value: 20 },
            { label: "Senior", value: 50 },
            { label: "Junior", value: 30 }
          ]}
        />

    </Page>
  </ThemeProvider>
);

export default Index;
<|endoftext|>


<commit_before>var allRequests = [],
    availableTypesOfRequests = ["POST"];

function extractDomain(url) {
    var domain;
    //find & remove protocol (http, ftp, etc.) and get domain
    if (url.indexOf("://") > -1) {
        domain = url.split('/')[2];
    }
    else {
        domain = url.split('/')[0];
    }
    //find & remove port number
    domain = domain.split(':')[0];
    return domain;
}

$(function() {
/////////////////////////////MAIN///////////////////////////////////////////////
  var requestPort = chrome.runtime.connect({ name: "request" });
  chrome.devtools.network.onRequestFinished.addListener(function(request) {
    if (availableTypesOfRequests.includes(request.request.method)) {
      requestPort.postMessage(request);

      var $div = $("

");

      $div.append("
"+request.request.method+""+request.request.url.split('/')[2]+" x
");
      $div.append("
"+request.request.url+"
");

      $(".requests_list").append($div);
      $(".request").filter(":even").addClass("_v2");

      allRequests.push(request);
    }
  });

  $(".requests_list").on("click", ".request", function(e) {
    e.preventDefault();
    $(".options").text(" ");

    var current_request = allRequests[parseInt($(this).prop("id"))],
        $form = $("<form></form>");
    $form.prop("id", $(this).prop("id"));

    var selectedQuery = chrome.runtime.connect({ name: "selected query" });
    selectedQuery.postMessage(current_request);

    var $formParams = $("

");
    $(".options").append("decodeURI");
    $(".options").append("encodeURI");

    function form_filling(myArray) {
      myArray.forEach(function(item, i, arr) {
        var $input = $("<input class='fname'></input>");
        $input.prop({ 'value': decodeURIComponent(item.name), "id": i });
        $formParams.append($input);

        var $input = $("<input class='fvalue'></input>");
        $input.prop({ 'value': decodeURIComponent(item.value), "id": i });
        $formParams.append($input);

        $formParams.append("x");
      });
      $form.append($formParams);
      var $myDiv = $("

");
      $myDiv.append($("Add field"));
      $myDiv.append($("<input type='submit' class='send btn' value='Submit'>"));
      $form.append($myDiv);
    }

    switch (current_request.request.method.toString()) {
      case "GET":
//-----------------------------GET--------------------------------------------//
        $formParams.append("URL: <input class='url fvalue' value="+current_request.request.url.split("://")[0]+"://"+extractDomain(current_request.request.url)+"></input>
");
        if (current_request.request.queryString) {
          form_filling(current_request.request.queryString);
        } else {
          $(".options").append("
There are no params
");
        }
        $(".options").append($form);
//----------------------------END-GET-----------------------------------------//
        break;
      case "POST":
//------------------------------POST------------------------------------------//
        $formParams.append("URL: <input class='url fvalue' value="+current_request.request.url+"></input>
");
        if (current_request.request.postData.params) {
          form_filling(current_request.request.postData.params);
        } else {
          $(".options").append("
There are no params
");
        }
        $(".options").append($form);
//-----------------------------------END-POST---------------------------------//
        break;
      default:
        $(".options").append("
This request type not supported
"+JSON.stringify(current_request.request)+"");
    }
  });

  $(".options").on("submit", "form", function(e) {
    e.preventDefault();
    var newTabPort = chrome.runtime.connect({ name: "new tab" }),
        new_url,
        params = [];
    $.each($(".options").find("form").find("input"), function(i, val) {
      params.push($(val).val());
    });
    new_url = params[0];
    params.shift();
    newTabPort.postMessage({
      params: params,
      request: allRequests[parseInt($(this).prop("id"))].request,
      new_url: new_url
    });
  });

////////////////////////////////////////////////////////////////////////////////

  $(".options").on("click", "a#decodeURI", function(e) {
    e.preventDefault();
    $(".options").find(".form_params").find("input").each(function() {
      $(this).val(decodeURIComponent($(this).val()));
    });
  });

  $(".options").on("click", "a#encodeURI", function(e) {
    e.preventDefault();
    $(".options").find(".form_params").find("input").each(function() {
      $(this).val(encodeURIComponent($(this).val()));
    });
  });

  $(".options").on("click", "a.remove_input", function(e) {
    e.preventDefault();
    var id = $(this).prop("id");
    $(".options").find("input#"+id).remove();
    $(this).remove();
  });

  $(".options").on("click", "a.add_field", function(e) {
    e.preventDefault();
    var $form = $(".options").find("form"),
        $formParams = $(".options").find(".form_params"),
        newId = $form.find("input").length + 1;

    var $input = $("<input class='fname'></input>");
    $input.prop({ "id": newId });
    $formParams.append($input);

    var $input = $("<input class='fvalue'></input>");
    $input.prop({ "id": newId });
    $formParams.append($input);
    $formParams.append("x");
  });

  $(".control_panel").on("click", "a#clear_all_requests", function(e) {
    e.preventDefault();
    $(".requests_list").find(".request").remove();
    allRequests = [];
  });

  $(".requests_list").on("click", ".head span.clear a", function(e) {
    e.preventDefault();
    $(this).parent().parent().parent().remove();
    $(".options").text(" ");
  });

  $(".availableTypeOfRequestIsPOST").change(function() {
    if ($(this).is(':checked')) {
      availableTypesOfRequests.push("POST");
    } else {
      availableTypesOfRequests.splice(availableTypesOfRequests.indexOf("POST"), 1);
    }
  });

  $(".availableTypeOfRequestIsGET").change(function() {
    if ($(this).is(':checked')) {
      availableTypesOfRequests.push("GET");
    } else {
      availableTypesOfRequests.splice(availableTypesOfRequests.indexOf("GET"), 1);
    }
  });

});
<commit_msg>fix GET url bug<commit_after>var allRequests = [],
    availableTypesOfRequests = ["POST"];

$(function() {
/////////////////////////////MAIN///////////////////////////////////////////////
  var requestPort = chrome.runtime.connect({ name: "request" });
  chrome.devtools.network.onRequestFinished.addListener(function(request) {
    if (availableTypesOfRequests.includes(request.request.method)) {
      requestPort.postMessage(request);

      var $div = $("

");

      $div.append("
"+request.request.method+""+request.request.url.split('/')[2]+" x
");
      $div.append("
"+request.request.url+"
");

      $(".requests_list").append($div);
      $(".request").filter(":even").addClass("_v2");

      allRequests.push(request);
    }
  });

  $(".requests_list").on("click", ".request", function(e) {
    e.preventDefault();
    $(".options").text(" ");

    var current_request = allRequests[parseInt($(this).prop("id"))],
        $form = $("<form></form>");
    $form.prop("id", $(this).prop("id"));

    var selectedQuery = chrome.runtime.connect({ name: "selected query" });
    selectedQuery.postMessage(current_request);

    var $formParams = $("

");
    $(".options").append("decodeURI");
    $(".options").append("encodeURI");

    function form_filling(myArray) {
      myArray.forEach(function(item, i, arr) {
        var $input = $("<input class='fname'></input>");
        $input.prop({ 'value': decodeURIComponent(item.name), "id": i });
        $formParams.append($input);

        var $input = $("<input class='fvalue'></input>");
        $input.prop({ 'value': decodeURIComponent(item.value), "id": i });
        $formParams.append($input);

        $formParams.append("x");
      });
      $form.append($formParams);
      var $myDiv = $("

");
      $myDiv.append($("Add field"));
      $myDiv.append($("<input type='submit' class='send btn' value='Submit'>"));
      $form.append($myDiv);
    }

    switch (current_request.request.method.toString()) {
      case "GET":
//-----------------------------GET--------------------------------------------//
        $formParams.append("URL: <input class='url fvalue' value="+current_request.request.url.split("?")[0]+"></input>
");
        if (current_request.request.queryString) {
          form_filling(current_request.request.queryString);
        } else {
          $(".options").append("
There are no params
");
        }
        $(".options").append($form);
//----------------------------END-GET-----------------------------------------//
        break;
      case "POST":
//------------------------------POST------------------------------------------//
        $formParams.append("URL: <input class='url fvalue' value="+current_request.request.url+"></input>
");
        if (current_request.request.postData.params) {
          form_filling(current_request.request.postData.params);
        } else {
          $(".options").append("
There are no params
");
        }
        $(".options").append($form);
//-----------------------------------END-POST---------------------------------//
        break;
      default:
        $(".options").append("
This request type not supported
"+JSON.stringify(current_request.request)+"");
    }
  });

  $(".options").on("submit", "form", function(e) {
    e.preventDefault();
    var newTabPort = chrome.runtime.connect({ name: "new tab" }),
        new_url,
        params = [];
    $.each($(".options").find("form").find("input"), function(i, val) {
      params.push($(val).val());
    });
    new_url = params[0];
    params.shift();
    newTabPort.postMessage({
      params: params,
      request: allRequests[parseInt($(this).prop("id"))].request,
      new_url: new_url
    });
  });

////////////////////////////////////////////////////////////////////////////////

  $(".options").on("click", "a#decodeURI", function(e) {
    e.preventDefault();
    $(".options").find(".form_params").find("input").each(function() {
      $(this).val(decodeURIComponent($(this).val()));
    });
  });

  $(".options").on("click", "a#encodeURI", function(e) {
    e.preventDefault();
    $(".options").find(".form_params").find("input").each(function() {
      $(this).val(encodeURIComponent($(this).val()));
    });
  });

  $(".options").on("click", "a.remove_input", function(e) {
    e.preventDefault();
    var id = $(this).prop("id");
    $(".options").find("input#"+id).remove();
    $(this).remove();
  });

  $(".options").on("click", "a.add_field", function(e) {
    e.preventDefault();
    var $form = $(".options").find("form"),
        $formParams = $(".options").find(".form_params"),
        newId = $form.find("input").length + 1;

    var $input = $("<input class='fname'></input>");
    $input.prop({ "id": newId });
    $formParams.append($input);

    var $input = $("<input class='fvalue'></input>");
    $input.prop({ "id": newId });
    $formParams.append($input);
    $formParams.append("x");
  });

  $(".control_panel").on("click", "a#clear_all_requests", function(e) {
    e.preventDefault();
    $(".requests_list").find(".request").remove();
    allRequests = [];
  });

  $(".requests_list").on("click", ".head span.clear a", function(e) {
    e.preventDefault();
    $(this).parent().parent().parent().remove();
    $(".options").text(" ");
  });

  $(".availableTypeOfRequestIsPOST").change(function() {
    if ($(this).is(':checked')) {
      availableTypesOfRequests.push("POST");
    } else {
      availableTypesOfRequests.splice(availableTypesOfRequests.indexOf("POST"), 1);
    }
  });

  $(".availableTypeOfRequestIsGET").change(function() {
    if ($(this).is(':checked')) {
      availableTypesOfRequests.push("GET");
    } else {
      availableTypesOfRequests.splice(availableTypesOfRequests.indexOf("GET"), 1);
    }
  });

});
<|endoftext|>


<commit_before><commit_msg>Update app.js<commit_after><|endoftext|>


<commit_before>var telepath = require('tele')
, stream = require('stream')
, asyncMap = require ('slide').asyncMap
, hash = require('hashish')

module.exports = function (usr) { // BRICOLEUR
  var self = this
  , map = null
  , _ = {} // module scope
  _.bus = self // fix this hack!
  telepath(this)

  this.map = {
    server:[],
    client:[]
  }

  // detect if running in node or in browser
  if (global.process) self.scope = 'server' // on sunos global.process.title != node
  if (!global.process) self.scope = 'client'
  if (usr) self.usr = usr

  this.recv = function (buffer) { // clean up!
    var data = JSON.parse(buffer.toString())
    console.log(data)

    if (data.event === 'mapping_done') {
      console.log('map complete')
    }
    if (data.event === 'clear') {
      console.log(usr.modules)
    }
    if (data.key === 'module_map') { // handle incoming module data
      for (var i = 0;i<data.scope.length;i++) {
        self.map[data.scope[i]].push(data)
      }
    } else if (!data.client_id) { // pass through to out
      if (self.client_id) data.id = self.client_id
      self.send(data)
    } else if (data.client_id) {
      self.map[self.scope] = data.map
      if (data.map) self.build()
    }
  }

  this.build = function () { // loadModule with mods from map array
    console.log(self.map[self.scope])

    asyncMap(self.map[self.scope], lookupModule, connModules)

    function lookupModule (mod, cb) {
      var modules = usr.modules[self.scope]
      for (var i=0;i<modules.length;i++) {
        if (modules[i]===mod.id) {
          console.log('loading mod '+mod.id)
          self.loadModule(mod)
          break
        }
      }
      cb()
    }

    function connModules () {
      if (usr.conns) {
        console.log('modules loaded :: connecting modules...')
        asyncMap(usr.conns[self.scope], self.connModule, function () {
          console.log('connected modules for : '+usr.host)
        })
      }
      if (!usr.conns) console.log('no conns for : '+usr.host)
    }
  }

  this.connModule = function (conn, cb) { // ['modA>modB','modB>modC'] make module connections
    var modA = null
    , modB = null

    for (key in conn) { // could be clearer
      modA = _[conn[key].split('>')[0]]
      modB = _[conn[key].split('>')[1]]
      console.log('connecting ' + conn[key])
      if (!modA.out || !modB.in) throw new Error(modA+','+modB+' :no .out or .in connections')
      if (modA.out && modB.in) modA.out.pipe(modB.in)
      cb()
    }
  }

  this.disconnModule = function (disconn) {
  }

  this.loadModule = function (mod) { // load module!
    if (self.scope==='server') _[mod.id.toUpperCase()] = require(mod.filePath)
    if (self.scope==='client') _[mod.id.toUpperCase()] = require(mod.id)
    _[mod.id] = new _[mod.id.toUpperCase()]()
    if (mod.html) _[mod.id].render(mod.html)
  }

  this.clear = function (cb) {
    asyncMap(usr.modules[self.scope], unloadModule, cb)
  }

  this.unloadModule = function (mod) {
    if (self.scope === 'client') _[mod].destroy()
    delete _[mod]
  }

  // ------------------------------------------------------------
  this.addConnection = function (key) { // user socket connection
    self[key] = {}
    var s = self[key]
    s.id = key

    // add write stream
    s.in = new stream.Writable()
    s.in._write = function (chunk, encoding, cb) {
      self.recv(chunk) // add id to obj -- for filtering
      cb()
    }

    // add read stream
    s.out = new stream()
    s.out.readable = true
    s.send = function (data) {
      s.out.emit('data',JSON.stringify(data))
    }
  }

  this.removeConnection = function (key) {
    self[key].out.emit('close')
    delete self[key]
  } // -----------------------------------------------------------
}
<commit_msg>added data.event switch to brico<commit_after>var telepath = require('tele')
, stream = require('stream')
, asyncMap = require ('slide').asyncMap
, hash = require('hashish')

module.exports = function (usr) { // BRICOLEUR
  var self = this
  , map = null
  , _ = {} // module scope
  _.bus = self // fix this hack!
  telepath(this)

  this.conns = []

  this.map = {
    server:[],
    client:[]
  }

  // detect if running in node or in browser
  if (global.process) self.scope = 'server' // on sunos global.process.title != node
  if (!global.process) self.scope = 'client'
  if (usr) self.usr = usr

  this.recv = function (buffer) { // clean up!
    var data = JSON.parse(buffer.toString())

    if (data.event) {
      switch (data.event) {
        case 'mapping_done' : self.build(); break;
      }
    }

    else if (data.key === 'module_map') { // handle incoming module data
      for (var i = 0;i<data.scope.length;i++) {
        self.map[data.scope[i]].push(data)
      }
    } else if (!data.client_id) { // pass through to out
      if (self.client_id) data.id = self.client_id
      self.send(data)
    } else if (data.client_id) {
      self.map[self.scope] = data.map
      if (data.map) self.build()
    }
  }

  this.build = function () { // loadModule with mods from map array
    asyncMap(self.map[self.scope], lookupModule, connModules)

    function lookupModule (mod, cb) {
      var modules = usr.modules[self.scope]
      for (var i=0;i<modules.length;i++) {
        if (modules[i]===mod.id) {
          console.log('loading mod '+mod.id)
          self.loadModule(mod)
          break
        }
      }
      cb()
    }

    function connModules () {
      if (usr.conns) {
        console.log('modules loaded :: connecting modules...')
        asyncMap(usr.conns[self.scope], self.connModule, function () {
          console.log('connected modules for : '+usr.host)
        })
      }
      if (!usr.conns) console.log('no conns for : '+usr.host)
    }
  }

  this.connModule = function (conn, cb) { // ['modA>modB','modB>modC'] make module connections
    var modA = null
    , modB = null

    for (key in conn) { // could be clearer
      modA = _[conn[key].split('>')[0]]
      modB = _[conn[key].split('>')[1]]
      console.log('connecting ' + conn[key])
      if (!modA.out || !modB.in) throw new Error(modA+','+modB+' :no .out or .in connections')
      if (modA.out && modB.in) modA.out.pipe(modB.in)
      cb()
    }
  }

  this.disconnModule = function (disconn) {}

  this.loadModule = function (mod) { // load module!
    if (self.scope==='server') _[mod.id.toUpperCase()] = require(mod.filePath)
    if (self.scope==='client') _[mod.id.toUpperCase()] = require(mod.id)
    _[mod.id] = new _[mod.id.toUpperCase()]()
    if (mod.html) _[mod.id].render(mod.html)
  }

  this.clear = function (cb) {
    asyncMap(usr.modules[self.scope], unloadModule, cb)
  }

  this.unloadModule = function (mod) {
    if (self.scope === 'client') _[mod].destroy()
    delete _[mod]
  }

  // ------------------------------------------------------------
  this.addConnection = function (key) { // user socket connection
    self[key] = {}
    var s = self[key]
    s.id = key
    self.conns.push(key)

    // add write stream
    s.in = new stream.Writable()
    s.in._write = function (chunk, encoding, cb) {
      self.recv(chunk) // add id to obj -- for filtering
      cb()
    }

    // add read stream
    s.out = new stream()
    s.out.readable = true
    s.send = function (data) {
      s.out.emit('data',JSON.stringify(data))
    }
  }

  this.removeConnection = function (key) {
    self[key].out.emit('close')
    delete self[key]
  } // -----------------------------------------------------------
}
<|endoftext|>


<commit_before><commit_msg>don't allow blank action name<commit_after><|endoftext|>


<commit_before><commit_msg>Removing line that doesn't help<commit_after><|endoftext|>


<commit_before><commit_msg>Moved function to top of index js<commit_after><|endoftext|>


<commit_before><commit_msg>improving pakia play<commit_after><|endoftext|>


<commit_before><commit_msg>fixing user storage<commit_after><|endoftext|>


<commit_before>angular.module('argus.controllers.viewMetrics', ['ngResource'])
.controller('ViewMetrics', ['$location', '$routeParams', '$scope', 'growl', 'Metrics', 'Annotations', 'SearchService', 'Controls'
    function ($location, $routeParams, $scope, growl, Metrics, Annotations, SearchService, Controls) {

        $scope.expression = $routeParams.expression ? $routeParams.expression : null;
        $scope.showChart = false;

        //sync the expression to URL param
        $scope.$watch('expression', function(val){
            if(val){
                var urlStr = Controls.getUrl([{name: 'expression', value: val}]);
                $location.search(urlStr);
            }
        });

        $scope.getMetricData = function () {
            if ($scope.expression !== null && $scope.expression.length) {
                Metrics.query({expression: $scope.expression}, function (data) {
                    $scope.updateChart({}, data);
                    $scope.showChart = true;
                }, function (error) {
                    $scope.updateChart({}, null);
                    $scope.showChart = false;
                    growl.error(error.data.message, {referenceId: 'viewmetrics-error'});
                });
            } else {
                $scope.updateChart({}, $scope.expression);
            }
        };

        $scope.searchMetrics = function(value, category) {

            var defaultParams = {
                namespace: '*',
                scope: '*',
                metric: '*',
                tagk: '*',
                tagv: '*',
                limit: 100,
                page: 1
            };

            var newParams = JSON.parse(JSON.stringify(defaultParams));

            // update params with values in $scope if they exist
            newParams['scope'] = ($scope.scope) ? $scope.scope : '*';
            newParams['metric'] = ($scope.metric) ? $scope.metric : '*';
            newParams['namespace'] = ($scope.namespace) ? $scope.namespace : '*';
            newParams['tagk'] = ($scope.tagk) ? $scope.tagk : '*';
            newParams['tagv'] = ($scope.tagv) ? $scope.tagv : '*';

            console.log( newParams );

            return SearchService.search(newParams)
                .then(SearchService.processResponses);
        };

        // -------------

        $scope.updateChart = function (config, data) {
            var options = config ? angular.copy(config) : {};
            var series = $scope.copySeries(data);
            options.credits = {enabled: false},
            options.rangeSelector = {selected: 1, inputEnabled: false};
            options.xAxis = {
            	type: 'datetime',
            	ordinal: false
            };

            //options.chart={renderTo: 'container',defaultSeriesType: 'line'};
            options.lang = {noData: 'No Data to Display'};
            options.legend = {
                enabled: true,
                maxHeight: 62,
                itemStyle: {
                    fontWeight: 'normal',
                    fontSize: '10px'
                },
                navigation : {
                    style : {
                        fontWeight: 'normal',
                        fontSize: '10px'
                    }
                }
            };
            options.series = series;
            options.plotOptions = {
            	series: {
            		animation: false,
            		connectNulls: true
            	},
            	line : {
            		gapSize:1.5
            	}
            };

            options.chart = {animation: false, borderWidth: 1, borderColor: 'lightGray', borderRadius: 5};

            $('#container').highcharts('StockChart', options);

            $scope.series = series;
            $scope.addAlertFlags(data);
        };

        // TODO: move all below scope functions to a puclic Scope service

        $scope.addAlertFlags = function (metrics) {
            if (metrics && metrics.length) {
                for (var i = 0; i < metrics.length; i++) {
                    $scope.addAlertFlag(metrics[i]);
                }
            }
        };

        $scope.addAlertFlag = function(metric) {
            var forName = $scope.createSeriesName(metric);
            Annotations.query({expression: $scope.getAlertFlagExpression(metric)}, function (data) {
                var series = $scope.copyFlagSeries(data);
                var chart = $('#container').highcharts();
                series.linkedTo = forName;
                series.color = chart.get(forName).color;
                chart.addSeries(series);
            });
        };

        $scope.getDatapointRange = function (datapoints) {
            var result = {start: Number.MAX_VALUE, end: Number.MIN_VALUE};
            for (var key in datapoints) {
                if (datapoints.hasOwnProperty(key)) {
                    if (key < result.start) {
                        result.start = key;
                    }
                    if (key > result.end) {
                        result.end = key;
                    }
                }
            }
            return result;
        };

        $scope.getAlertFlagExpression = function (metric) {
            if (metric && metric.datapoints) {
                var range = $scope.getDatapointRange(metric.datapoints);
                var scopeName = metric.scope;
                var metricName = metric.metric;
                var tagData = metric.tags;
                var result = range.start + ":" + range.end + ":" + scopeName + ":" + metricName;
                result += $scope.createTagString(tagData);
                result += ":ALERT";
                return result;
            } else {
                return null;
            }
        };

        $scope.copyFlagSeries = function (data) {
            var result;
            if (data) {
                result = {type: 'flags', shape: 'circlepin', stackDistance: 20, width: 16, lineWidth: 2};
                result.data = [];
                for (var i = 0; i < data.length; i++) {
                    var flagData = data[i];
                    result.data.push({x: flagData.timestamp, title: 'A', text: $scope.formatFlagText(flagData.fields)});
                }
            } else {
                result = null;
            }
            return result;
        };

        $scope.formatFlagText = function (fields) {
            var result = '';
            if (fields) {
                for (var field in fields) {
                    if (fields.hasOwnProperty(field)) {
                        result += (field + ': ' + fields[field] + '
');
                    }
                }
            }
            return result;
        };

        $scope.copySeries = function (data) {
            var result = [];
            if (data) {
                for (var i = 0; i < data.length; i++) {
                	var series = [];
                	for(var key in data[i].datapoints) {
                		var timestamp = parseInt(key);
                		if(data[i].datapoints[key] !=null){
                			var value = parseFloat(data[i].datapoints[key]);
                			series.push([timestamp, value]);
                		}
                	}
                    var id = $scope.createSeriesName(data[i]);
                    result.push({name: id, id: id, data: series,marker : {enabled : true, radius: 1}});
                }
            } else {
                result.push({name: 'result', data: []});
            }
            return result;
        };

        $scope.createSeriesName = function (metric) {
            var scope = metric.scope;
            var name = metric.metric;
            var tags = $scope.createTagString(metric.tags);
            return scope + ':' + name + tags;
        };

        $scope.createTagString = function (tags) {
            var result = '';
            if (tags) {
                var tagString ='';
                for (var key in tags) {
                    if (tags.hasOwnProperty(key)) {
                        tagString += (key + '=' + tags[key] + ',');
                    }
                }
                if(tagString.length) {
                    result += '{';
                    result += tagString.substring(0, tagString.length - 1);
                    result += '}';
                }
            }
            return result;
        };

        $scope.getMetricData(null);
    }]);
<commit_msg>fix typo in viewMetrics.<commit_after>angular.module('argus.controllers.viewMetrics', ['ngResource'])
.controller('ViewMetrics', ['$location', '$routeParams', '$scope', 'growl', 'Metrics', 'Annotations', 'SearchService', 'Controls',
    function ($location, $routeParams, $scope, growl, Metrics, Annotations, SearchService, Controls) {

        $scope.expression = $routeParams.expression ? $routeParams.expression : null;
        $scope.showChart = false;

        //sync the expression to URL param
        $scope.$watch('expression', function(val){
            if(val){
                var urlStr = Controls.getUrl([{name: 'expression', value: val}]);
                $location.search(urlStr);
            }
        });

        $scope.getMetricData = function () {
            if ($scope.expression !== null && $scope.expression.length) {
                Metrics.query({expression: $scope.expression}, function (data) {
                    $scope.updateChart({}, data);
                    $scope.showChart = true;
                }, function (error) {
                    $scope.updateChart({}, null);
                    $scope.showChart = false;
                    growl.error(error.data.message, {referenceId: 'viewmetrics-error'});
                });
            } else {
                $scope.updateChart({}, $scope.expression);
            }
        };

        $scope.searchMetrics = function(value, category) {

            var defaultParams = {
                namespace: '*',
                scope: '*',
                metric: '*',
                tagk: '*',
                tagv: '*',
                limit: 100,
                page: 1
            };

            var newParams = JSON.parse(JSON.stringify(defaultParams));

            // update params with values in $scope if they exist
            newParams['scope'] = ($scope.scope) ? $scope.scope : '*';
            newParams['metric'] = ($scope.metric) ? $scope.metric : '*';
            newParams['namespace'] = ($scope.namespace) ? $scope.namespace : '*';
            newParams['tagk'] = ($scope.tagk) ? $scope.tagk : '*';
            newParams['tagv'] = ($scope.tagv) ? $scope.tagv : '*';

            console.log( newParams );

            return SearchService.search(newParams)
                .then(SearchService.processResponses);
        };

        // -------------

        $scope.updateChart = function (config, data) {
            var options = config ? angular.copy(config) : {};
            var series = $scope.copySeries(data);
            options.credits = {enabled: false},
            options.rangeSelector = {selected: 1, inputEnabled: false};
            options.xAxis = {
            	type: 'datetime',
            	ordinal: false
            };

            //options.chart={renderTo: 'container',defaultSeriesType: 'line'};
            options.lang = {noData: 'No Data to Display'};
            options.legend = {
                enabled: true,
                maxHeight: 62,
                itemStyle: {
                    fontWeight: 'normal',
                    fontSize: '10px'
                },
                navigation : {
                    style : {
                        fontWeight: 'normal',
                        fontSize: '10px'
                    }
                }
            };
            options.series = series;
            options.plotOptions = {
            	series: {
            		animation: false,
            		connectNulls: true
            	},
            	line : {
            		gapSize:1.5
            	}
            };

            options.chart = {animation: false, borderWidth: 1, borderColor: 'lightGray', borderRadius: 5};

            $('#container').highcharts('StockChart', options);

            $scope.series = series;
            $scope.addAlertFlags(data);
        };

        // TODO: move all below scope functions to a puclic Scope service

        $scope.addAlertFlags = function (metrics) {
            if (metrics && metrics.length) {
                for (var i = 0; i < metrics.length; i++) {
                    $scope.addAlertFlag(metrics[i]);
                }
            }
        };

        $scope.addAlertFlag = function(metric) {
            var forName = $scope.createSeriesName(metric);
            Annotations.query({expression: $scope.getAlertFlagExpression(metric)}, function (data) {
                var series = $scope.copyFlagSeries(data);
                var chart = $('#container').highcharts();
                series.linkedTo = forName;
                series.color = chart.get(forName).color;
                chart.addSeries(series);
            });
        };

        $scope.getDatapointRange = function (datapoints) {
            var result = {start: Number.MAX_VALUE, end: Number.MIN_VALUE};
            for (var key in datapoints) {
                if (datapoints.hasOwnProperty(key)) {
                    if (key < result.start) {
                        result.start = key;
                    }
                    if (key > result.end) {
                        result.end = key;
                    }
                }
            }
            return result;
        };

        $scope.getAlertFlagExpression = function (metric) {
            if (metric && metric.datapoints) {
                var range = $scope.getDatapointRange(metric.datapoints);
                var scopeName = metric.scope;
                var metricName = metric.metric;
                var tagData = metric.tags;
                var result = range.start + ":" + range.end + ":" + scopeName + ":" + metricName;
                result += $scope.createTagString(tagData);
                result += ":ALERT";
                return result;
            } else {
                return null;
            }
        };

        $scope.copyFlagSeries = function (data) {
            var result;
            if (data) {
                result = {type: 'flags', shape: 'circlepin', stackDistance: 20, width: 16, lineWidth: 2};
                result.data = [];
                for (var i = 0; i < data.length; i++) {
                    var flagData = data[i];
                    result.data.push({x: flagData.timestamp, title: 'A', text: $scope.formatFlagText(flagData.fields)});
                }
            } else {
                result = null;
            }
            return result;
        };

        $scope.formatFlagText = function (fields) {
            var result = '';
            if (fields) {
                for (var field in fields) {
                    if (fields.hasOwnProperty(field)) {
                        result += (field + ': ' + fields[field] + '
');
                    }
                }
            }
            return result;
        };

        $scope.copySeries = function (data) {
            var result = [];
            if (data) {
                for (var i = 0; i < data.length; i++) {
                	var series = [];
                	for(var key in data[i].datapoints) {
                		var timestamp = parseInt(key);
                		if(data[i].datapoints[key] !=null){
                			var value = parseFloat(data[i].datapoints[key]);
                			series.push([timestamp, value]);
                		}
                	}
                    var id = $scope.createSeriesName(data[i]);
                    result.push({name: id, id: id, data: series,marker : {enabled : true, radius: 1}});
                }
            } else {
                result.push({name: 'result', data: []});
            }
            return result;
        };

        $scope.createSeriesName = function (metric) {
            var scope = metric.scope;
            var name = metric.metric;
            var tags = $scope.createTagString(metric.tags);
            return scope + ':' + name + tags;
        };

        $scope.createTagString = function (tags) {
            var result = '';
            if (tags) {
                var tagString ='';
                for (var key in tags) {
                    if (tags.hasOwnProperty(key)) {
                        tagString += (key + '=' + tags[key] + ',');
                    }
                }
                if(tagString.length) {
                    result += '{';
                    result += tagString.substring(0, tagString.length - 1);
                    result += '}';
                }
            }
            return result;
        };

        $scope.getMetricData(null);
    }]);
<|endoftext|>


<commit_before><commit_msg>Fixing type issue with different quarters.<commit_after><|endoftext|>


<commit_before><commit_msg>Refactor walli js code to be more flexible, remove duplicated codes and write comments on code.<commit_after><|endoftext|>


<commit_before><commit_msg>Read files asynchronously.<commit_after><|endoftext|>


<commit_before><commit_msg>more progressive redraw<commit_after><|endoftext|>


<commit_before><commit_msg>Made some changes<commit_after><|endoftext|>


<commit_before>function Character(scene, spriteSheet) {

	var self = quicktigame2d.createSpriteSheet({
		image: 'assets/' + spriteSheet,
		width: 32,
		height: 48,
		border: 0,
		margin: 1
	});

	var textsprite = quicktigame2d.createTextSprite({
		text: 'Lorem ipsum dolor sit amet',
		fontFamily: 'Verdana',
		fontSize: 14,
		textAlign: Ti.UI.TEXT_ALIGNMENT_CENTER,
		z: 2
	});

	textsprite.color(0, 0, 1);
	textsprite.hide();

	self.halt = function() {
		// Ti.API.debug("Halt facing: " + self.direction);
		switch (self.direction) {
		case "UP":
			self.pauseAt(13);
			break;
		case "DOWN":
			self.pauseAt(0);
			break;
		case "LEFT":
			self.pauseAt(4);
			break;
		case "RIGHT":
			self.pauseAt(8);
			break;
		default:
			self.pauseAt(0);
		}
	};

	self.turnTowards = function(newDirection) {
		// Ti.API.debug("Moving towards: " + newDirection);

		if (self.direction !== newDirection) {
			switch (newDirection) {
			case "UP":
				self.animate(13, 4, 250, -1);
				break;
			case "DOWN":
				self.animate(0, 4, 250, -1);
				break;
			case "LEFT":
				self.animate(4, 4, 250, -1);
				break;
			case "RIGHT":
				self.animate(8, 4, 250, -1);
				break;
			default:
				self.animate(0, 4, 250, -1);
			}
			self.direction = newDirection;
		}
	}

	self.say = function(caption) {
		textsprite.text = caption;

		textsprite.x = self.x -(textsprite.width * 0.5);
		textsprite.y = self.y - textsprite.height - 15;

		textsprite.show();

		setTimeout(function() { textsprite.hide() }, 5000);
	}

	scene.add(self);
	scene.add(textsprite);

	return self;
}

module.exports = Character;<commit_msg>The text color is now random<commit_after>function Character(scene, spriteSheet) {

	var self = quicktigame2d.createSpriteSheet({
		image: 'assets/' + spriteSheet,
		width: 32,
		height: 48,
		border: 0,
		margin: 1
	});

	var textsprite = quicktigame2d.createTextSprite({
		text: 'Lorem ipsum dolor sit amet',
		fontFamily: 'Verdana',
		fontSize: 14,
		textAlign: Ti.UI.TEXT_ALIGNMENT_CENTER,
		z: 2
	});

	textsprite.color(Math.random(), 0, 0);
	textsprite.hide();

	self.halt = function() {
		switch (self.direction) {
		case "UP":
			self.pauseAt(13);
			break;
		case "DOWN":
			self.pauseAt(0);
			break;
		case "LEFT":
			self.pauseAt(4);
			break;
		case "RIGHT":
			self.pauseAt(8);
			break;
		default:
			self.pauseAt(0);
		}
	};

	self.turnTowards = function(newDirection) {
		// Ti.API.debug("Moving towards: " + newDirection);

		if (self.direction !== newDirection) {
			switch (newDirection) {
			case "UP":
				self.animate(13, 4, 250, -1);
				break;
			case "DOWN":
				self.animate(0, 4, 250, -1);
				break;
			case "LEFT":
				self.animate(4, 4, 250, -1);
				break;
			case "RIGHT":
				self.animate(8, 4, 250, -1);
				break;
			default:
				self.animate(0, 4, 250, -1);
			}
			self.direction = newDirection;
		}
	}

	self.say = function(caption) {
		textsprite.text = caption;

		textsprite.x = self.x -(textsprite.width * 0.5);
		textsprite.y = self.y - textsprite.height - 15;

		textsprite.show();

		setTimeout(function() { textsprite.hide() }, 5000);
	}

	scene.add(self);
	scene.add(textsprite);

	return self;
}

module.exports = Character;<|endoftext|>


<commit_before><commit_msg>Add Board class to knockout.js<commit_after><|endoftext|>


<commit_before>const Thing = require('Thing.js');
const later = require('later');
const Controller = require('node-pid-controller');
const ascii = require('ascii-codes');
const _ = require('underscore');

/**
 * Grow is an extension of a Thing (which is basically a fancy event emitter).
 * See [Thing.js](https://github.com/CommonGarden/Thing.js) for more info on Things...
 * @param {Object} config  The thing object.
 * @return {Grow}   A new Grow instance.
 */
class Grow extends Thing {
  constructor(config) {
    super(config);
  }

  /**
   * Creates listeners for targets objects in grow files.
   * @param {Object} targets An object contain event keys and corresponding min / max values.
   */
  registerTargets(targets) {
    this.controllers = this.controllers || {};
    this.alerts = this.alerts || {};
    this.targets = _.extend(this.targets, targets);
    _.each(targets, (value, key) => {
      if (value.ideal) {
        // Create a controller with defaults.
        // Allow for them to define control parameters?
        if (typeof value.pid === 'object') {
          try {
            this.controllers[key] = new Controller(value.pid);
          } catch (err) {
            console.log(err);
            this.controllers[key] = new Controller({
              k_p: 0.25,
              k_i: 0.01,
              k_d: 0.01,
              dt: 1
            });
          }
        }

        // Simply set the target
        this.controllers[key].setTarget(value.ideal);
      }

      this.on(key, (eventData) => {
        if (Number(eventData) !== 'NaN') {
          if (value.ideal) {
            // console.log(Number(eventData));
            let correction = this.controllers[key].update(eventData);
            this.emit('correction', key, correction);
          }

          if (value.min && eventData < value.min) {
            if (this.alerts[key] !== 'low') {
              let alert = {};
              alert[key] = 'low';
              _.extend(this.alerts, alert);
              this.set('alerts', this.alerts);
              this.emit('alert', alert);
            }
          }

          else if (value.max && eventData > value.max) {
            if (this.alerts[key] !== 'high') {
              let alert = {};
              alert[key] = 'high';
              _.extend(this.alerts, alert);
              this.set('alerts', this.alerts);
              this.emit('alert', alert);
            }
          }

          else {
            if (this.alerts[key]) {
              let alert = {};
              alert[key] = 'ok';
              this.emit('alert', alert);
              this.alerts = _.omit(this.alerts, key);
              this.set('alerts', this.alerts);
            }
          }
        }
      });
    });

    this.emit('targets-updated', targets);
  }

  /**
   * Remove targets
   * @param {Object} targets  Alerts to be removed.
   */
  removeTargets(targets) {
    if (_.isArray(targets)) {
      _.each(targets, (value, key) => {
        this.removeAllListeners(value);
        this.targets = _.omit(this.targets, value);
        this.controllers = _.omit(this.controllers, value)
      });
    } else if (_.isObject(targets)) {
      _.each(targets, (value, key) => {
        this.removeAllListeners(key);
        this.targets = _.omit(this.targets, key);
        this.controllers = _.omit(this.controllers, key)
      });
    } else if (typeof targets === 'string') {
      this.removeAllListeners(targets);
      this.targets = _.omit(this.targets, targets);
      this.controllers = _.omit(this.controllers, targets)
    } else {
      this.targets = {};
      this.removeAllListeners();
    }
  }

  /**
   * Start the Growfile from the first phase.
   * @param {Object} growfile  The Growfile object.
   */
  startGrow (growfile) {
    if (growfile.phases) {
      let key = _.keys(growfile.phases)[0];
      this.startPhase(key, growfile);
    } else {
      if (growfile.targets) {
        this.registerTargets(growfile.targets);
      }
      if (growfile.cycles) {
        this.parseCycles(growfile.cycles);
      }
    }
  }

  /**
   * Start a new phase, such as going from vegetative to bloom, or to 'harvest'.
   * @param {String} phaseKey  The key of the phase to start.
   * @param {Object} growfile  The Growfile object.
   */
  startPhase (phaseKey, growfile) {
    let phases = growfile.phases;
    let cycles = phases[phaseKey].cycles;
    let targets = phases[phaseKey].targets;

    this.currentPhase = phaseKey;

    try {
      if (targets) {
        this.registerTargets(targets)
      }

      if (cycles) {
        this.parseCycles(cycles);
      }
    } catch (error) {
      console.log(error);
    };
  }

  /**
   * Schedules the cycles component of a phase or simple Growfile.
   * @param {Object} cycles  An object containing cycle objects
   */
  parseCycles(cycles) {
    _.each(cycles, (list, iteratee)=> {
      let scheduledTime = later.parse.text(String(cycles[iteratee].schedule));
      return later.setTimeout(()=> {
        try {
          if (cycles[iteratee].targets) {
            this.registerTargets(cycles[iteratee].targets);
          }

          if(cycles[iteratee].options) {
            this.call(iteratee, cycles[iteratee].options);
          } else {
            this.call(iteratee);
          }
        } catch (error) {
          console.log(error);
        };
      }, scheduledTime);
    });
  }

  /**
   * Returns true if the reading falls in a valid pH range.
   * @param {Number | String} reading  The reading to check.
   * @return {Number}
   */
  static parseAtlasPH (bytes) {
    let bytelist = [];
    if (bytes[0] === 1) {
      for (let i = 0; i < bytes.length; i++) {
        if (bytes[i] !== 1 && bytes[i] !== 0) {
          bytelist.push(ascii.symbolForDecimal(bytes[i]));
        }
      }
      return Number(bytelist.join(''));
    }
  }

  /**
   * Parses EC reading from data returned from Atlas Scientific Conductivity sensor.
   * @param {String} reading  The reading to parse.
   * @return {Number}
   */
  static parseAtlasEC (bytes) {
    let bytelist = [];
    if (bytes[0] === 1) {
      for (let i = 0; i < bytes.length; i++) {
        if (bytes[i] !== 1 && bytes[i] !== 0) {
          bytelist.push(ascii.symbolForDecimal(bytes[i]));
        }
      }
      return Number(bytelist.join('').split(',')[0]);
    }
  }

  /**
   * Parses EC reading from data returned from Atlas Scientific Conductivity sensor.
   * @param {String} reading  The reading to parse.
   * @return {Number}
   */
  static parseAtlasTemperature (bytes) {
    let bytelist = [];
    if (bytes[0] === 1) {
      for (let i = 0; i < bytes.length; i++) {
        if (bytes[i] !== 1 && bytes[i] !== 0) {
          bytelist.push(ascii.symbolForDecimal(bytes[i]));
        }
      }
      return Number(bytelist.join(''));
    }
  }
};

module.exports = Grow;
<commit_msg>Fixups galore.<commit_after>const Thing = require('Thing.js');
const later = require('later');
const Controller = require('node-pid-controller');
const ascii = require('ascii-codes');
const _ = require('underscore');

/**
 * Grow is an extension of a Thing (which is basically a fancy event emitter).
 * See [Thing.js](https://github.com/CommonGarden/Thing.js) for more info on Things...
 * @param {Object} config  The thing object.
 * @return {Grow}   A new Grow instance.
 */
class Grow extends Thing {
  constructor(config) {
    super(config);
  }

  /**
   * Creates listeners for targets objects in grow files.
   * @param {Object} targets An object contain event keys and corresponding min / max values.
   */
  registerTargets(targets) {
    this.controllers = this.controllers || {};
    this.alerts = this.alerts || {};
    this.targets = _.extend(this.targets, targets);
    _.each(targets, (value, key) => {
      if (value.ideal) {
        // Create a controller with defaults.
        // Allow for them to define control parameters?
        if (typeof value.pid === 'object') {
          try {
            this.controllers[key] = new Controller(value.pid);
          } catch (err) {
            console.log(err);
            this.controllers[key] = new Controller({
              k_p: 0.25,
              k_i: 0.01,
              k_d: 0.01,
              dt: 1
            });
          }
        }

        // Simply set the target
        this.controllers[key].setTarget(value.ideal);
      }

      this.on(key, (eventData) => {
        if (Number(eventData) !== 'NaN') {
          if (value.ideal) {
            let correction = this.controllers[key].update(eventData);
            this.emit('correction', key, correction);
          }

          if (value.min && eventData < value.min) {
            if (this.alerts[key] !== 'low') {
              let alert = {};
              alert[key] = 'low';
              _.extend(this.alerts, alert);
              this.set('alerts', this.alerts);
              this.emit('alert', alert);
            }
          }

          else if (value.max && eventData > value.max) {
            if (this.alerts[key] !== 'high') {
              let alert = {};
              alert[key] = 'high';
              _.extend(this.alerts, alert);
              this.set('alerts', this.alerts);
              this.emit('alert', alert);
            }
          }

          else {
            if (this.alerts[key]) {
              let alert = {};
              alert[key] = 'ok';
              this.emit('alert', alert);
              this.alerts = _.omit(this.alerts, key);
              this.set('alerts', this.alerts);
            }
          }
        }
      });
    });

    this.emit('targets-updated', targets);
  }

  /**
   * Remove targets
   * @param {Object} targets  Alerts to be removed.
   */
  removeTargets(targets) {
    if (_.isArray(targets)) {
      _.each(targets, (value, key) => {
        this.removeAllListeners(value);
        this.targets = _.omit(this.targets, value);
        this.controllers = _.omit(this.controllers, value)
      });
    } else if (_.isObject(targets)) {
      _.each(targets, (value, key) => {
        this.removeAllListeners(key);
        this.targets = _.omit(this.targets, key);
        this.controllers = _.omit(this.controllers, key)
      });
    } else if (typeof targets === 'string') {
      this.removeAllListeners(targets);
      this.targets = _.omit(this.targets, targets);
      this.controllers = _.omit(this.controllers, targets)
    } else {
      this.targets = {};
      this.removeAllListeners();
    }
  }

  /**
   * Start the Growfile from the first phase.
   * @param {Object} growfile  The Growfile object.
   */
  startGrow (growfile) {
    if (growfile.phases) {
      let key = _.keys(growfile.phases)[0];
      this.startPhase(key, growfile);
    } else {
      if (growfile.targets) {
        this.registerTargets(growfile.targets);
      }
      if (growfile.cycles) {
        this.parseCycles(growfile.cycles);
      }
    }
  }

  /**
   * Start a new phase, such as going from vegetative to bloom, or to 'harvest'.
   * @param {String} phaseKey  The key of the phase to start.
   * @param {Object} growfile  The Growfile object.
   */
  startPhase (phaseKey, growfile) {
    let phases = growfile.phases;
    let cycles = phases[phaseKey].cycles;
    let targets = phases[phaseKey].targets;

    this.currentPhase = phaseKey;

    try {
      if (targets) {
        this.registerTargets(targets)
      }

      if (cycles) {
        this.parseCycles(cycles);
      }
    } catch (error) {
      console.log(error);
    };
  }

  /**
   * Schedules the cycles component of a phase or simple Growfile.
   * @param {Object} cycles  An object containing cycle objects
   */
  parseCycles(cycles) {
    _.each(cycles, (list, iteratee)=> {
      let scheduledTime = later.parse.text(String(cycles[iteratee].schedule));
      return later.setTimeout(()=> {
        try {
          if (cycles[iteratee].targets) {
            this.registerTargets(cycles[iteratee].targets);
          }

          if(cycles[iteratee].options) {
            this.call(iteratee, cycles[iteratee].options);
          } else {
            this.call(iteratee);
          }
        } catch (error) {
          console.log(error);
        };
      }, scheduledTime);
    });
  }

  /**
   * Returns true if the reading falls in a valid pH range.
   * @param {Number | String} reading  The reading to check.
   * @return {Number}
   */
  static parseAtlasPH (bytes) {
    let bytelist = [];
    if (bytes[0] === 1) {
      for (let i = 0; i < bytes.length; i++) {
        if (bytes[i] !== 1 && bytes[i] !== 0) {
          bytelist.push(ascii.symbolForDecimal(bytes[i]));
        }
      }
      return Number(bytelist.join(''));
    }
  }

  /**
   * Parses EC reading from data returned from Atlas Scientific Conductivity sensor.
   * @param {String} reading  The reading to parse.
   * @return {Number}
   */
  static parseAtlasEC (bytes) {
    let bytelist = [];
    if (bytes[0] === 1) {
      for (let i = 0; i < bytes.length; i++) {
        if (bytes[i] !== 1 && bytes[i] !== 0) {
          bytelist.push(ascii.symbolForDecimal(bytes[i]));
        }
      }
      return Number(bytelist.join('').split(',')[0]);
    }
  }

  /**
   * Parses EC reading from data returned from Atlas Scientific Conductivity sensor.
   * @param {String} reading  The reading to parse.
   * @return {Number}
   */
  static parseAtlasTemperature (bytes) {
    let bytelist = [];
    if (bytes[0] === 1) {
      for (let i = 0; i < bytes.length; i++) {
        if (bytes[i] !== 1 && bytes[i] !== 0) {
          bytelist.push(ascii.symbolForDecimal(bytes[i]));
        }
      }
      return Number(bytelist.join(''));
    }
  }
};

module.exports = Grow;
<|endoftext|>


<commit_before>/*
/*    This program is free software: you can redistribute it and/or  modify
/*    it under the terms of the GNU Affero General Public License, version 3,
/*    as published by the Free Software Foundation.
/*
/*    This program is distributed in the hope that it will be useful,
/*    but WITHOUT ANY WARRANTY; without even the implied warranty of
/*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
/*    GNU Affero General Public License for more details.
/*
/*    You should have received a copy of the GNU Affero General Public License
/*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
/*
/*    The Original Code is "Pillars.js Modelator" aka "Modelator"
/*
/*    The Initial Developer of the Original Code is Francisco Javier Gallego Martín <bifuer.at.gmail.com>.
/*    Copyright (c) 2014-2017 Francisco Javier Gallego Martín.
/*/

/* jslint node: true, esnext: true */
"use strict";

const Tree = module.exports.Tree = function Tree(contents){
  // TODO: instance from Map?
  Object.assign(this, contents);
};
  Object.defineProperty(Tree.prototype, 'parse', {enumerable: false, value: function(marks){
    const result = {};
    Tree.treeParseWalker([], this, result, marks);
    return result;
  }});
const TreeArray = module.exports.TreeArray = function TreeArray(array){
  const treeArray = Array.apply(this, array);
  const proto = Object.assign([], Array.prototype);
  Object.defineProperty(proto, 'constructor', {enumerable: false, value: TreeArray});
  Object.setPrototypeOf(treeArray, proto);
  return treeArray;
};
  Object.defineProperty(TreeArray.prototype, 'parse', {enumerable: false, value: Tree.prototype.parse});
  Tree.create = function(dotFormat,array){
    // TODO: on insert ascendent after descendant overwrites
    const tree = new Tree();
    const checklist = array? [] : {};
    Object.getOwnPropertyNames(dotFormat).forEach((index)=>{
      const value = dotFormat[index];
      index = index.split(".");
      const name = index.shift();
      if(index.length > 0){
        const Type = /^[09]+$/.test(index[0])? TreeArray : Tree;
        checklist[name] = checklist[name] || new Type();
        checklist[name] = checklist[name].constructor === Type? checklist[name] : new Type();
        checklist[name][index.join(".")] = value;
      } else {
        checklist[name] = value;
      }
    });
    for(const index in checklist){
      if(checklist[index] instanceof Tree){
        checklist[index] = Tree.create(checklist[index]);
      } else if(checklist[index] instanceof TreeArray){
        checklist[index] = Tree.create(checklist[index],true);
      }
    }
    return array? new TreeArray(checklist) : new Tree(checklist);
  };
  Tree.treeParseWalker = function(path, tree, result, marks){
    const traverse = Tree.isTree(tree) || Tree.isTreeArray(tree);
    if(traverse){
      const keys = Tree.isTreeArray(tree)? tree : Object.getOwnPropertyNames(tree);

      for (let i = 0; i < keys.length; i++) {
        const key = Tree.isTreeArray(tree)? i : keys[i];
        if(Tree.isTreeArray(tree[key]) || Tree.isTree(tree[key])){
          if(marks){result[path.concat([key]).join('.')] = true;}
          Tree.treeParseWalker(path.concat([key]), tree[key], result, marks);
        } else if(tree[key] !== undefined){
          result[path.concat([key]).join('.')] = tree[key];
        } else {
          // ignore undefineds
        }
      }
    }
  };
  Tree.isTreeArray = function(tree){
    return TreeArray.prototype.isPrototypeOf(tree) || (tree && tree.constructor === TreeArray);
  };
  Tree.isTree = function(tree){
    return Tree.prototype.isPrototypeOf(tree)  || (tree && tree.constructor === Tree);
  };<commit_msg>Update Tree.js<commit_after>/* jslint node: true, esnext: true */
"use strict";

const Tree = module.exports.Tree = function Tree(contents){
  // TODO: instance from Map?
  Object.assign(this, contents);
};
  Object.defineProperty(Tree.prototype, 'parse', {enumerable: false, value: function(marks){
    const result = {};
    Tree.treeParseWalker([], this, result, marks);
    return result;
  }});
const TreeArray = module.exports.TreeArray = function TreeArray(array){
  const treeArray = Array.apply(this, array);
  const proto = Object.assign([], Array.prototype);
  Object.defineProperty(proto, 'constructor', {enumerable: false, value: TreeArray});
  Object.setPrototypeOf(treeArray, proto);
  return treeArray;
};
  Object.defineProperty(TreeArray.prototype, 'parse', {enumerable: false, value: Tree.prototype.parse});
  Tree.create = function(dotFormat,array){
    // TODO: on insert ascendent after descendant overwrites
    const tree = new Tree();
    const checklist = array? [] : {};
    Object.getOwnPropertyNames(dotFormat).forEach((index)=>{
      const value = dotFormat[index];
      index = index.split(".");
      const name = index.shift();
      if(index.length > 0){
        const Type = /^[09]+$/.test(index[0])? TreeArray : Tree;
        checklist[name] = checklist[name] || new Type();
        checklist[name] = checklist[name].constructor === Type? checklist[name] : new Type();
        checklist[name][index.join(".")] = value;
      } else {
        checklist[name] = value;
      }
    });
    for(const index in checklist){
      if(checklist[index] instanceof Tree){
        checklist[index] = Tree.create(checklist[index]);
      } else if(checklist[index] instanceof TreeArray){
        checklist[index] = Tree.create(checklist[index],true);
      }
    }
    return array? new TreeArray(checklist) : new Tree(checklist);
  };
  Tree.treeParseWalker = function(path, tree, result, marks){
    const traverse = Tree.isTree(tree) || Tree.isTreeArray(tree);
    if(traverse){
      const keys = Tree.isTreeArray(tree)? tree : Object.getOwnPropertyNames(tree);

      for (let i = 0; i < keys.length; i++) {
        const key = Tree.isTreeArray(tree)? i : keys[i];
        if(Tree.isTreeArray(tree[key]) || Tree.isTree(tree[key])){
          if(marks){result[path.concat([key]).join('.')] = true;}
          Tree.treeParseWalker(path.concat([key]), tree[key], result, marks);
        } else if(tree[key] !== undefined){
          result[path.concat([key]).join('.')] = tree[key];
        } else {
          // ignore undefineds
        }
      }
    }
  };
  Tree.isTreeArray = function(tree){
    return TreeArray.prototype.isPrototypeOf(tree) || (tree && tree.constructor === TreeArray);
  };
  Tree.isTree = function(tree){
    return Tree.prototype.isPrototypeOf(tree)  || (tree && tree.constructor === Tree);
  };
<|endoftext|>


<commit_before>// require fs extra
var fs = require('fs-extra');

// save caches
var caches = {};

/**
 * Create a new module instance cache
 *
 * @public
 * @param {string} The module instance cache name.
 * @param {function} The factory method.
 */
module.exports = function (name, factory) {

    // return existing cache
    if (caches[name]) {
        return caches[name];
    }

    // clone cache class
    var cache = engine.clone(Cache);

    // save factory method
    cache.factory = factory;

    // cache module packages info
    cache._modules = {};

    // cache the running module instances
    cache._data = {};

    // save cache
    caches[name] = cache;

    return cache;
};

/**
 * The composition cache class.
 *
 * @class Cache
 */
var Cache = {

    /**
     * Remove a module instance or empty cache.
     *
     * @public
     * @param {string} The module instance name.
     * @param {string} The role name.
     */
    rm: function (name, role) {

        // remove one item
        if (name) {

            if (!this._data[name]) {
                return;
            }

            // check role access
            if (!checkRoleAccess(this._data[name], role)) {
                return 0;
            }

            // remove cached item
            delete this._data[name];

            return;
        }

        // remove all items
        this._data = {};
    },

    /**
     * Get or create a module instance.
     *
     * @public
     * @param {string} The module instance name.
     * @param {string} The role name.
     * @param {function} The callback function.
     */
    get: function (name, role, callback) {
        var self = this;

        // check if object is already in cache
        if (self._data[name]) {

            var data = self._data[name];
            var error;

            // check role access
            if (!checkRoleAccess(self._data[name], role)) {
                data = undefined;
                error = new Error('access denied.');
            }

            // return cached instance or call the callback
            return callback ? callback(error, data) : error || data;
        }

        // dont load composition, when no callback is given
        if (!callback) {
            return;
        }

        // create path to composition file
        var path =  engine.paths.app_composition + name + '.json';

        // read the composition json
        fs.readJson(path, function (err, composition) {

            // handle error and check role access
            if (err || !checkRoleAccess(composition, role)) {
                return callback(err || new Error('access denied.'));
            }

            // watch file
            if (self._data[name] !== null) {
                fs.watch(path, function (event) {

                    // remove cached data on file change, to force reload
                    if (event === 'change' && self._data[name]) {

                        // remove the cached item
                        self._data[name] = null;
                    }
                });
            }

            // get the module's package infos
            getPackackeInfo.call(self, composition.module, function (err, moduleConfig) {

                // extend module instance config with the module dependencies
                composition.client = composition.client || {};

                // all dependencies of the instance dependencies must be in this array!
                // while installing a module, save all dependencies in the module deps
                // dependencies: ['./file.js', 's/o/modA/v']
                // => ModA deps: ['./file.js', 's/o/modB/v'] => ModB deps: []
                // => to client: ['./file.js', 's/o/n/v/file.js']
                composition.client.scripts = moduleConfig.engine.dependencies;

                // save main start script
                composition.main = moduleConfig.main;

                // create a new module instance
                self.factory(composition, function (err, module_instance) {

                    // handle error
                    if (err) {
                        return callback(err);
                    }

                    // save module instance in cache
                    self._data[name] = module_instance;

                    // save the module instance always under the configured name
                    if (moduleConfig.name !== name) {
                        self._data[moduleConfig.name] = module_instance;
                    }

                    // return data
                    callback(null, module_instance);
                });
            });
        });
    }
};

/**
 * Parse and get the engine package infos.
 *
 * @private
 * @param {string} The module name or the custom module config object.
 * @param {function} The callback function.
 */
function getPackackeInfo (module, callback) {
    var self = this;

    // check if it's a custom module
    if (typeof module === 'object') {
        return callback(null, module);
    }

    // create module path
    var path = engine.paths.app_modules + module + '/package.json';

    // return cached object
    if (self._modules[path]) {
        return callback(null, self._modules[path]);
    }

    // read and parse the packackage json file
    fs.readJson(path, function (err, packageInfo) {

        // handle errors
        if (err || !packageInfo || !packageInfo.engine) {
            return callback(err || new Error('No engine specific configs found.'));
        }

        // update file on change
        // TODO remove all module instance, when module changes
        if (self._data[path] !== null) {
            fs.watch(path, function (event) {

                // remove cached data on file change, to force reload
                if (event === 'change' && self._modules[path]) {

                    // remove the cached item
                    self._modules[path] = null;
                }
            });
        }

        // save package info in cache
        self._modules[path] = {
            main: packageInfo.main,
            engine: packageInfo.engine
        };

        // return the engine spezific package info
        callback(null, self._modules[path]);
    });
}

/**
 * Check the role access for a cache item.
 *
 * @private
 * @param {object} The cached item.
 * @param {string} The role name.
 */
function checkRoleAccess (item, role) {

    if (item.roles['*'] || (item.roles && item.roles[role])) {
        return true;
    }
}
<commit_msg>roles can be under different propertiies<commit_after>// require fs extra
var fs = require('fs-extra');

// save caches
var caches = {};

/**
 * Create a new module instance cache
 *
 * @public
 * @param {string} The module instance cache name.
 * @param {function} The factory method.
 */
module.exports = function (name, factory) {

    // return existing cache
    if (caches[name]) {
        return caches[name];
    }

    // clone cache class
    var cache = engine.clone(Cache);

    // save factory method
    cache.factory = factory;

    // cache module packages info
    cache._modules = {};

    // cache the running module instances
    cache._data = {};

    // save cache
    caches[name] = cache;

    return cache;
};

/**
 * The composition cache class.
 *
 * @class Cache
 */
var Cache = {

    /**
     * Remove a module instance or empty cache.
     *
     * @public
     * @param {string} The module instance name.
     * @param {string} The role name.
     */
    rm: function (name, role) {

        // remove one item
        if (name) {

            if (!this._data[name]) {
                return;
            }

            // check role access
            if (!checkRoleAccess(this._data[name], role)) {
                return 0;
            }

            // remove cached item
            delete this._data[name];

            return;
        }

        // remove all items
        this._data = {};
    },

    /**
     * Get or create a module instance.
     *
     * @public
     * @param {string} The module instance name.
     * @param {string} The role name.
     * @param {function} The callback function.
     */
    get: function (name, role, callback) {
        var self = this;

        // check if object is already in cache
        if (self._data[name]) {

            var data = self._data[name];
            var error;

            // check role access
            if (!checkRoleAccess(self._data[name], role)) {
                data = undefined;
                error = new Error('access denied.');
            }

            // return cached instance or call the callback
            return callback ? callback(error, data) : error || data;
        }

        // dont load composition, when no callback is given
        if (!callback) {
            return;
        }

        // create path to composition file
        var path =  engine.paths.app_composition + name + '.json';

        // read the composition json
        fs.readJson(path, function (err, composition) {

            // handle error and check role access
            if (err || !checkRoleAccess(composition, role)) {
                return callback(err || new Error('access denied.'));
            }

            // watch file
            if (self._data[name] !== null) {
                fs.watch(path, function (event) {

                    // remove cached data on file change, to force reload
                    if (event === 'change' && self._data[name]) {

                        // remove the cached item
                        self._data[name] = null;
                    }
                });
            }

            // get the module's package infos
            getPackackeInfo.call(self, composition.module, function (err, moduleConfig) {

                // extend module instance config with the module dependencies
                composition.client = composition.client || {};

                // all dependencies of the instance dependencies must be in this array!
                // while installing a module, save all dependencies in the module deps
                // dependencies: ['./file.js', 's/o/modA/v']
                // => ModA deps: ['./file.js', 's/o/modB/v'] => ModB deps: []
                // => to client: ['./file.js', 's/o/n/v/file.js']
                composition.client.scripts = moduleConfig.engine.dependencies;

                // save main start script
                composition.main = moduleConfig.main;

                // create a new module instance
                self.factory(composition, function (err, module_instance) {

                    // handle error
                    if (err) {
                        return callback(err);
                    }

                    // save module instance in cache
                    self._data[name] = module_instance;

                    // save the module instance always under the configured name
                    if (moduleConfig.name !== name) {
                        self._data[moduleConfig.name] = module_instance;
                    }

                    // return data
                    callback(null, module_instance);
                });
            });
        });
    }
};

/**
 * Parse and get the engine package infos.
 *
 * @private
 * @param {string} The module name or the custom module config object.
 * @param {function} The callback function.
 */
function getPackackeInfo (module, callback) {
    var self = this;

    // check if it's a custom module
    if (typeof module === 'object') {
        return callback(null, module);
    }

    // create module path
    var path = engine.paths.app_modules + module + '/package.json';

    // return cached object
    if (self._modules[path]) {
        return callback(null, self._modules[path]);
    }

    // read and parse the packackage json file
    fs.readJson(path, function (err, packageInfo) {

        // handle errors
        if (err || !packageInfo || !packageInfo.engine) {
            return callback(err || new Error('No engine specific configs found.'));
        }

        // update file on change
        // TODO remove all module instance, when module changes
        if (self._data[path] !== null) {
            fs.watch(path, function (event) {

                // remove cached data on file change, to force reload
                if (event === 'change' && self._modules[path]) {

                    // remove the cached item
                    self._modules[path] = null;
                }
            });
        }

        // save package info in cache
        self._modules[path] = {
            main: packageInfo.main,
            engine: packageInfo.engine
        };

        // return the engine spezific package info
        callback(null, self._modules[path]);
    });
}

/**
 * Check the role access for a cache item.
 *
 * @private
 * @param {object} The cached item.
 * @param {string} The role name.
 */
function checkRoleAccess (item, role) {

    var roles = item._roles || item.roles || {};

    if (roles['*'] || roles[role]) {
        return true;
    }
}
<|endoftext|>


<commit_before>var util = require('util');
var url = require('url');
var EventEmitter = require('events').EventEmitter;

var GitHubApi = require('./extern/node-github').GitHubApi;
var async = require('async');
var sprintf = require('sprintf').sprintf;
var log = require('logmagic').local('buildbot-github.core');

var BuildBot = require('./buildbot').BuildBot;
var utils = require('./utils');
var pollers = require('./pollers');
var server = require('./server');

function BuildbotGithub(options) {
  this._options = options;

  this._buildbotPoller = null;
  this._server = null;

  this._pullCache = {};
}

util.inherits(BuildbotGithub, EventEmitter);

BuildbotGithub.prototype._initialize = function() {
  var options;

  this._github = new GitHubApi(false);
  this._github.authenticateToken(this._options['github']['username'],
                                 this._options['github']['token']);

  // Set up server which listens for webhook events
  options = utils.merge({'username': this._options['github']['username'],
                         'trigger_string': this._options['general']['trigger_string']},
                         this._options['webserver']);
  this._server = new server.WebServer(options);

  // Set up poller
  this._buildbotPoller = new pollers.BuildbotPoller(this._options['buildbot'],
                                                    this._options['buildbot']['poll_interval']);

  // Set up Buildbot instance
  this._buildbot = new BuildBot(this._options['buildbot']);

  // Register change handlers
  this._buildbotPoller.on('new_build', this._handleNewBuild.bind(this));
  this._server.on('trigger_comment', this._handleTriggerComment.bind(this));
};

BuildbotGithub.prototype.start = function() {
  this._initialize();

  this._server.start();
  this._buildbotPoller.start();
};

BuildbotGithub.prototype.stop = function() {
  this._server.stop();
  this._buildbotPoller.stop();
};

BuildbotGithub.prototype._handleNewBuild = function(build) {
  var properties, pullId, revision, key, requestCache;
  properties = build.properties || [];
  pullId = utils.getPropertyValue(properties, 'pull-request-id');
  revision = utils.getPropertyValue(properties, 'revision');
  key = sprintf('%s-%s', pullId, revision);

  if (!pullId || !revision) {
    // Not triggered by us.
    return;
  }

  // Check if there are any pending builds with this key
  requestCache = this._pullCache[key];

  if (!requestCache || !requestCache['build_pending']) {
    log.infof('No pending builds for pull request #${id}', {'id': pullId,
                                                            'key': key});
    return;
  }

  requestCache['build_pending'] = false;
  this._postPullRequestComment(build, pullId, key);
};

BuildbotGithub.prototype._handleTriggerComment = function(payload) {
  var self = this,
      pullId = payload.issue.number;

  async.waterfall([
    function getDiscussion(callback) {
      // Pretty lame way to retrieve pull request info but atm I don't want t
      // deal with v3 api.
      self._github.getPullApi().getDiscussion(self._options['github']['user'],
                                              self._options['github']['project'],
                                              pullId, callback);
    },

    function populateCache(data, callback) {
      // TODO: Redis, kktnxbye
      var revision = data.head.sha, requestCache,
          key = sprintf('%s-%s', pullId, revision);

      if (!self._pullCache.hasOwnProperty(key)) {
        self._pullCache[key] = {
          'id': pullId,
          'build_pending': true
        };
      }

      requestCache = self._pullCache[key];
      requestCache['updated'] = parseInt(new Date().getTime() / 1000, 10);
      callback(null, data);
    },

    function sendChanges(data, callback) {
      var id = data.number,
          user = data.user,
          revision = data.head.sha,
          branch = data.head.ref;

      log.infof('Sending changes to buildbot', {'id': id, 'revision': revision,
                                               'branch': branch});
      self._buildbot.sendChanges(id, revision, user,
                                 self._options['github']['project'],
                                 self._options['github']['repository'],
                                 branch, callback);
    }
  ],

  function(err) {
    if (err) {
      log.errorf('Sending changes failed: ${err}', {'err': err.toString()});
      return;
    }

    log.infof('Successfully sent changes to buildbot');
  });
};

BuildbotGithub.prototype._postPullRequestComment = function(build, pullId,
                                                            key) {
  var self = this,
      requestCache, commentString, commentBody;
  requestCache = this._pullCache[key];

  function getTemplateObj() {
    var text, buildNumber, buildStatus, rand, image;

    buildNumber = build['number'];
    text = build['text'].join('');

    if (text.toLowerCase().indexOf('failed') !== -1) {
      buildStatus = 'failure';
      rand = utils.getRandomInt(0, self._options['templates']['images_failure'].length - 1);
      image = self._options['templates']['images_failure'][rand];
    }
    else {
      buildStatus = 'success';
      rand = utils.getRandomInt(0, self._options['templates']['images_success'].length - 1);
      image = self._options['templates']['images_success'][rand];
    }

    var urlObj = {
      protocol: (self._options['buildbot']['secure']) ? 'https:' : 'http',
      host: self._options['buildbot']['host'],
      port: self._options['buildbot']['port'],
      query: '',
      pathname: sprintf('/builders/%s/builds/%s',
                        self._options['buildbot']['builder_name'], buildNumber)
    };

    var templateObj = {
      'branch': build['sourceStamp']['branch'],
      'blame': build['blame'][0],
      'nickname': utils.getPropertyValue(build['properties'],
                                         'github-nickname'),
      'number': buildNumber,
      'builder_name': build['builderName'],
      'status': buildStatus,
      'build_url': url.format(urlObj),
      'image': image
    };

    return templateObj;
  }

  log.infof('Posting comment with build results to pull request #${id}',
           {'id': pullId});

  var templateObj = getTemplateObj();
  if (templateObj['status'] === 'success') {
    commentString = this._options['templates']['comment_success'];
  }
  else {
    commentString = this._options['templates']['comment_failure'];
  }

  commentBody = utils.applyFormatting(commentString, templateObj);
  this._github.getIssueApi().addComment(self._options['github']['user'],
                                        self._options['github']['project'],
                                        pullId, commentBody,
                                        function(err, body) {
    if (err) {
      log.errorf('Posting comment to pull request #${id} failed: ${err}',
                {'id': pullId, 'err': err.toString()});
      return;
    }

    log.infof('Successfully posted comment to pull request #${id}: ${body}',
             {'id': pullId, 'body': commentBody});
  });
};

exports.BuildbotGithub = BuildbotGithub;
<commit_msg>Don't call toString() on the error object.<commit_after>var util = require('util');
var url = require('url');
var EventEmitter = require('events').EventEmitter;

var GitHubApi = require('./extern/node-github').GitHubApi;
var async = require('async');
var sprintf = require('sprintf').sprintf;
var log = require('logmagic').local('buildbot-github.core');

var BuildBot = require('./buildbot').BuildBot;
var utils = require('./utils');
var pollers = require('./pollers');
var server = require('./server');

function BuildbotGithub(options) {
  this._options = options;

  this._buildbotPoller = null;
  this._server = null;

  this._pullCache = {};
}

util.inherits(BuildbotGithub, EventEmitter);

BuildbotGithub.prototype._initialize = function() {
  var options;

  this._github = new GitHubApi(false);
  this._github.authenticateToken(this._options['github']['username'],
                                 this._options['github']['token']);

  // Set up server which listens for webhook events
  options = utils.merge({'username': this._options['github']['username'],
                         'trigger_string': this._options['general']['trigger_string']},
                         this._options['webserver']);
  this._server = new server.WebServer(options);

  // Set up poller
  this._buildbotPoller = new pollers.BuildbotPoller(this._options['buildbot'],
                                                    this._options['buildbot']['poll_interval']);

  // Set up Buildbot instance
  this._buildbot = new BuildBot(this._options['buildbot']);

  // Register change handlers
  this._buildbotPoller.on('new_build', this._handleNewBuild.bind(this));
  this._server.on('trigger_comment', this._handleTriggerComment.bind(this));
};

BuildbotGithub.prototype.start = function() {
  this._initialize();

  this._server.start();
  this._buildbotPoller.start();
};

BuildbotGithub.prototype.stop = function() {
  this._server.stop();
  this._buildbotPoller.stop();
};

BuildbotGithub.prototype._handleNewBuild = function(build) {
  var properties, pullId, revision, key, requestCache;
  properties = build.properties || [];
  pullId = utils.getPropertyValue(properties, 'pull-request-id');
  revision = utils.getPropertyValue(properties, 'revision');
  key = sprintf('%s-%s', pullId, revision);

  if (!pullId || !revision) {
    // Not triggered by us.
    return;
  }

  // Check if there are any pending builds with this key
  requestCache = this._pullCache[key];

  if (!requestCache || !requestCache['build_pending']) {
    log.infof('No pending builds for pull request #${id}', {'id': pullId,
                                                            'key': key});
    return;
  }

  requestCache['build_pending'] = false;
  this._postPullRequestComment(build, pullId, key);
};

BuildbotGithub.prototype._handleTriggerComment = function(payload) {
  var self = this,
      pullId = payload.issue.number;

  async.waterfall([
    function getDiscussion(callback) {
      // Pretty lame way to retrieve pull request info but atm I don't want t
      // deal with v3 api.
      self._github.getPullApi().getDiscussion(self._options['github']['user'],
                                              self._options['github']['project'],
                                              pullId, callback);
    },

    function populateCache(data, callback) {
      // TODO: Redis, kktnxbye
      var revision = data.head.sha, requestCache,
          key = sprintf('%s-%s', pullId, revision);

      if (!self._pullCache.hasOwnProperty(key)) {
        self._pullCache[key] = {
          'id': pullId,
          'build_pending': true
        };
      }

      requestCache = self._pullCache[key];
      requestCache['updated'] = parseInt(new Date().getTime() / 1000, 10);
      callback(null, data);
    },

    function sendChanges(data, callback) {
      var id = data.number,
          user = data.user,
          revision = data.head.sha,
          branch = data.head.ref;

      log.infof('Sending changes to buildbot', {'id': id, 'revision': revision,
                                               'branch': branch});
      self._buildbot.sendChanges(id, revision, user,
                                 self._options['github']['project'],
                                 self._options['github']['repository'],
                                 branch, callback);
    }
  ],

  function(err) {
    if (err) {
      log.errorf('Sending changes failed: ${err}', {'err': err)});
      return;
    }

    log.infof('Successfully sent changes to buildbot');
  });
};

BuildbotGithub.prototype._postPullRequestComment = function(build, pullId,
                                                            key) {
  var self = this,
      requestCache, commentString, commentBody;
  requestCache = this._pullCache[key];

  function getTemplateObj() {
    var text, buildNumber, buildStatus, rand, image;

    buildNumber = build['number'];
    text = build['text'].join('');

    if (text.toLowerCase().indexOf('failed') !== -1) {
      buildStatus = 'failure';
      rand = utils.getRandomInt(0, self._options['templates']['images_failure'].length - 1);
      image = self._options['templates']['images_failure'][rand];
    }
    else {
      buildStatus = 'success';
      rand = utils.getRandomInt(0, self._options['templates']['images_success'].length - 1);
      image = self._options['templates']['images_success'][rand];
    }

    var urlObj = {
      protocol: (self._options['buildbot']['secure']) ? 'https:' : 'http',
      host: self._options['buildbot']['host'],
      port: self._options['buildbot']['port'],
      query: '',
      pathname: sprintf('/builders/%s/builds/%s',
                        self._options['buildbot']['builder_name'], buildNumber)
    };

    var templateObj = {
      'branch': build['sourceStamp']['branch'],
      'blame': build['blame'][0],
      'nickname': utils.getPropertyValue(build['properties'],
                                         'github-nickname'),
      'number': buildNumber,
      'builder_name': build['builderName'],
      'status': buildStatus,
      'build_url': url.format(urlObj),
      'image': image
    };

    return templateObj;
  }

  log.infof('Posting comment with build results to pull request #${id}',
           {'id': pullId});

  var templateObj = getTemplateObj();
  if (templateObj['status'] === 'success') {
    commentString = this._options['templates']['comment_success'];
  }
  else {
    commentString = this._options['templates']['comment_failure'];
  }

  commentBody = utils.applyFormatting(commentString, templateObj);
  this._github.getIssueApi().addComment(self._options['github']['user'],
                                        self._options['github']['project'],
                                        pullId, commentBody,
                                        function(err, body) {
    if (err) {
      log.errorf('Posting comment to pull request #${id} failed: ${err}',
                {'id': pullId, 'err': err.toString()});
      return;
    }

    log.infof('Successfully posted comment to pull request #${id}: ${body}',
             {'id': pullId, 'body': commentBody});
  });
};

exports.BuildbotGithub = BuildbotGithub;
<|endoftext|>