text:
#include <gtest/gtest.h>

#include "sca/ASTHelpers.h"
#include "shaders/ShaderGenerator.h"

#include "MockIncluder.h"

#include <filamat/Enums.h>

#include <utils/JobSystem.h>

#include <memory>

using namespace utils;
using namespace ASTUtils;
using namespace filament::backend;

static ::testing::AssertionResult PropertyListsMatch(const MaterialBuilder::PropertyList& expected,
        const MaterialBuilder::PropertyList& actual) {
    for (size_t i = 0; i < MaterialBuilder::MATERIAL_PROPERTIES_COUNT; i++) {
        if (expected[i] != actual[i]) {
            const auto& propString = Enums::toString<Property>(Property(i));
            return ::testing::AssertionFailure()
                    << "actual[" << propString << "] (" << actual[i]
                    << ") != expected[" << propString << "] (" << expected[i] << ")";
        }
    }
    return ::testing::AssertionSuccess();
}

std::string shaderWithAllProperties(JobSystem& jobSystem, ShaderStage type,
        const std::string& fragmentCode, const std::string& vertexCode = "",
        filamat::MaterialBuilder::Shading shadingModel = filamat::MaterialBuilder::Shading::LIT,
        filamat::MaterialBuilder::RefractionMode refractionMode = filamat::MaterialBuilder::RefractionMode::NONE,
        filamat::MaterialBuilder::VertexDomain vertexDomain = filamat::MaterialBuilder::VertexDomain::OBJECT) {
    MockIncluder includer;
    includer
            .sourceForInclude("modify_normal.h", "material.normal = vec3(0.8);");

    filamat::MaterialBuilder builder;
    builder.material(fragmentCode.c_str());
    builder.materialVertex(vertexCode.c_str());
    builder.platform(filamat::MaterialBuilder::Platform::MOBILE);
    builder.optimization(filamat::MaterialBuilder::Optimization::NONE);
    builder.shading(shadingModel);
    builder.includeCallback(includer);
    builder.refractionMode(refractionMode);
    builder.vertexDomain(vertexDomain);

    MaterialBuilder::PropertyList allProperties;
    std::fill_n(allProperties, MaterialBuilder::MATERIAL_PROPERTIES_COUNT, true);

    // We need to "build" the material to resolve any includes in user code.
    builder.build(jobSystem);

    return builder.peek(type, {
                    ShaderModel::MOBILE,
                    MaterialBuilder::TargetApi::OPENGL,
                    MaterialBuilder::TargetLanguage::GLSL
            },
            allProperties);
}

TEST(StaticCodeAnalysisHelper, getFunctionName) {
    auto name = getFunctionName("main(");
    EXPECT_EQ(name, "main");
}

TEST(StaticCodeAnalysisHelper, getFunctionNameNoParenthesis) {
    auto name = getFunctionName("main");
    EXPECT_EQ(name, "main");
}

class MaterialCompiler : public ::testing::Test {
protected:
    MaterialCompiler() = default;

    ~MaterialCompiler() override = default;

    void SetUp() override {
        jobSystem = std::make_unique<JobSystem>();
        jobSystem->adopt();
        MaterialBuilder::init();
    }

    void TearDown() override {
        jobSystem->emancipate();
        MaterialBuilder::shutdown();
    }

    std::unique_ptr<JobSystem> jobSystem;
};

TEST_F(MaterialCompiler, StaticCodeAnalyzerNothingDetected) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerNothingDetectedVertex) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
        }
    )");
    std::string vertexCode(R"(
        void materialVertex(inout MaterialVertexInputs material) {
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::VERTEX,
            fragmentCode, vertexCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::VERTEX, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerNotFollowingINParameters) {
    std::string fragmentCode(R"(
        void notAffectingInput(in MaterialInputs material) {
            material.baseColor = vec4(0.8);
        }
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            notAffectingInput(material);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerDirectAssign) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.baseColor = vec4(0.8);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::BASE_COLOR)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerDirectAssignVertex) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
        }
    )");
    std::string vertexCode(R"(
        void materialVertex(inout MaterialVertexInputs material) {
            material.clipSpaceTransform = mat4(2.0);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::VERTEX,
            fragmentCode, vertexCode,
            MaterialBuilder::Shading::LIT,
            MaterialBuilder::RefractionMode::NONE,
            MaterialBuilder::VertexDomain::DEVICE);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::VERTEX, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::CLIP_SPACE_TRANSFORM)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerDirectAssignWithSwizzling) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.baseColor.rgb = vec3(0.8);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::BASE_COLOR)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerSymbolAsOutParameterWithAliasing) {
    std::string fragmentCode(R"(

        void setBaseColor(inout vec4 aliasBaseColor) {
            aliasBaseColor = vec4(0.8,0.1,0.2,1.0);
        }

        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            setBaseColor(material.baseColor);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::BASE_COLOR)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerSymbolAsOutParameterWithAliasingAndSwizzling) {
    std::string fragmentCode(R"(

        void setBaseColor(inout float aliasedRed) {
            aliasedRed = 0.8;
        }

        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            setBaseColor(material.baseColor.r);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::BASE_COLOR)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerSymbolInOutInChainWithDirectIndexIntoStruct) {
    std::string fragmentCode(R"(

        float setBaseColorOtherFunction(inout vec4 myBaseColor) {
            myBaseColor = vec4(0.8,0.1,0.2,1.0);
            return 1.0;
        }

        void setBaseColor(inout vec4 aliaseBaseColor) {
            setBaseColorOtherFunction(aliaseBaseColor);
        }

        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            setBaseColor(material.baseColor);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::BASE_COLOR)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerSymbolInOutInChain) {
    std::string fragmentCode(R"(

        float setBaseColorOtherFunction(inout MaterialInputs foo) {
            foo.baseColor = vec4(0.8,0.1,0.2,1.0);
            return 1.0;
        }

        void setBaseColor(inout MaterialInputs bar) {
            setBaseColorOtherFunction(bar);
        }

        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            setBaseColor(material);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::BASE_COLOR)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

// Tests all attributes in Property type.
TEST_F(MaterialCompiler, StaticCodeAnalyzerBaseColor) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.baseColor = vec4(0.8);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::BASE_COLOR)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerRoughness) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.roughness = 0.8;
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::ROUGHNESS)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerMetallic) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.metallic = 0.8;
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::METALLIC)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerReflectance) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.reflectance= 0.8;
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::REFLECTANCE)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerAmbientOcclusion) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.ambientOcclusion = 0.8;
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::AMBIENT_OCCLUSION)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerClearCoat) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.clearCoat = 0.8;
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::CLEAR_COAT)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerTransmission) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.absorption = vec3(0.0);
            material.transmission = 0.96;
            material.ior = 1.33;
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT, fragmentCode,
            "",
            filamat::MaterialBuilder::Shading::LIT,
            filamat::MaterialBuilder::RefractionMode::CUBEMAP);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::ABSORPTION)] = true;
    expected[size_t(filamat::MaterialBuilder::Property::TRANSMISSION)] = true;
    expected[size_t(filamat::MaterialBuilder::Property::IOR)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerClearCoatRoughness) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.clearCoatRoughness = 0.8;
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT, fragmentCode,
            "");

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::CLEAR_COAT_ROUGHNESS)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerClearCoatNormal) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.clearCoat = 0.8;
            material.clearCoatNormal = vec3(1.0, 1.0, 1.0);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT, fragmentCode,
            "");

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::CLEAR_COAT)] = true;
    expected[size_t(filamat::MaterialBuilder::Property::CLEAR_COAT_NORMAL)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerThickness) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.thickness= 0.8;
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT, fragmentCode,
            "",
            filamat::MaterialBuilder::Shading::SUBSURFACE);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::THICKNESS)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerSubsurfacePower) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.subsurfacePower = 0.8;
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT, fragmentCode,
            "",
            filamat::MaterialBuilder::Shading::SUBSURFACE);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::SUBSURFACE_POWER)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerSubsurfaceColor) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.subsurfaceColor= vec3(0.8);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT, fragmentCode,
            "",
            filamat::MaterialBuilder::Shading::SUBSURFACE);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::SUBSURFACE_COLOR)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerAnisotropicDirection) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.anisotropyDirection = vec3(0.8);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::ANISOTROPY_DIRECTION)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerAnisotropic) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.anisotropy = 0.8;
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::ANISOTROPY)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerSheenColor) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.sheenColor = vec3(0.8);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT, fragmentCode,
            "",
            filamat::MaterialBuilder::Shading::CLOTH);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::SHEEN_COLOR)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerSheenRoughness) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.sheenRoughness = 1.0;
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::SHEEN_ROUGHNESS)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerNormal) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.normal= vec3(0.8);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::NORMAL)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerBentNormal) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.bentNormal = vec3(0.8);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::BENT_NORMAL)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerOutputFactor) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            material.postLightingColor = vec4(1.0);
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::POST_LIGHTING_COLOR)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, StaticCodeAnalyzerWithinInclude) {
    std::string fragmentCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
            #include "modify_normal.h"
        }
    )");

    std::string shaderCode = shaderWithAllProperties(*jobSystem, ShaderStage::FRAGMENT,
            fragmentCode);

    GLSLTools glslTools;
    MaterialBuilder::PropertyList properties{ false };
    glslTools.findProperties(ShaderStage::FRAGMENT, shaderCode, properties);
    MaterialBuilder::PropertyList expected{ false };
    expected[size_t(filamat::MaterialBuilder::Property::NORMAL)] = true;
    EXPECT_TRUE(PropertyListsMatch(expected, properties));
}

