<commit_before>/*@ extern crash :: forall A.() => A */

/*@ extern assume :: (boolean) => void */

/*@ extern assert :: ({x:boolean|(Prop x)}) => void */

/*@ extern requires :: (boolean) => void */

/*@ extern ensures :: (boolean) => void */

/*@ extern random :: () => number */

/*@ extern pos    :: () => {v:number | v > 0} */

/*************************************************************************/
/*********************** Temporary tag maps ******************************/
/*************************************************************************/
// From:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
//
// Undefined                                                              "undefined"
// Null                                                                   "object"
// Boolean                                                                "boolean"
// Number                                                                 "number"
// String                                                                 "string"
// Host object (provided by the JS environment)  Implementation-dependent
// Function object (implements [[Call]] in ECMA-262 terms)                "function"
// E4X XML object                                                         "xml"
// E4X XMLList object                                                     "xml"
// Any other object                                                       "object"
//
// For Null
// typeof null === 'object'; // This stands since the beginning of JavaScript

/*************************************************************************/
/***************** Types for list Operators ******************************/
/*************************************************************************/

/*@ type list[A]  {  data : A, next : list[A] + null } */

/*@ measure len :: forall A. (list [A]) => number                                                 */

/*@ extern cons  :: forall A. (A, xs:list[A] + null) => {list[A] | (len v) = 1 + (len xs)}               */
/*@ extern nil   :: () => { null | (len v) = 0}                                                           */
/*@ extern head  :: forall A. (xs:list[A]) => A                                                         */
/*@ extern tail  :: forall A. (xs:list [A]) => list [A] + null                                           */
/*@ extern nth   :: forall A. (xs:list [A], {i:number| ((0 <= i) && i < (len xs))}) => A                 */
/*@ extern empty :: forall A. (xango: list[A] + null ) =>
                        {v: boolean | (((Prop v) <=> len(xango) = 0) && ((Prop v) <=> ttag(xango) = "null"))}                      */
/*@ extern emptyPoly :: forall A. (x:A) => {v: boolean | ((Prop v) <=> ((ttag x) = "null"))}             */

/*@ extern length   :: forall A. (xs:list[A] + null) => {v:number | ((v >= 0) && v = (len xs))}         */
/*@ extern safehead :: forall A. (list[A]) => A                                     */
/*@ extern safetail :: forall A. (xs:list[A]) => {v:list[A] + null | (len v) = (len xs) - 1} */

/*@ extern Array    :: (n : { v: number | 0 <= v } ) => { v: [ undefined ] | (len v) = n }               */

/*************************************************************************/
/************************* Type Conversions ******************************/
/*************************************************************************/
/*@ extern sstring  :: forall A. (x: A) => string                               */

/*************************************************************************/
/************** Types for Builtin Operators ******************************/
/*************************************************************************/

/*@ extern builtin_BIBracketRef     :: forall A. (arr:[A], {idx:number | (0 <= idx && idx < (len arr))}) => A           */
/*@ extern builtin_BIBracketAssign  :: forall A. (arr:[A], {idx:number | (0 <= idx && idx < (len arr))}, val:A) => void */
/*@ extern builtin_BIArrayLit       :: forall A. (A) => {v:[A] | (len v) = builtin_BINumArgs}                           */
/*@ extern builtin_BIUndefined      :: forall A. {A | false}                                                            */

/*@ extern builtin_OpLT        :: ({x:number|true}, {y:number|true}) => {v:boolean | ((Prop v) <=> (x <  y)) }   */
/*@ extern builtin_OpLEq       :: ({x:number|true}, {y:number|true}) => {v:boolean | ((Prop v) <=> (x <= y)) }   */
/*@ extern builtin_OpGT        :: ({x:number|true}, {y:number|true}) => {v:boolean | ((Prop v) <=> (x >  y)) }   */
/*@ extern builtin_OpGEq       :: ({x:number|true}, {y:number|true}) => {v:boolean | ((Prop v) <=> (x >= y)) }   */

//PV: @==@ and @===@ could be handled more precisely
/*@ extern builtin_OpEq        :: forall A.   (x:A, y:A) => {v:boolean | ((Prop v) <=> (x = y)) }  */
/*@ extern builtin_OpSEq       :: forall A B. (x:A, y:B) => {v:boolean | ((Prop v) <=> (x = y)) }  */
/*@ extern builtin_OpNEq       :: forall A B. (x:A, y:B) => {v:boolean | ((Prop v) <=> (x != y)) } */

/*@ extern builtin_OpLAnd      :: ({x:top|true}, {y:top|true}) => {v:boolean | true}                             */
/*  builtin_OpLAnd      :: ({x:top|true}, {y:top|true}) =>
                            {v:boolean | ((Prop v) <=> (if (falsy x) then (v = y) else (v = x)))}         */

/*@ extern builtin_OpLOr       :: ({x:boolean|true}, {y:boolean|true}) =>
                            {v:boolean | ((Prop v) <=> ((Prop x) || (Prop y)))}                           */

// XXX: Will eventually switch to truthy and falsy:
/*  builtin_OpLOr       :: (x:top, y:top) =>
      { top | ((Prop v) <=> (if (falsy x) then (v = y) else (v = x) ))}           */

//TODO: We would like to have a more precise type (like the following) that
//would include strings into the game, but this does not work well with
//equality at the moment:

/*@ extern builtin_OpAdd :: /\ (x:number, y:number) => {number | v = x + y}
                     /\ (x:number, y:string) => string
                     /\ (x:string, y:number) => string
                     /\ (x:string, y:string) => string
  */

/* builtin_OpAdd      :: (x:number + string, y:number + string) =>
                              {v:number + string | (if ((ttag x) = "number" && (ttag y) = "number")
                                                    then ((ttag v) = "number" && v = x + y)
                                                    else (ttag v)  = "string")}
  */

/* builtin_OpAdd       :: ({x:number | true}, {y:number | true})  => {v:number | v = x + y}              */

// The following causes problems with equality. Can't "prove" 0 == (0 + 1) as
// the RHS has type {num | v = 0 + 1} + string. The crucial fact is buried under
// the sum -- the `top-level` refinement is `top` which is useless.

/* builtin_OpAdd       :: (x:number + string, y:number + string) =>
                              {number | ((ttag x) = "number" && (ttag y) = "number" && v = x + y) } +
                              {string | ((ttag x) = "string" || (ttag y) = "string") }

  */

/*@ extern builtin_OpSub       :: ({x:number | true}, {y:number | true})  => {v:number | v = x - y}              */
/*@ extern builtin_OpMul       :: (number,  number)  => number                                                   */
/*@ extern builtin_OpDiv       :: (number,  number)  => number                                                   */
/*@ extern builtin_OpMod       :: (number,  number)  => number                                                   */
/*@ extern builtin_PrefixMinus :: ({x:number  | true}) => {v:number  | v = (0 - x)}                              */
/*@ extern builtin_PrefixLNot  :: ({x:boolean | true}) => {v:boolean | ((Prop v) <=> not (Prop x))}              */

//Changing temprorarily until strings are supported
/* extern builtin_PrefixTypeof:: forall A. (A) => string                                                         */

//XXX: Is there an issue with keeping this with a capital P???
/*@ measure Prop        :: (boolean) => bool                              */

/*************************************************************************/
/************** Run-Time Tags ********************************************/
/*************************************************************************/

/*@ measure ttag :: forall A. (A) => string                               */

/*@ extern builtin_PrefixTypeof:: forall A. (x:A) => {v:string | (ttag x) = v }  */

/*@ invariant {v:undefined | ttag(v) = "undefined"} */
/*@ invariant {v:null      | ttag(v) = "null"     } */  //TODO: this is not very precise
/*@ invariant {v:boolean   | ttag(v) = "boolean"  } */
/*@ invariant {v:number    | ttag(v) = "number"   } */
/*@ invariant {v:string    | ttag(v) = "string"   } */
/*@ invariant {v:object    | ttag(v) = "object"   } */

/*************************************************************************/
/************** Pre-Loaded Qualifiers ************************************/
/*************************************************************************/

/*@ qualif Bot(v:a)       : 0 = 1                               */
/*@ qualif Bot(v:obj)     : 0 = 1                               */
/*@ qualif Bot(v:bool)    : 0 = 1                               */
/*@ qualif Bot(v:number)     : 0 = 1                            */
/*@ qualif CmpZ(v:number)    : v < 0                            */
/*@ qualif CmpZ(v:number)    : v <= 0                           */
/*@ qualif CmpZ(v:number)    : v >  0                           */
/*@ qualif CmpZ(v:number)    : v >= 0                           */
/*@ qualif CmpZ(v:number)    : v =  0                           */
/*@ qualif CmpZ(v:number)    : v != 0                           */

/*@ qualif Cmp(v:number, x:number)   : v <  x                   */
/*@ qualif Cmp(v:number, x:number)   : v <= x                   */
/*@ qualif Cmp(v:number, x:number)   : v >  x                   */
/*@ qualif Cmp(v:number, x:number)   : v >= x                   */

/*@ qualif Cmp(v:a,x:a)   : v =  x                              */
/*@ qualif Cmp(v:a,x:a)   : v != x                              */
/*@ qualif One(v:number)     : v = 1                            */
/*@ qualif True(v:bool)   : (? v)                               */
/*@ qualif False(v:bool)  : not (? v)                           */
/*@ qualif True1(v:Bool)  : (Prop v)                            */
/*@ qualif False1(v:Bool) : not (Prop v)                        */

// Somewhat more controversial qualifiers (i.e. "expensive"...)

/* qualif Add(v:number,x:number,y:number): v = x + y           */
/* qualif Sub(v:number,x:number,y:number): v = x - y           */

/*@ extern top_level :: () => void */
<commit_msg>Adding string properties in prelude<commit_after>/*@ extern crash :: forall A.() => A */

/*@ extern assume :: (boolean) => void */

/*@ extern assert :: ({x:boolean|(Prop x)}) => void */

/*@ extern requires :: (boolean) => void */

/*@ extern ensures :: (boolean) => void */

/*@ extern random :: () => number */

/*@ extern pos    :: () => {v:number | v > 0} */

/*************************************************************************/
/*********************** Temporary tag maps ******************************/
/*************************************************************************/
// From:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
//
// Undefined                                                              "undefined"
// Null                                                                   "object"
// Boolean                                                                "boolean"
// Number                                                                 "number"
// String                                                                 "string"
// Host object (provided by the JS environment)  Implementation-dependent
// Function object (implements [[Call]] in ECMA-262 terms)                "function"
// E4X XML object                                                         "xml"
// E4X XMLList object                                                     "xml"
// Any other object                                                       "object"
//
// For Null
// typeof null === 'object'; // This stands since the beginning of JavaScript

