<commit_before>/*global defineSuite*/
defineSuite([
        'Scene/Material',
        '../Specs/renderMaterial',
        '../Specs/createContext',
        '../Specs/destroyContext'
    ], function(
        Material,
        renderMaterial,
        createContext,
        destroyContext) {
    "use strict";
    /*global it,expect*/

    var context;

    beforeEach(function() {
        context = createContext();
    });

    afterEach(function() {
        destroyContext(context);
    });

    it('draws all base material types', function() {
        var materialTypes = ['Color', 'Image', 'DiffuseMap', 'AlphaMap', 'SpecularMap', 'EmissionMap',
            'BumpMap', 'NormalMap','Reflection', 'Refraction', 'Fresnel', 'Brick', 'Wood', 'Asphalt',
            'Cement', 'Grass', 'Stripe', 'Checkerboard','Dot','TieDye', 'Facet', 'Blob'];
        for (var i = 0; i < materialTypes.length; i++) {
            var materialID = materialTypes[i];
            var material = new Material({
                context : context,
                strict : true,
                fabric : {
                    "id" : materialID
                }
            });
            var pixel = renderMaterial(material, context);
            expect(pixel).not.toEqual([0, 0, 0, 0]);
        }
    });

    it('creates a new material type and builds off of it', function() {
        var material1 = new Material({
            context : context,
            strict : true,
            fabric : {
                "id" : "New",
                "components" : {
                    "diffuse" : "vec3(0.0, 0.0, 0.0)"
                }
            }
        });

        var material2 = new Material({
            context : context,
            strict : true,
            fabric : {
                "materials" : {
                    "first" : {
                        "id" : "New"
                    }
                },
                "components" : {
                    "diffuse" : "first.diffuse"
                }
            }
        });

        var pixel1 = renderMaterial(material1, context);
        expect(pixel1).not.toEqual([0, 0, 0, 0]);
        var pixel2 = renderMaterial(material2, context);
        expect(pixel2).not.toEqual([0, 0, 0, 0]);
    });

    it('accesses material properties after construction', function() {
        var material = new Material({
            context : context,
            strict : true,
            fabric : {
                "materials" : {
                    "first" : {
                        "id" : "DiffuseMap"
                    }
                },
                "uniforms" : {
                    "value" : {
                        "x" : 0.0,
                        "y" : 0.0,
                        "z" : 0.0
                    }
                },
                "components" : {
                    "diffuse" : "value + first.diffuse"
                }
            }
        });
        material.uniforms.value.x = 1.0;
        material.materials.first.uniforms.repeat.x = 2.0;

        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('creates a material inside a material inside a material', function () {
        var material = new Material({
            context : context,
            strict : true,
            fabric : {
                "materials" : {
                    "first" : {
                        "materials" : {
                            "second" : {
                                "components" : {
                                    "diffuse" : "vec3(0.0, 0.0, 0.0)"
                                }
                            }
                        },
                        "components" : {
                            "diffuse" : "second.diffuse"
                        }
                    }
                },
                "components" : {
                    "diffuse" : "first.diffuse"
                }
            }
        });
        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('creates a material with an image uniform', function () {
        var material = new Material({
            context : context,
            strict : true,
            fabric : {
                "id" : "DiffuseMap",
                "uniforms" : {
                    "image" :  "./Data/Images/Blue.png"
                }
            }
        });
        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('create a material with a matrix uniform', function () {
        var material1 = new Material({
            context : context,
            strict : true,
            fabric : {
                "uniforms" : {
                    "value" : [0.5, 0.5, 0.5, 0.5]
                },
                "components" : {
                    "diffuse" : "vec3(value[0][0], value[0][1], value[1][0])",
                    "alpha" : "value[1][1]"
                }
            }
        });
        var pixel = renderMaterial(material1, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);

        var material2 = new Material({
            context : context,
            strict : true,
            fabric : {
                "uniforms" : {
                    "value" : [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
                },
                "components" : {
                    "diffuse" : "vec3(value[0][0], value[0][1], value[1][0])",
                    "alpha" : "value[2][2]"
                }
            }
        });
        pixel = renderMaterial(material2, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);

        var material3 = new Material({
            context : context,
            strict : true,
            fabric : {
                "uniforms" : {
                    "value" : [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
                },
                "components" : {
                    "diffuse" : "vec3(value[0][0], value[0][1], value[1][0])",
                    "alpha" : "value[3][3]"
                }
            }
        });
        pixel = renderMaterial(material3, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('creates a material using unusual uniform and material names', function () {
        var material = new Material({
            context : context,
            strict : true,
            fabric : {
                "uniforms" : {
                    "i" : 0.5
                },
                "materials" : {
                    "d" : {
                        "id" : "ColorMaterial"
                    },
                    "diffuse" : {
                        "id" : "ColorMaterial"
                    }
                },
                "components" : {
                    "diffuse" : "(d.diffuse + diffuse.diffuse)*i",
                    "specular" : "i"
                }
            }
        });
        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('create a material using fromID', function () {
        var material = Material.fromID(context, 'Color');
        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('throws without context for material that uses images', function() {
        expect(function() {
            return new Material({
                context : undefined,
                fabric : {
                    "id" : "DiffuseMap"
                }
            });
        }).toThrow();
    });

    it('throws with source and components in same template', function () {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "components" : {
                        "diffuse" : "vec3(0.0, 0.0, 0.0)"
                    },
                    "source" : "agi_material agi_getMaterial(agi_materialInput materialInput)\n{\n" +
                               "agi_material material = agi_getDefaultMaterial(materialInput);\n" +
                               "return material;\n}\n"
                }
            });
        }).toThrow();

        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "id" : "DiffuseMap",
                    "components" : {
                        "diffuse" : "vec3(0.0, 0.0, 0.0)"
                    }
                }
            });
        }).toThrow();
    });

    it('throws with duplicate names in materials and uniforms', function () {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "uniforms" : {
                        "first" : 0.0,
                        "second" : 0.0
                    },
                    "materials" : {
                        "second" : {}
                    }
                }
            });
        }).toThrow();
    });

    it('throws with invalid template type', function() {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "invalid" : 3
                }
            });
        }).toThrow();
    });

    it('throws with invalid component type', function () {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "components" : {
                        "difuse" : "vec3(0.0, 0.0, 0.0)"
                    }
                }
            });
        }).toThrow();
    });

    it('throws with invalid uniform type', function() {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "uniforms" : {
                        "value" : {
                            "x" : 0.0,
                            "y" : 0.0,
                            "z" : 0.0,
                            "w" : 0.0,
                            "t" : 0.0
                        }
                    }
                }
            });
        }).toThrow();

        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "uniforms" : {
                        "value" : [0.0, 0.0, 0.0, 0.0, 0.0]
                    }
                }
            });
        }).toThrow();
    });

    it('throws with unused uniform string', function() {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "uniforms" : {
                        "image" : "agi_defaultImage",
                        "channels" : "rgb"
                    }
                },
                "components" : {
                    "diffuse" : "texture2D(image, materialInput.st).rgb"
                }
            });
        }).toThrow();

        // If strict is false, unused uniform strings are ignored.
        var material = new Material({
            context : context,
            strict : false,
            fabric : {
                "uniforms" : {
                    "image" : "agi_defaultImage",
                    "channels" : "rgb"
                },
                "components" : {
                    "diffuse" : "texture2D(image, materialInput.st).rgb"
                }
            }
        });
        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('throws with unused uniform', function() {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "uniforms" : {
                        "first" : {
                            "x" : 0.0,
                            "y" : 0.0,
                            "z" : 0.0
                        }
                    }
                }
            });
        }).toThrow();

        // If strict is false, unused uniforms are ignored.
        var material = new Material({
            context : context,
            strict : false,
            fabric : {
                "uniforms" : {
                    "first" : {
                        "x" : 0.0,
                        "y" : 0.0,
                        "z" : 0.0
                    }
                }
            }
        });
        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('throws with unused material', function() {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "materials" : {
                        "first" : {
                            "id" : "DiffuseMap"
                        }
                    }
                }
            });
        }).toThrow();

        // If strict is false, unused materials are ignored.
        var material = new Material({
            context : context,
            strict : false,
            fabric : {
                "materials" : {
                    "first" : {
                        "id" : "DiffuseMap"
                    }
                }
            }
        });
        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('throws with invalid id sent to fromID', function() {
        expect(function() {
            return Material.fromID(context, "Nothing");
        }).toThrow();
    });
});
<commit_msg>Made material tests more fine-grain<commit_after>/*global defineSuite*/
defineSuite([
        'Scene/Material',
        '../Specs/renderMaterial',
        '../Specs/createContext',
        '../Specs/destroyContext'
    ], function(
        Material,
        renderMaterial,
        createContext,
        destroyContext) {
    "use strict";
    /*global it,expect*/

    var context;

    beforeEach(function() {
        context = createContext();
    });

    afterEach(function() {
        destroyContext(context);
    });

    function verifyMaterial(id) {
        var material = new Material({
            context : context,
            strict : true,
            fabric : {
                "id" : id
            }
        });
        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    }

    it('draws Color built-in material', function() {
        verifyMaterial('Color');
    });

    it('draws Image built-in material', function() {
        verifyMaterial('Image');
    });

    it('draws DiffuseMap built-in material', function() {
        verifyMaterial('DiffuseMap');
    });

    it('draws AlphaMap built-in material', function() {
        verifyMaterial('AlphaMap');
    });

    it('draws SpecularMap built-in material', function() {
        verifyMaterial('SpecularMap');
    });

    it('draws EmissionMap built-in material', function() {
        verifyMaterial('EmissionMap');
    });

    it('draws BumpMap built-in material', function() {
        verifyMaterial('BumpMap');
    });

    it('draws NormalMap built-in material', function() {
        verifyMaterial('NormalMap');
    });

    it('draws Reflection built-in material', function() {
        verifyMaterial('Reflection');
    });

    it('draws Refraction built-in material', function() {
        verifyMaterial('Refraction');
    });

    it('draws Fresnel built-in material', function() {
        verifyMaterial('Fresnel');
    });

    it('draws Brick built-in material', function() {
        verifyMaterial('Brick');
    });

    it('draws Wood built-in material', function() {
        verifyMaterial('Wood');
    });

    it('draws Asphalt built-in material', function() {
        verifyMaterial('Asphalt');
    });

    it('draws Cement built-in material', function() {
        verifyMaterial('Cement');
    });

    it('draws Grass built-in material', function() {
        verifyMaterial('Grass');
    });

    it('draws Stripe built-in material', function() {
        verifyMaterial('Stripe');
    });

    it('draws Checkerboard built-in material', function() {
        verifyMaterial('Checkerboard');
    });

    it('draws Dot built-in material', function() {
        verifyMaterial('Dot');
    });

    it('draws TieDye built-in material', function() {
        verifyMaterial('TieDye');
    });

    it('draws Facet built-in material', function() {
        verifyMaterial('Facet');
    });

    it('draws Blob built-in material', function() {
        verifyMaterial('Blob');
    });

    it('creates a new material type and builds off of it', function() {
        var material1 = new Material({
            context : context,
            strict : true,
            fabric : {
                "id" : "New",
                "components" : {
                    "diffuse" : "vec3(0.0, 0.0, 0.0)"
                }
            }
        });

        var material2 = new Material({
            context : context,
            strict : true,
            fabric : {
                "materials" : {
                    "first" : {
                        "id" : "New"
                    }
                },
                "components" : {
                    "diffuse" : "first.diffuse"
                }
            }
        });

        var pixel1 = renderMaterial(material1, context);
        expect(pixel1).not.toEqual([0, 0, 0, 0]);
        var pixel2 = renderMaterial(material2, context);
        expect(pixel2).not.toEqual([0, 0, 0, 0]);
    });

    it('accesses material properties after construction', function() {
        var material = new Material({
            context : context,
            strict : true,
            fabric : {
                "materials" : {
                    "first" : {
                        "id" : "DiffuseMap"
                    }
                },
                "uniforms" : {
                    "value" : {
                        "x" : 0.0,
                        "y" : 0.0,
                        "z" : 0.0
                    }
                },
                "components" : {
                    "diffuse" : "value + first.diffuse"
                }
            }
        });
        material.uniforms.value.x = 1.0;
        material.materials.first.uniforms.repeat.x = 2.0;

        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('creates a material inside a material inside a material', function () {
        var material = new Material({
            context : context,
            strict : true,
            fabric : {
                "materials" : {
                    "first" : {
                        "materials" : {
                            "second" : {
                                "components" : {
                                    "diffuse" : "vec3(0.0, 0.0, 0.0)"
                                }
                            }
                        },
                        "components" : {
                            "diffuse" : "second.diffuse"
                        }
                    }
                },
                "components" : {
                    "diffuse" : "first.diffuse"
                }
            }
        });
        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('creates a material with an image uniform', function () {
        var material = new Material({
            context : context,
            strict : true,
            fabric : {
                "id" : "DiffuseMap",
                "uniforms" : {
                    "image" :  "./Data/Images/Blue.png"
                }
            }
        });
        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('create a material with a matrix uniform', function () {
        var material1 = new Material({
            context : context,
            strict : true,
            fabric : {
                "uniforms" : {
                    "value" : [0.5, 0.5, 0.5, 0.5]
                },
                "components" : {
                    "diffuse" : "vec3(value[0][0], value[0][1], value[1][0])",
                    "alpha" : "value[1][1]"
                }
            }
        });
        var pixel = renderMaterial(material1, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);

        var material2 = new Material({
            context : context,
            strict : true,
            fabric : {
                "uniforms" : {
                    "value" : [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
                },
                "components" : {
                    "diffuse" : "vec3(value[0][0], value[0][1], value[1][0])",
                    "alpha" : "value[2][2]"
                }
            }
        });
        pixel = renderMaterial(material2, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);

        var material3 = new Material({
            context : context,
            strict : true,
            fabric : {
                "uniforms" : {
                    "value" : [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
                },
                "components" : {
                    "diffuse" : "vec3(value[0][0], value[0][1], value[1][0])",
                    "alpha" : "value[3][3]"
                }
            }
        });
        pixel = renderMaterial(material3, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('creates a material using unusual uniform and material names', function () {
        var material = new Material({
            context : context,
            strict : true,
            fabric : {
                "uniforms" : {
                    "i" : 0.5
                },
                "materials" : {
                    "d" : {
                        "id" : "ColorMaterial"
                    },
                    "diffuse" : {
                        "id" : "ColorMaterial"
                    }
                },
                "components" : {
                    "diffuse" : "(d.diffuse + diffuse.diffuse)*i",
                    "specular" : "i"
                }
            }
        });
        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('create a material using fromID', function () {
        var material = Material.fromID(context, 'Color');
        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('throws without context for material that uses images', function() {
        expect(function() {
            return new Material({
                context : undefined,
                fabric : {
                    "id" : "DiffuseMap"
                }
            });
        }).toThrow();
    });

    it('throws with source and components in same template', function () {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "components" : {
                        "diffuse" : "vec3(0.0, 0.0, 0.0)"
                    },
                    "source" : "agi_material agi_getMaterial(agi_materialInput materialInput)\n{\n" +
                               "agi_material material = agi_getDefaultMaterial(materialInput);\n" +
                               "return material;\n}\n"
                }
            });
        }).toThrow();

        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "id" : "DiffuseMap",
                    "components" : {
                        "diffuse" : "vec3(0.0, 0.0, 0.0)"
                    }
                }
            });
        }).toThrow();
    });

    it('throws with duplicate names in materials and uniforms', function () {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "uniforms" : {
                        "first" : 0.0,
                        "second" : 0.0
                    },
                    "materials" : {
                        "second" : {}
                    }
                }
            });
        }).toThrow();
    });

    it('throws with invalid template type', function() {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "invalid" : 3
                }
            });
        }).toThrow();
    });

    it('throws with invalid component type', function () {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "components" : {
                        "difuse" : "vec3(0.0, 0.0, 0.0)"
                    }
                }
            });
        }).toThrow();
    });

    it('throws with invalid uniform type', function() {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "uniforms" : {
                        "value" : {
                            "x" : 0.0,
                            "y" : 0.0,
                            "z" : 0.0,
                            "w" : 0.0,
                            "t" : 0.0
                        }
                    }
                }
            });
        }).toThrow();

        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "uniforms" : {
                        "value" : [0.0, 0.0, 0.0, 0.0, 0.0]
                    }
                }
            });
        }).toThrow();
    });

    it('throws with unused uniform string', function() {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "uniforms" : {
                        "image" : "agi_defaultImage",
                        "channels" : "rgb"
                    }
                },
                "components" : {
                    "diffuse" : "texture2D(image, materialInput.st).rgb"
                }
            });
        }).toThrow();

        // If strict is false, unused uniform strings are ignored.
        var material = new Material({
            context : context,
            strict : false,
            fabric : {
                "uniforms" : {
                    "image" : "agi_defaultImage",
                    "channels" : "rgb"
                },
                "components" : {
                    "diffuse" : "texture2D(image, materialInput.st).rgb"
                }
            }
        });
        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('throws with unused uniform', function() {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "uniforms" : {
                        "first" : {
                            "x" : 0.0,
                            "y" : 0.0,
                            "z" : 0.0
                        }
                    }
                }
            });
        }).toThrow();

        // If strict is false, unused uniforms are ignored.
        var material = new Material({
            context : context,
            strict : false,
            fabric : {
                "uniforms" : {
                    "first" : {
                        "x" : 0.0,
                        "y" : 0.0,
                        "z" : 0.0
                    }
                }
            }
        });
        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('throws with unused material', function() {
        expect(function() {
            return new Material({
                context : context,
                strict : true,
                fabric : {
                    "materials" : {
                        "first" : {
                            "id" : "DiffuseMap"
                        }
                    }
                }
            });
        }).toThrow();

        // If strict is false, unused materials are ignored.
        var material = new Material({
            context : context,
            strict : false,
            fabric : {
                "materials" : {
                    "first" : {
                        "id" : "DiffuseMap"
                    }
                }
            }
        });
        var pixel = renderMaterial(material, context);
        expect(pixel).not.toEqual([0, 0, 0, 0]);
    });

    it('throws with invalid id sent to fromID', function() {
        expect(function() {
            return Material.fromID(context, "Nothing");
        }).toThrow();
    });
});
<|endoftext|>