TEST_F(MaterialCompiler, EmptyName) {
    std::string shaderCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
        }
    )");

    filamat::MaterialBuilder builder;
    builder.material(shaderCode.c_str());
    // The material should compile successfully with an empty name
    builder.name("");
    filamat::Package result = builder.build(*jobSystem);
}

TEST_F(MaterialCompiler, Uv0AndUv1) {
    filamat::MaterialBuilder builder;
    // Requiring both sets of UV coordinates should not fail.
    builder.require(filament::VertexAttribute::UV0);
    builder.require(filament::VertexAttribute::UV1);
    filamat::Package result = builder.build(*jobSystem);
    EXPECT_TRUE(result.isValid());
}

TEST_F(MaterialCompiler, Arrays) {
    filamat::MaterialBuilder builder;

    builder.parameter("f4", 1, UniformType::FLOAT4);
    builder.parameter("f1", 1, UniformType::FLOAT);

    filamat::Package result = builder.build(*jobSystem);
    EXPECT_TRUE(result.isValid());
}

TEST_F(MaterialCompiler, CustomSurfaceShadingRequiresLit) {
    filamat::MaterialBuilder builder;
    builder.customSurfaceShading(true);
    builder.shading(filament::Shading::UNLIT);
    filamat::Package result = builder.build(*jobSystem);
    EXPECT_FALSE(result.isValid());
}

TEST_F(MaterialCompiler, CustomSurfaceShadingRequiresFunction) {
    filamat::MaterialBuilder builder;
    builder.customSurfaceShading(true);
    builder.shading(filament::Shading::LIT);
    filamat::Package result = builder.build(*jobSystem);
    EXPECT_FALSE(result.isValid());
}

TEST_F(MaterialCompiler, CustomSurfaceShadingHasFunction) {
    std::string shaderCode(R"(
        void material(inout MaterialInputs material) {
            prepareMaterial(material);
        }

        vec3 surfaceShading(
                const MaterialInputs materialInputs,
                const ShadingData shadingData,
                const LightData lightData
        ) {
            return vec3(1.0);
        }
    )");

    filamat::MaterialBuilder builder;
    builder.customSurfaceShading(true);
    builder.shading(filament::Shading::LIT);
    builder.material(shaderCode.c_str());
    filamat::Package result = builder.build(*jobSystem);
    EXPECT_TRUE(result.isValid());
}

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}


text:
NY Jets: Bryce Hall to make his NFL debut tonight against the Patriots
NY Jets' rookie cornerback Bryce Hall is expected to make his NFL debut in Week 9.
The NY Jets have made a host of roster moves ahead of their Monday night showdown with the New England Patriots in Week 9 and the most notable of which was the activation of rookie cornerback Bryce Hall to the 53-man roster.
Aside from Hall being activated, the Jets announced that they had signed quarterback Mike White to the active roster, placed tight end Trevon Wesco on injured reserve, and elevated tight end Ross Travis and defensive lineman Tanzel Smart to the active roster.
Hall was drafted by the Jets in the fifth round of the 2020 NFL Draft after a standout career at Virginia. Many saw the talented cornerback as an early Day 2 selection before a devastating ankle injury cut his senior season short.
The same ankle injury that caused his draft stock to plummet also kept him out for all of training camp as well as the first eight weeks of the season. Hall was placed on the non-football injury list to start the year, but was designated to return a few weeks back.
Now, after undergoing extensive rehab for months, he's set to make his NFL debut tonight against the Patriots.
The Jets will surely welcome back a player who many feel could be the steal of the entire draft. With the likes of Blessuan Austin and Pierre Desir having inconsistent seasons, it wouldn't be surprising to see Hall in the starting lineup at some point.
The release of Quincy Wilson this weekend opened up the opportunity for Hall to be activated.
The NY Jets also made a handful of other transactions not related to Bryce Hall.
White was signed to the active roster from the practice squad because Sam Darnold is set to miss this week's game with a shoulder injury.
The team has already used up both of White's temporary promotions so if they want to send him back down to the practice squad he'll have to pass through waivers.
The Jets also have fourth-round rookie James Morgan on the active roster, although he'll likely be a game-day inactive once again.
Wesco lands on IR after injuring his ankle in practice this week. The 2019 fourth-round pick has failed to make an impact again in his sophomore NFL season and has just one catch for five yards on two targets in 2020.
Travis was promoted to take his place and the former Kansas City Chiefs tight end is a very intriguing player with an interesting background. A former college basketball star, Travis hadn't played football in eight years before earning a tryout with the Chiefs in 2015.
The 27-year-old has played in 24 career games split between the Chiefs and Indianapolis Colts hauling in 14 receptions for 142 yards.
Smart was a sixth-round pick of the Los Angeles Rams in 2017 and has played in 31 career games — all with the Rams. He was signed to the Jets' practice squad around a month ago.
Next. NY Jets: Top 3 players to watch in Week 9 against the New England Patriots
But, of course, this biggest news here is that Bryce Hall is expected to make his NFL debut tonight. And that's one thing that every Jets fan could get excited about.

redpajama_set_name: RedPajamaCommonCrawl