/*************************************************************************/
/***************** Types for list Operators ******************************/
/*************************************************************************/

/*@ type list[A]  {  data : A, next : list[A] + null } */

/*@ measure len :: forall A. (list [A]) => number                                                 */

/*@ extern cons  :: forall A. (A, xs:list[A] + null) => {list[A] | (len v) = 1 + (len xs)}               */
/*@ extern nil   :: () => { null | (len v) = 0}                                                           */
/*@ extern head  :: forall A. (xs:list[A]) => A                                                         */
/*@ extern tail  :: forall A. (xs:list [A]) => list [A] + null                                           */
/*@ extern nth   :: forall A. (xs:list [A], {i:number| ((0 <= i) && i < (len xs))}) => A                 */
/*@ extern empty :: forall A. (xango: list[A] + null ) =>
                        {v: boolean | (((Prop v) <=> len(xango) = 0) && ((Prop v) <=> ttag(xango) = "null"))}                      */
/*@ extern emptyPoly :: forall A. (x:A) => {v: boolean | ((Prop v) <=> ((ttag x) = "null"))}             */

/*@ extern length   :: forall A. (xs:list[A] + null) => {v:number | ((v >= 0) && v = (len xs))}         */
/*@ extern safehead :: forall A. (list[A]) => A                                     */
/*@ extern safetail :: forall A. (xs:list[A]) => {v:list[A] + null | (len v) = (len xs) - 1} */

/*@ extern Array    :: (n : { v: number | 0 <= v } ) => { v: [ undefined ] | (len v) = n }               */

/*************************************************************************/
/************************* Type Conversions ******************************/
/*************************************************************************/
/*@ extern sstring  :: forall A. (x: A) => string                               */

/*************************************************************************/
/************** Types for Builtin Operators ******************************/
/*************************************************************************/

/*@ extern builtin_BIBracketRef     :: forall A. (arr:[A], {idx:number | (0 <= idx && idx < (len arr))}) => A           */
/*@ extern builtin_BIBracketAssign  :: forall A. (arr:[A], {idx:number | (0 <= idx && idx < (len arr))}, val:A) => void */
/*@ extern builtin_BIArrayLit       :: forall A. (A) => {v:[A] | (len v) = builtin_BINumArgs}                           */
/*@ extern builtin_BIUndefined      :: forall A. {A | false}                                                            */

/*@ extern builtin_OpLT        :: ({x:number|true}, {y:number|true}) => {v:boolean | ((Prop v) <=> (x <  y)) }   */
/*@ extern builtin_OpLEq       :: ({x:number|true}, {y:number|true}) => {v:boolean | ((Prop v) <=> (x <= y)) }   */
/*@ extern builtin_OpGT        :: ({x:number|true}, {y:number|true}) => {v:boolean | ((Prop v) <=> (x >  y)) }   */
/*@ extern builtin_OpGEq       :: ({x:number|true}, {y:number|true}) => {v:boolean | ((Prop v) <=> (x >= y)) }   */

//PV: @==@ and @===@ could be handled more precisely
/*@ extern builtin_OpEq        :: forall A.   (x:A, y:A) => {v:boolean | ((Prop v) <=> (x = y)) }  */
/*@ extern builtin_OpSEq       :: forall A B. (x:A, y:B) => {v:boolean | ((Prop v) <=> (x = y)) }  */
/*@ extern builtin_OpNEq       :: forall A B. (x:A, y:B) => {v:boolean | ((Prop v) <=> (x != y)) } */

/*@ extern builtin_OpLAnd      :: ({x:top|true}, {y:top|true}) => {v:boolean | true}                             */
/*  builtin_OpLAnd      :: ({x:top|true}, {y:top|true}) =>
                            {v:boolean | ((Prop v) <=> (if (falsy x) then (v = y) else (v = x)))}         */

/*@ extern builtin_OpLOr       :: ({x:boolean|true}, {y:boolean|true}) =>
                            {v:boolean | ((Prop v) <=> ((Prop x) || (Prop y)))}                           */

// XXX: Will eventually switch to truthy and falsy:
/*  builtin_OpLOr       :: (x:top, y:top) =>
      { top | ((Prop v) <=> (if (falsy x) then (v = y) else (v = x) ))}           */

/*@ extern builtin_OpAdd :: /\ (x:number, y:number) => {number | v = x + y}
                     /\ (x:number, y:string) => string
                     /\ (x:string, y:number) => string
                     /\ (x:string, y:string) => string
  */

/* builtin_OpAdd      :: (x:number + string, y:number + string) =>
                              {v:number + string | (if ((ttag x) = "number" && (ttag y) = "number")
                                                    then ((ttag v) = "number" && v = x + y)
                                                    else (ttag v)  = "string")}
  */

/* builtin_OpAdd       :: ({x:number | true}, {y:number | true})  => {v:number | v = x + y}              */

// The following causes problems with equality. Can't "prove" 0 == (0 + 1) as
// the RHS has type {num | v = 0 + 1} + string. The crucial fact is buried under
// the sum -- the `top-level` refinement is `top` which is useless.

/* builtin_OpAdd       :: (x:number + string, y:number + string) =>
                              {number | ((ttag x) = "number" && (ttag y) = "number" && v = x + y) } +
                              {string | ((ttag x) = "string" || (ttag y) = "string") }

  */

/*@ extern builtin_OpSub       :: ({x:number | true}, {y:number | true})  => {v:number | v = x - y}              */
/*@ extern builtin_OpMul       :: (number,  number)  => number                                                   */
/*@ extern builtin_OpDiv       :: (number,  number)  => number                                                   */
/*@ extern builtin_OpMod       :: (number,  number)  => number                                                   */
/*@ extern builtin_PrefixMinus :: ({x:number  | true}) => {v:number  | v = (0 - x)}                              */
/*@ extern builtin_PrefixLNot  :: ({x:boolean | true}) => {v:boolean | ((Prop v) <=> not (Prop x))}              */

//Changing temprorarily until strings are supported
/* extern builtin_PrefixTypeof:: forall A. (A) => string                                                         */

//XXX: Is there an issue with keeping this with a capital P???
/*@ measure Prop        :: (boolean) => bool                              */

/*************************************************************************/
/************** Ambient Objects ******************************************/
/*************************************************************************/
// Taken from here:
// http://typescript.codeplex.com/SourceControl/latest#typings/lib.d.ts

/*@ extern Number :: (x: top) => number */

/*@ extern Math :: {
    E       : number,
    LN10    : number,
    LN2     : number,
    LOG2E   : number,
    LOG10E  : number,
    PI      : number,
    SQRT1_2 : number,
    SQRT2   : number,
    abs     : (x: number) => number,
    acos    : (x: number) => number,
    asin    : (x: number) => number,
    atan    : (x: number) => number,
    atan2   : (y: number, x: number) =>  number,
    ceil    : (x: number) => number,
    cos     : (x: number) => number,
    exp     : (x: number) => number,
    floor   : (x: number) => number,
    log     : (x: number) => number,
    max     : (values: [number]) => number,
    min     : (values: [number]) => number,
    pow     : (x: number, y: number) => number,
    random  : () =>  number,
    round   : (x: number) => number,
    sin     : (x: number) => number,
    sqrt    : (x: number) => number,
    tan     : (x: number) => number
} */

/*@ extern String     :: {
    toString          : () => string,
    charAt            : (pos: number) => string,
    charCodeAt        : (index: number) => number,
    concat            : (strings: [string]) => string,
    indexOf           : (searchString: string, position: number) => number,
    lastIndexOf       : (searchString: string, position: number) => number,
    localeCompare     : (that: string) => number,
    match             : (regexp: string) => [string],
    replace           : (searchValue: string, replaceValue: string) => string,
    search            : (regexp: string) => number,
    slice             : (start: number, end: number) => string,
    split             : (separator: string, limit: number) => [string],
    substring         : (start: number, end: number) => string,
    toLowerCase       : () => string,
    toLocaleLowerCase : () => string,
    toUpperCase       : () => string,
    toLocaleUpperCase : () => string,
    trim              : () => string,

    length: number,

    substr            : (from: number, length: number) => string
} */

// Ideally we'd like to use this version:
/*  extern String     : {
    toString          : () => string,
    charAt            : (pos: number) => string,
    charCodeAt        : (index: number) => number,
    concat            : (...strings: [string]) => string,
    indexOf           : (searchString: string, position?: number) => number,
    lastIndexOf       : (searchString: string, position?: number) => number,
    localeCompare     : (that: string) => number,
    match             : (regexp: string) => [string],
    match             : (regexp: RegExp) => [string],
    replace           : (searchValue: string, replaceValue: string) => string,
    replace           : (searchValue: string, replaceValue: (substring: string, ...args: [top]) => string) => string,
    replace           : (searchValue: RegExp, replaceValue: string) => string,
    replace           : (searchValue: RegExp, replaceValue: (substring: string, ...args: [top]) => string) => string,
    search            : (regexp: string) => number,
    search            : (regexp: RegExp) => number,
    slice             : (start: number, end?: number) => string,
    split             : (separator: string, limit?: number) => [string],
    split             : (separator: RegExp, limit?: number) => [string],
    substring         : (start: number, end?: number) => string,
    toLowerCase       : () => string,
    toLocaleLowerCase : () => string,
    toUpperCase       : () => string,
    toLocaleUpperCase : () => string,
    trim              : () => string,

    length: number,

    substr            : (from: number, length?: number) => string
} */

/*************************************************************************/
/************** Run-Time Tags ********************************************/
/*************************************************************************/

/*@ measure ttag :: forall A. (A) => string                               */

/*@ extern builtin_PrefixTypeof:: forall A. (x:A) => {v:string | (ttag x) = v }  */

/*@ invariant {v:undefined | ttag(v) = "undefined"} */
/*@ invariant {v:null      | ttag(v) = "null"     } */  //TODO: this is not very precise
/*@ invariant {v:boolean   | ttag(v) = "boolean"  } */
/*@ invariant {v:number    | ttag(v) = "number"   } */
/*@ invariant {v:string    | ttag(v) = "string"   } */
/*@ invariant {v:object    | ttag(v) = "object"   } */

/*************************************************************************/
/************** Pre-Loaded Qualifiers ************************************/
/*************************************************************************/

/*@ qualif Bot(v:a)       : 0 = 1                               */
/*@ qualif Bot(v:obj)     : 0 = 1                               */
/*@ qualif Bot(v:bool)    : 0 = 1                               */
/*@ qualif Bot(v:number)     : 0 = 1                            */
/*@ qualif CmpZ(v:number)    : v < 0                            */
/*@ qualif CmpZ(v:number)    : v <= 0                           */
/*@ qualif CmpZ(v:number)    : v >  0                           */
/*@ qualif CmpZ(v:number)    : v >= 0                           */
/*@ qualif CmpZ(v:number)    : v =  0                           */
/*@ qualif CmpZ(v:number)    : v != 0                           */