<commit_before>// Generated on 2015-09-21 using
// generator-webapp 1.0.1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// If you want to recursively match all subfolders, use:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Automatically load required grunt tasks
  require('jit-grunt')(grunt, {
      useminPrepare: 'grunt-usemin'
  });

  // Configurable paths
  var config = {
    app: 'app',
    dist: 'dist'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    config: config,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      babel: {
        files: ['<%= config.app %>/scripts/{,*/}*.js'],
        tasks: ['babel:dist']
      },
      babelTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['babel:test', 'test:watch']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      sass: {
        files: ['<%= config.app %>/styles/{,*/}*.{scss,sass}'],
        tasks: ['sass:server', 'postcss']
      },
      styles: {
        files: ['<%= config.app %>/styles/{,*/}*.css'],
        tasks: ['newer:copy:styles', 'postcss']
      }
    },

    browserSync: {
      options: {
        notify: false,
        background: true
      },
      livereload: {
        options: {
          files: [
            '<%= config.app %>/{,*/}*.html',
            '.tmp/styles/{,*/}*.css',
            '<%= config.app %>/images/{,*/}*',
            '.tmp/scripts/{,*/}*.js'
          ],
          port: 9000,
          server: {
            baseDir: ['.tmp', config.app],
            routes: {
              '/bower_components': './bower_components'
            }
          }
        }
      },
      test: {
        options: {
          port: 9001,
          open: false,
          logLevel: 'silent',
          host: 'localhost',
          server: {
            baseDir: ['.tmp', './test', config.app],
            routes: {
              '/bower_components': './bower_components'
            }
          }
        }
      },
      dist: {
        options: {
          background: false,
          server: '<%= config.dist %>'
        }
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= config.dist %>/*',
            '!<%= config.dist %>/.git*'
          ]
        }]
      },
      server: '.tmp'
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    eslint: {
      target: [
        'Gruntfile.js',
        '<%= config.app %>/scripts/{,*/}*.js',
        '!<%= config.app %>/scripts/vendor/*',
        'test/spec/{,*/}*.js'
      ]
    },

    // Mocha testing framework configuration options
    mocha: {
      all: {
        options: {
          run: true,
          urls: ['http://<%= browserSync.test.options.host %>:<%= browserSync.test.options.port %>/index.html']
        }
      }
    },

    // Compiles ES6 with Babel
    babel: {
      options: {
          sourceMap: true
      },
      dist: {
        files: [{
          expand: true,
          cwd: '<%= config.app %>/scripts',
          src: '{,*/}*.js',
          dest: '.tmp/scripts',
          ext: '.js'
        }]
      },
      test: {
        files: [{
          expand: true,
          cwd: 'test/spec',
          src: '{,*/}*.js',
          dest: '.tmp/spec',
          ext: '.js'
        }]
      }
    },

    // Compiles Sass to CSS and generates necessary files if requested
    sass: {
      options: {
        sourceMap: true,
        sourceMapEmbed: true,
        sourceMapContents: true,
        includePaths: ['.']
      },
      dist: {
        files: [{
          expand: true,
          cwd: '<%= config.app %>/styles',
          src: ['*.{scss,sass}'],
          dest: '.tmp/styles',
          ext: '.css'
        }]
      },
      server: {
        files: [{
          expand: true,
          cwd: '<%= config.app %>/styles',
          src: ['*.{scss,sass}'],
          dest: '.tmp/styles',
          ext: '.css'
        }]
      }
    },

    postcss: {
      options: {
        map: true,
        processors: [
          // Add vendor prefixed styles
          require('autoprefixer-core')({
            browsers: ['> 1%', 'last 2 versions', 'Firefox ESR', 'Opera 12.1']
          })
        ]
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the HTML file
    wiredep: {
      app: {
        src: ['<%= config.app %>/index.html'],
        ignorePath: /^(\.\.\/)*\.\./
      },
      sass: {
        src: ['<%= config.app %>/styles/{,*/}*.{scss,sass}'],
        ignorePath: /^(\.\.\/)+/
      }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= config.dist %>/scripts/{,*/}*.js',
          '<%= config.dist %>/styles/{,*/}*.css',
          '<%= config.dist %>/images/{,*/}*.*',
          '<%= config.dist %>/styles/fonts/{,*/}*.*',
          '<%= config.dist %>/*.{ico,png}'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      options: {
        dest: '<%= config.dist %>'
      },
      html: '<%= config.app %>/index.html'
    },

    // Performs rewrites based on rev and the useminPrepare configuration
    usemin: {
      options: {
        assetsDirs: [
          '<%= config.dist %>',
          '<%= config.dist %>/images',
          '<%= config.dist %>/styles'
        ]
      },
      html: ['<%= config.dist %>/{,*/}*.html'],
      css: ['<%= config.dist %>/styles/{,*/}*.css']
    },

    // The following *-min tasks produce minified files in the dist folder
    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= config.app %>/images',
          src: '{,*/}*.{gif,jpeg,jpg,png}',
          dest: '<%= config.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= config.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= config.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseBooleanAttributes: true,
          collapseWhitespace: true,
          conservativeCollapse: true,
          removeAttributeQuotes: true,
          removeCommentsFromCDATA: true,
          removeEmptyAttributes: true,
          removeOptionalTags: true,
          // true would impact styles with attribute selectors
          removeRedundantAttributes: false,
          useShortDoctype: true
        },
        files: [{
          expand: true,
          cwd: '<%= config.dist %>',
          src: '{,*/}*.html',
          dest: '<%= config.dist %>'
        }]
      }
    },

    // By default, your `index.html`'s <!-- Usemin block --> will take care
    // of minification. These next options are pre-configured if you do not
    // wish to use the Usemin blocks.
    // cssmin: {
    //   dist: {
    //     files: {
    //       '<%= config.dist %>/styles/main.css': [
    //         '.tmp/styles/{,*/}*.css',
    //         '<%= config.app %>/styles/{,*/}*.css'
    //       ]
    //     }
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%= config.dist %>/scripts/scripts.js': [
    //         '<%= config.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= config.app %>',
          dest: '<%= config.dist %>',
          src: [
            '*.{ico,png,txt}',
            'images/{,*/}*.webp',
            '{,*/}*.html',
            'styles/fonts/{,*/}*.*'
          ]
        }]
      }
    },

    // Run some tasks in parallel to speed up build process
    concurrent: {
      server: [
        'babel:dist',
        'sass:server'
      ],
      test: [
        'babel'
      ],
      dist: [
        'babel',
        'sass',
        'imagemin',
        'svgmin'
      ]
    }
  });

  grunt.registerTask('serve', 'start the server and preview your app', function (target) {

    if (target === 'dist') {
      return grunt.task.run(['build', 'browserSync:dist']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'postcss',
      'browserSync:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run([target ? ('serve:' + target) : 'serve']);
  });

  grunt.registerTask('test', function (target) {
    if (target !== 'watch') {
      grunt.task.run([
        'clean:server',
        'concurrent:test',
        'postcss'
      ]);
    }

    grunt.task.run([
      'browserSync:test',
      'mocha'
    ]);
  });

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'postcss',
    'concat',
    'cssmin',
    'uglify',
    'copy:dist',
    'filerev',
    'usemin',
    'htmlmin'
  ]);

  grunt.registerTask('default', [
    'newer:eslint',
    'test',
    'build'
  ]);
};
<commit_msg>commit<commit_after>// Generated on 2015-09-21 using
// generator-webapp 1.0.1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// If you want to recursively match all subfolders, use:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Automatically load required grunt tasks
  require('jit-grunt')(grunt, {
      useminPrepare: 'grunt-usemin'
  });

  // Configurable paths
  var config = {
    app: 'app',
    dist: 'dist'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    config: config,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },

      gruntfile: {
        files: ['Gruntfile.js']
      },
      styles: {
        files: ['<%= config.app %>/styles/{,*/}*.css'],
        tasks: ['newer:copy:styles', 'postcss']
      }
    },

    browserSync: {
      options: {
        notify: false,
        background: true
      },
      livereload: {
        options: {
          files: [
            '<%= config.app %>/{,*/}*.html',
            '.tmp/styles/{,*/}*.css',
            '<%= config.app %>/images/{,*/}*',
            '.tmp/scripts/{,*/}*.js'
          ],
          port: 9000,
          server: {
            baseDir: ['.tmp', config.app],
            routes: {
              '/bower_components': './bower_components'
            }
          }
        }
      }
    }
  })
  grunt.registerTask('serve', 'start the server and preview your app', function (target) {

    grunt.task.run([
      'browserSync:livereload',
      'watch'
    ]);
  });

    grunt.registerTask('default', [
    'serve'
  ]);
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