the mint street: Happy 1 year to Themintstreet!
Happy 1 year to Themintstreet!
Hoy, hace exactamente un año que escribí el primer post del blog, sabía que este proyecto en colaboración con R&E Valladolid sería a largo plazo pero no sabía que después de un año tuviera más de 500 seguidores y más del doble en Twitter, gracias a vosotros que día a día visitáis el blog , esto sigue adelante , ¿por cuanto tiempo más? no lo se, pero espero que dentro de un año pueda escribir otro post parecido a este ... Como veis ha cambiado el diseño del blog y en twitter desde el ordenador podéis ver de fondo una de las fotos finales que he realizado para la nueva línea de looks de R&E Valladolid... muchas gracias a todos !
Exactly one year ago I wrote the first post of the blog, I knew that this project in collaboration with R & E Valladolid would be long term but did not know that after a year had more than 500 followers and more than double on Twitter, thanks to you that day by day you visit the blog, this goes ahead, for how long? do not know, but I hope that in a year i can to write another post like this ... as you can see the design of the blog has changed and you can see on my twitter as a background a new photo for the last collaboration with R&E Valladolid ... thank you very much to all!
Coming up three new outfits for R&E Collaboration , stay tuned guys !
che post carino!! un anno.. congratulazioni!!
congratulations on your anniversary! you look totally awesome in that photo and i love the new desgn !!
I'm so happy for you…! It's great how fast your career went forward…and I know it wont stop now.
happy anniversary! wow I can't believe your blog is only a year old!
me encanta la foto nueva !!!!!!!!
Congratulazioni iago! Un anno di vita va festeggiato degnamente!!! Io ho appena aperto un blog http://tiffanysbreak.blogspot.com; ogni suggerimento sarebbe gradito soprattutto dopo un anno ricco di soddisfazioni come hai avuto tu!
Già 1 anno … congratulazioni!!!
No podías salir más guapo en la nueva foto de la cabecera y la grande, GENIAL espero leerte mucho tiempo mas besazo!
really like the new design and the banner you look so great !
I just found your blog about 1-2 month ago but now it's one of my favourites! Wish you more and more experiments with this fantastic blog!
You are doing an amazing job iago!!!
I started mine around the same time, you are such an inspiration to me!
i can't believe how much your blog has grown in only one year!
No puedo creer la enorme diferencia de este banner al otro ... muchiisimo mejor, en el otro parecias un niño y ahora un hombreton, genial el outfit de la foto y sales increible, sigue así un besin desde Cáceres te sigo al twiter!
I can't believe your only blogging for a year now; your blog is huge! You give me so much inspiration at every post!!
I can't wait for your upcoming posts, and enjoy the one year anniversary!!
Jeeeej, congratulations! Your blog is great! Keep on the good work!
congratulations on your wonderfull blog! It is one of the best in the web and you deserve it that it has grown so successfully! I really enjoy following you.
So cool, you started your blog on my birthday!
I started mine on 28th of february, but started fashion blogging since june. You are such a great inspiration for me and I hope to make my blog as big as yours one day!
You had so many readers in just one year?
congratulations! I like your blog so much!
Happy anniversary I am glad that you have started your blog! Cause I love to read it everyday!
CONGRATULAZIONI!! IL TUO BLOG è STUPENDO!!!
HAPPY ANNIVERSARY!! What a fantastic year for you! Great idea for celebrating your blog!
I'm very happy for themintstreet's aniversary. I hope everything will go you good.
Kisses from a small island of Spain.
keep doing your thing honey!!!
congrats on making it a full year! a blog is a lot of work, and sometimes hard to keep up. You do it with such ease and obviously every new post of your fashionable life keep us coming back for more!
OMG you look totally HOT iago i really love the photo ! You have a wonderful blog and should be very proud.
Good Job , Iago! My congratulations :) Love your outfits, music and travels!


text:
Saint-Saturnin is een gemeente in het Franse departement Cher (regio Centre-Val de Loire) en telt 466 inwoners (1999). De plaats maakt deel uit van het arrondissement Saint-Amand-Montrond.

Geografie
De oppervlakte van Saint-Saturnin bedraagt 39,5 km², de bevolkingsdichtheid is 11,8 inwoners per km².

Demografie
Onderstaande figuur toont het verloop van het inwonertal (bron: INSEE-tellingen).

Externe links

Gemeente in Cher

redpajama_set_name: RedPajamaWikipedia


text:
'use strict';
const cliBoxes = require('./boxes.json');

module.exports = cliBoxes;
// TODO: Remove this for the next major release
module.exports.default = cliBoxes;

redpajama_set_name: RedPajamaGithub


text:
La baia di Duperré è una baia larga circa 6 km situata sulla costa sud-occidentale dell'isola Brabant, una delle isole dell'arcipelago Palmer, al largo della costa nord-occidentale della Terra di Graham, in Antartide. Nella baia, la cui bocca si apre tra punta Humann, a nord, e la penisola Hulot, a sud, si gettano diversi ghiacciai, tra cui il Dimkov.

Storia
Scoperta durante la spedizione di ricerca francese in Antartide svolta dal 1904 al 1907 al comando di Jean-Baptiste Charcot, la baia di Duperré è stata da quest'ultimo così battezzata in onore di Charles-Marie Duperré, un contrammiraglio della marina militare francese. Nel 1960 tale nome fu infine confermato dal Comitato consultivo dei nomi antartici.

Note

Collegamenti esterni

Duperré, baia


text:
The Expat Group has acquired hotel management institute Ecole Hoteliere at Lavasa, a part of the Ecole hôtelière de Lausanne in Switzerland.
Global real estate company The Expat Group has acquired hotel management institute Ecole Hoteliere at Lavasa, a part of the Ecole hôtelière de Lausanne in Switzerland, for an undisclosed amount, the company said on Tuesday.
Through this deal, Expat Group has entered into the education domain.
"We believe this partnership will provide a real fillip to young, talented individuals looking to build a career in the hospitality industry by providing facilities and education that compares favourably with global standards but within the reach of Indian students," said Nathan Andrews, director – projects, Expat Group and director, Ecole Hoteliere at Lavasa.
Ecole Hoteliere at Lavasa offers students a combination of real world learning opportunities, including multiple star hotels, restaurants, convention center, club and outdoor catering all within immediate access to the campus.
It is located at Lavasa, a market city development in west India. Promoted by public listed construction firm HCC, Lavasa is in the queue to float its initial public offer (IPO).
"Ecole Hoteliere at Lavasa is a premier hospitality institute with a modern approach towards hospitality management and is a perfect match for our vision for the education segment. The experience gained by the students will make them thorough professionals with an in-depth understanding of the business," said Santosh Shetty, CMD, Expat Group.
Incepted in 1994, Expat Group is into real estate related business including transaction and investment advisory besides being a developer and owner of projects itself. Headquartered in Bangalore, it also has a significant presence in the Middle East besides the US, Africa and Southeast Asia.
SOURCE: VC Circle
READ MORE: http://bit.ly/1OauyIV
The Expat Group has acquired hotel management inst...
Expat NewsBurst: Reliance ADAG Gets 289 Acres in M...


The KC Freedom Project is a faith based advocacy group which provides assistance for wrongly convicted persons who have made the brave decision to fight for their freedom. Understanding how difficult it is to fight a case from behind bars we serve as the incarcerated individuals advocate and we diligently work on their behalf to prove their innocence. We serve as a faith based support system for the wrongly accused.
We are currently pursuing the implementation of a Conviction Integrity Unit within the Jackson County Mo. Prosecutor's Office.