/*@ qualif Cmp(v:number, x:number)   : v <  x                   */
/*@ qualif Cmp(v:number, x:number)   : v <= x                   */
/*@ qualif Cmp(v:number, x:number)   : v >  x                   */
/*@ qualif Cmp(v:number, x:number)   : v >= x                   */

/*@ qualif Cmp(v:a,x:a)   : v =  x                              */
/*@ qualif Cmp(v:a,x:a)   : v != x                              */
/*@ qualif One(v:number)     : v = 1                            */
/*@ qualif True(v:bool)   : (? v)                               */
/*@ qualif False(v:bool)  : not (? v)                           */
/*@ qualif True1(v:Bool)  : (Prop v)                            */
/*@ qualif False1(v:Bool) : not (Prop v)                        */

// Somewhat more controversial qualifiers (i.e. "expensive"...)

/* qualif Add(v:number,x:number,y:number): v = x + y           */
/* qualif Sub(v:number,x:number,y:number): v = x - y           */

/*@ extern top_level :: () => void */
<|endoftext|>


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

var palette = new Rickshaw.Color.Palette({scheme: "classic9"});
var sensorType1 = "PIR";
var sensorType2 = "ULTRASONIC";
var sensorType1Graph;
var sensorType2Graph;

function drawGraph_senseme(from, to)
{
    var devices = $("#details").data("devices");
    var tzOffset = new Date().getTimezoneOffset() * 60;
    var chartWrapperElmId = "#chartDivSensorType1";
    var graphWidth = $(chartWrapperElmId).width() - 50;
    var graphConfigSensorType1 = getGraphConfig("chartSensorType1");
    var graphConfigSensorType2 = getGraphConfig("chartSensorType2");

    function getGraphConfig(placeHolder) {
        return {
            element: document.getElementById(placeHolder),
            width: graphWidth,
            height: 400,
            strokeWidth: 2,
            renderer: 'line',
            interpolation: "linear",
            unstack: true,
            stack: false,
            xScale: d3.time.scale(),
            padding: {top: 0.2, left: 0.02, right: 0.02, bottom: 0.2},
            series: []
        }
    };

    if (devices) {
        for (var i = 0; i < devices.length; i++) {
            graphConfigSensorType1['series'].push(
                {
                    'color': palette.color(),
                    'data': [{
                        x: parseInt(new Date().getTime() / 1000),
                        y: 0
                    }],
                    'name': devices[i].name
                });

            graphConfigSensorType2['series'].push(
                {
                    'color': palette.color(),
                    'data': [{
                        x: parseInt(new Date().getTime() / 1000),
                        y: 0
                    }],
                    'name': devices[i].name
                });
        }
    } else {
        graphConfigSensorType1['series'].push(
            {
                'color': palette.color(),
                'data': [{
                    x: parseInt(new Date().getTime() / 1000),
                    y: 0
                }],
                'name': $("#details").data("devicename")
            });
        graphConfigSensorType2['series'].push(
            {
                'color': palette.color(),
                'data': [{
                    x: parseInt(new Date().getTime() / 1000),
                    y: 0
                }],
                'name': $("#details").data("devicename")
            });
    }

    sensorType1Graph = new Rickshaw.Graph(graphConfigSensorType1);
    sensorType2Graph = new Rickshaw.Graph(graphConfigSensorType2);
    drawGraph(sensorType1Graph, "sensorType1yAxis", "sensorType1Slider", "sensorType1Legend", sensorType1
        , graphConfigSensorType1, "chartSensorType1");
    drawGraph(sensorType2Graph, "sensorType2yAxis", "sensorType2Slider", "sensorType2Legend", sensorType2
        , graphConfigSensorType2, "chartSensorType2");

    function drawGraph(graph, yAxis, slider, legend, sensorType, graphConfig, chart) {
        graph.render();
        var xAxis = new Rickshaw.Graph.Axis.Time({
            graph: graph
        });
        xAxis.render();
        var yAxis = new Rickshaw.Graph.Axis.Y({
            graph: graph,
            orientation: 'left',
            element: document.getElementById(yAxis),
            width: 40,
            height: 410
        });
        yAxis.render();
        var slider = new Rickshaw.Graph.RangeSlider.Preview({
            graph: graph,
            element: document.getElementById(slider)
        });
        var legend = new Rickshaw.Graph.Legend({
            graph: graph,
            element: document.getElementById(legend)
        });
        var hoverDetail = new Rickshaw.Graph.HoverDetail({
            graph: graph,
            formatter: function (series, x, y) {
                var date = '' +
                    moment.unix((x + tzOffset) * 1000).format('Do MMM YYYY h:mm:ss a') + '';
                var swatch = '';
                return swatch + series.name + ": " + parseInt(y) + '
' + date;
            }
        });
        var shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
            graph: graph,
            legend: legend
        });
        var order = new Rickshaw.Graph.Behavior.Series.Order({
            graph: graph,
            legend: legend
        });
        var highlighter = new Rickshaw.Graph.Behavior.Series.Highlight({
            graph: graph,
            legend: legend
        });
        var deviceIndex = 0;
        if (devices) {
            getData(chat, deviceIndex, sensorType);
        } else {
            var backendApiUrl = $("#" + chart + "").data("backend-api-url") + "?from=" + from + "&to=" + to
                + "&sensorType=" + sensorType;
            var successCallback = function (data) {
                if (data) {
                    drawLineGraph(JSON.parse(data), sensorType, deviceIndex, graphConfig, graph);
                }
            };
            invokerUtil.get(backendApiUrl, successCallback, function (message) {
                console.log(message);
            });
        }
    }

    function getData(placeHolder, deviceIndex, sensorType, graphConfig, graph) {
        if (deviceIndex >= devices.length) {
            return;
        }
        var backendApiUrl = $("#" + placeHolder + "").data("backend-api-url") + devices[deviceIndex].deviceIdentifier
            + "?from=" + from + "&to=" + to + "&sensorType=" + sensorType;
        var successCallback = function (data) {
            if (data) {
                drawLineGraph(JSON.parse(data), sensorType, deviceIndex, graphConfig, graph);
            }
            deviceIndex++;
            getData(placeHolder, deviceIndex, sensorType);
        };
        invokerUtil.get(backendApiUrl, successCallback, function (message) {
            console.log(message);
            deviceIndex++;
            getData(placeHolder, deviceIndex, sensorType);
        });
    }

    function drawLineGraph(data, sensorType, deviceIndex, graphConfig, graph) {
        if (data.length === 0 || data.length === undefined) {
            return;
        }
        var chartData = [];
        for (var i = 0; i < data.length; i++) {
            chartData.push(
                {
                    x: parseInt(data[i].values.meta_time) - tzOffset,
                    y: parseInt(data[i].values[sensorType])
                }
            );
        }
        graphConfig.series[deviceIndex].data = chartData;
        graph.update();
    }
}
<commit_msg>Analytics improvements<commit_after>/*
 * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

var palette = new Rickshaw.Color.Palette({scheme: "classic9"});
var sensorType1 = "PIR";
var sensorType2 = "ULTRASONIC";
var sensorType1Graph;
var sensorType2Graph;

function drawGraph_senseme(from, to)
{
    var devices = $("#details").data("devices");
    var tzOffset = new Date().getTimezoneOffset() * 60;
    var chartWrapperElmId = "#chartDivSensorType1";
    var graphWidth = $(chartWrapperElmId).width() - 50;
    var graphConfigSensorType1 = getGraphConfig("chartSensorType1");
    var graphConfigSensorType2 = getGraphConfig("chartSensorType2");

    function getGraphConfig(placeHolder) {
        return {
            element: document.getElementById(placeHolder),
            width: graphWidth,
            height: 400,
            strokeWidth: 2,
            renderer: 'line',
            interpolation: "linear",
            unstack: true,
            stack: false,
            xScale: d3.time.scale(),
            padding: {top: 0.2, left: 0.02, right: 0.02, bottom: 0.2},
            series: []
        }
    };

    if (devices) {
        for (var i = 0; i < devices.length; i++) {
            graphConfigSensorType1['series'].push(
                {
                    'color': palette.color(),
                    'data': [{
                        x: parseInt(new Date().getTime() / 1000),
                        y: 0
                    }],
                    'name': devices[i].name
                });

            graphConfigSensorType2['series'].push(
                {
                    'color': palette.color(),
                    'data': [{
                        x: parseInt(new Date().getTime() / 1000),
                        y: 0
                    }],
                    'name': devices[i].name
                });
        }
    } else {
        graphConfigSensorType1['series'].push(
            {
                'color': palette.color(),
                'data': [{
                    x: parseInt(new Date().getTime() / 1000),
                    y: 0
                }],
                'name': $("#details").data("devicename")
            });
        graphConfigSensorType2['series'].push(
            {
                'color': palette.color(),
                'data': [{
                    x: parseInt(new Date().getTime() / 1000),
                    y: 0
                }],
                'name': $("#details").data("devicename")
            });
    }

    sensorType1Graph = new Rickshaw.Graph(graphConfigSensorType1);
    sensorType2Graph = new Rickshaw.Graph(graphConfigSensorType2);
    drawGraph(sensorType1Graph, "sensorType1yAxis", "sensorType1Slider", "sensorType1Legend", sensorType1
        , graphConfigSensorType1, "chartSensorType1");
    drawGraph(sensorType2Graph, "sensorType2yAxis", "sensorType2Slider", "sensorType2Legend", sensorType2
        , graphConfigSensorType2, "chartSensorType2");

    function drawGraph(graph, yAxis, slider, legend, sensorType, graphConfig, chart) {
        graph.render();
        var xAxis = new Rickshaw.Graph.Axis.Time({
            graph: graph
        });
        xAxis.render();
        var yAxis = new Rickshaw.Graph.Axis.Y({
            graph: graph,
            orientation: 'left',
            element: document.getElementById(yAxis),
            width: 40,
            height: 410
        });
        yAxis.render();
        var slider = new Rickshaw.Graph.RangeSlider.Preview({
            graph: graph,
            element: document.getElementById(slider)
        });
        var legend = new Rickshaw.Graph.Legend({
            graph: graph,
            element: document.getElementById(legend)
        });
        var hoverDetail = new Rickshaw.Graph.HoverDetail({
            graph: graph,
            formatter: function (series, x, y) {
                var date = '' +
                    moment.unix(x + tzOffset).format('Do MMM YYYY h:mm:ss a') + '';
                var swatch = '';
                return swatch + series.name + ": " + parseInt(y) + '
' + date;
            }
        });
        var shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
            graph: graph,
            legend: legend
        });
        var order = new Rickshaw.Graph.Behavior.Series.Order({
            graph: graph,
            legend: legend
        });
        var highlighter = new Rickshaw.Graph.Behavior.Series.Highlight({
            graph: graph,
            legend: legend
        });
        var deviceIndex = 0;
        if (devices) {
            getData(chat, deviceIndex, sensorType);
        } else {
            var backendApiUrl = $("#" + chart + "").data("backend-api-url") + "?from=" + from + "&to=" + to
                + "&sensorType=" + sensorType;
            var successCallback = function (data) {
                if (data) {
                    drawLineGraph(JSON.parse(data), sensorType, deviceIndex, graphConfig, graph);
                }
            };
            invokerUtil.get(backendApiUrl, successCallback, function (message) {
                console.log(message);
            });
        }
    }

    function getData(placeHolder, deviceIndex, sensorType, graphConfig, graph) {
        if (deviceIndex >= devices.length) {
            return;
        }
        var backendApiUrl = $("#" + placeHolder + "").data("backend-api-url") + devices[deviceIndex].deviceIdentifier
            + "?from=" + from + "&to=" + to + "&sensorType=" + sensorType;
        var successCallback = function (data) {
            if (data) {
                drawLineGraph(JSON.parse(data), sensorType, deviceIndex, graphConfig, graph);
            }
            deviceIndex++;
            getData(placeHolder, deviceIndex, sensorType);
        };
        invokerUtil.get(backendApiUrl, successCallback, function (message) {
            console.log(message);
            deviceIndex++;
            getData(placeHolder, deviceIndex, sensorType);
        });
    }

    function drawLineGraph(data, sensorType, deviceIndex, graphConfig, graph) {
        if (data.length === 0 || data.length === undefined) {
            return;
        }
        var chartData = [];
        for (var i = 0; i < data.length; i++) {
            chartData.push(
                {
                    x: parseInt(data[i].values.meta_time) - tzOffset,
                    y: parseInt(sensorType)
                }
            );
        }
        graphConfig.series[deviceIndex].data = chartData;
        graph.update();
    }
}
<|endoftext|>


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

var valid = spdx.valid.bind(spdx);

var lastResorts = [
  ['APACHE', 'Apache-2.0'],
  ['AFFERO', 'AGPL-3.0'],
  ['WTF', 'WTFPL'],
  ['GPL', 'GPL-3.0'],
  ['MIT', 'MIT'],
  ['Affero', 'AGPL-3.0'],
  ['AGPL', 'AGPL-3.0'],
  ['ZLIB', 'Zlib'],
  ['3-CLAUSE', 'BSD-3-Clause'],
  ['2-CLAUSE', 'BSD-2-Clause'],
  ['3 CLAUSE', 'BSD-3-Clause'],
  ['2 CLAUSE', 'BSD-2-Clause'],
  ['Unli', 'Unlicense']
];

module.exports = function(identifier) {
  var upperCased = identifier.toUpperCase();
  if (valid(upperCased)) {
    return upperCased;
  }
  if (valid(identifier.trim())) {
    return identifier.trim();
  }
  if (/\s*(\d)/.test(identifier)) {
    var hyphenated = identifier.replace(/\s*(\d)/, '-$1');
    if (valid(hyphenated)) {
      return hyphenated;
    }
  }
  if (/\s*V\s*\d/.test(identifier)) {
    var withHyphen = identifier.replace(/\s*V\s*(\d)/, '-$1');
    if (valid(withHyphen)) {
      return withHyphen;
    }
    var dotZero = withHyphen.replace(/(\d)$/, '$1.0');
    if (valid(dotZero)) {
      return dotZero;
    }
  }
  for (var i = 0; i < lastResorts.length; i++) {
    var pair = lastResorts[i];
    if (upperCased.indexOf(pair[0]) > -1) {
      return pair[1];
    }
  }
  return null;
};
<commit_msg>refactor "transforms"<commit_after>var spdx = require('spdx');

var valid = spdx.valid.bind(spdx);

var transforms = [
  function(argument) {
    return argument.toUpperCase();
  },
  function(argument) {
    return argument.trim();
  },
  function(argument) {
    return argument.replace(/\s+/g, '');
  },
  function(argument) {
    return argument.replace(/\s*(\d)/, '-$1');
  },
  function(argument) {
    return argument.replace(/\s*(\d)/, '-$1');
  },
  function(argument) {
    return argument.replace(/\s*V\s*(\d)/, '-$1');
  },
  function(argument) {
    return argument
      .replace(/\s*V\s*(\d)/, '-$1')
      .replace(/(\d)$/, '$1.0');
  }
];

var lastResorts = [
  ['APACHE', 'Apache-2.0'],
  ['AFFERO', 'AGPL-3.0'],
  ['WTF', 'WTFPL'],
  ['GPL', 'GPL-3.0'],
  ['MIT', 'MIT'],
  ['Affero', 'AGPL-3.0'],
  ['AGPL', 'AGPL-3.0'],
  ['ZLIB', 'Zlib'],
  ['3-CLAUSE', 'BSD-3-Clause'],
  ['2-CLAUSE', 'BSD-2-Clause'],
  ['3 CLAUSE', 'BSD-3-Clause'],
  ['2 CLAUSE', 'BSD-2-Clause'],
  ['Unli', 'Unlicense']
];

var SUBSTRING = 0;
var IDENTIFER = 1;

module.exports = function(identifier) {
  var i;

  for (i = 0; i < transforms.length; i++) {
    var transformed = transforms[i](identifier);
    if (valid(transformed)) {
      return transformed;
    }
  }

  var upperCased = identifier.toUpperCase();
  for (i = 0; i < lastResorts.length; i++) {
    var lastResort = lastResorts[i];
    if (upperCased.indexOf(lastResort[SUBSTRING]) > -1) {
      return lastResort[IDENTIFER];
    }
  }

  return null;
};
<|endoftext|>


<commit_before>import d3 from 'd3';
import vg from 'vega';
import { isArray, isString, read } from 'datalib';
import axisTemplate from './axis.json';
import { getElementSize } from '..';

let getNestedRec = function (spec, parts) {
  if (spec === undefined || parts.length === 0) {
    return spec;
  }
  return getNestedRec(spec[parts[0]], parts.slice(1));
};

let getNested = function (spec, name) {
  return getNestedRec(spec, name.split('.'));
};

let setNestedRec = function (spec, parts, value) {
  if (parts.length === 1) {
    spec[parts[0]] = value;
    return;
  }
  if (spec[parts[0]] === undefined) {
    spec[parts[0]] = {};
  }
  setNestedRec(spec[parts[0]], parts.slice(1), value);
};

let setNested = function (spec, name, value) {
  setNestedRec(spec, name.split('.'), value);
};

let templateFunctions = {
  defaults: function (args, options, scope) {
    for (let index = 0; index < args[0].length; index += 1) {
      let name = transform(args[0][index][0], options, scope);
      let value = getNested(scope, name);
      if (value === undefined) {
        value = getNested(options, name);
      }
      if (value === undefined) {
        value = transform(args[0][index][1], options, scope);
        setNested(scope, name, value);
      }
    }
    return transform(args[1], options, scope);
  },

  let: function (args, options, scope) {
    for (let index = 0; index < args[0].length; index += 1) {
      let name = transform(args[0][index][0], options, scope);
      let value = transform(args[0][index][1], options, scope);
      setNested(scope, name, value);
    }
    return transform(args[1], options, scope);
  },

  get: function (args, options, scope) {
    let name = transform(args[0], options, scope);
    let value = getNested(scope, name);
    if (value === undefined) {
      value = getNested(options, name);
    }
    if (value === undefined) {
      value = transform(args[1], options, scope);
    }
    if (value === undefined) {
      value = null;
    }
    return value;
  },

  map: function (args, options, scope) {
    let transformed = [];
    let elements = transform(args[0], options, scope);

    if (!Array.isArray(elements)) {
      return transformed;
    }

    for (let elementIndex = 0; elementIndex < elements.length; elementIndex += 1) {
      scope[args[1]] = elements[elementIndex];
      scope.index = elementIndex;
      for (let itemIndex = 2; itemIndex < args.length; itemIndex += 1) {
        let element = transform(args[itemIndex], options, scope);
        if (element !== null) {
          transformed.push(element);
        }
      }
    }
    return transformed;
  },

  if: function (args, options, scope) {
    let condition = transform(args[0], options, scope);
    if (condition) {
      return transform(args[1], options, scope);
    }
    return transform(args[2], options, scope);
  },

  eq: function (args, options, scope) {
    let a = transform(args[0], options, scope);
    let b = transform(args[1], options, scope);
    return (a === b);
  },

  lt: function (args, options, scope) {
    let a = transform(args[0], options, scope);
    let b = transform(args[1], options, scope);
    return (a < b);
  },

  gt: function (args, options, scope) {
    let a = transform(args[0], options, scope);
    let b = transform(args[1], options, scope);
    return (a > b);
  },

  length: function (args, options, scope) {
    let a = transform(args[0], options, scope);
    if (isArray(a) || isString(a)) {
      return a.length;
    }
    return 0;
  },

  and: function (args, options, scope) {
    let arr = transform(args, options, scope);
    for (let i = 0; i < arr.length; i += 1) {
      if (!arr[i]) {
        return false;
      }
    }
    return true;
  },

  or: function (args, options, scope) {
    let arr = transform(args, options, scope);
    for (let i = 0; i < arr.length; i += 1) {
      if (arr[i]) {
        return true;
      }
    }
    return false;
  },

  mult: function (args, options, scope) {
    let arr = transform(args, options, scope);
    let value = 1;
    for (let i = 0; i < arr.length; i += 1) {
      value *= arr[i];
    }
    return value;
  },

  add: function (args, options, scope) {
    let arr = transform(args, options, scope);
    let value = 0;
    for (let i = 0; i < arr.length; i += 1) {
      value += arr[i];
    }
    return value;
  },

  join: function (args, options, scope) {
    let result = '';
    let sep = transform(args[0], options, scope);
    let arr = transform(args[1], options, scope);
    if (!Array.isArray(arr)) {
      return result;
    }
    for (let i = 0; i < arr.length; i += 1) {
      if (i > 0) {
        result += sep;
      }
      result += arr[i];
    }
    return result;
  },

  merge: function (args, options, scope) {
    let merged = transform(args[0], options, scope);
    for (let i = 1; i < args.length; i += 1) {
      merged = merge(merged, transform(args[i], options, scope));
    }
    return merged;
  },

  colorScale: function (args, options, scope) {
    let params = transform(args[0], options, scope);
    let name = params.name || 'color';
    if (!Array.isArray(params.values) ||
      params.values.length < 1 ||
      params.values[0][params.field] === undefined ||
      typeof params.values[0][params.field] === 'string') {
      return {
        name: name,
        type: 'ordinal',
        domain: {data: params.data, field: params.field},
        range: 'category10'
      };
    }
    return {
      name: name,
      type: 'linear',
      zero: false,
      domain: {data: params.data, field: params.field},
      range: ['#df2709', '#2709df']
    };
  },

  axis: function (args, options, scope) {
    let opt = transform(args[0], options, scope);
    if (opt.data && Array.isArray(opt.data) && opt.field) {
      if (!opt.data.__types__) {
        read(opt.data, {parse: 'auto'});
      }
      let type = opt.data.__types__[opt.field];
      if (type === 'string') {
        opt.formatType = 'string';
      } else if (type === 'date') {
        opt.type = opt.type || 'time';
        opt.formatType = 'time';
        opt.format = '%Y-%m-%d';
      } else {
        opt.formatType = 'number';
        opt.format = 's';
      }
    }
    return transform(axisTemplate, opt);
  },

  isStringField: function (args, options, scope) {
    let values = transform(args[0], options, scope);
    let field = transform(args[1], options, scope);

    if (!Array.isArray(values) ||
      values.length < 1 ||
      values[0][field] === undefined ||
      typeof values[0][field] === 'string') {
      return true;
    }
    return false;
  },

  orient: function (args, options, scope) {
    let dir = transform(args[0], options, scope);
    let obj = transform(args[1], options, scope);
    let transformed = {};
    let matching = {
      x: 'y',
      x2: 'y2',
      xc: 'yc',
      y: 'x',
      y2: 'x2',
      yc: 'xc',
      width: 'height',
      height: 'width'
    };
    if (dir === 'horizontal') {
      return obj;
    }
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        if (matching[key]) {
          transformed[matching[key]] = obj[key];
        } else {
          transformed[key] = obj[key];
        }
      }
    }
    return transformed;
  }
};

let transform = function (spec, options, scope) {
  options = options || {};
  scope = scope || {};

  if (Array.isArray(spec)) {
    if (spec.length > 0 && (typeof spec[0] === 'string') && spec[0].slice(0, 1) === '@') {
      return templateFunctions[spec[0].slice(1)](spec.slice(1), options, scope);
    }
    let transformed = [];
    for (let index = 0; index < spec.length; index += 1) {
      transformed.push(transform(spec[index], options, scope));
    }
    return transformed;
  }
  if (spec === null) {
    return spec;
  }
  if (spec instanceof Date) {
    return spec;
  }
  if (typeof spec === 'object') {
    let transformed = {};
    for (let key in spec) {
      if (spec.hasOwnProperty(key)) {
        transformed[key] = transform(spec[key], options, scope);
      }
    }
    return transformed;
  }
  return spec;
};

let isObjectLiteral = function (object) {
  return object && object.constructor && object.constructor.name === 'Object';
};

let isArrayLiteral = function (object) {
  return object && object.constructor && object.constructor.name === 'Array';
};

let extend = function (defaults, options) {
  if (options === undefined) {
    return defaults;
  }
  if (isObjectLiteral(defaults)) {
    let extended = {};
    for (let prop in defaults) {
      if (Object.prototype.hasOwnProperty.call(defaults, prop)) {
        extended[prop] = extend(defaults[prop], options[prop]);
      }
    }
    for (let prop in options) {
      if (!Object.prototype.hasOwnProperty.call(defaults, prop)) {
        extended[prop] = options[prop];
      }
    }
    return extended;
  }
  if (isArrayLiteral(defaults)) {
    let extended = [];
    for (let index = 0; index < defaults.length; index += 1) {
      extended.push(extend(defaults[index], options[index]));
    }
    if (isArrayLiteral(options)) {
      for (let index = defaults.length; index < options.length; index += 1) {
        extended.push(options[index]);
      }
    }
    return extended;
  }
  return options;
};

let merge = function (defaults, options) {
  if (options === undefined || options === null) {
    return defaults;
  }
  if (defaults === undefined || defaults === null) {
    return options;
  }
  if (isObjectLiteral(defaults)) {
    let extended = {};
    for (let prop in defaults) {
      if (Object.prototype.hasOwnProperty.call(defaults, prop)) {
        extended[prop] = merge(defaults[prop], options[prop]);
      }
    }
    for (let prop in options) {
      if (!Object.prototype.hasOwnProperty.call(extended, prop)) {
        extended[prop] = options[prop];
      }
    }
    return extended;
  }
  if (isArrayLiteral(defaults)) {
    let extended = [];
    for (let index = 0; index < defaults.length; index += 1) {
      extended.push(defaults[index]);
    }
    if (isArrayLiteral(options)) {
      for (let index = 0; index < options.length; index += 1) {
        extended.push(options[index]);
      }
    }
    return extended;
  }
  return defaults;
};

let parseChart = function (spec, element, options) {
  // Use element size to set size, unless size explicitly specified or
  // element size is zero.
  let el = d3.select(element)[0][0];
  let sizeOptions = {};

  const size = getElementSize(el);
  const elWidth = size.width;
  const elHeight = size.height;

  if (elWidth !== 0 && elHeight !== 0) {
    if (options.width === undefined) {
      sizeOptions.width = elWidth;
    }
    if (options.height === undefined) {
      sizeOptions.height = elHeight;
    }
  }
  let curOptions = extend(options, sizeOptions);

  // Options that go directly to Vega runtime
  let vegaOptions = {
    el: el,
    renderer: curOptions.renderer
  };

  let vegaSpec = transform(spec, curOptions);

  // Return a promise for the Vega chart object
  return new Promise(resolve => {
    vg.parse.spec(vegaSpec, chartObj => {
      let chart = chartObj(vegaOptions);
      chart.update();
      resolve(chart);
    });
  });
};

export default {
  transform,
  parseChart
};
<commit_msg>refactor: bring vega util function up to spec for d3 v4<commit_after>import { select } from 'd3-selection';
import vg from 'vega';
import { isArray, isString, read } from 'datalib';
import axisTemplate from './axis.json';
import { getElementSize } from '..';

let getNestedRec = function (spec, parts) {
  if (spec === undefined || parts.length === 0) {
    return spec;
  }
  return getNestedRec(spec[parts[0]], parts.slice(1));
};

let getNested = function (spec, name) {
  return getNestedRec(spec, name.split('.'));
};

let setNestedRec = function (spec, parts, value) {
  if (parts.length === 1) {
    spec[parts[0]] = value;
    return;
  }
  if (spec[parts[0]] === undefined) {
    spec[parts[0]] = {};
  }
  setNestedRec(spec[parts[0]], parts.slice(1), value);
};

let setNested = function (spec, name, value) {
  setNestedRec(spec, name.split('.'), value);
};

let templateFunctions = {
  defaults: function (args, options, scope) {
    for (let index = 0; index < args[0].length; index += 1) {
      let name = transform(args[0][index][0], options, scope);
      let value = getNested(scope, name);
      if (value === undefined) {
        value = getNested(options, name);
      }
      if (value === undefined) {
        value = transform(args[0][index][1], options, scope);
        setNested(scope, name, value);
      }
    }
    return transform(args[1], options, scope);
  },

  let: function (args, options, scope) {
    for (let index = 0; index < args[0].length; index += 1) {
      let name = transform(args[0][index][0], options, scope);
      let value = transform(args[0][index][1], options, scope);
      setNested(scope, name, value);
    }
    return transform(args[1], options, scope);
  },

  get: function (args, options, scope) {
    let name = transform(args[0], options, scope);
    let value = getNested(scope, name);
    if (value === undefined) {
      value = getNested(options, name);
    }
    if (value === undefined) {
      value = transform(args[1], options, scope);
    }
    if (value === undefined) {
      value = null;
    }
    return value;
  },

  map: function (args, options, scope) {
    let transformed = [];
    let elements = transform(args[0], options, scope);

    if (!Array.isArray(elements)) {
      return transformed;
    }

    for (let elementIndex = 0; elementIndex < elements.length; elementIndex += 1) {
      scope[args[1]] = elements[elementIndex];
      scope.index = elementIndex;
      for (let itemIndex = 2; itemIndex < args.length; itemIndex += 1) {
        let element = transform(args[itemIndex], options, scope);
        if (element !== null) {
          transformed.push(element);
        }
      }
    }
    return transformed;
  },

  if: function (args, options, scope) {
    let condition = transform(args[0], options, scope);
    if (condition) {
      return transform(args[1], options, scope);
    }
    return transform(args[2], options, scope);
  },

  eq: function (args, options, scope) {
    let a = transform(args[0], options, scope);
    let b = transform(args[1], options, scope);
    return (a === b);
  },

  lt: function (args, options, scope) {
    let a = transform(args[0], options, scope);
    let b = transform(args[1], options, scope);
    return (a < b);
  },

  gt: function (args, options, scope) {
    let a = transform(args[0], options, scope);
    let b = transform(args[1], options, scope);
    return (a > b);
  },

  length: function (args, options, scope) {
    let a = transform(args[0], options, scope);
    if (isArray(a) || isString(a)) {
      return a.length;
    }
    return 0;
  },

  and: function (args, options, scope) {
    let arr = transform(args, options, scope);
    for (let i = 0; i < arr.length; i += 1) {
      if (!arr[i]) {
        return false;
      }
    }
    return true;
  },

  or: function (args, options, scope) {
    let arr = transform(args, options, scope);
    for (let i = 0; i < arr.length; i += 1) {
      if (arr[i]) {
        return true;
      }
    }
    return false;
  },

  mult: function (args, options, scope) {
    let arr = transform(args, options, scope);
    let value = 1;
    for (let i = 0; i < arr.length; i += 1) {
      value *= arr[i];
    }
    return value;
  },

  add: function (args, options, scope) {
    let arr = transform(args, options, scope);
    let value = 0;
    for (let i = 0; i < arr.length; i += 1) {
      value += arr[i];
    }
    return value;
  },

  join: function (args, options, scope) {
    let result = '';
    let sep = transform(args[0], options, scope);
    let arr = transform(args[1], options, scope);
    if (!Array.isArray(arr)) {
      return result;
    }
    for (let i = 0; i < arr.length; i += 1) {
      if (i > 0) {
        result += sep;
      }
      result += arr[i];
    }
    return result;
  },

  merge: function (args, options, scope) {
    let merged = transform(args[0], options, scope);
    for (let i = 1; i < args.length; i += 1) {
      merged = merge(merged, transform(args[i], options, scope));
    }
    return merged;
  },

  colorScale: function (args, options, scope) {
    let params = transform(args[0], options, scope);
    let name = params.name || 'color';
    if (!Array.isArray(params.values) ||
      params.values.length < 1 ||
      params.values[0][params.field] === undefined ||
      typeof params.values[0][params.field] === 'string') {
      return {
        name: name,
        type: 'ordinal',
        domain: {data: params.data, field: params.field},
        range: 'category10'
      };
    }
    return {
      name: name,
      type: 'linear',
      zero: false,
      domain: {data: params.data, field: params.field},
      range: ['#df2709', '#2709df']
    };
  },

  axis: function (args, options, scope) {
    let opt = transform(args[0], options, scope);
    if (opt.data && Array.isArray(opt.data) && opt.field) {
      if (!opt.data.__types__) {
        read(opt.data, {parse: 'auto'});
      }
      let type = opt.data.__types__[opt.field];
      if (type === 'string') {
        opt.formatType = 'string';
      } else if (type === 'date') {
        opt.type = opt.type || 'time';
        opt.formatType = 'time';
        opt.format = '%Y-%m-%d';
      } else {
        opt.formatType = 'number';
        opt.format = 's';
      }
    }
    return transform(axisTemplate, opt);
  },

  isStringField: function (args, options, scope) {
    let values = transform(args[0], options, scope);
    let field = transform(args[1], options, scope);

    if (!Array.isArray(values) ||
      values.length < 1 ||
      values[0][field] === undefined ||
      typeof values[0][field] === 'string') {
      return true;
    }
    return false;
  },

  orient: function (args, options, scope) {
    let dir = transform(args[0], options, scope);
    let obj = transform(args[1], options, scope);
    let transformed = {};
    let matching = {
      x: 'y',
      x2: 'y2',
      xc: 'yc',
      y: 'x',
      y2: 'x2',
      yc: 'xc',
      width: 'height',
      height: 'width'
    };
    if (dir === 'horizontal') {
      return obj;
    }
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        if (matching[key]) {
          transformed[matching[key]] = obj[key];
        } else {
          transformed[key] = obj[key];
        }
      }
    }
    return transformed;
  }
};

let transform = function (spec, options, scope) {
  options = options || {};
  scope = scope || {};

  if (Array.isArray(spec)) {
    if (spec.length > 0 && (typeof spec[0] === 'string') && spec[0].slice(0, 1) === '@') {
      return templateFunctions[spec[0].slice(1)](spec.slice(1), options, scope);
    }
    let transformed = [];
    for (let index = 0; index < spec.length; index += 1) {
      transformed.push(transform(spec[index], options, scope));
    }
    return transformed;
  }
  if (spec === null) {
    return spec;
  }
  if (spec instanceof Date) {
    return spec;
  }
  if (typeof spec === 'object') {
    let transformed = {};
    for (let key in spec) {
      if (spec.hasOwnProperty(key)) {
        transformed[key] = transform(spec[key], options, scope);
      }
    }
    return transformed;
  }
  return spec;
};

let isObjectLiteral = function (object) {
  return object && object.constructor && object.constructor.name === 'Object';
};

let isArrayLiteral = function (object) {
  return object && object.constructor && object.constructor.name === 'Array';
};

let extend = function (defaults, options) {
  if (options === undefined) {
    return defaults;
  }
  if (isObjectLiteral(defaults)) {
    let extended = {};
    for (let prop in defaults) {
      if (Object.prototype.hasOwnProperty.call(defaults, prop)) {
        extended[prop] = extend(defaults[prop], options[prop]);
      }
    }
    for (let prop in options) {
      if (!Object.prototype.hasOwnProperty.call(defaults, prop)) {
        extended[prop] = options[prop];
      }
    }
    return extended;
  }
  if (isArrayLiteral(defaults)) {
    let extended = [];
    for (let index = 0; index < defaults.length; index += 1) {
      extended.push(extend(defaults[index], options[index]));
    }
    if (isArrayLiteral(options)) {
      for (let index = defaults.length; index < options.length; index += 1) {
        extended.push(options[index]);
      }
    }
    return extended;
  }
  return options;
};

let merge = function (defaults, options) {
  if (options === undefined || options === null) {
    return defaults;
  }
  if (defaults === undefined || defaults === null) {
    return options;
  }
  if (isObjectLiteral(defaults)) {
    let extended = {};
    for (let prop in defaults) {
      if (Object.prototype.hasOwnProperty.call(defaults, prop)) {
        extended[prop] = merge(defaults[prop], options[prop]);
      }
    }
    for (let prop in options) {
      if (!Object.prototype.hasOwnProperty.call(extended, prop)) {
        extended[prop] = options[prop];
      }
    }
    return extended;
  }
  if (isArrayLiteral(defaults)) {
    let extended = [];
    for (let index = 0; index < defaults.length; index += 1) {
      extended.push(defaults[index]);
    }
    if (isArrayLiteral(options)) {
      for (let index = 0; index < options.length; index += 1) {
        extended.push(options[index]);
      }
    }
    return extended;
  }
  return defaults;
};

let parseChart = function (spec, element, options) {
  // Use element size to set size, unless size explicitly specified or
  // element size is zero.
  let el = select(element).node();
  let sizeOptions = {};

  const size = getElementSize(el);
  const elWidth = size.width;
  const elHeight = size.height;

  if (elWidth !== 0 && elHeight !== 0) {
    if (options.width === undefined) {
      sizeOptions.width = elWidth;
    }
    if (options.height === undefined) {
      sizeOptions.height = elHeight;
    }
  }
  let curOptions = extend(options, sizeOptions);

  // Options that go directly to Vega runtime
  let vegaOptions = {
    el: el,
    renderer: curOptions.renderer
  };

  let vegaSpec = transform(spec, curOptions);

  // Return a promise for the Vega chart object
  return new Promise(resolve => {
    vg.parse.spec(vegaSpec, chartObj => {
      let chart = chartObj(vegaOptions);
      chart.update();
      resolve(chart);
    });
  });
};

export default {
  transform,
  parseChart
};
<|endoftext|>


<commit_before>export {AST} from './src/change_detection/parser/ast';
export {Lexer} from './src/change_detection/parser/lexer';
export {Parser} from './src/change_detection/parser/parser';
export {ContextWithVariableBindings}
    from './src/change_detection/parser/context_with_variable_bindings';
export {ExpressionChangedAfterItHasBeenChecked, ChangeDetectionError}
    from './src/change_detection/exceptions';
export {ChangeRecord, ChangeDispatcher, ChangeDetector,
    CHECK_ONCE, CHECK_ALWAYS, DETACHED, CHECKED} from './src/change_detection/interfaces';
export {ProtoChangeDetector, DynamicProtoChangeDetector, JitProtoChangeDetector}
    from './src/change_detection/proto_change_detector';
export {DynamicChangeDetector}
    from './src/change_detection/dynamic_change_detector';
export * from './src/change_detection/pipes/pipe_registry';
export * from './src/change_detection/pipes/pipe';

import {ProtoChangeDetector, DynamicProtoChangeDetector, JitProtoChangeDetector}
    from './src/change_detection/proto_change_detector';
import {PipeRegistry} from './src/change_detection/pipes/pipe_registry';
import {ArrayChangesFactory} from './src/change_detection/pipes/array_changes';
import {NullPipeFactory} from './src/change_detection/pipes/null_pipe';

export class ChangeDetection {
  createProtoChangeDetector(name:string):ProtoChangeDetector{
    // TODO: this should be abstract, once supported in AtScript
    return null;
  }
}

export var defaultPipes = {
  "iterableDiff" : [
    new ArrayChangesFactory(),
    new NullPipeFactory()
  ]
};

export class DynamicChangeDetection extends ChangeDetection {
  registry:PipeRegistry;

  constructor(registry:PipeRegistry) {
    super();
    this.registry = registry;
  }

  createProtoChangeDetector(name:string):ProtoChangeDetector{
    return new DynamicProtoChangeDetector(this.registry);
  }
}

export class JitChangeDetection extends ChangeDetection {
  registry:PipeRegistry;

  constructor(registry:PipeRegistry) {
    super();
    this.registry = registry;
  }

  createProtoChangeDetector(name:string):ProtoChangeDetector{
    return new JitProtoChangeDetector(this.registry);
  }
}

var _registry = new PipeRegistry(defaultPipes);

export var dynamicChangeDetection = new DynamicChangeDetection(_registry);
export var jitChangeDetection = new JitChangeDetection(_registry);<commit_msg>feat: add keyValDiff to default pipes<commit_after>export {AST} from './src/change_detection/parser/ast';
export {Lexer} from './src/change_detection/parser/lexer';
export {Parser} from './src/change_detection/parser/parser';
export {ContextWithVariableBindings}
    from './src/change_detection/parser/context_with_variable_bindings';
export {ExpressionChangedAfterItHasBeenChecked, ChangeDetectionError}
    from './src/change_detection/exceptions';
export {ChangeRecord, ChangeDispatcher, ChangeDetector,
    CHECK_ONCE, CHECK_ALWAYS, DETACHED, CHECKED} from './src/change_detection/interfaces';
export {ProtoChangeDetector, DynamicProtoChangeDetector, JitProtoChangeDetector}
    from './src/change_detection/proto_change_detector';
export {DynamicChangeDetector}
    from './src/change_detection/dynamic_change_detector';
export * from './src/change_detection/pipes/pipe_registry';
export * from './src/change_detection/pipes/pipe';

import {ProtoChangeDetector, DynamicProtoChangeDetector, JitProtoChangeDetector}
    from './src/change_detection/proto_change_detector';
import {PipeRegistry} from './src/change_detection/pipes/pipe_registry';
import {ArrayChangesFactory} from './src/change_detection/pipes/array_changes';
import {KeyValueChangesFactory} from './src/change_detection/pipes/keyvalue_changes';
import {NullPipeFactory} from './src/change_detection/pipes/null_pipe';

export class ChangeDetection {
  createProtoChangeDetector(name:string):ProtoChangeDetector{
    // TODO: this should be abstract, once supported in AtScript
    return null;
  }
}

export var defaultPipes = {
  "iterableDiff" : [
    new ArrayChangesFactory(),
    new NullPipeFactory()
  ],
  "keyValDiff" : [
    new KeyValueChangesFactory(),
    new NullPipeFactory()
  ]
};

export class DynamicChangeDetection extends ChangeDetection {
  registry:PipeRegistry;

  constructor(registry:PipeRegistry) {
    super();
    this.registry = registry;
  }

  createProtoChangeDetector(name:string):ProtoChangeDetector{
    return new DynamicProtoChangeDetector(this.registry);
  }
}

export class JitChangeDetection extends ChangeDetection {
  registry:PipeRegistry;

  constructor(registry:PipeRegistry) {
    super();
    this.registry = registry;
  }

  createProtoChangeDetector(name:string):ProtoChangeDetector{
    return new JitProtoChangeDetector(this.registry);
  }
}

var _registry = new PipeRegistry(defaultPipes);

export var dynamicChangeDetection = new DynamicChangeDetection(_registry);
export var jitChangeDetection = new JitChangeDetection(_registry);
<|endoftext|>


<commit_before>import { join, isAbsolute } from 'path'
import createDebug from 'debug'
import untildify from 'untildify'
import tildify from 'tildify'
import lndconnect from 'lndconnect'
import fs from 'fs'
import util from 'util'
import pick from 'lodash/pick'
import config from 'config'
import { mainLog } from '@zap/utils/log'
import getLndListen from '@zap/utils/getLndListen'

const readFile = util.promisify(fs.readFile)

const debug = createDebug('zap:lnd-config')

const LNDCONFIG_TYPE_LOCAL = 'local'
const LNDCONFIG_TYPE_CUSTOM = 'custom'

// Supported connection types.
export const types = {
  [LNDCONFIG_TYPE_LOCAL]: 'Local',
  [LNDCONFIG_TYPE_CUSTOM]: 'Custom',
}

// Supported chains.
export const chains = {
  bitcoin: 'Bitcoin',
  litecoin: 'Litecoin',
}

// Supported networks.
export const networks = {
  mainnet: 'Mainnet',
  testnet: 'Testnet',
}

const _isReady = new WeakMap()
const _lndconnectQRCode = new WeakMap()

// Utility methods to clean and prepare data.
const safeTrim = val => (typeof val === 'string' ? val.trim() : val)
const safeTildify = val => (typeof val === 'string' ? tildify(val) : val)
const safeUntildify = val => (typeof val === 'string' ? untildify(val) : val)

/**
 * @class LndConfig
 * @param {*} options Lnd config options.
 */