var Benchmark = require("benchmark"),
    sprintf = require("sprintf").sprintf;

var Graph = require("..").Graph,
    alg = require("..").alg;

var NODE_SIZES = [100],
    EDGE_DENSITY = 0.2,
    KEY_SIZE = 10;

function runBenchmark(name, fn) {
  var options = {};
  options.onComplete = function(bench) {
    var target = bench.target,
        hz = target.hz,
        stats = target.stats,
        rme = stats.rme,
        samples = stats.sample.length,
        msg = sprintf("    %25s: %13s ops/sec \xb1 %s%% (%3d run(s) sampled)",
                      target.name,
                      Benchmark.formatNumber(hz.toFixed(2)),
                      rme.toFixed(2),
                      samples);
    console.log(msg);
  };
  options.onError = function(bench) {
    console.error("    " + bench.target.error);
  };
  options.setup = function() {
    this.count = Math.random() * 1000;
    this.nextInt = function(range) {
      return Math.floor(this.count++ % range );
    };
  };
  new Benchmark(name, fn, options).run();
}

function keys(count) {
  var ks = [],
      k;
  for (var i = 0; i < count; ++i) {
    k = "";
    for (var j = 0; j < KEY_SIZE; ++j) {
      k += String.fromCharCode(97 + Math.floor(Math.random() * 26));
    }
    ks.push(k);
  }
  return ks;
}