Thank you for that introduction, and thank you all for coming. As all of you know, we are at an important moment in the debate over financial regulation and the future profile of financial markets in the United States, and throughout the world. So I am pleased to have this opportunity to share some of my thoughts about where we've been and where we can hopefully go.
Today, to extend the metaphor, the patient is healthier, and seems to have been stabilized, but is certainly not ready for a clean bill of health. There's been a strong recovery in the equity markets, but some sectors, such as the securitization market, are still on life support. Similarly, unemployment numbers are still rising—and approaching double digits.
The last two years have been a deeply unsettling period. For countless individuals, it has meant a plunge in their investment portfolios and their savings. It has also fostered a severe erosion of confidence in the entire financial system—and one of the great challenges ahead for everyone associated with the financial-services industry is working to win back that confidence.
That process is underway, with much-needed discussion and debate about the underlying causes of the financial turmoil, and how we can reduce the likelihood of it being repeated. It needs to be emphasized that we collectively as securities industry leaders and securities regulators have a solemn responsibility here—we must push ourselves honestly to ask what lessons we have learned and resolve to chart a specific and concrete path forward that focuses fundamentally on investors.
It would be presumptuous of me to retrace the ground covered by so many analyzing what went wrong before and during the market implosion. It's more important to evaluate where we are today in a world where in a very real way everything has changed for your firms and the industry. From capital and liquidity demands to frozen credit and asset-backed markets to risk management and market volatility, fundamental assumptions and strategies have been trashed or, at least, subject to complete rethinking. Moreover, the implications of increased government entanglement and, for a number of you, the shift to a bank holding company—with all the organizational complications and regulatory oversight changes that entails—have fundamentally changed the way you conduct your business.
Yet in other ways, the warning yellow flashing signs of regulatory danger remain the same; the industry continues to operate in a complex environment replete with conflicts that need to be controlled and properly disclosed. The inexorable quarterly earnings pressures—as well as the need to respond to customers' demands for strategies that work in this unstable economic environment—continue to push the industry to redesign and offer an explosion of proprietary structured products and variable annuities as well as a menagerie of exchange traded funds.
Simultaneously, regulators have had to rethink how they can do their job better and properly assimilate the lessons of regulatory failure exposed by the financial implosion.
In that spirit, I would like to explore some of the new paradigms we're seeing emerge—both in regulation and in the industry's business practices and how we must respond.
I'd like to suggest we start by focusing on regulation, and regulators. One of the fundamental challenges facing any financial regulator is trying to keep pace with the dynamism and change that defines financial markets. The challenge is particularly acute right now, given the paradigm shift that's underway. While the immediate task is to reform the regulatory architecture to address the many vulnerabilities in the financial system and help restore investor confidence, part of the long-term objective must be to create an architecture in which regulations can evolve to adapt to the inevitability of changed circumstances in the financial sector. If we simply look backward, we will be, in some sense, "fighting the last war." The real test will be whether the regulatory system can evolve along with the financial system and help to prevent the excesses that are destined to develop.
One specific area for regulatory modernization is the regulation of broker-dealers and investment advisers. FINRA whole-heartedly embraces the Administration's goal of harmonizing regulation of these two sectors. For while they are distinct entities, the everyday reality is, as the Rand Institute said in a study last year, that "trends in the financial service market since the early 1990s have blurred the boundaries between them."
Indeed, as you are aware, most investors cannot distinguish between the investment advisory service they receive and their brokerage service. But broker-dealers and investment advisers are regulated differently and held to different standards.
As you know, the Administration has proposed that the SEC write rules establishing consistent fiduciary standards of care for investment advisers and brokers providing investment advice. FINRA stands in agreement with numerous interested parties, including SIFMA, that the standard of care in both channels should be a fiduciary standard for the provision of advice.
As we look for ways to achieve harmonization, we should start with a commitment that the standard is "business model neutral" and focus on the basic shift that each recommendation must be in the "best interest of the customer." While I believe all present business models can thrive in a properly designed customer-facing fiduciary standard, there also should be no question that this will involve real change. There is an important cultural change from shifting the question from is a product "suitable" or "ok" to is it "in the best interests of the customer." While it will be up to the SEC to design the precise parameters of the standard, it's worth taking a moment to discuss what you as senior management should be focusing on now.
First, disclosure: there is no question that the quality of account opening disclosure has steadily improved over the years. But the process has been painful, involving lengthy debates and often enforcement actions as conflict by conflict has been identified and resulted in improper selling practices. The anticipation of a common fiduciary standard provides an important opportunity for firms to revisit their current account opening disclosure to ensure that its discussion of potential conflicts is clear, complete and in plain English.
Similarly, this is an opportunity to rethink your training of dual-hatted financial advisers as well as their point-of-sale disclosure to ensure that your customers understand any conflicts that may impact the recommendation as well as the worst case risks of the product and any alternative investments they might consider. The risk that an investment may not be "in the best interests of the customer" can only be increased if he or she doesn't fully understand each of these facts. Of course it may be in the interest of the client to have access to IPO's, fixed income offerings that the firm trades as a dealer or structured products—but only if the risks and conflicts raised by these products are clearly understood.
In addition to establishing a consistent fiduciary standard, we also need to harmonize the oversight and enforcement of that standard and the other rules relevant to each channel, to better ensure that participants in that industry comply with those obligations. Harmonization of the standard of care is an important first step. However, given the number of recently revealed frauds perpetrated by investment advisers bound by the fiduciary standard, it is clear that the existence of the fiduciary standard of care alone is not a guarantee against misconduct. Compliance with that standard must be regularly and vigorously examined and enforced to ensure the protection of investors.
Especially today, when so many firms and individuals are dually registered as both broker-dealers and investment advisers, or have affiliated businesses that work closely together, it is vital that both sides of those businesses be examined on a regular basis so that regulators can see the full picture of both sides of the business.
Just as regulation needs to adapt to new circumstances, so do regulators. One way we are doing that at FINRA is to focus on making our examinations, as well as our regulatory programs, more effective in identifying and fighting fraud.
Gathering more information—prior to each exam—regarding a firm's ownership and affiliate relationships.
Identifying indications of problematic behavior concerning the opening of investment advisory accounts at a broker-dealer.
Examining the relationship between broker-dealers and/or their affiliates with feeder funds, or master funds that utilize feeder funds.
Identifying potentially fraudulent activity by examining for material misstatements in financial reporting, unusual money movement, and apparent red flags involving a firm's auditor and off balance sheet items.
Of course, these types of procedures and inquiries have been part of the FINRA examination program for some time. Our enhancements are based on what we have learned from the many recently exposed frauds—including many that involve non-registered entities. For this latter group, we are not looking to extend our jurisdiction, but we are more focused on relationships that broker-dealers have with affiliated and other third parties so that we can assess the impact on the broker-dealer and thus on investor protection.
In addition, back in March, we established an Office of the Whistleblower to handle high-risk tips. And earlier this month, we announced the creation of FINRA's Office of Fraud Detection and Market Intelligence. This new office provides a heightened review of incoming allegations of serious frauds, a centralized point of contact internally and externally on fraud issues and consolidates recognized expertise in expedited fraud detection and investigation.
The office is also one element of our larger effort to change the regulatory culture with respect to detecting fraud. We are placing renewed importance on attracting staff who bring a range of skills and experiences. In addition to fraud detection, they need to have forensic capabilities, knowledge of the technology used to facilitate securities manipulation and insider trading, and a background that equips them to ask the right questions. And as they chase down leads and deal with peripheral issues, they need to be able to maintain a laser-like focus on the end goal.
Just as regulation and regulators need to adapt to the new climate, so does the financial industry. It's clear that firms need to rethink a number of long-established business practices, and focus on complying not only with the letter of the laws, but also the spirit underpinning them, and do this through a fiduciary lens. Let me touch on a few areas, starting with conflicts of interest.
While the profile of the financial sector has been transformed over the past two years, conflicts remain—and they demand greater disclosure. Failing to disclose conflicts frequently results in exposure of conflicts. And that brings even greater scrutiny from the press, the public and regulators; it heightens reputational risk, and it contributes to an erosion of investor confidence. More fundamentally, disclosure is the right thing to do—customers should know when a firm's interests may not be aligned with their interests.
While disclosure improvements are important, it is equally critical to review your conflict identification process. In a fiduciary world, the regular examination of conflict of interest becomes even more fundamental. Institutions should make reviewing their conflicts a part of their standard operating procedure. It is not enough to do a conflict review once every few years and put it in a drawer. It should be a continuous, evolving process that's just as real-time as the changes in a firm's business and the financial products it manufactures and sells. This process is important today and crucial to meeting the new fiduciary disclosure and compliance expectations. Finally, it sends an important message to your employees that enhancing shareholder value is important but that, long term, that will only be accomplished by always placing the customer first.
Next, I'd like to turn to how financial services firms should think about the products they offer and the sales practices they utilize.
In recent years, business practices have evolved to a point where for some firms products and services were being offered not on the basis of whether they were in the best interest of the customer, but whether they met a minimum standard of acceptability. We've seen this with a variety of structured products, in which there was no change in the business model despite a dramatic change in the business climate.
As I mentioned earlier, while firms have made some real progress in the new products process over the last few years—through the incorporation of compliance earlier in the product creation process—too often the analysis ends when the product is pushed out for the first time. Today, firms typically maintain product review committees, to review what the firm is selling, how popular and profitable their products are, and to explore additional products that could potentially be offered. Having a formal committee pass judgment on financial products is a good step, but more is needed.
Like the reviews of conflicts of interest, product committees need to be institutionalized. And the committees need to broaden their focus to look at not just whether a product is acceptable, but also how products have evolved, who they have been sold to, whether they have become riskier over time, and whether they continue to serve the needs of investors. That requires an in-depth understanding of the components of the products. It also demands a sophisticated analysis of which external forces could influence their behavior, and how. This kind of front-end analysis will help to prevent problems that can culminate in enforcement actions and civil litigation. Most importantly, it will help prevent harm to the investing public.
The recent experience with auction rate securities highlights the need to understand the risk-reward quotient of products. That understanding must extend from the product originator to any firm marketing the product. Product review cannot be a static process and firms must understand when market forces render a change in the risks of a product at the earliest reasonable time.
As firms develop new products, I hope they will redouble their efforts to focus on whether and how the product will serve their customers. This is more important now than ever, given the aging of the population and the changes to the U.S. retirement system that have shifted the burden of risk from large institutions to individual investors.
As baby boomers, once again, create a secular explosion—this time with the number of persons verging on retirement—I am continually troubled by products and practices that prey on seniors, who are among the most vulnerable to questionable products and practices. The explosion in the number of retirees makes this an area where the industry can both provide tremendous benefit and yet also be exposed to new levels of compliance risk. FINRA has devoted significant time and resources to educating seniors on financial issues and how to avoid frauds and scams. And we've also devoted significant resources to enforcing high standards on firms that deal with seniors.
Annuities are a particular concern when seniors are involved, because they are complex investments designed for the long-term investor. They are not suitable for meeting short-term goals because of substantial penalties if one withdraws money early. Therefore, the product, in many cases, is not suitable for older investors who may need access to their money in the short-term. FINRA has brought a number of cases in the last two years against firms who have moved elderly investors into variable annuities inappropriately.
Our concern about the marketing and sale of variable annuities to seniors led FINRA to adopt a new rule, Rule 2821, which details specific sales practice standards and supervisory requirements. Beyond this, however, is the fact that the product is continually changing. The guarantees that became critical in the last year are being revised to control underwriters' risk. That provides you with the challenge to ensure that your financial advisers and their customers understand how the product works, how much it costs and what alternatives should be considered.
Another area where there is a need for firms to live up to the fiduciary standard is life settlements. Life settlement products have grown in popularity in recent years, and there's some evidence that they are being aggressively marketed without giving investors the information they need to make an informed decision.
At one time, the owner of a life insurance policy who no longer wanted or could not afford it had two options: to let the policy lapse or surrender it to the issuer for its cash surrender value. The emergence of a secondary market for existing life insurance policies provides a third alternative: to sell the policy to a third party for less than the net death benefit, but more than the cash surrender value. Such transactions are typically referred to as life settlements.
While life settlements can be a valuable source of liquidity for people who would otherwise surrender their policies or allow them to lapse, they can have high transaction costs and unintended consequences. Individual policyholders have also said that determining a fair price can be very difficult. Given the complexity of these products, and the sensitivity connected to any product linked to end-of-life issues, firms need to make extra efforts to ensure that they are serving the long-term needs of both their customers and associated family members.
FINRA can implement and enforce high standards, and we have done so, but the larger point is that there needs to be a shift in the way some firms approach their development of new products and the way they market these products to the public. Your integrity and commitment to good business practices should be the first line of defense in investor protection, and I urge you to view your responsibilities in a true fiduciary spirit.
Similarly, how can firms evolve the way they communicate with customers while still meeting regulatory requirements and without sacrificing the protection of the very audience they are trying to reach? We continue to witness the advent of technologies that will challenge your ability to ensure compliance with regulatory requirements. The social networking phenomenon is one such innovation. Social networking sites such as Facebook or LinkedIn provide new ways to connect, inform and interact with customers. They also raise new regulatory challenges. For example, as currently designed they may not allow you to archive and maintain the communications on your own books and records.
Many registered representatives, particularly younger ones, want to use social networking sites to communicate with friends and potential customers. As currently constructed, these sites would not permit you to easily supervise these communications. For that reason, most firms prohibit their employees from using these sites for their business. Nevertheless, interest in these sites will not go unabated. Overcoming many of these challenges will require technology solutions. In fact, we are aware of new technologies that may soon enable firms to archive employee communications in order to comply with supervision and recordkeeping requirements.
FINRA is trying to do its part. We have formed a Social Networking Task Force comprised of industry participants to explore how regulation can embrace technological advancements in ways that improve the flow of information between firms and their customers—without compromising investor protection.
Let me turn now to changes in the markets and what that means for regulators and the industry alike. We talk constantly and aspirationally about anticipating issues, about seeing structural changes as they happen and responding, before the crisis, scandal, or meltdown forces us to respond. Unfortunately, as both regulators and as an industry, our record needs to get much better. But I would like to discuss one such opportunity, and it concerns the rapidly changing world of equity market structure.
The story in the equities markets is a good one. Despite the turmoil of the past year, the markets structurally came through relatively unscathed, despite both historic market volatility and unprecedented regulatory volatility, mostly in the area of short selling.
Yet all is not as stable as it appears, and there are impediments to regulatory effectiveness that are not terribly well understood and potentially damaging to the integrity of the markets. I'm not specifically speaking about the hot topics in the equities world of high frequency trading and dark pools, although I'm delighted that the SEC is focused closely on these issues. My interest is in the fragmentation we see in the markets, and the increasing number of genuine liquidity centers, and what these do to the ability of regulators to oversee the markets.
The decline of the primary market concept, where there was a single price discovery market whose on-site regulator saw 90-plus percent of the trading activity, has obviously become a reality. In its place are now two or three or maybe four regulators, all looking at an incomplete picture of the market and knowing full well that this fractured approach does not work. This is especially true given how easy it is for market participants to move volume on a second-by-second basis between venues.
Structural developments in other ways serve to cloud the audit trail. Order information is inconsistent and incomplete—overwhelming in some contexts and non-existent in others. While FINRA serves as the trade repository and regulator of dark pool activity, it's not always clear what activity emanates from the pool versus what emanates from unrelated desks throughout the sponsoring firm. And data quality varies across the exchanges, with no clear set of reporting requirements. It is also becoming easier to hide the identity of the actual participant in a trade in the trade report, further frustrating our efforts. It often takes days, not minutes, to understand who traded and where, and that is not the standard we want for a well-regulated and modern market.
Audit trails used to be relatively straightforward, analytically if not technologically. The information the market needed for the tape and for clearing was exactly the information the regulator needed for surveillance. But that dynamic doesn't work so well in the current environment. I think we need to look at the data we get versus the data we need, and find cost effective ways to close that gap.
At a minimum, all the data needs to be consolidated, with a single set of eyes looking at the market holistically. We've taken that first step by consolidating the surveillance for insider trading based on listed market. But there is much more to be done in the areas of frontrunning, manipulation, abusive short selling, and just having a better understanding of who is moving the markets and why.
The consolidated data pool likewise should be surveilled by a unified single regulator. A single regulator that can bring the best technology, the best people, and a unified set of rules needs to be empowered. Today, there are multiple regulators attempting to respond in a timely way to market changes, using scarce resources to try to simultaneously develop similar systems and processes. A stronger, single regulator would be equipped to meet market surveillance objectives more effectively, and with less expense, than multiple regulators.
What I'm proposing is somewhat daunting, because it is simultaneously a significant undertaking and a baby step. I say it's a significant undertaking because I have been around long enough to know that any attempt to change the routine flow of market information without overburdening the market itself is a challenge. I also appreciate, as the former regulator of multiple markets at NYSE Regulation, and the current regulator of multiple markets at FINRA, that combining regulatory databases is much easier said than done.
But it's also a baby step because consolidation is already assumed to be the norm, and prior to market fragmentation it more or less was the norm. While there's been some progress on consolidated surveillance, there are still a number of steps that need to be taken to give us a more complete picture of the markets, starting with the more difficult step of integrating listed options. After that, we need to capture information from the credit default swap market that is 100 percent opaque right now. After the events of last fall, nobody can say that swap spreads and underlying equity prices are never linked, but at this point it is very hard to see and even harder to prove.
Finally, we need more information on the entities that move markets-the high-frequency traders and hedge funds that are not registered. Right now, we are looking through a translucent veil, and only seeing the registered firms, and that gives us an incomplete—if not inaccurate—picture of the markets.
In short, there is a lot of work ahead, but not a lot of time.
Having spent most of my professional life working in financial-market regulation, I've seen the commitment to a strong culture of compliance ebb and flow—often in correlation with market movements. And while there's been progress, one of the lessons of the past two years is that there is still work to do—as there always will be. As Thomas Jefferson once said, "the price of liberty is eternal vigilance."
The regulatory reforms pending before Congress can help to wring some excesses out of the system, and prevent abuses. And SIFMA can continue to play a constructive role in this process. But we should remember that regulation, while critically important, is not going to prevent every instance of fraud or deception. What's most important of all is for market participants—from senior executives to individual investors—to possess a commitment to ethics, integrity and professional responsibility.
A marketplace defined by a high level of trust and confidence will be one where capital can flow efficiently to those who use it wisely and productively. And that trust and confidence will, in the long run, help to deliver the greatest economic dividends of all.