class LndConfig {
  constructor(options) {
    debug('LndConfig constructor called with options: %o', options)

    Object.defineProperties(this, {
      wallet: {
        enumerable: true,
        get() {
          return `wallet-${this.id}`
        },
      },
      lndconnectQRCode: {
        enumerable: true,
        get() {
          return _lndconnectQRCode.get(this)
        },
      },

      isReady: {
        enumerable: false,
        get() {
          return _isReady.get(this)
        },
      },
      lndDir: {
        enumerable: true,
        get() {
          if (this.type === LNDCONFIG_TYPE_LOCAL) {
            return join(options.userDataDir, 'lnd', this.chain, this.network, this.wallet)
          }
          return
        },
      },
      host: {
        enumerable: true,
        set(host) {
          return this.setConnectionProp('host', host)
        },
        get() {
          return this.getConnectionProp('host')
        },
      },
      cert: {
        enumerable: true,
        set(cert) {
          return this.setConnectionProp('cert', cert)
        },
        get() {
          return this.getConnectionProp('cert')
        },
      },
      macaroon: {
        enumerable: true,
        set(macaroon) {
          return this.setConnectionProp('macaroon', macaroon)
        },
        get() {
          return this.getConnectionProp('macaroon')
        },
      },
    })

    // Assign default options.
    this.type = 'local'
    this.chain = config.chain
    this.network = config.network

    // Set base config.
    const baseConfig = pick(options, [
      'id',
      'type',
      'chain',
      'network',
      'decoder',
      'binaryPath',
      'protoDir',
    ])
    Object.assign(this, baseConfig)

    // Retrieve default autopilot config.
    const {
      autopilot: {
        active: autopilot,
        private: autopilotPrivate,
        maxchannels: autopilotMaxchannels,
        minchansize: autopilotMinchansize,
        maxchansize: autopilotMaxchansize,
        allocation: autopilotAllocation,
        minconfs: autopilotMinconfs,
      },
      assumechanvalid,
    } = config.lnd

    // Assign default settings.
    const lndDefaults = {
      name: null,
      alias: null,
      autopilot,
      autopilotPrivate,
      autopilotMaxchannels,
      autopilotMinchansize,
      autopilotMaxchansize,
      autopilotAllocation,
      autopilotMinconfs,
      assumechanvalid,
    }
    // Merge in whitelisted settings.
    const userSettings = pick(options, Object.keys(lndDefaults))
    const settings = { ...lndDefaults, ...userSettings }
    debug('Applying settings as: %o', settings)
    Object.assign(this, settings)

    // In order to calculate the `lndconnect` property value we must perform some async operations. This prevents us
    // from being able to set the value directly in the constructor as we do for all the other properties. So, we define
    // a `ready` property that resolves once we have calculated this value so that users of this class to wait until the
    // `ready` property has been resolved before using the class instance in order to ensure that the instance has been
    // fully instantiated.
    const isReady = async () => {
      try {
        // Generate lndConenct uri.
        const lndconnectUri = await this.generateLndconnectUri(options)
        if (lndconnectUri) {
          debug('Generated lndconnectUri: %s', lndconnectUri)
          this.lndconnectUri = lndconnectUri
        }
        // Generate lndConenct QR code..
        if (this.lndconnectUri) {
          const lndconnectQRCode = await this.generateLndconnectQRCode()
          _lndconnectQRCode.set(this, lndconnectQRCode)
        }
        return true
      } catch (e) {
        mainLog.error('Unable to generate lndconnect uri: %o', e)
        return true
      }
    }
    _isReady.set(this, isReady())
  }