function buildGraph(numNodes, edgeDensity) {
  var g = new Graph(),
      numEdges = numNodes * numNodes * edgeDensity,
      ks = keys(numNodes);

  ks.forEach(function(k) { g.node(k); });

  for (var i = 0; i < numEdges; ++i) {
    var v, w;
    do {
      v = ks[Math.floor(Math.random() * ks.length)];
      w = ks[Math.floor(Math.random() * ks.length)];
    } while (g.hasEdge(v, w));
    g.edge(v, w);
  }
  return g;
}

runBenchmark("constructor", function () { new Graph(); });

NODE_SIZES.forEach(function(size) {
  var g = buildGraph(size, EDGE_DENSITY),
      nodeIds = g.allNodes(),
      nameSuffix = "(" + size + "," + EDGE_DENSITY + ")";

  runBenchmark("allNodes" + nameSuffix, function() {
    g.allNodes();
  });

  runBenchmark("sources" + nameSuffix, function() {
    g.sources();
  });

  runBenchmark("sinks" + nameSuffix, function() {
    g.sinks();
  });

  runBenchmark("nodes" + nameSuffix, function() {
    g.nodes("a", "b", "c", "d", "e");
  });

  runBenchmark("node" + nameSuffix, function() {
    g.node("key");
  });

  runBenchmark("node + remove" + nameSuffix, function() {
    g.node("key");
    g.removeNode("key");
  });

  runBenchmark("predecessors" + nameSuffix, function() {
    g.predecessors(nodeIds[this.nextInt(nodeIds.length)]);
  });

  runBenchmark("successors" + nameSuffix, function() {
    g.successors(nodeIds[this.nextInt(nodeIds.length)]);
  });

  runBenchmark("neighbors" + nameSuffix, function() {
    g.neighbors(nodeIds[this.nextInt(nodeIds.length)]);
  });

  runBenchmark("allEdges" + nameSuffix, function() {
    g.allEdges();
  });

  runBenchmark("path" + nameSuffix, function() {
    g.path("a", "b", "c", "d", "e");
  });

  runBenchmark("edge" + nameSuffix, function() {
    g.edge("from", "to");
  });

  runBenchmark("edge + remove" + nameSuffix, function() {
    g.edge("from", "to");
    g.removeEdge("from", "to");
  });

  runBenchmark("inEdges" + nameSuffix, function() {
    g.inEdges(nodeIds[this.nextInt(nodeIds.length)]);
  });

  runBenchmark("outEdges" + nameSuffix, function() {
    g.outEdges(nodeIds[this.nextInt(nodeIds.length)]);
  });

  runBenchmark("edges" + nameSuffix, function() {
    g.edges(nodeIds[this.nextInt(nodeIds.length)]);
  });

  runBenchmark("components" + nameSuffix, function() {
    alg.components(g);
  });

  runBenchmark("dijkstraAll" + nameSuffix, function() {
    alg.dijkstraAll(g);
  });

  runBenchmark("greedyFAS" + nameSuffix, function() {
    alg.greedyFAS(g);
  });

  runBenchmark("copy" + nameSuffix, function() {
    g.copy();
  });
});
<commit_msg>Remove copy<commit_after>#!/usr/bin/env node

var Benchmark = require("benchmark"),
    sprintf = require("sprintf").sprintf;

var Graph = require("..").Graph,
    alg = require("..").alg;

var NODE_SIZES = [100],
    EDGE_DENSITY = 0.2,
    KEY_SIZE = 10;

function runBenchmark(name, fn) {
  var options = {};
  options.onComplete = function(bench) {
    var target = bench.target,
        hz = target.hz,
        stats = target.stats,
        rme = stats.rme,
        samples = stats.sample.length,
        msg = sprintf("    %25s: %13s ops/sec \xb1 %s%% (%3d run(s) sampled)",
                      target.name,
                      Benchmark.formatNumber(hz.toFixed(2)),
                      rme.toFixed(2),
                      samples);
    console.log(msg);
  };
  options.onError = function(bench) {
    console.error("    " + bench.target.error);
  };
  options.setup = function() {
    this.count = Math.random() * 1000;
    this.nextInt = function(range) {
      return Math.floor(this.count++ % range );
    };
  };
  new Benchmark(name, fn, options).run();
}

function keys(count) {
  var ks = [],
      k;
  for (var i = 0; i < count; ++i) {
    k = "";
    for (var j = 0; j < KEY_SIZE; ++j) {
      k += String.fromCharCode(97 + Math.floor(Math.random() * 26));
    }
    ks.push(k);
  }
  return ks;
}

function buildGraph(numNodes, edgeDensity) {
  var g = new Graph(),
      numEdges = numNodes * numNodes * edgeDensity,
      ks = keys(numNodes);

  ks.forEach(function(k) { g.node(k); });

  for (var i = 0; i < numEdges; ++i) {
    var v, w;
    do {
      v = ks[Math.floor(Math.random() * ks.length)];
      w = ks[Math.floor(Math.random() * ks.length)];
    } while (g.hasEdge(v, w));
    g.edge(v, w);
  }
  return g;
}

runBenchmark("constructor", function () { new Graph(); });

NODE_SIZES.forEach(function(size) {
  var g = buildGraph(size, EDGE_DENSITY),
      nodeIds = g.allNodes(),
      nameSuffix = "(" + size + "," + EDGE_DENSITY + ")";

  runBenchmark("allNodes" + nameSuffix, function() {
    g.allNodes();
  });

  runBenchmark("sources" + nameSuffix, function() {
    g.sources();
  });

  runBenchmark("sinks" + nameSuffix, function() {
    g.sinks();
  });

  runBenchmark("nodes" + nameSuffix, function() {
    g.nodes("a", "b", "c", "d", "e");
  });

  runBenchmark("node" + nameSuffix, function() {
    g.node("key");
  });

  runBenchmark("node + remove" + nameSuffix, function() {
    g.node("key");
    g.removeNode("key");
  });

  runBenchmark("predecessors" + nameSuffix, function() {
    g.predecessors(nodeIds[this.nextInt(nodeIds.length)]);
  });

  runBenchmark("successors" + nameSuffix, function() {
    g.successors(nodeIds[this.nextInt(nodeIds.length)]);
  });

  runBenchmark("neighbors" + nameSuffix, function() {
    g.neighbors(nodeIds[this.nextInt(nodeIds.length)]);
  });

  runBenchmark("allEdges" + nameSuffix, function() {
    g.allEdges();
  });

  runBenchmark("path" + nameSuffix, function() {
    g.path("a", "b", "c", "d", "e");
  });

  runBenchmark("edge" + nameSuffix, function() {
    g.edge("from", "to");
  });

  runBenchmark("edge + remove" + nameSuffix, function() {
    g.edge("from", "to");
    g.removeEdge("from", "to");
  });

  runBenchmark("inEdges" + nameSuffix, function() {
    g.inEdges(nodeIds[this.nextInt(nodeIds.length)]);
  });

  runBenchmark("outEdges" + nameSuffix, function() {
    g.outEdges(nodeIds[this.nextInt(nodeIds.length)]);
  });

  runBenchmark("edges" + nameSuffix, function() {
    g.edges(nodeIds[this.nextInt(nodeIds.length)]);
  });

  runBenchmark("components" + nameSuffix, function() {
    alg.components(g);
  });

  runBenchmark("dijkstraAll" + nameSuffix, function() {
    alg.dijkstraAll(g);
  });

  runBenchmark("greedyFAS" + nameSuffix, function() {
    alg.greedyFAS(g);
  });
});
<|endoftext|>


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

const colors = require('ansi-colors');
const file = require('gulp-file');
const fs = require('fs-extra');
const gulp = require('gulp');
const log = require('fancy-log');
const {
  bootstrapThirdPartyFrames,
  compileAllMinifiedJs,
  compileCoreRuntime,
  compileJs,
  endBuildStep,
  hostname,
  mkdirSync,
  printConfigHelp,
  printNobuildHelp,
  toPromise,
  transferSrcsToTempDir,
} = require('./helpers');
const {
  createCtrlcHandler,
  exitCtrlcHandler,
} = require('../common/ctrlcHandler');
const {
  createModuleCompatibleES5Bundle,
} = require('./create-module-compatible-es5-bundle');
const {
  distNailgunPort,
  startNailgunServer,
  stopNailgunServer,
} = require('./nailgun');
const {buildExtensions, parseExtensionFlags} = require('./extension-helpers');
const {cleanupBuildDir} = require('../compile/compile');
const {compileCss, cssEntryPoints} = require('./css');
const {compileJison} = require('./compile-jison');
const {formatExtractedMessages} = require('../compile/log-messages');
const {maybeUpdatePackages} = require('./update-packages');
const {VERSION} = require('../compile/internal-version');

const {green, cyan} = colors;
const argv = require('minimist')(process.argv.slice(2));

const WEB_PUSH_PUBLISHER_FILES = [
  'amp-web-push-helper-frame',
  'amp-web-push-permission-dialog',
];

const WEB_PUSH_PUBLISHER_VERSIONS = ['0.1'];

/**
 * Prints a useful help message prior to the gulp dist task
 */