Zenit St. Petersburg shirt - Zenit shop online at Unisport!
FC Zenit Saint Petersburg are one of Russia's most successful teams. Now you can show your support for Zenitchiki by buying your latest kit!
Zenit St. Petersburg is one the biggest teams in Russia of recent times. The have been doing the business both in Russia and out in Europe. One of the club's biggest triumphs was back in 2008 when they took home the UEFA Cup. The final was played in Manchester where the club beat Glasgow Rangers. Are you looking to, exactly like the players, wear a Zenit St. Petersburg football shirt then you will find it right here.
The team are often to be found in the top of the Russian league, something that the supporters are really enjoying. If you are planning to visit for a match and experience the atmosphere, then you should not forget to pack your Zenit St. Petersburg soccer jersey. You don't have one? Then you can get yourself one here on Unisportstore.com.
We can offer both the home- and away shirt. With or without print, and even with the matching shorts and socks. So what are you waiting for? You decide if you wanna go for just the Zenit St. Petersburg soccer jersey or the full kit, what player you want on the back and then you are ready to order swiftly and easily on our website. Cheap prices and fast delivery.


text:
DS Celebrates 60th Anniversary at Rétromobile
DS Celebrates its 60th Anniversary at Rétromobile
For 2015, its first year as a brand in its own right, DS will be at the 40th Rétromobile show in Paris (France), celebrating the 60th anniversary of the original 1955 DS.
From the 4th to 8th February 2015, car lovers will enjoy a stroll around the DS stand at the Porte de Versailles Exhibition Centre in Paris, for an enthralling look back at the DS legend. The DS exhibition, organized with precious support from the Amicales Citroën* associations along with DS and SM** enthusiasts' clubs, will include five prestige period models plus one of the latest arrivals to the DS brand line-up, the DS3 Cabrio, in its Ultra Prestige version.
Thanks to the invaluable support from Citroën enthusiasts' clubs, there will be five exceptional histroic cars on show, providing visitors with a fabulous insight into the exceptional heritage that inspires today's DS brand in its quest to offer customers the very best in design, technology, comfort, driving experience, quality materials and outstanding attention to detail. The stars of the show are:
DS 19 (1959), in its original configuration, with grey-rosé body, aubergine roof, and royal blue interior. This model, adapted for export to Germany, features an engine temperature gauge on the dashboard plus an FM/LW radio. The three-main-bearing engine is coupled through a four-speed gearbox with hydraulic control.
DS 21 Cabriolet (1968), with hydraulic-control gearbox. The superb finish on this exceptionally elegant model extends to red leather upholstery, contrasting with the Carrare white body and black bonnet.
DS 20 Pallas (1973), a top-end luxury model featuring tobacco leather upholstery, beige Tholonet bodywork, tinted windows and even a sunroof. The 1985 cm3 engine is mated to a hydraulic-control four-speed synchromesh gearbox.
SM Coupé (1971), previously owned by King Hassan II of Morocco. This model features metal beige paintwork, special registration plates, natural leather upholstery, air conditioning, Continental Edison hi-fi radio specific to this model, tinted windows and foglamps. The engine is a Maserati V6.
SM Coupé (1972), a first-hand model with Scarabée brown body and light brown upholstery. In addition to the self-levelling hydraulic suspension, similar to that on the DS, this car also boasts Citroën's innovative DIRAVI "power-assisted return" steering, for exceptional driveability.
Alongside these emblematic historic cars, visitors will also be able to admire a DS3 Cabrio Ultra Prestige, boasting the same genetic make-up as the groundbreaking avant-garde DS and SM models.
Rétromobile opened to the public on Wednesday 4 February 2015. The DS showroom is in Hall 1.
*The Amicales Citroën organizations comprise L'Amicale des Clubs Citroën France and L'Amicale Citroën Internationale, associations whose mission is to coordinate the operations of enthusiasts' clubs with the Citroën and DS brands.
**The clubs contributing to Rétromobile 2015 are: DS ID Club de France, Idéale DS France, DS Club Révolution 55, Le Monde de la DS, SM Club de France, Euro SM Club, and Club automobile André Citroën.
C4 Cactus Wins the '2015 World Car Design of the Year' Award in New York
Citroën's Double Success in Fleet News Awards
DS range