  /**
   * generateLndconnectUri - Generate an lndconnect uri based on the config options.
   *
   * @param {*} options Lnd config options
   * @returns {string} Lndconnect uri
   */
  async generateLndconnectUri(options) {
    let { lndconnectUri, host, cert, macaroon } = options

    // If this is a local wallet, set the lnd connection details based on wallet config.
    if (this.type === LNDCONFIG_TYPE_LOCAL) {
      host = await getLndListen('rpc')
      cert = join(this.lndDir, 'tls.cert')
      macaroon = join(this.lndDir, 'data', 'chain', this.chain, this.network, 'admin.macaroon')
      return lndconnect.encode({ host, cert, macaroon })
    }

    // If lndconnectUri is provided, use it as is.
    else if (lndconnectUri) {
      return lndconnectUri
    }

    // If this is a custom type, assign the host, cert, and macaroon. This will generate the lndconnectUri.
    else if (this.type === LNDCONFIG_TYPE_CUSTOM) {
      return lndconnect.encode({ host, cert, macaroon })
    }
  }

  /**
   * generateLndconnectQRCode - Generate a flattened lnd connect uri.
   *
   * This will follow any filepaths, read the files and add the decoded content.
   *
   * @returns {string} Embedded lndconnect uri.
   */
  async generateLndconnectQRCode() {
    const { decoder, lndconnectUri } = this
    switch (decoder) {
      case 'lnd.lndconnect.v1':
        if (lndconnectUri) {
          return LndConfig.qrcodeFromLndconnectUri(lndconnectUri)
        }
        break
    }
  }