function printDistHelp() {
  if (argv.fortesting) {
    let cmd = 'gulp dist --fortesting';
    if (argv.single_pass) {
      cmd = cmd + ' --single_pass';
    }
    printConfigHelp(cmd);
  }
  if (argv.single_pass) {
    log(
      green('Building all AMP extensions in'),
      cyan('single_pass'),
      green('mode.')
    );
  } else {
    parseExtensionFlags();
  }
}

/**
 * Dist Build
 * @return {!Promise}
 */
async function dist() {
  maybeUpdatePackages();
  const handlerProcess = createCtrlcHandler('dist');
  process.env.NODE_ENV = 'production';
  printNobuildHelp();
  printDistHelp();

  cleanupBuildDir();
  await prebuild();
  await compileCss();
  await compileJison();

  // This is the temp directory processing for multi-pass (single-pass does its
  // own processing). Executed after `compileCss` and `compileJison` so their
  // results can be copied too.
  if (!argv.single_pass) {
    transferSrcsToTempDir({isForTesting: argv.fortesting});
  }

  await copyCss();
  await copyParsers();
  await bootstrapThirdPartyFrames(/* watch */ false, /* minify */ true);

  // Steps that use closure compiler. Small ones before large (parallel) ones.
  await startNailgunServer(distNailgunPort, /* detached */ false);
  if (argv.core_runtime_only) {
    await compileCoreRuntime(/* watch */ false, /* minify */ true);
  } else {
    await buildExperiments({minify: true, watch: false});
    await buildLoginDone('0.1', {minify: true, watch: false});
    await buildWebPushPublisherFiles({minify: true, watch: false});
    await compileAllMinifiedJs();
    await buildExtensions({minify: true, watch: false});
  }
  await stopNailgunServer(distNailgunPort);

  if (argv.esm) {
    await Promise.all([
      createModuleCompatibleES5Bundle('v0.js'),
      createModuleCompatibleES5Bundle('amp4ads-v0.js'),
      createModuleCompatibleES5Bundle('shadow-v0.js'),
    ]);
  }

  if (!argv.core_runtime_only) {
    await formatExtractedMessages();
    await generateFileListing();
  }
  return exitCtrlcHandler(handlerProcess);
}

/**
 * Build AMP experiments.js.
 *
 * @param {!Object} options
 * @return {!Promise}
 */
function buildExperiments(options) {
  return compileJs(
    './build/experiments/',
    'experiments.max.js',
    './dist.tools/experiments/',
    {
      watch: false,
      minify: options.minify || argv.minify,
      includePolyfills: true,
      minifiedName: 'experiments.js',
    }
  );
}

/**
 * Build amp-login-done-${version}.js file.
 *
 * @param {string} version
 * @param {!Object} options
 * @return {!Promise}
 */
function buildLoginDone(version, options) {
  const buildDir = `build/all/amp-access-${version}/`;
  const builtName = `amp-login-done-${version}.max.js`;
  const minifiedName = `amp-login-done-${version}.js`;
  const latestName = 'amp-login-done-latest.js';
  return compileJs('./' + buildDir, builtName, './dist/v0/', {
    watch: false,
    includePolyfills: true,
    minify: options.minify || argv.minify,
    minifiedName,
    latestName,
    extraGlobs: [
      buildDir + 'amp-login-done-0.1.max.js',
      buildDir + 'amp-login-done-dialog.js',
    ],
  });
}

/**
 * Build amp-web-push publisher files HTML page.
 *
 * @param {!Object} options
 */
async function buildWebPushPublisherFiles(options) {
  const distDir = 'dist/v0';
  const promises = [];
  WEB_PUSH_PUBLISHER_VERSIONS.forEach(version => {
    WEB_PUSH_PUBLISHER_FILES.forEach(fileName => {
      const tempBuildDir = `build/all/amp-web-push-${version}/`;
      const builtName = fileName + '.js';
      const minifiedName = fileName + '.js';
      const p = compileJs('./' + tempBuildDir, builtName, './' + distDir, {
        watch: options.watch,
        includePolyfills: true,
        minify: options.minify || argv.minify,
        minifiedName,
        extraGlobs: [tempBuildDir + '*.js'],
      });
      promises.push(p);
    });
  });
  await Promise.all(promises);
  await postBuildWebPushPublisherFilesVersion();
}

async function prebuild() {
  await preBuildExperiments();
  await preBuildLoginDone();
  await preBuildWebPushPublisherFiles();
}

/**
 * Copies the css from the build folder to the dist folder
 * @return {!Promise}
 */
function copyCss() {
  const startTime = Date.now();

  cssEntryPoints.forEach(({outCss}) => {
    fs.copySync(`build/css/${outCss}`, `dist/${outCss}`);
  });

  return toPromise(
    gulp
      .src('build/css/amp-*.css', {base: 'build/css/'})
      .pipe(gulp.dest('dist/v0'))
  ).then(() => {
    endBuildStep('Copied', 'build/css/*.css to dist/v0/*.css', startTime);
  });
}

/**
 * Copies parsers from the build folder to the dist folder
 * @return {!Promise}
 */
function copyParsers() {
  const startTime = Date.now();
  return fs.copy('build/parsers', 'dist/v0').then(() => {
    endBuildStep('Copied', 'build/parsers/ to dist/v0', startTime);
  });
}

/**
 * Obtain a recursive file listing of a directory
 * @param {string} dest - Directory to be scanned
 * @return {Array} - All files found in directory
 */
async function walk(dest) {
  const filelist = [];
  const files = await fs.readdir(dest);

  for (let i = 0; i < files.length; i++) {
    const file = `${dest}/${files[i]}`;

    fs.statSync(file).isDirectory()
      ? Array.prototype.push.apply(filelist, await walk(file))
      : filelist.push(file);
  }

  return filelist;
}

/**
 * Generate a listing of all files in dist/ and save as dist/files.txt
 */
async function generateFileListing() {
  const startTime = Date.now();
  const distDir = 'dist';
  const filesOut = `${distDir}/files.txt`;
  fs.writeFileSync(filesOut, '');
  const files = (await walk(distDir)).map(f => f.replace(`${distDir}/`, ''));
  fs.writeFileSync(filesOut, files.join('\n'));
  endBuildStep('Generated', filesOut, startTime);
}

/**
 * Build amp-web-push publisher files HTML page.
 *
 * @return {!Promise<!Array>}
 */
async function preBuildWebPushPublisherFiles() {
  mkdirSync('dist');
  mkdirSync('dist/v0');
  const promises = [];

  WEB_PUSH_PUBLISHER_VERSIONS.forEach(version => {
    WEB_PUSH_PUBLISHER_FILES.forEach(fileName => {
      const basePath = `extensions/amp-web-push/${version}/`;
      const tempBuildDir = `build/all/amp-web-push-${version}/`;

      // Build Helper Frame JS
      const js = fs.readFileSync(basePath + fileName + '.js', 'utf8');
      const builtName = fileName + '.js';
      const promise = toPromise(
        gulp
          .src(basePath + '/*.js', {base: basePath})
          .pipe(file(builtName, js))
          .pipe(gulp.dest(tempBuildDir))
      );
      promises.push(promise);
    });
  });
  return Promise.all(promises);
}

/**
 * post Build amp-web-push publisher files HTML page.
 */
function postBuildWebPushPublisherFilesVersion() {
  const distDir = 'dist/v0';
  WEB_PUSH_PUBLISHER_VERSIONS.forEach(version => {
    const basePath = `extensions/amp-web-push/${version}/`;
    WEB_PUSH_PUBLISHER_FILES.forEach(fileName => {
      const minifiedName = fileName + '.js';
      if (!fs.existsSync(distDir + '/' + minifiedName)) {
        throw new Error(`Cannot find ${distDir}/${minifiedName}`);
      }

      // Build Helper Frame HTML
      let fileContents = fs.readFileSync(basePath + fileName + '.html', 'utf8');
      fileContents = fileContents.replace(
        '<!-- [GULP-MAGIC-REPLACE ' + fileName + '.js] -->',
        '<script>' +
          fs.readFileSync(distDir + '/' + minifiedName, 'utf8') +
          '</script>'
      );

      fs.writeFileSync('dist/v0/' + fileName + '.html', fileContents);
    });
  });
}

/**
 * Precompilation steps required to build experiment js binaries.
 * @return {!Promise}
 */
async function preBuildExperiments() {
  const path = 'tools/experiments';
  const htmlPath = path + '/experiments.html';
  const jsPath = path + '/experiments.js';

  // Build HTML.
  const html = fs.readFileSync(htmlPath, 'utf8');
  const minHtml = html
    .replace(
      '/dist.tools/experiments/experiments.js',
      `https://${hostname}/v0/experiments.js`
    )
    .replace(/\$internalRuntimeVersion\$/g, VERSION);

  await toPromise(
    gulp
      .src(htmlPath)
      .pipe(file('experiments.cdn.html', minHtml))
      .pipe(gulp.dest('dist.tools/experiments/'))
  );

  // Build JS.
  const js = fs.readFileSync(jsPath, 'utf8');
  const builtName = 'experiments.max.js';
  return toPromise(
    gulp
      .src(path + '/*.js')
      .pipe(file(builtName, js))
      .pipe(gulp.dest('build/experiments/'))
  );
}

/**
 * Build "Login Done" page.
 * @return {!Promise}
 */
function preBuildLoginDone() {
  return preBuildLoginDoneVersion('0.1');
}