I've talked a lot about it, but I still haven't taken a proper twitter break. I took a break for about a week. Toward the end of the break, I didn't think about twitter a whole lot, but I still thought about it. It's quite a habit.
Making it take a couple of steps to check my twitter account wasn't enough, so I'm going to try something else—making my twitter account private. One reason for logging back into my twitter account after such a short amount of time was to replace the current tweets on my twitter profile with fresh ones. Now my twitter profile can only be seen by those whom I follow, so that won't be such a concern this time.
I made it clear in my twitter profile that I'm taking a break from twitter and will still be reading my DM's. Hopefully people won't worry about me this time like a few did when I abruptly deleted my twitter account last October.
So, why has twitter been such a problem for me? I think a big part of it is that I'm not in control of my experience. If I was in charge, I would make my twitter account purely a microblog. People couldn't see who I was subscribed to. I would also change how I manage users and filter and aggregate my feeds. This latter part I can change by writing my own twitter account, which is something I might do at some point.


text:
Advertise On 4RFV
BROADCAST FILM AND VIDEO DIRECTORY
Subscribe to Daily Broadcast News
Submit a Broadcast News Story
Channel 4 Promotes Jonathan Allen To CEO
Channel 4 has announced that Jonathan Allan has been promoted to the role of Chief Operating Officer as part of a restructured leadership team which brings together all the key operational functions into a newly expanded COO's office.
In the new role, Jonathan – who is currently Chief Commercial Officer – will oversee a number of departments including: All 4, Communications & Corporate Affairs, Consumer & Strategy, Content Management, Finance, HR, Nations & Regions and Technology. Finance Director Vince Russell, who joined Channel 4 from Sky in 2018, will take on additional responsibilities for leading Workspace and will report directly to Jonathan.
Keith Underwood has decided to take this moment to pursue new opportunities and will leave Channel 4 at the end of January. Keith, who has been part of the Executive team at Channel 4 for eight years as COO and previously Director of Strategy & Technology, has played a significant role in Channel 4's success – in particular leading the launch of All 4, transforming digital development capabilities, rebuilding and repositioning the finance function, and successfully delivering the operational elements of the 4 All the UK programme.
As a result of these changes Chief Consumer & Strategy Officer, Sarah Rose will also be leaving Channel 4 after the summer. Sarah has made a lasting contribution to a range of key business areas at Channel 4, including launching VOD, leading the commercial and business development teams, and most recently the consumer insight, data and strategy department. For the next few months she will continue to work closely with the Exec team to oversee key strategic partnerships.
Top Related Stories
Click here for the latest broadcast news stories.
RTS Announces Television Journalism Awards 2016
The Royal Television Society (RTS) has announced the nominations for the RTS Television Journalism Awards 2016. The awards, for news and current aff
CHANNEL 4 LAUNCH 4 VENTURES LIMITED
CHANNEL 4 have published their Annual Report for 2000 and formally launched a new incorporated company, 4 Ventures Limited, to manage all their film a
Production News : Channel 4 Announces Return Of Lookalikes
Following the success of the pilot episode and subsequent series, Channel 4 has commissioned another series of structured reality show 'Lookalikes'. T
RTS Announces TV Journalism Awards
Last night saw the Royal Television Society (RTS) present awards to the winners of the RTS Television Journalism Awards 2012/2013. The ceremony was ch
Production News : Sky To Launch Animation Channel
Sky Cinema is offering both classic and new animation titles on a channel for the first time starting this month. Launching on Saturday 14 October, an
Disney Channel Announce Senior Promotions
In recognition of Disney Channel's successful performance over the past year, the Channel has announced a raft of senior promotions across the busines
Arqiva Provides Satellite Distribution Of Channel 4 HD To Sky And Freesat
Arqiva has secured a satellite distribution deal for Channel 4 HD. The new arrangement facilitates transmission of Channel 4 HD for the first time on
BBC to provide programming to the Community Channel
The BBC recently announced signing a content deal to supply programming from its extensive library to the Community Channel. The BBC joins Channel 4,
Leader Names Jigsaw24 & root6 As European Channel Partner
Leader Electronics has further expanded its sales and support network with the appointment of Jigsaw24 & root6 as a European channel partner. Commenti
Production News : Channel 4 Specialist Factual Commissions Guy Martin's Pit Stop
Channel 4 Specialist Factual has commissioned Guy Martin's Pit Stop. Guy is set to take on the most coveted job in automotive engineering - being give
Production News : New Entertainment Show Heads To Channel 4
A new entertainment show has been commissioned for Channel 4, it has been announced. Host The Week will see a celebrity guest host an episode for one
Production News : Channel 4 Commissions 'A Year On The Farm'
A new series – A Year On The Farm (working title) – has been commissioned by Channel 4. The 4x60' series, which is due to air later this year, will ca
GatesAir Facilitate Channel Relocation
GatesAir has been selected by WTTW-TV to fulfil its FCCTV spectrum repack requirements. WTTW-TV is the primary PBS member station which serves the Chi
HHB Named Avid's EMEA Audio Top Channel Partner
HHB Communications, including its post-focused division Scrub, have been named Avid's EMEA Audio Top Channel Partner. The award is the third in four y
Production News : Channel 4 Announces New Gardening Show
Channel 4 has commissioned a new gardening show, Down The Garden Path With Dee Hart Dyke (w/t). Dee Hart Dyke is one of Britain's best amateur gardene
More News From Around The Web
Tweets by @4BroadcastNews
Flagship Media Group Ltd, Unit C3, 6 Westbank Drive, Belfast, BT3 9LA, Northern Ireland