  /**
   * setConnectionProp - Setter helper for connection properties.
   *
   * @param {string} key key
   * @param {string} value Value
   */
  setConnectionProp(key, value) {
    if (this.decoder === 'lnd.lndconnect.v1') {
      const decoded = lndconnect.decode(this.lndconnectUri)
      this.lndconnectUri = lndconnect.encode({ ...decoded, [key]: safeTildify(safeTrim(value)) })
    }
  }

  /**
   * getConnectionProp - Getter helper for connection keyerties.
   *
   * @param {string} key key
   * @returns {string} Value
   */
  getConnectionProp(key) {
    if (this.decoder === 'lnd.lndconnect.v1') {
      const decoded = lndconnect.decode(this.lndconnectUri)
      return safeUntildify(decoded[key])
    }
  }

  /**
   * qrcodeFromLndconnectUri - Generate an lndconnect QR code from an lndconenctUri.
   *
   * @param {string} lndconnectUri Lndconnect Uri
   * @returns {string} Embedded lndconnect uri
   */
  static async qrcodeFromLndconnectUri(lndconnectUri) {
    const { host, cert, macaroon } = lndconnect.decode(lndconnectUri)
    const [certData, macaroonData] = await Promise.all([
      isAbsolute(cert) ? readFile(cert) : cert,
      isAbsolute(macaroon) ? readFile(macaroon) : macaroon,
    ])
    return lndconnect.encode({ host, cert: certData, macaroon: macaroonData })
  }
}