/**
 * Build "Login Done" page for the specified version.
 *
 * @param {string} version
 * @return {!Promise}
 */
function preBuildLoginDoneVersion(version) {
  const path = `extensions/amp-access/${version}/`;
  const buildDir = `build/all/amp-access-${version}/`;
  const htmlPath = path + 'amp-login-done.html';
  const jsPath = path + 'amp-login-done.js';

  // Build HTML.
  const html = fs.readFileSync(htmlPath, 'utf8');
  const minJs = `https://${hostname}/v0/amp-login-done-${version}.js`;
  const minHtml = html
    .replace(`../../../dist/v0/amp-login-done-${version}.max.js`, minJs)
    .replace(`../../../dist/v0/amp-login-done-${version}.js`, minJs);
  if (minHtml.indexOf(minJs) == -1) {
    throw new Error('Failed to correctly set JS in login-done.html');
  }

  mkdirSync('dist');
  mkdirSync('dist/v0');

  fs.writeFileSync('dist/v0/amp-login-done-' + version + '.html', minHtml);

  // Build JS.
  const js = fs.readFileSync(jsPath, 'utf8');
  const builtName = 'amp-login-done-' + version + '.max.js';
  return toPromise(
    gulp
      .src(path + '/*.js', {base: path})
      .pipe(file(builtName, js))
      .pipe(gulp.dest(buildDir))
  );
}

module.exports = {
  dist,
};

/* eslint "google-camelcase/google-camelcase": 0 */