Shenzhen Tuyu Trading Co., Ltd.
We will do provide what you need.
We have been in Electronic Components area more than 5 year, with a very rich searching and collecting experience for all kinds of New Original ICs, Capacitors and Resistors, IGBT(module), Mosfets and so on.
We are now starting a new company Tuyu Trading, to set up a new business type. We will keep doing our professional searching and collecting area, but we will extend our product range, not just stay on Electronic Components.
We plan to offer a very new type of chandelier, which looks like a moon, but with a very modern functions, to offer you a new life sensor. And also, we have another new part, which comes from Huawei, Huawei Gpon terminal, and this is very not right now for all market.
Hope we can offer such nice and hot parts for all.


Centerpointe Mall is located in Michigan, city Grand Rapids. Shopping mall has over 123 stores and address is: 3665 28th St., Grand Rapids, Michigan - MI 49512. Centerpointe Mall info: address, gps, map, location, direction planner, store list, opening hours, phone number.
Monday - Saturday 10:00 am - 9:00 pm, Sunday 12:00 pm - 6:00 pm.


text:
import createReducer from '../utils/createReducer'

// consts
import * as appConst from '../utils/constants'

const API_DATA_LOADING = 'home/API_DATA_LOADING'
const API_DATA_SUCCESS = 'home/API_DATA_SUCCESS'
const API_DATA_ERROR = 'home/API_DATA_ERROR'
const TOGGLE_DRAWER = 'home/TOGGLE_DRAWER'
const FILTER_MEETINGS = 'home/FILTER_MEETINGS'
const TOGGLE_DIALOG = 'home/TOGGLE_DIALOG'
const SELECT_MEETING = 'home/SELECT_MEETING'
const UNSELECT_MEETING = 'home/UNSELECT_MEETING'