export default LndConfig
<commit_msg>fix(lnd): ensure lndconnect qrcode uses embeded format<commit_after>import { join, isAbsolute } from 'path'
import createDebug from 'debug'
import untildify from 'untildify'
import tildify from 'tildify'
import lndconnect from 'lndconnect'
import fs from 'fs'
import util from 'util'
import pick from 'lodash/pick'
import config from 'config'
import { mainLog } from '@zap/utils/log'
import getLndListen from '@zap/utils/getLndListen'

const readFile = util.promisify(fs.readFile)

const debug = createDebug('zap:lnd-config')

const LNDCONFIG_TYPE_LOCAL = 'local'
const LNDCONFIG_TYPE_CUSTOM = 'custom'

// Supported connection types.
export const types = {
  [LNDCONFIG_TYPE_LOCAL]: 'Local',
  [LNDCONFIG_TYPE_CUSTOM]: 'Custom',
}

// Supported chains.
export const chains = {
  bitcoin: 'Bitcoin',
  litecoin: 'Litecoin',
}

// Supported networks.
export const networks = {
  mainnet: 'Mainnet',
  testnet: 'Testnet',
}

const _isReady = new WeakMap()
const _lndconnectQRCode = new WeakMap()

// Utility methods to clean and prepare data.
const safeTrim = val => (typeof val === 'string' ? val.trim() : val)
const safeTildify = val => (typeof val === 'string' ? tildify(val) : val)
const safeUntildify = val => (typeof val === 'string' ? untildify(val) : val)

/**
 * @class LndConfig
 * @param {*} options Lnd config options.
 */