dist.description = 'Build production binaries';
dist.flags = {
  pseudo_names:
    '  Compiles with readable names. ' +
    'Great for profiling and debugging production code.',
  pretty_print:
    '  Outputs compiled code with whitespace. ' +
    'Great for debugging production code.',
  fortesting: '  Compiles production binaries for local testing',
  config: '  Sets the runtime\'s AMP_CONFIG to one of "prod" or "canary"',
  single_pass: "Compile AMP's primary JS bundles in a single invocation",
  extensions: '  Builds only the listed extensions.',
  extensions_from: '  Builds only the extensions from the listed AMP(s).',
  noextensions: '  Builds with no extensions.',
  core_runtime_only: '  Builds only the core runtime.',
  single_pass_dest:
    '  The directory closure compiler will write out to ' +
    'with --single_pass mode. The default directory is `dist`',
  full_sourcemaps: '  Includes source code content in sourcemaps',
  disable_nailgun:
    "  Doesn't use nailgun to invoke closure compiler (much slower)",
};
<commit_msg>Add terminal newline to files.txt (#26513)<commit_after>/**
 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const colors = require('ansi-colors');
const file = require('gulp-file');
const fs = require('fs-extra');
const gulp = require('gulp');
const log = require('fancy-log');
const {
  bootstrapThirdPartyFrames,
  compileAllMinifiedJs,
  compileCoreRuntime,
  compileJs,
  endBuildStep,
  hostname,
  mkdirSync,
  printConfigHelp,
  printNobuildHelp,
  toPromise,
  transferSrcsToTempDir,
} = require('./helpers');
const {
  createCtrlcHandler,
  exitCtrlcHandler,
} = require('../common/ctrlcHandler');
const {
  createModuleCompatibleES5Bundle,
} = require('./create-module-compatible-es5-bundle');
const {
  distNailgunPort,
  startNailgunServer,
  stopNailgunServer,
} = require('./nailgun');
const {buildExtensions, parseExtensionFlags} = require('./extension-helpers');
const {cleanupBuildDir} = require('../compile/compile');
const {compileCss, cssEntryPoints} = require('./css');
const {compileJison} = require('./compile-jison');
const {formatExtractedMessages} = require('../compile/log-messages');
const {maybeUpdatePackages} = require('./update-packages');
const {VERSION} = require('../compile/internal-version');

const {green, cyan} = colors;
const argv = require('minimist')(process.argv.slice(2));

const WEB_PUSH_PUBLISHER_FILES = [
  'amp-web-push-helper-frame',
  'amp-web-push-permission-dialog',
];

const WEB_PUSH_PUBLISHER_VERSIONS = ['0.1'];

/**
 * Prints a useful help message prior to the gulp dist task
 */
function printDistHelp() {
  if (argv.fortesting) {
    let cmd = 'gulp dist --fortesting';
    if (argv.single_pass) {
      cmd = cmd + ' --single_pass';
    }
    printConfigHelp(cmd);
  }
  if (argv.single_pass) {
    log(
      green('Building all AMP extensions in'),
      cyan('single_pass'),
      green('mode.')
    );
  } else {
    parseExtensionFlags();
  }
}

/**
 * Dist Build
 * @return {!Promise}
 */
async function dist() {
  maybeUpdatePackages();
  const handlerProcess = createCtrlcHandler('dist');
  process.env.NODE_ENV = 'production';
  printNobuildHelp();
  printDistHelp();

  cleanupBuildDir();
  await prebuild();
  await compileCss();
  await compileJison();

  // This is the temp directory processing for multi-pass (single-pass does its
  // own processing). Executed after `compileCss` and `compileJison` so their
  // results can be copied too.
  if (!argv.single_pass) {
    transferSrcsToTempDir({isForTesting: argv.fortesting});
  }

  await copyCss();
  await copyParsers();
  await bootstrapThirdPartyFrames(/* watch */ false, /* minify */ true);

  // Steps that use closure compiler. Small ones before large (parallel) ones.
  await startNailgunServer(distNailgunPort, /* detached */ false);
  if (argv.core_runtime_only) {
    await compileCoreRuntime(/* watch */ false, /* minify */ true);
  } else {
    await buildExperiments({minify: true, watch: false});
    await buildLoginDone('0.1', {minify: true, watch: false});
    await buildWebPushPublisherFiles({minify: true, watch: false});
    await compileAllMinifiedJs();
    await buildExtensions({minify: true, watch: false});
  }
  await stopNailgunServer(distNailgunPort);

  if (argv.esm) {
    await Promise.all([
      createModuleCompatibleES5Bundle('v0.js'),
      createModuleCompatibleES5Bundle('amp4ads-v0.js'),
      createModuleCompatibleES5Bundle('shadow-v0.js'),
    ]);
  }

  if (!argv.core_runtime_only) {
    await formatExtractedMessages();
    await generateFileListing();
  }
  return exitCtrlcHandler(handlerProcess);
}

/**
 * Build AMP experiments.js.
 *
 * @param {!Object} options
 * @return {!Promise}
 */
function buildExperiments(options) {
  return compileJs(
    './build/experiments/',
    'experiments.max.js',
    './dist.tools/experiments/',
    {
      watch: false,
      minify: options.minify || argv.minify,
      includePolyfills: true,
      minifiedName: 'experiments.js',
    }
  );
}

/**
 * Build amp-login-done-${version}.js file.
 *
 * @param {string} version
 * @param {!Object} options
 * @return {!Promise}
 */
function buildLoginDone(version, options) {
  const buildDir = `build/all/amp-access-${version}/`;
  const builtName = `amp-login-done-${version}.max.js`;
  const minifiedName = `amp-login-done-${version}.js`;
  const latestName = 'amp-login-done-latest.js';
  return compileJs('./' + buildDir, builtName, './dist/v0/', {
    watch: false,
    includePolyfills: true,
    minify: options.minify || argv.minify,
    minifiedName,
    latestName,
    extraGlobs: [
      buildDir + 'amp-login-done-0.1.max.js',
      buildDir + 'amp-login-done-dialog.js',
    ],
  });
}

/**
 * Build amp-web-push publisher files HTML page.
 *
 * @param {!Object} options
 */
async function buildWebPushPublisherFiles(options) {
  const distDir = 'dist/v0';
  const promises = [];
  WEB_PUSH_PUBLISHER_VERSIONS.forEach(version => {
    WEB_PUSH_PUBLISHER_FILES.forEach(fileName => {
      const tempBuildDir = `build/all/amp-web-push-${version}/`;
      const builtName = fileName + '.js';
      const minifiedName = fileName + '.js';
      const p = compileJs('./' + tempBuildDir, builtName, './' + distDir, {
        watch: options.watch,
        includePolyfills: true,
        minify: options.minify || argv.minify,
        minifiedName,
        extraGlobs: [tempBuildDir + '*.js'],
      });
      promises.push(p);
    });
  });
  await Promise.all(promises);
  await postBuildWebPushPublisherFilesVersion();
}

async function prebuild() {
  await preBuildExperiments();
  await preBuildLoginDone();
  await preBuildWebPushPublisherFiles();
}

/**
 * Copies the css from the build folder to the dist folder
 * @return {!Promise}
 */
function copyCss() {
  const startTime = Date.now();

  cssEntryPoints.forEach(({outCss}) => {
    fs.copySync(`build/css/${outCss}`, `dist/${outCss}`);
  });

  return toPromise(
    gulp
      .src('build/css/amp-*.css', {base: 'build/css/'})
      .pipe(gulp.dest('dist/v0'))
  ).then(() => {
    endBuildStep('Copied', 'build/css/*.css to dist/v0/*.css', startTime);
  });
}

/**
 * Copies parsers from the build folder to the dist folder
 * @return {!Promise}
 */
function copyParsers() {
  const startTime = Date.now();
  return fs.copy('build/parsers', 'dist/v0').then(() => {
    endBuildStep('Copied', 'build/parsers/ to dist/v0', startTime);
  });
}

/**
 * Obtain a recursive file listing of a directory
 * @param {string} dest - Directory to be scanned
 * @return {Array} - All files found in directory
 */
async function walk(dest) {
  const filelist = [];
  const files = await fs.readdir(dest);

  for (let i = 0; i < files.length; i++) {
    const file = `${dest}/${files[i]}`;

    fs.statSync(file).isDirectory()
      ? Array.prototype.push.apply(filelist, await walk(file))
      : filelist.push(file);
  }

  return filelist;
}

/**
 * Generate a listing of all files in dist/ and save as dist/files.txt
 */
async function generateFileListing() {
  const startTime = Date.now();
  const distDir = 'dist';
  const filesOut = `${distDir}/files.txt`;
  fs.writeFileSync(filesOut, '');
  const files = (await walk(distDir)).map(f => f.replace(`${distDir}/`, ''));
  fs.writeFileSync(filesOut, files.join('\n') + '\n');
  endBuildStep('Generated', filesOut, startTime);
}

/**
 * Build amp-web-push publisher files HTML page.
 *
 * @return {!Promise<!Array>}
 */
async function preBuildWebPushPublisherFiles() {
  mkdirSync('dist');
  mkdirSync('dist/v0');
  const promises = [];

  WEB_PUSH_PUBLISHER_VERSIONS.forEach(version => {
    WEB_PUSH_PUBLISHER_FILES.forEach(fileName => {
      const basePath = `extensions/amp-web-push/${version}/`;
      const tempBuildDir = `build/all/amp-web-push-${version}/`;

      // Build Helper Frame JS
      const js = fs.readFileSync(basePath + fileName + '.js', 'utf8');
      const builtName = fileName + '.js';
      const promise = toPromise(
        gulp
          .src(basePath + '/*.js', {base: basePath})
          .pipe(file(builtName, js))
          .pipe(gulp.dest(tempBuildDir))
      );
      promises.push(promise);
    });
  });
  return Promise.all(promises);
}

/**
 * post Build amp-web-push publisher files HTML page.
 */
function postBuildWebPushPublisherFilesVersion() {
  const distDir = 'dist/v0';
  WEB_PUSH_PUBLISHER_VERSIONS.forEach(version => {
    const basePath = `extensions/amp-web-push/${version}/`;
    WEB_PUSH_PUBLISHER_FILES.forEach(fileName => {
      const minifiedName = fileName + '.js';
      if (!fs.existsSync(distDir + '/' + minifiedName)) {
        throw new Error(`Cannot find ${distDir}/${minifiedName}`);
      }

      // Build Helper Frame HTML
      let fileContents = fs.readFileSync(basePath + fileName + '.html', 'utf8');
      fileContents = fileContents.replace(
        '<!-- [GULP-MAGIC-REPLACE ' + fileName + '.js] -->',
        '<script>' +
          fs.readFileSync(distDir + '/' + minifiedName, 'utf8') +
          '</script>'
      );

      fs.writeFileSync('dist/v0/' + fileName + '.html', fileContents);
    });
  });
}

/**
 * Precompilation steps required to build experiment js binaries.
 * @return {!Promise}
 */
async function preBuildExperiments() {
  const path = 'tools/experiments';
  const htmlPath = path + '/experiments.html';
  const jsPath = path + '/experiments.js';

  // Build HTML.
  const html = fs.readFileSync(htmlPath, 'utf8');
  const minHtml = html
    .replace(
      '/dist.tools/experiments/experiments.js',
      `https://${hostname}/v0/experiments.js`
    )
    .replace(/\$internalRuntimeVersion\$/g, VERSION);

  await toPromise(
    gulp
      .src(htmlPath)
      .pipe(file('experiments.cdn.html', minHtml))
      .pipe(gulp.dest('dist.tools/experiments/'))
  );

  // Build JS.
  const js = fs.readFileSync(jsPath, 'utf8');
  const builtName = 'experiments.max.js';
  return toPromise(
    gulp
      .src(path + '/*.js')
      .pipe(file(builtName, js))
      .pipe(gulp.dest('build/experiments/'))
  );
}

/**
 * Build "Login Done" page.
 * @return {!Promise}
 */
function preBuildLoginDone() {
  return preBuildLoginDoneVersion('0.1');
}

/**
 * Build "Login Done" page for the specified version.
 *
 * @param {string} version
 * @return {!Promise}
 */
function preBuildLoginDoneVersion(version) {
  const path = `extensions/amp-access/${version}/`;
  const buildDir = `build/all/amp-access-${version}/`;
  const htmlPath = path + 'amp-login-done.html';
  const jsPath = path + 'amp-login-done.js';

  // Build HTML.
  const html = fs.readFileSync(htmlPath, 'utf8');
  const minJs = `https://${hostname}/v0/amp-login-done-${version}.js`;
  const minHtml = html
    .replace(`../../../dist/v0/amp-login-done-${version}.max.js`, minJs)
    .replace(`../../../dist/v0/amp-login-done-${version}.js`, minJs);
  if (minHtml.indexOf(minJs) == -1) {
    throw new Error('Failed to correctly set JS in login-done.html');
  }

  mkdirSync('dist');
  mkdirSync('dist/v0');

  fs.writeFileSync('dist/v0/amp-login-done-' + version + '.html', minHtml);

  // Build JS.
  const js = fs.readFileSync(jsPath, 'utf8');
  const builtName = 'amp-login-done-' + version + '.max.js';
  return toPromise(
    gulp
      .src(path + '/*.js', {base: path})
      .pipe(file(builtName, js))
      .pipe(gulp.dest(buildDir))
  );
}

module.exports = {
  dist,
};

/* eslint "google-camelcase/google-camelcase": 0 */

dist.description = 'Build production binaries';
dist.flags = {
  pseudo_names:
    '  Compiles with readable names. ' +
    'Great for profiling and debugging production code.',
  pretty_print:
    '  Outputs compiled code with whitespace. ' +
    'Great for debugging production code.',
  fortesting: '  Compiles production binaries for local testing',
  config: '  Sets the runtime\'s AMP_CONFIG to one of "prod" or "canary"',
  single_pass: "Compile AMP's primary JS bundles in a single invocation",
  extensions: '  Builds only the listed extensions.',
  extensions_from: '  Builds only the extensions from the listed AMP(s).',
  noextensions: '  Builds with no extensions.',
  core_runtime_only: '  Builds only the core runtime.',
  single_pass_dest:
    '  The directory closure compiler will write out to ' +
    'with --single_pass mode. The default directory is `dist`',
  full_sourcemaps: '  Includes source code content in sourcemaps',
  disable_nailgun:
    "  Doesn't use nailgun to invoke closure compiler (much slower)",
};
<|endoftext|>


<commit_before>/* jshint -W097 */// jshint strict:false
/*jslint node: true */

"use strict";

var utils   = require(__dirname + '/lib/utils'); // Get common adapter utils

var channels = [];
var iopkg;

var adapter = utils.adapter({
    name: 'feiertage',
    useFormatDate: true,
    /*
    unload: function (callback) {
        adapter.log.info("adapter feiertage is unloading");
    },
    discover: function (callback) {
        adapter.log.info("adapter feiertage discovered");
    },
    install: function (callback) {
        adapter.log.info("adapter feiertage installed");
    },
    uninstall: function (callback) {
        adapter.log.info("adapter feiertage UN-installed");
    }, */
    ready: function () {
        adapter.log.debug("Adapter feiertage got 'Ready' Signal");
        adapter.log.debug("adapter feiertage initializing objects");
        checkHolidays();
        adapter.log.info("adapter feiertage objects written");

        setTimeout(function () {
            adapter.log.info('force terminating after 4 minutes');
            adapter.stop();
        }, 240000);
    }
});

// Script ermittelt, ob heute oder morgen ein Feiertag ist
var sj;                 // Schaltjahr
var ostern;             // Ostersonntag: Tag im Jahr

// Regional nicht relevante Feiertage auskommentieren oder löschen !!
function feiertag(day) {
    var Name = '';
    if (day == 1) Name = 'Neujahr';
    else if (day == 6) Name = 'Heilige Drei Könige (BW,BY,ST)';
    else if (sj + 121 == day) Name = 'Maifeiertag';
    else if (day == sj + 227) Name = 'Maria Himmelfahrt (BY (nicht überall), SL)';
    else if (day == sj + 276) Name = 'Tag der dt. Einheit';
    else if (day == sj + 304) Name = 'Reformationstag (BB, MV, SA, ST,TH)';
    else if (day == sj + 305) Name = 'Allerheiligen (BW, BY, NW, RP, SL)';
    else if (day == sj + 358) Name = 'Heiligabend';
    else if (day == sj + 359) Name = '1. Weihnachtstag';
    else if (day == sj + 360) Name = '2. Weihnachtstag';
    else if (day == sj + 365) Name = 'Silvester';

    else if (day == ostern - 48) Name = 'Rosenmontag';
    else if (day == ostern -  2) Name = 'Karfreitag';
    else if (day == ostern)      Name = 'Ostersonntag';
    else if (day == ostern +  1) Name = 'Ostermontag';
    else if (day == ostern + 39) Name = 'Christi Himmelfahrt';
    else if (day == ostern + 49) Name = 'Pfingstsonntag';
    else if (day == ostern + 50) Name = 'Pfingstmontag';
    else if (day == ostern + 60) Name = 'Fronleichnam (BW, BY, HE, NW, RP, SL (SA, TH nicht überall))';
    else Name = '';
    return (Name);

}

function tagdesjahresZudatum (day) {
    var day_ms = (day - sj) * 24 * 60 * 60 * 1000;                              // Tag des Jahres in Millisekunden seit Neujahr Mitternacht
    var jetzt = new Date();
    var Jahr = jetzt.getFullYear();
    var neujahr = new Date(Jahr,0,1,0,0,0,0);                                   // Dies Jahr Neujahr Mitternacht
    var neujahr_ms = neujahr.getTime();

    var datum = new Date();
    datum.setTime(neujahr_ms + day_ms);                                         // Addition Neujahr in ms plus Tag des Jahres in ms = gesuchtes Datum in ms
    return(datum);
}

// auf Feiertag testen
function checkHolidays() {
   var jetzt = new Date();
   var Jahr = jetzt.getFullYear();
   sj = (Jahr % 4 === 0) ? 1 : 0;

// Die modifizierte Gauss-Formel nach Lichtenberg, gültig bis 2048
    var A = 120 + (19 * (Jahr % 19) + 24) % 30;
    var B = (A + parseInt(5 * Jahr / 4)) % 7;
    ostern = A - B - 33 + sj;

// Tag des Jahres
   var heutestart = new Date(jetzt.setHours(0,0,0,0));
   var neujahr = new Date(Jahr,0,1);
   var difftage = (heutestart - neujahr) / (24*60*60*1000) + 1;
   var tag = Math.ceil(difftage);

   // heute
   var istFeiertag;
   adapter.setState("heute.Name", feiertag(tag));
   istFeiertag = (feiertag(tag).length < 2) ? false : true;
   adapter.setState("heute.boolean", istFeiertag);

   // morgen
   tag = tag + 1;
   if (tag > 365 + sj) tag = 1;
   adapter.setState("morgen.Name", feiertag(tag));
   istFeiertag = (feiertag(tag).length < 2) ? false : true;
   adapter.setState("morgen.boolean", istFeiertag);

   // übermorgen
   tag = tag + 1;
   if (tag > 365 + sj) tag = 1;
   adapter.setState("uebermorgen.Name", feiertag(tag));
   istFeiertag = (feiertag(tag).length < 2) ? false : true;
   adapter.setState("uebermorgen.boolean", istFeiertag);

   // nächster Feiertag
   var noch = 0;
   while (feiertag(tag).length < 2) {
       tag = tag + 1;
       noch = noch + 1;
       istFeiertag = (feiertag(tag).length < 2) ? false : true;
       if (istFeiertag) {
           var datum_tdj = tagdesjahresZudatum(tag);
           adapter.setState("naechster.Name", feiertag(tag));
           adapter.setState("naechster.Datum", formatDate(datum_tdj));
           adapter.log.info('Nächster Feiertag: '  + feiertag(tag) + ' in ' + noch + ' Tagen am ' + formatDate(datum_tdj));
           adapter.setState("naechster.Dauer", noch);
       }
   }
}
<commit_msg>Workaround für formatDate<commit_after>/* jshint -W097 */// jshint strict:false
/*jslint node: true */

"use strict";

var utils   = require(__dirname + '/lib/utils'); // Get common adapter utils

var channels = [];
var iopkg;

var adapter = utils.adapter({
    name: 'feiertage',
    useFormatDate: true,
    /*
    unload: function (callback) {
        adapter.log.info("adapter feiertage is unloading");
    },
    discover: function (callback) {
        adapter.log.info("adapter feiertage discovered");
    },
    install: function (callback) {
        adapter.log.info("adapter feiertage installed");
    },
    uninstall: function (callback) {
        adapter.log.info("adapter feiertage UN-installed");
    }, */
    ready: function () {
        adapter.log.debug("Adapter feiertage got 'Ready' Signal");
        adapter.log.debug("adapter feiertage initializing objects");
        checkHolidays();
        adapter.log.info("adapter feiertage objects written");

        setTimeout(function () {
            adapter.log.info('force terminating after 4 minutes');
            adapter.stop();
        }, 240000);
    }
});

// Script ermittelt, ob heute oder morgen ein Feiertag ist
var sj;                 // Schaltjahr
var ostern;             // Ostersonntag: Tag im Jahr

// Regional nicht relevante Feiertage auskommentieren oder löschen !!
function feiertag(day) {
    var Name = '';
    if (day == 1) Name = 'Neujahr';
    else if (day == 6) Name = 'Heilige Drei Könige (BW,BY,ST)';
    else if (sj + 121 == day) Name = 'Maifeiertag';
    else if (day == sj + 227) Name = 'Maria Himmelfahrt (BY (nicht überall), SL)';
    else if (day == sj + 276) Name = 'Tag der dt. Einheit';
    else if (day == sj + 304) Name = 'Reformationstag (BB, MV, SA, ST,TH)';
    else if (day == sj + 305) Name = 'Allerheiligen (BW, BY, NW, RP, SL)';
    else if (day == sj + 358) Name = 'Heiligabend';
    else if (day == sj + 359) Name = '1. Weihnachtstag';
    else if (day == sj + 360) Name = '2. Weihnachtstag';
    else if (day == sj + 365) Name = 'Silvester';

    else if (day == ostern - 48) Name = 'Rosenmontag';
    else if (day == ostern -  2) Name = 'Karfreitag';
    else if (day == ostern)      Name = 'Ostersonntag';
    else if (day == ostern +  1) Name = 'Ostermontag';
    else if (day == ostern + 39) Name = 'Christi Himmelfahrt';
    else if (day == ostern + 49) Name = 'Pfingstsonntag';
    else if (day == ostern + 50) Name = 'Pfingstmontag';
    else if (day == ostern + 60) Name = 'Fronleichnam (BW, BY, HE, NW, RP, SL (SA, TH nicht überall))';
    else Name = '';
    return (Name);

}

function tagdesjahresZudatum (day) {
    var day_ms = (day - sj) * 24 * 60 * 60 * 1000;                              // Tag des Jahres in Millisekunden seit Neujahr Mitternacht
    var jetzt = new Date();
    var Jahr = jetzt.getFullYear();
    var neujahr = new Date(Jahr,0,1,0,0,0,0);                                   // Dies Jahr Neujahr Mitternacht
    var neujahr_ms = neujahr.getTime();

    var datum = new Date();
    datum.setTime(neujahr_ms + day_ms);                                         // Addition Neujahr in ms plus Tag des Jahres in ms = gesuchtes Datum in ms
    return(datum);
}

// auf Feiertag testen
function checkHolidays() {
   var jetzt = new Date();
   var Jahr = jetzt.getFullYear();
   sj = (Jahr % 4 === 0) ? 1 : 0;

// Die modifizierte Gauss-Formel nach Lichtenberg, gültig bis 2048
    var A = 120 + (19 * (Jahr % 19) + 24) % 30;
    var B = (A + parseInt(5 * Jahr / 4)) % 7;
    ostern = A - B - 33 + sj;

// Tag des Jahres
   var heutestart = new Date(jetzt.setHours(0,0,0,0));
   var neujahr = new Date(Jahr,0,1);
   var difftage = (heutestart - neujahr) / (24*60*60*1000) + 1;
   var tag = Math.ceil(difftage);

   // heute
   var istFeiertag;
   adapter.setState("heute.Name", feiertag(tag));
   istFeiertag = (feiertag(tag).length < 2) ? false : true;
   adapter.setState("heute.boolean", istFeiertag);

   // morgen
   tag = tag + 1;
   if (tag > 365 + sj) tag = 1;
   adapter.setState("morgen.Name", feiertag(tag));
   istFeiertag = (feiertag(tag).length < 2) ? false : true;
   adapter.setState("morgen.boolean", istFeiertag);

   // übermorgen
   tag = tag + 1;
   if (tag > 365 + sj) tag = 1;
   adapter.setState("uebermorgen.Name", feiertag(tag));
   istFeiertag = (feiertag(tag).length < 2) ? false : true;
   adapter.setState("uebermorgen.boolean", istFeiertag);

   // nächster Feiertag
   var noch = 0;
   while (feiertag(tag).length < 2) {
       tag = tag + 1;
       noch = noch + 1;
       istFeiertag = (feiertag(tag).length < 2) ? false : true;
       if (istFeiertag) {
           var datum_tdj = tagdesjahresZudatum(tag);
           adapter.setState("naechster.Name", feiertag(tag));

           // Workaround für formatDate
           var next_ft_jahr = datum_tdj.getFullYear();
           var next_ft_monat = ( (datum_tdj.getMonth() + 1) < 10) ? '0' + (datum_tdj.getMonth() + 1) : (datum_tdj.getMonth() + 1);
           var next_ft_tag = ( datum_tdj.getDate() < 10) ? '0' + datum_tdj.getDate() : datum_tdj.getDate();
           var next_ft = next_ft_tag + '.' + next_ft_monat + '.' + next_ft_jahr;
           adapter.log.info('Nächster Feiertag: '  + feiertag(tag) + ' in ' + noch + ' Tagen am ' + next_ft);
           adapter.setState("naechster.Datum", next_ft);
           // Ende Workaround

           //adapter.setState("naechster.Datum", formatDate(datum_tdj));
           //adapter.log.info('Nächster Feiertag: '  + feiertag(tag) + ' in ' + noch + ' Tagen am ' + formatDate(datum_tdj));
           adapter.setState("naechster.Dauer", noch);
       }
   }
}
<|endoftext|>