const defaultState = {
  meetingId: null,
  dialog: false,
  filter: appConst.PAST_MEETINGS,
  drawer: typeof window === 'object' && window.innerWidth > 900,
  project: null,
  loading: false,
  error: null
}

export default createReducer(defaultState, {
  [API_DATA_LOADING]: (state) => {
    return Object.assign({}, state, {
      project: null,
      error: null,
      loading: true
    })
  },
  [API_DATA_SUCCESS]: (state, action) => {
    return Object.assign({}, state, {
      project: action.data,
      loading: false
    })
  },
  [API_DATA_ERROR]: (state, action) => {
    return Object.assign({}, state, {
      error: action.error,
      loading: false
    })
  },
  [TOGGLE_DIALOG]: (state) => {
    return Object.assign({}, state, {
      dialog: !state.dialog
    })
  },
  [TOGGLE_DRAWER]: (state) => {
    return Object.assign({}, state, {
      drawer: !state.drawer
    })
  },
  [FILTER_MEETINGS]: (state, action) => {
    return Object.assign({}, state, {
      filter: action.filter
    })
  },
  [SELECT_MEETING]: (state, action) => {
    return Object.assign({}, state, {
      meetingId: action.meeting
    })
  },
  [UNSELECT_MEETING]: (state) => {
    return Object.assign({}, state, {
      meetingId: null
    })
  }
})

export function selectMeeting (meeting) {
  return (dispatch) => {
    dispatch({
      type: SELECT_MEETING,
      meeting
    })
  }
}

export function unselectMeeting () {
  return (dispatch) => {
    dispatch({
      type: UNSELECT_MEETING
    })
  }
}

export function toggleDrawer () {
  return (dispatch) => {
    dispatch({
      type: TOGGLE_DRAWER
    })
  }
}

export function toggleDialog () {
  return (dispatch) => {
    dispatch({
      type: TOGGLE_DIALOG
    })
  }
}

export function updateFilter (filter) {
  return (dispatch) => {
    dispatch({
      type: FILTER_MEETINGS,
      filter
    })
  }
}

export function loadApiData (data) {
  return (dispatch) => {
    dispatch({
      type: API_DATA_LOADING
    })

    const p1 = new Promise(
      (resolve, reject) => {
        setTimeout(() => {
          resolve(data)
        }, 1000)
      }
    )

    return p1.then((data) => {
      dispatch({
        type: API_DATA_SUCCESS,
        data
      })
    })
    .catch((error) => {
      dispatch({
        type: API_DATA_ERROR,
        error: error.message
      })
    })
  }
}


If you or your family take herbal supplements this NYT article is a must-read. It reports that one of the national's largest supplement makers will conduct advanced DNA testing to ensure its products contain the ingredients listed on the label.
This is a breakthrough. Pharmaceutical companies have long been critical of the regulation over health supplements, calling for pharmaceutical level standardization and quality assurance. Investigators have found that big US names have been selling questionable products.
This is a multi-billion Dollar industry. Big brands like Solgar will strengthen their product differentiation with DNA testing. Expect the new standards to shake the industry leaving consumers of these expensive products angry and confused.
Octagon Nutrition MMA Nutritional Supplement Line!


Aldersley Leisure Village in Wolverhampton was the superb venue for this year's 5 and 7 mile event. The 7 miler started at 1400 hrs with the ladies' 5 mile race starting at 1300 hrs. We had one lady Rebecca Raper in the 5 miler and 3 men to fly the Red and White flag-Ross, Simon and me.
It's a strange thing but this is the top XC event in the Midlands yet only 185 entered and only 139 ran in the men's event. This is less than in a division 3 B'ham league XC race. Over the years I can count on one hand the number of times MF had had a team in (6 counters needed) and yesterday only 13 teams had 6 or more runners. Also Cov Godiva had nobody running at all! Believe it or not I've been a MF counter in the past but we only had 6 runners.
Just don't get it and never did. In fact in recent years Martin Smith and I have often been the only regular MF runners.
Anyway the course was easier than at Leamington the other week and was mud free, grassy, quite a few lengthy slopes but not like Beacon Hillat Newbold Common. Plus a jog along a disused railway line made it a good course. It was like Leam with 1 shorter lap and 3 large ones. So as usual I had laps 1 and 4 to myself- cannot stand crowds anyway.
Many times Simon Brown and Ross Cooper passed me as in lapping me or going up the slopes as I was coming down next to them. The friendship from all the runners was great and the marshals did a great job and were full of encouragement.
When I apologised for keeping them out a bit late they wished that more runners of all abilities had entered. Nice one I thought.
Good reception and prize giving and Guinness in the bar at the Wolverhampton and Bilston track Stadium afterwards made for a great occasion.
Dare I ask that MF have a team next year? Ross will anyway-won't you Ross!
Winning mens team: Notts AC.


text:
Grant Austin Taylor (born May 9, 1995) is an American rock and blues guitarist from Norfolk, Virginia. He started playing guitar at the age of 6 and made his performing debut at the opening of the Town Point Park in his hometown with the alternative rock band Better Than Ezra on May 30, 2003. While Grant Austin Taylor is mainly known for his solo work, he is also the vocalist, lead guitarist and harmonica player in the Grant Austin Taylor Band. In 2020, Grant Austin Taylor and his girlfriend, Taylor Anne Drumwright, together became the acoustic duo called The Taylors.

Awards and recognition
On the May 15, 2005 episode of America's Most Talented Kids, Taylor won the night's competition with his rendition of Bob Dylan's Knockin' on Heaven's Door which received a score of 9.85. He won $1000, a Gibson Les Paul guitar, a stereo system, and a karaoke machine.
On  December 3, 2005 the USO awarded Taylor the "Patriot Award" after his performance at the USO holiday party at Rockwell Hall.
On March 10, 2007 Taylor received the special award for Outstanding Young Original Blues-Rock Artist at the 28th annual Young Artist Awards in Studio City, California. He performed his song "Make This Love Last" and James Taylor's "Steamroller" at the awards ceremony.

References

External links
Official Grant Austin Taylor website
The Grant Austin Taylor Band at MySpace.
Grant Austin Taylor  at the Boy Choir and Soloist Directory.

1995 births
Living people
American child singers
American rock guitarists
American blues guitarists
American male guitarists
21st-century American male singers
21st-century American singers
21st-century American guitarists