class LndConfig {
  constructor(options) {
    debug('LndConfig constructor called with options: %o', options)

    Object.defineProperties(this, {
      wallet: {
        enumerable: true,
        get() {
          return `wallet-${this.id}`
        },
      },
      lndconnectQRCode: {
        enumerable: true,
        get() {
          return _lndconnectQRCode.get(this)
        },
      },

      isReady: {
        enumerable: false,
        get() {
          return _isReady.get(this)
        },
      },
      lndDir: {
        enumerable: true,
        get() {
          if (this.type === LNDCONFIG_TYPE_LOCAL) {
            return join(options.userDataDir, 'lnd', this.chain, this.network, this.wallet)
          }
          return
        },
      },
      host: {
        enumerable: true,
        set(host) {
          return this.setConnectionProp('host', host)
        },
        get() {
          return this.getConnectionProp('host')
        },
      },
      cert: {
        enumerable: true,
        set(cert) {
          return this.setConnectionProp('cert', cert)
        },
        get() {
          return this.getConnectionProp('cert')
        },
      },
      macaroon: {
        enumerable: true,
        set(macaroon) {
          return this.setConnectionProp('macaroon', macaroon)
        },
        get() {
          return this.getConnectionProp('macaroon')
        },
      },
    })

    // Assign default options.
    this.type = 'local'
    this.chain = config.chain
    this.network = config.network

    // Set base config.
    const baseConfig = pick(options, [
      'id',
      'type',
      'chain',
      'network',
      'decoder',
      'binaryPath',
      'protoDir',
    ])
    Object.assign(this, baseConfig)

    // Retrieve default autopilot config.
    const {
      autopilot: {
        active: autopilot,
        private: autopilotPrivate,
        maxchannels: autopilotMaxchannels,
        minchansize: autopilotMinchansize,
        maxchansize: autopilotMaxchansize,
        allocation: autopilotAllocation,
        minconfs: autopilotMinconfs,
      },
      assumechanvalid,
    } = config.lnd

    // Assign default settings.
    const lndDefaults = {
      name: null,
      alias: null,
      autopilot,
      autopilotPrivate,
      autopilotMaxchannels,
      autopilotMinchansize,
      autopilotMaxchansize,
      autopilotAllocation,
      autopilotMinconfs,
      assumechanvalid,
    }
    // Merge in whitelisted settings.
    const userSettings = pick(options, Object.keys(lndDefaults))
    const settings = { ...lndDefaults, ...userSettings }
    debug('Applying settings as: %o', settings)
    Object.assign(this, settings)

    // In order to calculate the `lndconnect` property value we must perform some async operations. This prevents us
    // from being able to set the value directly in the constructor as we do for all the other properties. So, we define
    // a `ready` property that resolves once we have calculated this value so that users of this class to wait until the
    // `ready` property has been resolved before using the class instance in order to ensure that the instance has been
    // fully instantiated.
    const isReady = async () => {
      try {
        // Generate lndConenct uri.
        const lndconnectUri = await this.generateLndconnectUri(options)
        if (lndconnectUri) {
          debug('Generated lndconnectUri: %s', lndconnectUri)
          this.lndconnectUri = lndconnectUri
        }
        // Generate lndConenct QR code..
        if (this.lndconnectUri) {
          const lndconnectQRCode = await this.generateLndconnectQRCode()
          _lndconnectQRCode.set(this, lndconnectQRCode)
        }
        return true
      } catch (e) {
        mainLog.error('Unable to generate lndconnect uri: %o', e)
        return true
      }
    }
    _isReady.set(this, isReady())
  }

  /**
   * generateLndconnectUri - Generate an lndconnect uri based on the config options.
   *
   * @param {*} options Lnd config options
   * @returns {string} Lndconnect uri
   */
  async generateLndconnectUri(options) {
    let { lndconnectUri, host, cert, macaroon } = options

    // If this is a local wallet, set the lnd connection details based on wallet config.
    if (this.type === LNDCONFIG_TYPE_LOCAL) {
      host = await getLndListen('rpc')
      cert = join(this.lndDir, 'tls.cert')
      macaroon = join(this.lndDir, 'data', 'chain', this.chain, this.network, 'admin.macaroon')
      return lndconnect.encode({ host, cert, macaroon })
    }

    // If lndconnectUri is provided, use it as is.
    else if (lndconnectUri) {
      return lndconnectUri
    }

    // If this is a custom type, assign the host, cert, and macaroon. This will generate the lndconnectUri.
    else if (this.type === LNDCONFIG_TYPE_CUSTOM) {
      return lndconnect.encode({ host, cert, macaroon })
    }
  }

  /**
   * generateLndconnectQRCode - Generate a flattened lnd connect uri.
   *
   * This will follow any filepaths, read the files and add the decoded content.
   *
   * @returns {string} Embedded lndconnect uri.
   */
  async generateLndconnectQRCode() {
    const { decoder, lndconnectUri } = this
    switch (decoder) {
      case 'lnd.lndconnect.v1':
        if (lndconnectUri) {
          return LndConfig.qrcodeFromLndconnectUri(lndconnectUri)
        }
        break
    }
  }

  /**
   * setConnectionProp - Setter helper for connection properties.
   *
   * @param {string} key key
   * @param {string} value Value
   */
  setConnectionProp(key, value) {
    if (this.decoder === 'lnd.lndconnect.v1') {
      const decoded = lndconnect.decode(this.lndconnectUri)
      this.lndconnectUri = lndconnect.encode({ ...decoded, [key]: safeTildify(safeTrim(value)) })
    }
  }

  /**
   * getConnectionProp - Getter helper for connection keyerties.
   *
   * @param {string} key key
   * @returns {string} Value
   */
  getConnectionProp(key) {
    if (this.decoder === 'lnd.lndconnect.v1') {
      const decoded = lndconnect.decode(this.lndconnectUri)
      return safeUntildify(decoded[key])
    }
  }

  /**
   * qrcodeFromLndconnectUri - Generate an lndconnect QR code from an lndconenctUri.
   *
   * @param {string} lndconnectUri Lndconnect Uri
   * @returns {string} Embedded lndconnect uri
   */
  static async qrcodeFromLndconnectUri(lndconnectUri) {
    let { host, cert, macaroon } = lndconnect.decode(lndconnectUri)
    cert = safeUntildify(cert)
    macaroon = safeUntildify(macaroon)
    const [certData, macaroonData] = await Promise.all([
      isAbsolute(cert) ? readFile(cert) : cert,
      isAbsolute(macaroon) ? readFile(macaroon) : macaroon,
    ])
    return lndconnect.encode({ host, cert: certData, macaroon: macaroonData })
  }
}

export default LndConfig
<|endoftext|>


<commit_before>'use strict';

/* eslint-disable no-for-of-loops/no-for-of-loops */

// Copies the contents of the new fork into the old fork

const {promisify} = require('util');
const glob = promisify(require('glob'));
const {spawnSync} = require('child_process');
const fs = require('fs');
const minimist = require('minimist');

const stat = promisify(fs.stat);
const copyFile = promisify(fs.copyFile);

const argv = minimist(process.argv.slice(2), {
  boolean: ['reverse'],
});

async function main() {
  const oldFilenames = await glob('packages/react-reconciler/**/*.old.js');
  await Promise.all(oldFilenames.map(unforkFile));

  // Use ESLint to autofix imports
  spawnSync('yarn', ['linc', '--fix'], {
    stdio: ['inherit', 'inherit', 'pipe'],
  });
  // TODO: If eslint crashes, it may not have successfully fixed all
  // the imports, which would leave the reconciler files in an inconsistent
  // state. So we used to crash and reset the working directory. But that
  // solution assumed that the working directory was clean before you run the
  // command — if it wasn't, it'll not only reset the synced reconciler files,
  // but all the other uncommitted changes.
  //
  // We need a different strategy to prevent loss of work. For example, we could
  // exit early if the working directory is not clean before you run the script.
  //
  // Until we think of something better, I've commmented out this branch to
  // prevent work from accidentally being lost.
  // if (spawn.stderr.toString() !== '') {
  //   spawnSync('git', ['checkout', '.']);

  //   console.log(Error(spawn.stderr));
  //   process.exitCode = 1;
  // }
}

async function unforkFile(oldFilename) {
  let oldStats;
  try {
    oldStats = await stat(oldFilename);
  } catch {
    return;
  }
  if (!oldStats.isFile()) {
    return;
  }

  const newFilename = oldFilename.replace(/\.old.js$/, '.new.js');
  let newStats;
  try {
    newStats = await stat(newFilename);
  } catch {
    return;
  }
  if (!newStats.isFile()) {
    return;
  }

  if (argv.reverse) {
    await copyFile(oldFilename, newFilename);
  } else {
    await copyFile(newFilename, oldFilename);
  }
}

main();
<commit_msg>replace-fork: Cleanup after failure if no unstaged changes (#22364)<commit_after>'use strict';

/* eslint-disable no-for-of-loops/no-for-of-loops */

// Copies the contents of the new fork into the old fork

const chalk = require('chalk');
const {promisify} = require('util');
const glob = promisify(require('glob'));
const {execSync, spawnSync} = require('child_process');
const fs = require('fs');
const minimist = require('minimist');

const stat = promisify(fs.stat);
const copyFile = promisify(fs.copyFile);

const argv = minimist(process.argv.slice(2), {
  boolean: ['reverse'],
});

async function main() {
  const status = execSync('git status').toString();
  const hadUnstagedChanges = status.includes('Changes not staged for commit');
  if (hadUnstagedChanges) {
    const readline = require('readline');
    const rl = readline.createInterface({
      input: process.stdin,
      output: process.stdout,
    });

    await new Promise(resolve => {
      rl.question(
        `\n${chalk.yellow.bold(
          'Unstaged changes were found in repository.'
        )} Do you want to continue? (Y/n) `,
        input => {
          switch (input.trim().toLowerCase()) {
            case '':
            case 'y':
            case 'yes':
              resolve();
              break;
            default:
              console.log('No modifications were made.');
              process.exit(0);
              break;
          }
        }
      );
    });
  }

  const oldFilenames = await glob('packages/react-reconciler/**/*.old.js');
  await Promise.all(oldFilenames.map(unforkFile));

  // Use ESLint to autofix imports
  const command = spawnSync('yarn', ['linc', '--fix'], {
    stdio: ['inherit', 'inherit', 'pipe'],
  });
  if (command.status === 1) {
    console.log(
      chalk.bold.red('\nreplace-fork script failed with the following error:')
    );
    console.error(Error(command.stderr));

    // If eslint crashes, it may not have successfully fixed all the imports,
    // which would leave the reconciler files in an inconsistent stat.
    // It would be nice to clean up the working directory in this case,
    // but it's only safe to do that if we aren't going to override any previous changes.
    if (!hadUnstagedChanges) {
      spawnSync('git', ['checkout', '.']);
    } else {
      console.log(
        `\n${chalk.yellow.bold(
          'Unstaged changes were present when `replace-fork` was run.'
        )} ` +
          `To cleanup the repository run:\n  ${chalk.bold(
            'git checkout packages/react-reconciler'
          )}`
      );
    }

    process.exit(1);
  } else {
    process.exit(0);
  }
}

async function unforkFile(oldFilename) {
  let oldStats;
  try {
    oldStats = await stat(oldFilename);
  } catch {
    return;
  }
  if (!oldStats.isFile()) {
    return;
  }

  const newFilename = oldFilename.replace(/\.old.js$/, '.new.js');
  let newStats;
  try {
    newStats = await stat(newFilename);
  } catch {
    return;
  }
  if (!newStats.isFile()) {
    return;
  }

  if (argv.reverse) {
    await copyFile(oldFilename, newFilename);
  } else {
    await copyFile(newFilename, oldFilename);
  }
}

main();
<|endoftext|>