text:
/*
 * File:   Compiler.cpp
 * Author: alain
 *
 * Created on March 4, 2017, 5:16 PM
 */

#include <Surelog/API/PythonAPI.h>
#include <Surelog/CommandLine/CommandLineParser.h>
#include <Surelog/Common/FileSystem.h>
#include <Surelog/Config/ConfigSet.h>
#include <Surelog/Design/Design.h>
#include <Surelog/Design/FileContent.h>
#include <Surelog/DesignCompile/Builtin.h>
#include <Surelog/DesignCompile/CompileDesign.h>
#include <Surelog/Library/Library.h>
#include <Surelog/Library/LibrarySet.h>
#include <Surelog/Library/ParseLibraryDef.h>
#include <Surelog/Package/Precompiled.h>
#include <Surelog/SourceCompile/AnalyzeFile.h>
#include <Surelog/SourceCompile/CheckCompile.h>
#include <Surelog/SourceCompile/CompilationUnit.h>
#include <Surelog/SourceCompile/CompileSourceFile.h>
#include <Surelog/SourceCompile/Compiler.h>
#include <Surelog/SourceCompile/ParseFile.h>
#include <Surelog/SourceCompile/SymbolTable.h>
#include <Surelog/Utils/ContainerUtils.h>
#include <Surelog/Utils/StringUtils.h>
#include <Surelog/Utils/Timer.h>
#include <antlr4-runtime.h>

#include <filesystem>
#include <thread>

#if defined(_MSC_VER)
#include <direct.h>
#else
#include <sys/param.h>
#include <unistd.h>
#endif

namespace SURELOG {

namespace fs = std::filesystem;

Compiler::Compiler(CommandLineParser* commandLineParser, ErrorContainer* errors,
                   SymbolTable* symbolTable)
    : m_commandLineParser(commandLineParser),
      m_errors(errors),
      m_symbolTable(symbolTable),
      m_commonCompilationUnit(nullptr),
      m_librarySet(new LibrarySet()),
      m_configSet(new ConfigSet()),
      m_design(new Design(getErrorContainer(), m_librarySet, m_configSet)),
      m_uhdmDesign(0),
      m_compileDesign(nullptr) {
#ifdef USETBB
  if (getCommandLineParser()->useTbb() &&
      (getCommandLineParser()->getNbMaxTreads() > 0))
    tbb::task_scheduler_init init(getCommandLineParser()->getNbMaxTreads());
#endif
}

Compiler::Compiler(CommandLineParser* commandLineParser, ErrorContainer* errors,
                   SymbolTable* symbolTable, const std::string& text)
    : m_commandLineParser(commandLineParser),
      m_errors(errors),
      m_symbolTable(symbolTable),
      m_commonCompilationUnit(nullptr),
      m_librarySet(new LibrarySet()),
      m_configSet(new ConfigSet()),
      m_design(new Design(getErrorContainer(), m_librarySet, m_configSet)),
      m_uhdmDesign(0),
      m_text(text),
      m_compileDesign(nullptr) {}

Compiler::~Compiler() {
  for (auto& entry : m_antlrPpMap) {
    delete entry.second;
  }

  m_antlrPpMap.clear();
  delete m_design;
  delete m_configSet;
  delete m_librarySet;
  delete m_commonCompilationUnit;

  cleanup_();
}

struct FunctorCompileOneFile {
  FunctorCompileOneFile(CompileSourceFile* compileSource,
                        CompileSourceFile::Action action)
      : m_compileSourceFile(compileSource), m_action(action) {}

  int operator()() const {
#ifdef SURELOG_WITH_PYTHON
    if (m_compileSourceFile->getCommandLineParser()->pythonListener() ||
        m_compileSourceFile->getCommandLineParser()
            ->pythonEvalScriptPerFile()) {
      PyThreadState* interpState = PythonAPI::initNewInterp();
      m_compileSourceFile->setPythonInterp(interpState);
    }
#endif
    return m_compileSourceFile->compile(m_action);
  }

 private:
  CompileSourceFile* m_compileSourceFile;
  CompileSourceFile::Action m_action;
};

bool Compiler::compileOneFile_(CompileSourceFile* compiler,
                               CompileSourceFile::Action action) {
  bool status = compiler->compile(action);
  return status;
}

bool Compiler::isLibraryFile(PathId id) const {
  return (m_libraryFiles.find(id) != m_libraryFiles.end());
}

bool Compiler::ppinit_() {
  FileSystem* const fileSystem = FileSystem::getInstance();
  if (!m_commandLineParser->fileunit()) {
    m_commonCompilationUnit = new CompilationUnit(false);
    if (m_commandLineParser->parseBuiltIn()) {
      Builtin* builtin = new Builtin(nullptr, nullptr);
      builtin->addBuiltinMacros(m_commonCompilationUnit);
    }
  }

  CompilationUnit* comp_unit = m_commonCompilationUnit;

  // Source files (.v, .sv on the command line)
  PathIdSet sourceFiles;
  for (const PathId& sourceFileId : m_commandLineParser->getSourceFiles()) {
    SymbolTable* symbols = m_symbolTable;
    if (m_commandLineParser->fileunit()) {
      comp_unit = new CompilationUnit(true);
      if (m_commandLineParser->parseBuiltIn()) {
        Builtin* builtin = new Builtin(nullptr, nullptr);
        builtin->addBuiltinMacros(comp_unit);
      }
      m_compilationUnits.push_back(comp_unit);
      symbols = m_commandLineParser->getSymbolTable()->CreateSnapshot();
      m_symbolTables.push_back(symbols);
    }
    ErrorContainer* errors = new ErrorContainer(symbols);
    m_errorContainers.push_back(errors);
    errors->registerCmdLine(m_commandLineParser);

    Library* library = m_librarySet->getLibrary(sourceFileId);
    sourceFiles.insert(sourceFileId);

    CompileSourceFile* compiler =
        new CompileSourceFile(sourceFileId, m_commandLineParser, errors, this,
                              symbols, comp_unit, library);
    m_compilers.push_back(compiler);
  }

  if (!m_text.empty()) {
    Library* library = new Library("UnitTest", m_symbolTable);
    CompileSourceFile* compiler =
        new CompileSourceFile(BadPathId, m_commandLineParser, m_errors, this,
                              m_symbolTable, comp_unit, library, m_text);
    m_compilers.push_back(compiler);
  }

  // Library files
  PathIdSet libFileIdSet;
  // (-v <file>)
  const auto& libFiles = m_commandLineParser->getLibraryFiles();
  std::copy_if(libFiles.begin(), libFiles.end(),
               std::inserter(libFileIdSet, libFileIdSet.end()),
               [&sourceFiles](const PathId& libFileId) {
                 return sourceFiles.find(libFileId) == sourceFiles.end();
               });

  // (-y <path> +libext+<ext>)
  for (const PathId& libFileId : m_commandLineParser->getLibraryPaths()) {
    for (const SymbolId& ext : m_commandLineParser->getLibraryExtensions()) {
      PathIdVector fileIds;
      fileSystem->collect(libFileId,
                          m_commandLineParser->getSymbolTable()->getSymbol(ext),
                          m_commandLineParser->getSymbolTable(), fileIds);
      std::copy_if(fileIds.begin(), fileIds.end(),
                   std::inserter(libFileIdSet, libFileIdSet.end()),
                   [&sourceFiles](const PathId& libFileId) {
                     return sourceFiles.find(libFileId) == sourceFiles.end();
                   });
    }
  }
  for (const auto& libFileId : libFileIdSet) {
    SymbolTable* symbols = m_symbolTable;
    if (m_commandLineParser->fileunit()) {
      comp_unit = new CompilationUnit(true);
      m_compilationUnits.push_back(comp_unit);
      symbols = m_commandLineParser->getSymbolTable()->CreateSnapshot();
      m_symbolTables.push_back(symbols);
    }
    ErrorContainer* errors = new ErrorContainer(symbols);
    m_errorContainers.push_back(errors);
    errors->registerCmdLine(m_commandLineParser);

    // This line registers the file in the "work" library:
    /*Library* library  = */ m_librarySet->getLibrary(libFileId);
    m_libraryFiles.insert(libFileId);
    // No need to register a compiler
    // CompileSourceFile* compiler = new CompileSourceFile
    // (m_commandLineParser->getLibraryFiles ()[i],
    //                                                     m_commandLineParser,
    //                                                     errors, this,
    //                                                     symbols, comp_unit,
    //                                                     library);
    // m_compilers.push_back (compiler);
  }

  // Libraries (.map)
  for (auto& lib : m_librarySet->getLibraries()) {
    for (const PathId& id : lib.getFiles()) {
      if (sourceFiles.find(id) != sourceFiles.end()) {
        // These files are already included in the command line
        continue;
      }

      std::string_view type =
          std::get<1>(fileSystem->getType(id, lib.getSymbols()));
      if (type == ".map") {
        // .map files are not parsed with the regular parser
        continue;
      }
      SymbolTable* symbols = m_symbolTable;
      if (m_commandLineParser->fileunit()) {
        comp_unit = new CompilationUnit(true);
        m_compilationUnits.push_back(comp_unit);
        symbols = m_commandLineParser->getSymbolTable()->CreateSnapshot();
        m_symbolTables.push_back(symbols);
      }
      ErrorContainer* errors = new ErrorContainer(symbols);
      m_errorContainers.push_back(errors);
      errors->registerCmdLine(m_commandLineParser);

      CompileSourceFile* compiler = new CompileSourceFile(
          id, m_commandLineParser, errors, this, symbols, comp_unit, &lib);
      m_compilers.push_back(compiler);
    }
  }
  return true;
}

bool Compiler::createFileList_() {
  if (!((m_commandLineParser->writePpOutput() ||
         m_commandLineParser->writePpOutputFileId()) &&
        (!m_commandLineParser->parseOnly()))) {
    return true;
  }
  FileSystem* const fileSystem = FileSystem::getInstance();
  SymbolTable* symbolTable = getSymbolTable();
  {
    PathId fileId = fileSystem->getChild(m_commandLineParser->getCompileDirId(),
                                         "file.lst", symbolTable);
    std::ostream& ofs = fileSystem->openForWrite(fileId);
    if (ofs.good()) {
      for (CompileSourceFile* sourceFile : m_compilers) {
        m_ppFileMap[sourceFile->getFileId()].emplace_back(
            sourceFile->getPpOutputFileId());

        ofs << fileSystem->toPath(sourceFile->getPpOutputFileId()) << std::endl;
      }
      ofs.flush();
      fileSystem->close(ofs);
    } else {
      std::cerr << "Could not create filelist: " << PathIdPP(fileId)
                << std::endl;
    }
  }
  {
    PathId fileId = fileSystem->getChild(m_commandLineParser->getCompileDirId(),
                                         "file_map.lst",
                                         m_commandLineParser->getSymbolTable());
    std::ostream& ofs = fileSystem->openForWrite(fileId);
    if (ofs.good()) {
      for (CompileSourceFile* sourceFile : m_compilers) {
        ofs << fileSystem->toPath(sourceFile->getPpOutputFileId()) << " "
            << fileSystem->toPath(sourceFile->getFileId()) << std::endl;
      }
      ofs.flush();
      fileSystem->close(ofs);
    } else {
      std::cerr << "Could not create filelist: " << PathIdPP(fileId)
                << std::endl;
    }
  }
  {
    if (m_commandLineParser->sepComp()) {
      std::ostringstream concatFiles;
      for (CompileSourceFile* sourceFile : m_compilers) {
        const PathId sourceFileId = sourceFile->getFileId();
        concatFiles << fileSystem->toPath(sourceFileId) << "|";
      }
      std::size_t val = std::hash<std::string>{}(concatFiles.str());
      std::string hashedName = std::to_string(val) + ".sep_lst";
      PathId fileId = fileSystem->getChild(
          m_commandLineParser->getCompileDirId(), hashedName,
          m_commandLineParser->getSymbolTable());
      std::ostream& ofs = fileSystem->openForWrite(fileId);
      if (ofs.good()) {
        for (CompileSourceFile* sourceFile : m_compilers) {
          ofs << fileSystem->toPath(sourceFile->getFileId()) << " ";
        }
        fileSystem->close(ofs);
      } else {
        std::cerr << "Could not create filelist: " << PathIdPP(fileId)
                  << std::endl;
      }
    }
  }
  return true;
}

bool Compiler::createMultiProcessParser_() {
  unsigned int nbProcesses = m_commandLineParser->getNbMaxProcesses();
  if (nbProcesses == 0) return true;

  if (!(m_commandLineParser->writePpOutput() ||
        m_commandLineParser->writePpOutputFileId())) {
    return true;
  }

  FileSystem* const fileSystem = FileSystem::getInstance();
  SymbolTable* symbolTable = getSymbolTable();

  // Create CMakeLists.txt
  const bool muted = m_commandLineParser->muteStdout();
  const fs::path outputDir =
      fileSystem->toPlatformPath(m_commandLineParser->getOutputDirId());
  const fs::path programPath =
      fileSystem->toPlatformPath(m_commandLineParser->getProgramId());
  const std::string_view profile =
      m_commandLineParser->profile() ? " -profile " : " ";
  const std::string_view sverilog =
      m_commandLineParser->fullSVMode() ? " -sverilog " : " ";
  const std::string_view fileUnit =
      m_commandLineParser->fileunit() ? " -fileunit " : " ";
  std::string synth =
      m_commandLineParser->reportNonSynthesizable() ? " -synth " : " ";
  synth += m_commandLineParser->reportNonSynthesizableWithFormal() ? " -formal "
                                                                   : " ";
  const std::string_view noHash =
      m_commandLineParser->noCacheHash() ? " -nohash " : " ";

  // Optimize the load balance, try to even out the work in each thread by
  // the size of the files
  std::vector<std::vector<CompileSourceFile*>> jobArray(nbProcesses);
  std::vector<unsigned long> jobSize(nbProcesses, 0);
  size_t largestJob = 0;
  for (const auto& compiler : m_compilers) {
    size_t size = compiler->getJobSize(CompileSourceFile::Action::Parse);
    if (size > largestJob) {
      largestJob = size;
    }
  }

  unsigned int bigJobThreashold = (largestJob / nbProcesses) * 3;
  std::vector<CompileSourceFile*> bigJobs;
  Precompiled* prec = Precompiled::getSingleton();

  const fs::path workingDir = fileSystem->getWorkingDir();
  for (const auto& compiler : m_compilers) {
    if (prec->isFilePrecompiled(compiler->getFileId(),
                                compiler->getSymbolTable())) {
      continue;
    }
    unsigned int size = compiler->getJobSize(CompileSourceFile::Action::Parse);
    if (size > bigJobThreashold) {
      bigJobs.push_back(compiler);
      continue;
    }
    unsigned int newJobIndex = 0;
    uint64_t minJobQueue = ULLONG_MAX;
    for (size_t ii = 0; ii < nbProcesses; ii++) {
      if (jobSize[ii] < minJobQueue) {
        newJobIndex = ii;
        minJobQueue = jobSize[ii];
      }
    }
    jobSize[newJobIndex] += size;
    jobArray[newJobIndex].push_back(compiler);
  }

  std::vector<std::string> batchProcessCommands;
  std::vector<std::string> targets;
  int absoluteIndex = 0;

  // Big jobs
  for (CompileSourceFile* compiler : bigJobs) {
    absoluteIndex++;
    std::string targetname =
        StrCat(absoluteIndex, "_",
               std::get<1>(fileSystem->getLeaf(compiler->getPpOutputFileId(),
                                               compiler->getSymbolTable())));
    std::string_view svFile =
        m_commandLineParser->isSVFile(compiler->getFileId()) ? " -sv " : " ";
    std::string batchCmd =
        StrCat(profile, fileUnit, sverilog, synth, noHash,
               " -parseonly -nostdout -nobuiltin -mt 0 -mp 0 -l ",
               targetname + ".log ", svFile,
               fileSystem->toPath(compiler->getPpOutputFileId()));
    for (const std::string& wd : fileSystem->getWorkingDirs()) {
      StrAppend(&batchCmd, " -wd ", wd);
    }

    if (nbProcesses > 1) {
      StrAppend(&batchCmd, " -o ", outputDir);
    }

    targets.emplace_back(std::move(targetname));
    batchProcessCommands.emplace_back(std::move(batchCmd));
  }

  // Small jobs batch in clump processes
  for (size_t i = 0; i < nbProcesses; i++) {
    std::string fileList;
    absoluteIndex++;
    for (const auto compiler : jobArray[i]) {
      fs::path fileName =
          fileSystem->toPlatformPath(compiler->getPpOutputFileId());
      std::string_view svFile =
          m_commandLineParser->isSVFile(compiler->getFileId()) ? " -sv " : " ";
      StrAppend(&fileList, svFile, fileName);
    }
    if (!fileList.empty()) {
      std::string targetname =
          StrCat(std::to_string(absoluteIndex), "_",
                 std::get<1>(fileSystem->getLeaf(
                     jobArray[i].back()->getPpOutputFileId(),
                     jobArray[i].back()->getSymbolTable())));

      std::string batchCmd =
          StrCat(profile, fileUnit, sverilog, synth, noHash,
                 " -parseonly -nostdout -nobuiltin -mt 0 -mp 0 -l ",
                 targetname + ".log ", fileList);
      for (const std::string& wd : fileSystem->getWorkingDirs()) {
        StrAppend(&batchCmd, " -wd ", wd);
      }

      if (nbProcesses > 1) {
        StrAppend(&batchCmd, " -o ", outputDir);
      }

      targets.emplace_back(std::move(targetname));
      batchProcessCommands.emplace_back(std::move(batchCmd));
    }
  }

  const PathId dirId = fileSystem->getPpMultiprocessingDir(
      m_commandLineParser->fileunit(), symbolTable);
  fileSystem->mkdirs(dirId);

  if (nbProcesses == 1) {
    // Single child process
    const PathId fileId =
        fileSystem->getChild(dirId, "parser_batch.txt", symbolTable);
    if (!fileSystem->writeLines(fileId, batchProcessCommands)) {
      std::cerr << "FATAL: Could not create file: " << PathIdPP(fileId)
                << std::endl;
      return false;
    }

    const std::string command =
        StrCat("cd ", workingDir, "; ", programPath, " -o ", outputDir,
               " -nostdout -batch ", fileSystem->toPath(fileId));
    if (!muted) std::cout << "Running: " << command << std::endl << std::flush;
    int result = system(command.c_str());
    if (!muted) std::cout << "Surelog parsing status: " << result << std::endl;
    if (!result) return false;
  } else {
    // Multiple child processes managed by cmake
    const PathId fileId =
        fileSystem->getChild(dirId, "CMakeLists.txt", symbolTable);
    std::ostream& ofs = fileSystem->openForWrite(fileId);
    if (ofs.good()) {
      ofs << "cmake_minimum_required (VERSION 3.0)" << std::endl;
      ofs << "# Auto generated by Surelog" << std::endl;
      ofs << "project(SurelogParsing NONE)" << std::endl << std::endl;

      for (int i = 0, n = targets.size(); i < n; ++i) {
        ofs << "add_custom_command(OUTPUT " << targets[i] << std::endl;
        ofs << "  COMMAND " << programPath << batchProcessCommands[i];
        ofs << std::endl;
        ofs << "  WORKING_DIRECTORY " << workingDir << std::endl;
        ofs << ")" << std::endl;
      }
      ofs << std::endl;

      ofs << "add_custom_target(Parse ALL DEPENDS" << std::endl;
      for (const auto& target : targets) {
        ofs << "  " << target << std::endl;
      }
      ofs << ")" << std::endl;
      ofs << std::flush;
      fileSystem->close(ofs);
    } else {
      std::cerr << "FATAL: Could not create file: " << PathIdPP(fileId)
                << std::endl;
      return false;
    }

    const std::string command =
        StrCat("cd ", fileSystem->toPath(dirId),
               "; cmake -G \"Unix Makefiles\" .; make -j ", nbProcesses);
    if (!muted) std::cout << "Running: " << command << std::endl << std::flush;
    int result = system(command.c_str());
    if (!muted) std::cout << "Surelog parsing status: " << result << std::endl;
    if (!result) return false;
  }
  return true;
}

bool Compiler::createMultiProcessPreProcessor_() {
  unsigned int nbProcesses = m_commandLineParser->getNbMaxProcesses();
  if (nbProcesses == 0) return true;

  if (!(m_commandLineParser->writePpOutput() ||
        m_commandLineParser->writePpOutputFileId())) {
    return true;
  }

  FileSystem* const fileSystem = FileSystem::getInstance();
  SymbolTable* symbolTable = getSymbolTable();

  const bool muted = m_commandLineParser->muteStdout();
  const fs::path workingDir = fileSystem->getWorkingDir();
  const fs::path outputDir =
      fileSystem->toPlatformPath(m_commandLineParser->getOutputDirId());
  const fs::path programPath =
      fileSystem->toPlatformPath(m_commandLineParser->getProgramId());
  const std::string_view profile =
      m_commandLineParser->profile() ? " -profile " : " ";
  const std::string_view sverilog =
      m_commandLineParser->fullSVMode() ? " -sverilog " : " ";
  const std::string_view fileUnit =
      m_commandLineParser->fileunit() ? " -fileunit " : " ";
  std::string synth =
      m_commandLineParser->reportNonSynthesizable() ? " -synth " : " ";
  synth += m_commandLineParser->reportNonSynthesizableWithFormal() ? " -formal "
                                                                   : " ";
  const std::string_view noHash =
      m_commandLineParser->noCacheHash() ? " -nohash " : " ";

  std::string fileList;
  // +define+
  for (const auto& [id, value] : m_commandLineParser->getDefineList()) {
    const std::string& defName =
        m_commandLineParser->getSymbolTable()->getSymbol(id);
    std::string val = StringUtils::replaceAll(value, "#", "\\#");
    StrAppend(&fileList, " -D", defName, "=", val);
  }

  // Source files (.v, .sv on the command line)
  for (const PathId& id : m_commandLineParser->getSourceFiles()) {
    std::string_view svFile = m_commandLineParser->isSVFile(id) ? " -sv " : " ";
    StrAppend(&fileList, svFile, fileSystem->toPath(id));
  }
  // Library files (-v <file>)
  for (const PathId& id : m_commandLineParser->getLibraryFiles()) {
    StrAppend(&fileList, " -v ", fileSystem->toPath(id));
  }
  // (-y <path> +libext+<ext>)
  for (const PathId& id : m_commandLineParser->getLibraryPaths()) {
    StrAppend(&fileList, " -y ", fileSystem->toPath(id));
  }
  // +libext+
  for (const SymbolId& id : m_commandLineParser->getLibraryExtensions()) {
    const std::string& extName =
        m_commandLineParser->getSymbolTable()->getSymbol(id);
    StrAppend(&fileList, " +libext+", extName);
  }
  // Include dirs
  for (const PathId& id : m_commandLineParser->getIncludePaths()) {
    StrAppend(&fileList, " -I", fileSystem->toPath(id));
  }

  std::string batchCmd = StrCat(profile, fileUnit, sverilog, synth, noHash,
                                " -writepp -mt 0 -mp 0 -nobuiltin -noparse "
                                "-nostdout -l preprocessing.log -cd ",
                                workingDir, fileList);
  for (const std::string& wd : fileSystem->getWorkingDirs()) {
    StrAppend(&batchCmd, " -wd ", wd);
  }

  const PathId dirId = fileSystem->getParserMultiprocessingDir(
      m_commandLineParser->fileunit(), symbolTable);
  fileSystem->mkdirs(dirId);

  if (nbProcesses == 1) {
    // Single child process
    const PathId fileId =
        fileSystem->getChild(dirId, "pp_batch.txt", symbolTable);
    if (!fileSystem->writeContent(fileId, batchCmd)) {
      std::cerr << "FATAL: Could not create file: " << PathIdPP(fileId)
                << std::endl;
      return false;
    }
    std::string command =
        StrCat("cd ", workingDir, "; ", programPath, " -o ", outputDir,
               " -nostdout -batch ", fileSystem->toPath(fileId));
    if (!muted) std::cout << "Running: " << command << std::endl << std::flush;
    int result = system(command.c_str());
    if (!muted) std::cout << "Surelog preproc status: " << result << std::endl;
    if (!result) return false;
  } else {
    // Create CMakeLists.txt
    StrAppend(&batchCmd, " -o ", outputDir);

    const PathId fileId =
        fileSystem->getChild(dirId, "CMakeLists.txt", symbolTable);
    std::ostream& ofs = fileSystem->openForWrite(fileId);
    if (ofs.good()) {
      ofs << "cmake_minimum_required (VERSION 3.0)" << std::endl;
      ofs << "# Auto generated by Surelog" << std::endl;
      ofs << "project(SurelogPreprocessing NONE)" << std::endl << std::endl;
      ofs << "add_custom_command(OUTPUT preprocessing" << std::endl;
      ofs << "  COMMAND " << programPath << batchCmd << std::endl;
      ofs << "  WORKING_DIRECTORY " << workingDir << std::endl;
      ofs << ")" << std::endl << std::endl;
      ofs << "add_custom_target(Parse ALL DEPENDS preprocessing)" << std::endl;
      ofs << std::flush;
      fileSystem->close(ofs);
    } else {
      std::cerr << "FATAL: Could not create file: " << PathIdPP(fileId)
                << std::endl;
      return false;
    }

    std::string command =
        StrCat("cd ", fileSystem->toPath(dirId),
               "; cmake -G \"Unix Makefiles\" .; make -j ", nbProcesses);
    if (!muted) std::cout << "Running: " << command << std::endl << std::flush;
    int result = system(command.c_str());
    if (!muted) std::cout << "Surelog preproc status: " << result << std::endl;
    if (!result) return false;
  }

  return true;
}

static int calculateEffectiveThreads(int nbThreads) {
  if (nbThreads <= 4) return nbThreads;
  return (int)(log(((float)nbThreads + 1.0) / 4.0) * 10.0);
}

bool Compiler::parseinit_() {
  Precompiled* const prec = Precompiled::getSingleton();

  // Single out the large files.
  // Small files are going to be scheduled in multiple threads based on size.
  // Large files are going to be compiled in a different batch in multithread

  if (!m_commandLineParser->fileunit()) {
    DeleteContainerPointersAndClear(&m_symbolTables);
    DeleteContainerPointersAndClear(&m_errorContainers);
  }

  std::vector<CompileSourceFile*> tmp_compilers;
  for (CompileSourceFile* const compiler : m_compilers) {
    const unsigned int nbThreads =
        prec->isFilePrecompiled(compiler->getPpOutputFileId(),
                                compiler->getSymbolTable())
            ? 0
            : m_commandLineParser->getNbMaxTreads();

    const int effectiveNbThreads = calculateEffectiveThreads(nbThreads);

    AnalyzeFile* const fileAnalyzer = new AnalyzeFile(
        m_commandLineParser, m_design, compiler->getPpOutputFileId(),
        compiler->getFileId(), effectiveNbThreads, m_text);
    fileAnalyzer->analyze();
    compiler->setFileAnalyzer(fileAnalyzer);
    if (fileAnalyzer->getSplitFiles().size() > 1) {
      // Schedule parent
      m_compilersParentFiles.push_back(compiler);
      compiler->initParser();

      if (!m_commandLineParser->fileunit()) {
        SymbolTable* symbols =
            m_commandLineParser->getSymbolTable()->CreateSnapshot();
        m_symbolTables.push_back(symbols);
        compiler->setSymbolTable(symbols);
        // fileContent->setSymbolTable(symbols);
        ErrorContainer* errors = new ErrorContainer(symbols);
        m_errorContainers.push_back(errors);
        errors->registerCmdLine(m_commandLineParser);
        compiler->setErrorContainer(errors);
      }

      compiler->getParser()->setFileContent(new FileContent(
          compiler->getParser()->getFileId(0),
          compiler->getParser()->getLibrary(), compiler->getSymbolTable(),
          compiler->getErrorContainer(), nullptr, BadPathId));

      int j = 0;
      for (const auto& ppId : fileAnalyzer->getSplitFiles()) {
        SymbolTable* symbols =
            m_commandLineParser->getSymbolTable()->CreateSnapshot();
        m_symbolTables.push_back(symbols);
        CompileSourceFile* chunkCompiler = new CompileSourceFile(
            compiler, ppId, fileAnalyzer->getLineOffsets()[j]);
        // Schedule chunk
        tmp_compilers.push_back(chunkCompiler);

        chunkCompiler->setSymbolTable(symbols);
        ErrorContainer* errors = new ErrorContainer(symbols);
        m_errorContainers.push_back(errors);
        errors->registerCmdLine(m_commandLineParser);
        chunkCompiler->setErrorContainer(errors);
        // chunkCompiler->getParser ()->setFileContent (fileContent);

        FileContent* const chunkFileContent =
            new FileContent(compiler->getParser()->getFileId(0),
                            compiler->getParser()->getLibrary(), symbols,
                            errors, nullptr, ppId);
        chunkCompiler->getParser()->setFileContent(chunkFileContent);
        getDesign()->addFileContent(compiler->getParser()->getFileId(0),
                                    chunkFileContent);

        j++;
      }
    } else {
      if ((!m_commandLineParser->fileunit()) && m_text.empty()) {
        SymbolTable* symbols =
            m_commandLineParser->getSymbolTable()->CreateSnapshot();
        m_symbolTables.push_back(symbols);
        compiler->setSymbolTable(symbols);
        ErrorContainer* errors = new ErrorContainer(symbols);
        m_errorContainers.push_back(errors);
        errors->registerCmdLine(m_commandLineParser);
        compiler->setErrorContainer(errors);
      }

      tmp_compilers.push_back(compiler);
    }
  }
  m_compilers = tmp_compilers;

  return true;
}

bool Compiler::pythoninit_() { return parseinit_(); }

ErrorContainer::Stats Compiler::getErrorStats() const {
  ErrorContainer::Stats stats;
  for (const auto& s : m_errorContainers) {
    stats += s->getErrorStats();
  }

  return stats;
}

bool Compiler::cleanup_() {
  DeleteContainerPointersAndClear(&m_compilers);
  DeleteContainerPointersAndClear(&m_compilationUnits);
  DeleteContainerPointersAndClear(&m_symbolTables);
  DeleteContainerPointersAndClear(&m_errorContainers);
  return true;
}

bool Compiler::compileFileSet_(CompileSourceFile::Action action,
                               bool allowMultithread,
                               std::vector<CompileSourceFile*>& container) {
  FileSystem* const fileSystem = FileSystem::getInstance();
  const unsigned short maxThreadCount =
      allowMultithread ? m_commandLineParser->getNbMaxTreads() : 0;

  if (maxThreadCount < 1) {
    // Single thread
    for (CompileSourceFile* const source : container) {
#ifdef SURELOG_WITH_PYTHON
      source->setPythonInterp(PythonAPI::getMainInterp());
#endif
      bool status = compileOneFile_(source, action);
      m_errors->appendErrors(*source->getErrorContainer());
      m_errors->printMessages(m_commandLineParser->muteStdout());
      if ((!status) || source->getErrorContainer()->hasFatalErrors()) {
        return false;
      }
    }
  } else if (getCommandLineParser()->useTbb() &&
             (action != CompileSourceFile::Action::Parse)) {
#ifdef USETBB
    // TBB Thread management
    if (maxThreadCount) {
      for (CompileSourceFile* const source : container) {
        m_taskGroup.run(FunctorCompileOneFile(source, action));
      }
      m_taskGroup.wait();
      bool fatalErrors = false;
      for (CompileSourceFile* const source : container) {
        // Promote report to master error container
        m_errors->appendErrors(*source->getErrorContainer());
        if (source->getErrorContainer()->hasFatalErrors()) {
          fatalErrors = true;
        }
        if (getCommandLineParser()->pythonListener()) {
          source->shutdownPythonInterp();
        }
        m_errors->printMessages(m_commandLineParser->muteStdout());
      }
      if (fatalErrors) return false;
    } else {
      for (CompileSourceFile* const source : container) {
        source->setPythonInterp(PythonAPI::getMainInterp());
        bool status = compileOneFile_(source, action);
        m_errors->appendErrors(*souirce->getErrorContainer());
        m_errors->printMessages(m_commandLineParser->muteStdout());
        if ((!status) || source->getErrorContainer()->hasFatalErrors())
          return false;
      }
    }
#endif
  } else {
    // Custom Thread management

    // Optimize the load balance, try to even out the work in each thread by the
    // size of the files
    std::vector<std::vector<CompileSourceFile*>> jobArray(maxThreadCount);
    std::vector<unsigned long> jobSize(maxThreadCount, 0);

    for (CompileSourceFile* const source : container) {
      const unsigned int size = source->getJobSize(action);
      unsigned int newJobIndex = 0;
      uint64_t minJobQueue = ULLONG_MAX;
      for (unsigned short ii = 0; ii < maxThreadCount; ii++) {
        if (jobSize[ii] < minJobQueue) {
          newJobIndex = ii;
          minJobQueue = jobSize[ii];
        }
      }

      jobSize[newJobIndex] += size;
      jobArray[newJobIndex].push_back(source);
    }

    if (getCommandLineParser()->profile()) {
      if (action == CompileSourceFile::Preprocess)
        std::cout << "Preprocessing task" << std::endl;
      else if (action == CompileSourceFile::Parse)
        std::cout << "Parsing task" << std::endl;
      else
        std::cout << "Misc Task" << std::endl;
      for (unsigned short i = 0; i < maxThreadCount; i++) {
        std::cout << "Thread " << i << " : " << std::endl;
        int sum = 0;
        for (const CompileSourceFile* job : jobArray[i]) {
          PathId fileId;
          if (job->getPreprocessor())
            fileId = job->getPreprocessor()->getFileId(0);
          else if (job->getParser())
            fileId = job->getParser()->getFileId(0);
          sum += job->getJobSize(action);
          std::cout << job->getJobSize(action) << " "
                    << fileSystem->toPath(fileId) << std::endl;
        }
        std::cout << ", Total: " << sum << std::endl << std::flush;
      }
    }

    // Create the threads with their respective workloads
    std::vector<std::thread*> threads;
    for (unsigned short i = 0; i < maxThreadCount; i++) {
      std::thread* th = new std::thread([=] {
        for (CompileSourceFile* job : jobArray[i]) {
#ifdef SURELOG_WITH_PYTHON
          if (getCommandLineParser()->pythonListener() ||
              getCommandLineParser()->pythonEvalScriptPerFile()) {
            PyThreadState* interpState = PythonAPI::initNewInterp();
            job->setPythonInterp(interpState);
          }
#endif
          job->compile(action);
#ifdef SURELOG_WITH_PYTHON
          if (getCommandLineParser()->pythonListener() ||
              getCommandLineParser()->pythonEvalScriptPerFile()) {
            job->shutdownPythonInterp();
          }
#endif
        }
      });
      threads.push_back(th);
    }

    // Wait for all of them to finish
    for (auto& t : threads) {
      t->join();
    }

    // Delete the threads
    DeleteContainerPointersAndClear(&threads);

    // Promote report to master error container
    bool fatalErrors = false;
    for (CompileSourceFile* const source : container) {
      m_errors->appendErrors(*source->getErrorContainer());
      if (source->getErrorContainer()->hasFatalErrors()) {
        fatalErrors = true;
      }
    }
    m_errors->printMessages(m_commandLineParser->muteStdout());

    if (fatalErrors) return false;
  }
  return true;
}

bool Compiler::compile() {
  FileSystem* const fileSystem = FileSystem::getInstance();
  std::string profile;
  Timer tmr;
  Timer tmrTotal;
  // Scan the libraries definition
  if (!parseLibrariesDef_()) return false;

  if (m_commandLineParser->profile()) {
    std::string msg = "Scan libraries took " +
                      StringUtils::to_string(tmr.elapsed_rounded()) + "s\n";
    std::cout << msg << std::endl;
    profile += msg;
    tmr.reset();
  }

  // Preprocess
  ppinit_();
  createMultiProcessPreProcessor_();
  if (!compileFileSet_(CompileSourceFile::Preprocess,
                       m_commandLineParser->fileunit(), m_compilers)) {
    return false;
  }
  // Single thread post Preprocess
  if (!compileFileSet_(CompileSourceFile::PostPreprocess, false, m_compilers)) {
    return false;
  }

  if (m_commandLineParser->profile()) {
    std::string msg = "Preprocessing took " +
                      StringUtils::to_string(tmr.elapsed_rounded()) + "s\n";
    std::cout << msg << std::endl;
    for (const CompileSourceFile* compiler : m_compilers) {
      msg += compiler->getPreprocessor()->getProfileInfo();
    }
    std::cout << msg << std::endl;
    profile += msg;
    tmr.reset();
  }

  // Parse
  bool parserInitialized = false;
  if (m_commandLineParser->parse() || m_commandLineParser->pythonListener() ||
      m_commandLineParser->pythonEvalScriptPerFile() ||
      m_commandLineParser->pythonEvalScript()) {
    parseinit_();
    createFileList_();
    createMultiProcessParser_();
    parserInitialized = true;
    if (!compileFileSet_(CompileSourceFile::Parse, true, m_compilers)) {
      return false;  // Small files and large file chunks
    }
    if (!compileFileSet_(CompileSourceFile::Parse, true,
                         m_compilersParentFiles)) {
      return false;  // Recombine chunks
    }
  } else {
    createFileList_();
  }

  if (m_commandLineParser->profile()) {
    std::string msg =
        "Parsing took " + StringUtils::to_string(tmr.elapsed_rounded()) + "s\n";
    for (const CompileSourceFile* compilerParent : m_compilersParentFiles) {
      msg += compilerParent->getParser()->getProfileInfo();
    }
    for (const CompileSourceFile* compiler : m_compilers) {
      msg += compiler->getParser()->getProfileInfo();
    }

    std::cout << msg << std::endl;
    profile += msg;
    tmr.reset();
  }

  // Check Parsing
  CheckCompile* checkComp = new CheckCompile(this);
  bool parseOk = checkComp->check();
  delete checkComp;
  m_errors->printMessages(m_commandLineParser->muteStdout());

  // Python Listener
  if (parseOk && (m_commandLineParser->pythonListener() ||
                  m_commandLineParser->pythonEvalScriptPerFile())) {
    if (!parserInitialized) pythoninit_();
    if (!compileFileSet_(CompileSourceFile::PythonAPI, true, m_compilers))
      return false;
    if (!compileFileSet_(CompileSourceFile::PythonAPI, true,
                         m_compilersParentFiles))
      return false;

    if (m_commandLineParser->profile()) {
      std::string msg = "Python file processing took " +
                        StringUtils::to_string(tmr.elapsed_rounded()) + "s\n";
      std::cout << msg << std::endl;
      profile += msg;
      tmr.reset();
    }
  }

  if (parseOk && m_commandLineParser->compile()) {
    // Compile Design, has its own thread management
    m_compileDesign = new CompileDesign(this);
    m_compileDesign->compile();
    m_errors->printMessages(m_commandLineParser->muteStdout());

    if (m_commandLineParser->profile()) {
      std::string msg = "Compilation took " +
                        StringUtils::to_string(tmr.elapsed_rounded()) + "s\n";
      std::cout << msg << std::endl;
      profile += msg;
      tmr.reset();
    }

    if (m_commandLineParser->elaborate()) {
      m_compileDesign->elaborate();
      m_errors->printMessages(m_commandLineParser->muteStdout());

      if (m_commandLineParser->profile()) {
        std::string msg = "Elaboration took " +
                          StringUtils::to_string(tmr.elapsed_rounded()) + "s\n";
        std::cout << msg << std::endl;
        profile += msg;
        tmr.reset();
      }

      if (m_commandLineParser->pythonEvalScript()) {
        PythonAPI::evalScript(
            fileSystem->toPath(m_commandLineParser->pythonEvalScriptId()),
            m_design);
        if (m_commandLineParser->profile()) {
          std::string msg = "Python design processing took " +
                            StringUtils::to_string(tmr.elapsed_rounded()) +
                            "s\n";
          profile += msg;
          std::cout << msg << std::endl;
          tmr.reset();
        }
      }
      m_errors->printMessages(m_commandLineParser->muteStdout());
    }

    PathId uhdmFileId = fileSystem->getChild(
        m_commandLineParser->getCompileDirId(), "surelog.uhdm",
        m_compileDesign->getCompiler()->getSymbolTable());
    m_uhdmDesign = m_compileDesign->writeUHDM(uhdmFileId);
    // Do not delete as now UHDM has to live past the compilation step
    // delete compileDesign;
  }
  if (m_commandLineParser->profile()) {
    std::string msg = "Total time " +
                      StringUtils::to_string(tmrTotal.elapsed_rounded()) +
                      "s\n";
    profile += msg;
    profile = std::string("==============\n") + "PROFILE\n" +
              std::string("==============\n") + profile + "==============\n";
    std::cout << profile << std::endl;
    m_errors->printToLogFile(profile);
  }
  return true;
}

void Compiler::registerAntlrPpHandlerForId(
    SymbolId id, PreprocessFile::AntlrParserHandler* pp) {
  std::map<SymbolId, PreprocessFile::AntlrParserHandler*>::iterator itr =
      m_antlrPpMap.find(id);
  if (itr != m_antlrPpMap.end()) {
    delete (*itr).second;
    m_antlrPpMap.erase(itr);
    m_antlrPpMap.emplace(id, pp);
    return;
  }
  m_antlrPpMap.emplace(id, pp);
}

PreprocessFile::AntlrParserHandler* Compiler::getAntlrPpHandlerForId(
    SymbolId id) {
  std::map<SymbolId, PreprocessFile::AntlrParserHandler*>::iterator itr =
      m_antlrPpMap.find(id);
  if (itr != m_antlrPpMap.end()) {
    PreprocessFile::AntlrParserHandler* ptr = (*itr).second;
    return ptr;
  }
  return nullptr;
}

bool Compiler::parseLibrariesDef_() {
  ParseLibraryDef* libParser = new ParseLibraryDef(
      m_commandLineParser, m_errors, m_symbolTable, m_librarySet, m_configSet);
  return libParser->parseLibrariesDefinition();
}
}  // namespace SURELOG

redpajama_set_name: RedPajamaGithub


text:
Vaccine Claims
Disability & ERISA Claims
Home/IIHS Rates Crash Avoidance Systems
IIHS Rates Crash Avoidance Systems
webadmin2019-10-11T18:33:04-06:00
The continual advance of technology has generated various types of systems and features that claim to improve the safety of motor vehicles by attempting to reduce the incidence of car accidents. Known as crash avoidance systems, these features can do anything from slow down or automatically stop cars to actually turning or guiding vehicles without a motorist's intentional action. Some examples of more common crash avoidance systems (or crash avoidance technologies, as they are also known) include (but are not limited to):
Lane departure warning systems, which use sensors, cameras or radar to detect when a car may be leaving its designated traffic lane and, when this occurs, automatically steer the car back into its chosen lane
Front crash prevention systems, which use radar or cameras to sense when vehicles are vehicles are within a minimal distance of other cars – This systems can generally automatically apply a vehicle's brakes when they sense that a car is close to crashing into a vehicle in front of it.
Blind spot detection systems, which also use sensors or radar to perceive whether there is an object in a car's blind spot when a driver is trying to turn or change lanes – If something is detected in the blind spot, then an automatic steering action can be put into action to prevent the driver from crashing into the object in his blind spot.
Backover prevention systems, which also use sensors, radar and/or cameras to perceive whether there is an object behind a reversing car and, if so, automatically apply the brakes to prevent the vehicle from crashing into the object behind it.
These systems, while alleged to improve vehicle safety, can come at a high price – sometimes adding thousands of dollars to the cost of a car. Given their cost and their purported safety benefits, the Insurance Institute of Highway Safety (IIHS) conducted an in-depth study to test how safe these systems really are and which ones are worth the extra money.
How the IIHS Tested Crash Avoidance Systems
To test the safety of various crash avoidance technologies, the IIHS simulated a crash in which a vehicle would slam into the back of a stopped SUV. They did this by creating a large cloth box and propelling the vehicles to be tested into that box. The front crash prevention systems of more than 70 cars were tested in this manner.
Based on the performance of the crash avoidance system, the IIHS gave out the following ratings:
Superior – the highest rating, which was given to systems that prevented a collision entirely or were able to slow the vehicle enough to substantially reduce the severity of the crash
Advanced – the second highest rating, which was given if the system reduced the impact speed by at least 5 mph
Basic – the lowest rating, which was given when the system only had a minimal (if any) effect on preventing the crash or the severity of it.
The IIHS' Findings: What Systems Are Worth the Expense
According to the IIHS, the following vehicles received a Superior rating:
Cadillac ATS and SRX
Volvo S60 and XC60.
Advanced ratings were given to the following vehicles:
Audi A4 and Q5 SUV
Lexus ES.
Both the Toyota Prius V wagon and the Infiniti JX35 were among the vehicles that received a Basic rating.
The bottom line, according to the IIHS, is that safety is worth paying for but that consumers should do their research before believing car makers' claims about how effective their crash avoidance technologies actually are.
Get in Touch with the Boulder Car Accident Lawyers at Cederberg Law
If you or a loved one has been injured in a car accident – or if you have lost a loved one in any type of motor vehicle accident, contact the Boulder car accident lawyers at Cederberg Law by calling us at 303-499-0449 or emailing us using the form at the right-hand side of the screen.
We have been successful at obtaining results, compensation and justice for people who have been seriously injured in traffic accidents for more than 35 years. Having handled countless cases, our attorneys have a deep understanding of the law, as well as the legal experience you need, and we can fiercely defend your rights in any legal setting. In fact, our trusted car accident attorneys are a formidable force, and we will not back down until you secure the maximum possible compensation for your injuries, expenses and losses.
Retired Pro Cyclist Loses Arm After Colliding with Truck Above Boulder
Will New On-Ramp Metering Fix Colorado's Traffic Problems?
Fatal ATV Accidents: Too Common & Often Preventable [Infographic]
July 4th Is the Deadliest Day to Be on the Roads [Infographic]
May Is Motorcycle Safety Awareness Month [Infographic]
If you have been injured, it is important to consult with experienced lawyers who have helped individuals through similar situations in the past. Luke Cederberg provides well-respected representation to clients throughout Colorado…Read More
Being the victim of another person's negligence can change your life in a second. When you are hurt in an accident because of the wrongdoing of another individual, it is critical to seek knowledgeable guidance from skilled personal injury lawyers…Read More
You pay good money for insurance to protect your financial security and help with your financial needs in times of trouble or calamity. You deserve the peace of mind that having such protection brings…Read More
© 2019 | Cederberg Law | All rights reserved.
Cederberg Law | 1200 28th Street, Suite 302, Boulder, CO 80303

redpajama_set_name: RedPajamaCommonCrawl


Did you know a dental cleaning, is only part of the equation when it comes to your overall health?
We consider, the mouth to be the gateway to the rest of the body because many other illnesses first represent themselves as changes within the mouth. As a result, a comprehensive oral dental exam is recommended every 3- 5 years to re-evaluate your dental health and over all health.
It is also recommended if you have had a substantial change in your health history since your last regular visit, or if you have not been to your regular dentist in more than three years.
Your hygienist and dentist will also perform a visual and digital examination of all the hard and soft tissues of your head and neck, including lymph nodes. Think of it like a physical for your head and neck, lips, cheeks, and gums. It's not just about your teeth!
A comprehensive oral evaluation is a valuable part of your preventative health plan, and your Barrie dentist and hygienist are a great ally in keeping an eye out for undiagnosed illnesses. Have you had your COE? Call us today to reserve time with our team!


text:
Op-ed: Making the shift—An autonomous vehicle future requires bigger thinking
Written by Keane Gruending, Communications Manager, Renewable Cities. This op-ed originally appeared in the November 9, 2017 edition of the Vancouver Observer.
In Canadian cities, most people move around today the same way they did a decade ago. Which is to say, for the most part, personal cars still dominate, while walking, cycling, and transit represent a smaller piece of the transportation pie.
Even Vancouver, which is held up as a fine example of transportation planning, sees 50% of trips in the city made by automobiles. While progress is being made in shifting to other modes, the way people get around seems destined to stay about the same for the foreseeable future.
But behind the scenes the fundamentals of passenger transportation are undergoing seismic shifts.
Converging developments in autonomous car technology, sharing platforms, and vehicle electrification promise to reshape the future of personal mobility in places like Metro Vancouver. Over the last six months, Tesla eclipsed General Motors as the most valuable car company in the United States.
Uber registered its two billionth trip, while its ride sharing platform, UberPool hit a high watermark of nearly a million trips per day in China. Ford recently bankrolled a billion dollars into an artificial intelligence startup for vehicles. Daimler, Renault, Google, and others are developing and pitching their own driverless car solutions.
To be sure, it will be some time before this tsunami of new technologies and business models hits the shores of personal mobility. Ever bullish, Elon Musk says most new vehicles will be capable of autonomy inside of ten years. Total SA, one of the world's oil majors, claims that up to one third of new cars sold could be of the electric variety by 2030. More sober predictions peg mid-century as the point when autonomous vehicles become either the majority or even mandatory.
Regardless of when autonomous vehicles, possibly electrified and shared, become mainstream, they promise to massively impact the shapes of communities—for better or worse. Even the limited adoption of driverless cars covering 5-10% of trips in a city, which is entirely possible within ten years, will have wide-ranging impacts on transportation systems.
How are cities planning to tackle the challenges and opportunities presented by driverless vehicles?
Some municipalities are staying ahead by hosting active trials. San Diego, whose regional planning agency sees driverless cars starting to displace conventional automobiles by 2025, is home to a cluster of tech providers.
In Pittsburgh, Uber users were treated to free rides in luxury SUVs as part of an experiment. The caveat? Passengers had to be OK with a computer behind the wheel. Pittsburgh's edge in the autonomous vehicles arms race is a high concentration of local robotics experts, thanks to its partnership with Carnegie Mellon.
However, the truth is that most cities are not thinking about autonomous cars at all. A recent survey yielded that only four of the United States' largest 68 cities are considering driverless technologies in their transportation planning.
For its part, Vancouver City Council recently considered a report that presented two of the major consensus views about the future of autonomous vehicles in cities.
In one camp, proponents of autonomous vehicles cite a utopian future where everyone—seniors and people with disabilities included—enjoy convenient, safe, and cost-effective mobility, without the burdens of private car ownership.
The economics of shared and driverless vehicles make fossil fuel combustion uneconomic; why wouldn't a fleet operator choose electricity over petroleum? If the suburbs aren't going anywhere, then electric and autonomous vehicles are the ticket to completely renewable transportation.
As cars efficiently hug each others' bumpers in "platoon driving formation" in segregated autonomous car superhighways, the streets, including most parking, are reclaimed for more human uses such as treed boulevards, bike lanes, and playgrounds. Free from the burdens of bumper to bumper traffic, goods and freight movement are unlocked, providing economic benefits for everyone.
The critical camp view autonomous vehicles as the ultimate suburban subsidy. Smart and efficient computer driving is a double-edged sword. The backside of the blade is that the time and expense penalties of commuting to work over long distances are removed; It's transportation economics 101.
Why live downtown if the suburbs offer cheap land, housing, and travel? No waiting at stoplights or circling city blocks looking for parking. Why take the bus when a roving autonomous taxi can be outside of your door in mere minutes? You can even nap or perfect your double Windsor Knot en route. The critical camp's view is that autonomous cars will promote urban sprawl, chewing through land and resources.
So how will municipalities, including those in Metro Vancouver, respond to this groundswell of new personal mobility? The advice coming from Bloomberg is that there is a narrow window of time to shape the future of driverless cars.
With an eye to the mid-20th century takeover of city streets by automobiles, Peter D. Norton writes in Fighting Traffic, "There is a naive view that autonomous vehicles are in themselves beneficial. They can be beneficial only if we deliberately make them so." This view is also reflected in a recent Greenest City Scholar report, recently submitted to the City of Vancouver.
The report lays out some ground rules for dealing with autonomous vehicles and capturing local benefits: Autonomous vehicles need to complement active transportation, not the other way around. Walking and cycling need to be the easiest and most convenient way to travel. Plan for a zero-emissions transportation future and continue to build compact communities that support active and healthy transportation.
The economic and environmental upside of autonomous vehicles done well are tremendous. But cities would be wise to keep people at the centre of the urban and transportation planning.


Modern feeds are high-tech products. They offer fishes and crustaceans in aquaculture everything they need for their existence and ensure that the organisms grow fast, remain healthy and develop normally. But who knows exactly what such feeds contain? There is probably no area of aquaculture where so many rumours are rampant, or where so much is assumed, speculated and alleged as in the feed sector.
Wild cod don't have to worry about the composition of their prey. With every herring, capelin or smaller fish that they swallow they are taking in a good share of protein packed full with vitamins and minerals, plus a quantum of fat containing polyunsaturated fatty acids , some of them of the Omega 3 type. And as if that weren't enough, the organisms they feed on also contain carbohydrates, enzymes, hormones and other substances because every living organism is a veritable cocktail of various chemical substances. So as long as a cod manages to get hold of a fish regularly enough it will be getting a well-balanced diet and lack nothing.
The situation for fishes that live in aquaculture facilities is completely different. However much trouble farmers go to to offer their fishes acceptable "real-life" farm conditions this is not possible where feed is concerned. The ponds, net cages, raceways and tanks in which the fishes are kept are made of plastic or concrete and as such are artificial habitats that offer much too little natural feed – in fact, usually none at all. This means that feed has to be introduced into the system from the outside… and there has to be enough of it, too, because the intention is not only that the fish will survive but that they will grow quickly and in the desired quality. So they have to get everything they need to stay healthy. During the early years of aquaculture farmers often fed their fishes on cheap slaughter waste or chopped up feed fishes. But this wet feed did not prove very useful because it was difficult to store and dose and also polluted the water in no small measure.
During the search for alternatives the idea arose that it might make sense to dry the feed fish, grind them and form the resulting meal into small dry pellets in the shape of pills. This could then be fed to the fishes. And that was the birth of the efficient feeds that were to give a decisive boost to the development of modern aquaculture. But there was still a long way to go to reach this point. Dry feed, too, proved to have some serious drawbacks at first. It had to be heated in order to dry it and during this heating process, for example, some key ingredients were destroyed so that the fishmeal did not have the same biological value as that of the live fish. Some of the substances that fishmeal contains are not suited to storage and evaporate or decompose over the course of time. Others alter during the mixing and extruding process. Yet another problem at that time was caused by the relatively hard consistencies and the different flavour of the new feed which of course had a different feel in the fishes' mouths and also tasted different from their usual soft feed.
In order to put an end to these and other inadequacies more and more substances were added to the feed to adapt it as closely as possible to the fishes' needs. In countless experiments scientists searched for suitable substances that would solve a particular problem of the feed, and numerous new formulae were tested and optimised. This was no easy task because the feed had to contain all the nutrients and other components in the exact quantities that the fish needed for healthy development and growth. Added to this is the fact that different fish species make different demands on their feed and that juveniles have to be fed different feed from adult fishes. Since the share of fishmeal and fish oil in feed has been constantly reduced through substitution by vegetable alternatives from agriculture, the feed formulae have become much more complicated and demanding with regard to nutritional and physiological aspects. Fishmeal contains high-quality fish protein in a highly digestible form which suits the needs of fishes in aquaculture perfectly. Vegetable proteins, on the other hand, often lack certain amino acids, which then have to be added to the feed later on. Some plants can even slow down digestive and metabolic processes (anti-nutritional factors) or they can also be toxic.
It's not easy to find one's way through the large number of additives. The choice ranges from simple minerals which are added to the feed as micronutrients, through vitamins, enzymes and pH-reducing acidifiers, to pigments and complex premixes in which several additives are mixed together in specific combinations so that they complement and intensify their effects. Some additives are already added to the feeds during their production by the manufacturer, others are mixed by the fish farmer himself directly prior to feeding. Additives produce effects in relatively small quantities and so their share in the feed usually constitutes only fractions of a per cent or is even measured in thousandths. Additives can be inorganic by nature (e.g. minerals) or they can be of organic origin. Some are gained from natural raw materials such as bacteria, yeasts or plants, others through purely chemical processes, i.e. they are produced synthetically. The latter group also includes "nature identical" additives that are produced in test tubes but whose molecular structure is absolutely identical to that of their natural models.
A well-known example of a nature identical additive is astaxanthin, a pigment that is nearly always produced synthetically for aquacultural purposes and which (together with other carotenoids) gives salmon flesh its red colouring. Astaxanthin is, however, not only a "colorant" as some people still think but has other important biological functions beyond that. For example, it has an anti-oxidative effect, it encourages the function and health of the nervous system, and it improves growth and fertility in salmon. Wild salmon living in their natural environment absorb carotenoids when they eat shrimps. Because this is hardly possible in aquaculture, however, an alternative had to be found – and was found in the synthetic, but nature identical, astaxanthin. How close the "copy" is to the natural substance can be seen in the fact that it fulfils all the biological functions within the organism exactly as the natural pigment does.
A reason for using additives can also be found in production technology. In the past, steam was used during the feed production process. The resulting pellets were compact and once in the water they sank quickly. With the modern extrusion techniques which are today state-of-the-art, however, the feed expands as soon as it leaves the extruder so that the specific weight of the pellets decreases and they thus sink more slowly or are even suspended in the water. This gives the fishes more time to pick up the feed particles. Two further advantages of extrusion are the higher digestibility of the feed produced in this way and a longer durability span of the pellets in the water. Both these benefits are the result of thermal treatment of the feed raw material because through heating the nutrients are better solubilised and as from a temperature of about 70°C the contained starch agglutinates the pellets, which also has a stabilising effect. However, heating also contributes towards the destruction of vitamins. Because some vitamins also react sensitively to light and oxygen and thus cannot be stored for long the feed producers had to come up with an idea to get around this problem, too, because a feed that lacks vitamins or certain vitamins would not be of any use to aquaculture. Rainbow trout, for example, needs at least a dozen different vitamins to grow normally and remain healthy.
Today, ready-made "premixes", which contain all the necessary vitamins in a well-balanced mixture are usually added to the feed in the correct dosage. They are also of course available separately in case only one particular vitamin is lacking in a feed. In both cases additives have the advantage that before mixing in the vitamins they can be made less sensitive to light, oxygen, moisture and other external influences by special pre-treatment (mostly coating). Without this, the vitamins in the additives would decompose if the pellets were not fed to the fishes immediately after their production.
All feeds lose quality over the course of time. Their quality is at its best directly after their production because, from then on, creeping changes occur that gradually become more and more noticeable. Firstly it is only digestibility and nutritional value that change but after a time the feed can become completely unusable. How long that takes depends on the storage conditions. In the tropics, where it is always hot with high humidity and intensive sunlight, feed will often spoil within two to three weeks. The protein-rich pellets are also a welcome substrate for all kinds of germs, particularly for fungi. The fat in the pellets oxidises and makes the feed rancid. The small pellet sizes are particularly susceptible to rancidity because their surface is relatively large compared to their volume and this furthers oxidation. Feed producers try to prevent these processes by adding stabilising additives but ultimately decomposition processes cannot be halted but only delayed.
In the meantime a whole industry has developed that is specialised in feed additives and is constantly searching for new, rewarding additives. In complicated experiments attempts are undertaken to find out which substances are particularly effective and what benefits they offer. Dimethylthetin (DMT), for example, which belongs to the additive group of feed attractants, is said to offer a whole bunch of positive effects. This white powder is mainly intended to encourage the fishes to eat and to ensure that they eat more often and thus absorb more nutrients. At the same time, however, it increases their desire to swim and has a stress-reducing effect. DMT stimulates the release of the hormone ecdyson in crustaceans. This hormone is largely responsible for controlling moulting. The crystalline substance TMAO (trimethylamine-N-oxide dihydrate), another feed attractant is, beyond this, also said to directly stimulate growth. It accelerates the cell division rate in the muscle tissue and thus contributes towards faster growth of the fillet. Apart from that, TMAO also reduces fat deposits in the cells, stabilises protein structures and has a positive influence on the organism's osmotic stability.
Probiotics that are mainly based on lactic acid bacteria have recently become increasingly popular in aquaculture. They are said to have a biological balancing and correcting effect.
An application area of additives that is of economic significance to aquaculture is the improvement of certain of the fishes' performance parameters, particularly their growth and survival rate. In the past, antibiotics often used to be added to feed in aquaculture, too, because they have these very effects, i.e. they accelerate growth and encourage good health. Due to growing concerns among the public this routine use of antibiotics in fish feed is illegal almost throughout the world. At the same rate as antibiotics disappeared from feed scientists began looking for alternative substances that would have similar effects but would pose less of a risk. The substances they came up with included derivatives of organic acids such as potassium diformate, a crystalline salt of formic acid. If added to the feed in low dosage potassium diformate improves, for example, feed utilisation in salmon and encourages growth in tilapia.
A fast growing group are "medical" additives that are used to prevent diseases or are used as disease therapy. Here, too, the range extends from relatively simple substances with broad-spectrum effects which are mostly organically based and thus have a high natural availability to complicated and very complex mixtures that have very specific effects. Examples of simple additives with broad-spectrum effects are L- and DL-selenomethionine. The whitish powder is said to "optimise" the fishes' immune systems, improve the body tissue's anti-oxidative power and prevent neoplasm and cancer. The selenium additive apparently also improves the mobility of the sperm cells in spawners. In contrast, a premix of ciprofloxacine and berberine which is used specifically to fight bacterial infections in eel has a highly specific effect.
Additives can also include certain vaccines if they are administered orally with the feed. Vaccines – which are mostly either part of a pathogen or a weakened pathogen – stimulate the protective system of the body to build up an immune defence so that it creates antibodies. The immune system "stores" this reaction and can call it up quickly if this type of germ threatens the organism in reality. Vaccine additives are not to be found in every pellet, however, because they are only mixed into the fish feed for the short duration of immunisation. To prevent the vaccines from being washed out of the feed or modified and being made inactive by digestive enzymes in the intestine they are protected using a special technique (e.g. bioencapsulation, coating). Oral vaccination is easy and causes little stress but it cannot be used against all diseases. Apart from that it mostly only enables immunity over a limited period of time. There also exist special additives for fighting external parasites like salmon lice which can be mixed into the feed. Giving it with the feed is much less harmful to the environment than the immersion therapies which are also used but does not work so quickly and entails a certain toxic risk for the fishes. Among the particularly effective and therefore frequently used substances in feed for delousing fishes are emamectin benzoate and some avermectines.
As is the case in a lot of areas of life there has been an unmistakable trend for some years now in the direction of using natural substances in the feed additive segment, too. Scientists are trying to replace synthetically produced additives with substances that are isolated from yeast cells, for example, or taken from certain plants. Natural additives often have similar if not identical effects to those of purely chemical products which makes careful testing essential prior to usage. Experiments to compare natural and synthetic antioxidants that were carried out by Fiskeriforskning in Norway showed, however, that natural additives are almost as effective as chemical products and might possibly be able to replace controversial synthetic additives such as ethoxyquine (EMQ).
"Probiotic" effects that are mainly based on lactic acid bacteria have recently become increasingly popular in aquaculture. They are said to have a biological balancing and correcting effect. At the moment probiotic bacteria are mainly only used in aquaculture for improving water quality (they are said to "balance" the bacteria population in the water and suppress the development of pathogen species) but they are also already available as additives that are mixed into the feed to strengthen the fishes' immune systems, and to improve feed utilisation and growth. The use of probiotics in aquaculture is a relatively new and controversial concept. Alleged benefits for human, farm animal and fish nutrition are often still faced by a lack of any scientific proof of these kinds of positive effects to date. Irrespective of such disputes a lot of research teams are working all over the world on selecting even more effective probiotic bacteria strains for aquaculture.
The growing number of possible additives in fish feed makes it increasingly difficult even for experts to keep pace with developments and maintain an overview to enable appropriate evaluation of the risks connected to them. Institutes like the Danish DHI Centre for Environment and Toxicology have specialised (among other work areas) in evaluating scientific publications and carrying out their own eco-toxicological studies to enable realistic evaluation of the benefits and risks of additives. Upon the basis of their findings, it is then possible to make expert assessments, for example, or prepare applications for the approval of new additives.


ScarlettWithLove CassieGrace livejasmin. Nancysweetty. EmmaJacob. KimmKa.
HotAngelboy96LuckyStar9999AcollinsxCindyLi .JasminMadisonJanettasweetWendyElizahotPrettyKattys .TenderxLoverGiannaVoAurierBoqDitaFoxy .WhatAboutLoveOliviaJonesJulianAndKassieLaylaHale .FoxyM36DDLittleCinderellaAnnogaNancysweetty .Janettasweetbabycakes4uLiloSexyHotaugusstina .GoldenSweetBBFavulous69LittleJakNastyPartners .SoniaYoungNicoleinloveEdwardsis24cmIcyQueen .KimmKakendraebonyJustinKewellWildBarbarax .MRBHIGCOCKXXXWendyElizahotWhatAboutLoveNaugthyBoys .AvaBarbarahornycouplelatinPamyEllaCindyLi .
LuckyStar9999LittleJakEva38DDPureYoung .Eva38DDSnowQueen7777LittleCat7MysteriousWoman .LorenyShermanLovleyTynaAryaNMorrisLittleCinderella .NastyPartnershirinaPureYoungEvaPrettySweet .Eva38DDJulianAndKassieMissVoggueCindydream .EvaPrettySweetAlineDias995AlineDias995HotAngelboy96 .TenderxLoverAryaNMorrisJhonDorianLaylaHale .MRBHIGCOCKXXXlatinlover1234EmmaJacobHotAngelboy96 .a0RoughDrillingLovleyTynahirinaUnst0pableTS .SunnBunnyNicoleinloveJasminMadisonWendyElizahot .MyklxDaryna7LittleCat7DitaFoxyLittleCinderella .


text:
SAEDA – Student Activists Ending Dating Abuse
Men With Wellspring
Wellspring Newsletter
Wellspring Receives $40,000 Donation from The Rotary Club of Saratoga Springs for New Building
Funds to help support growth of programs and services for survivors of relationship and sexual abuse
SARATOGA COUNTY, NY—Wellspring, the domestic violence and sexual assault services resource for Saratoga County residents, is pleased to announce a charitable contribution in the amount of $40,000 from The Rotary Club of Saratoga Springs. This generous donation supports the development of Wellspring's brand-new facility located just south of exit 13 on Rt. 9 in Malta, which is set to be complete in October 2021. The new building will replace Wellspring's existing facility at 480 Broadway in Saratoga Springs, and allow the organization to provide more impactful programs and services for survivors of domestic violence and sexual assault in Saratoga County.
"The Rotary Club of Saratoga Springs is proud to support Wellspring's ongoing work toward ending relationship and sexual abuse in our community," Stephen Kyne of The Rotary Club of Saratoga Springs says. The organization, which is comprised of a 65+ network of neighbors and business professionals, serves the community by providing funding for local organizations and youth scholarships, as well as through service-oriented events.
"We are grateful for The Rotary Club of Saratoga Spring's donation to Wellspring in addition to their ongoing support of the community," Wellspring Executive Director Maggie Fronk states. "Support from partners like The Rotary Club of Saratoga Springs are crucial in making Wellspring's services more accessible to our community."
The $3 million project will allow Wellspring to offer more safe spaces for counseling, skill growth programs and community prevention initiatives. To support this development, community members are encouraged to spread the word about Wellspring's programs and services, and make a donation directly to the campaign.
Wellspring's mission is to support survivors and engage the community to end relationship and sexual abuse. Each year, Wellspring's crisis intervention and survivor services support more than 1,000 clients—providing safe housing to adults and children either fleeing or homeless because of domestic violence, as well as comprehensive support in the form of counseling, legal advocacy, and case management. Wellspring staff provides prevention and education programs to school-aged youth, as well as training and education programs for parents, faith-based congregations and professional organizations.
To learn more about Wellspring's mission, services and programs, visit www.wellspringcares.org, call their office at 518-583-0280 or reach their hotline at 518-584-8188.
(Pictured from left to right: Wellspring Executive Director Maggie Fronk, The Rotary Club of Saratoga Springs President Susan Rhoades and Stephen Kyne the chair of the major gifts committee for The Rotary Club of Saratoga Springs)
Click to hide your screen
24/7 Free and Confidential Hotline
Archives Select Month January 2023 December 2022 November 2022 October 2022 June 2022 March 2022 May 2021 March 2021 February 2021 January 2021 December 2020 November 2018 September 2018 July 2018 June 2018 March 2018 December 2017 October 2017 September 2017 August 2017 July 2017 June 2017 May 2017 April 2017 March 2017 February 2017 January 2017 November 2016 October 2016 September 2016 August 2016 June 2016 May 2016 April 2016 March 2016 February 2016 January 2016 December 2015 November 2015 October 2015 September 2015 August 2015 July 2015 June 2015 May 2015 April 2015 March 2015 February 2015 January 2015 December 2014 November 2014 October 2014 September 2014 August 2014 July 2014 June 2014 April 2014 March 2014 February 2014 January 2014 December 2013 November 2013 October 2013 September 2013 August 2013 July 2013 June 2013 May 2013 April 2013 March 2013 December 2012 October 2012
For nearly 40 years, Wellspring has been committed to helping survivors of relationship abuse (domestic violence) and sexual assault. What started as a small organization to provide basic shelter and crisis services now has a vision of ending relationship and sexual abuse in our community.
See our 2021-2022 Annual Report
24/7 Hotline: 518-584-8188
Email: info@wellspringcares.org
Monday-Thursday – 9am-6pm
Friday – 8am-5pm
Get Updates From Wellspring!
Yes, I would like to receive emails from Wellspring. (You can unsubscribe anytime.) *


text:
Myron Arlen
Fialeck has helped upgrade our electical system over several years... read moreFialeck has helped upgrade our electical system over several years after previous companies incorrectly wired our home. Fialeck eventally placed twin 240 volt circuits into the house to handle all problems. Recently when handling a short that had suddenly appeared, they noticed that certain fixtures having halogen bulbs were overheating. On checking the wiring it was found that several of the fixtures had their insulation burnt off the wires into the fixtures with extension into the ceiling. If left unrepaired it would be a major source for a spontaneous fire developing. Fortunately they were able to remove and rewire all sites needing immediate repair. read less
Brandon Benilevi
Extremely happy with their service all around. Adam was honest... read moreExtremely happy with their service all around. Adam was honest and straightforward all the way through. Steve, Mike and Bryan were the guys who assembled my high hats, and they were efficient, effective and oh so kind! I have gotten sooo many headaches with electricians before, but these guys were the real deal... A++ read less
Lorraine Kutzing
I am extremely pleased with the service I have received... read moreI am extremely pleased with the service I have received from Fielack Electric. Annette was extremely helpful whenever I called, and Jim was always available to review what I needed done and to communicate that to the electricians assigned to the job. The electricians (Dave, Dan, and Bryan) were very professional and did a great job. They reviewed everything with me before performing the work and made excellent suggestions as well. I would definitely recommend Fielack Electric to anyone looking for quality electricians! read less
Steven Lazarre
I had a bunch of high hats and flood lights... read moreI had a bunch of high hats and flood lights installed two months ago. The lights work great. Lou and Adam provide great customer service. I will definitely use Fielack again for my electrical needs. read less
barbara Sims
Done right I had to install a new line... read moreDone right I had to install a new line for electric stove. read less
Electrician in Lido Beach, NY 11561
Fielack Electric: A Premier Lido Beach, NY Electrician
For more than 30 years, Fielack Electric, a leading Lido Beach, NY electrician, has been providing top-quality residential and commercial electrical services. From breaker and fuse box installations to basic service and repair, we do it all. All of the work we provide is backed by our "Done Once, Done Right" guarantee. Should anything go wrong, all parts and labor are covered absolutely for free for one full year. Our guarantee is a true testament to our commitment to our clients.
Full-Scale Lido Beach, NY Residential and Commercial Electrical Services
Fielack Electric is a full-scale Lido Beach, NY electrician. Our master electricians are fully certified to provide both residential and commercial electrical repairs and installations. Whether you're a homeowner who wants to upgrade your electrical system or install new lighting, or you're a business owner that's in need of data lines or security lighting, our team has got you covered.
Our commitment to providing top-quality results is why you should consider us for all of your Lido Beach, NY electrical installation and repair needs.
Some information about Lido Beach, NY
Lido Beach is a hamlet and census-designated place (CDP) in Nassau County, New York, United States. The population was 2,897 at the 2010 census.
Lido Beach was developed by William H. Reynolds, in the early 1900s. The 39-year-old former state senator and real estate developer had already developed four Brooklyn neighborhoods (Bedford-Stuyvesant, Borough Park, Bensonhurst, and South Brownsville), as well as Coney Island's Dreamland, the world's largest amusement park. Reynolds also owned a theater and produced plays.
Beginning in 1906, he gathered investors and acquired the oceanfront from private owners and the rest of Long Beach island from the Town of Hempstead in 1907; he planned to build a boardwalk, homes, and hotels, and dredged Reynolds Channel to create the Long Beach, New York resort area. The dredging made the island more accessible to leisure boating.
The Lido Beach community was named after a villa in Venice, Italy. In 1929, after Reynolds was defeated for re-election as the Long Beach mayor, he turned his attention to the unincorporated area just east of the city and constructed the Moorish-style Lido Beach Hotel.
Learn more about Lido Beach.
Useful links for Lido Beach, NY
Open a Lido Beach, NY map
Find the Lido Beach, NY United States Post Office
Locate nearby Lido Beach, NY pharmacies
View the current Lido Beach, NY weather report
Browse a list of Lido Beach, NY public and private schools
Lido Beach, NY is located in Nassau county in New York State
Directions from Lido Beach, NY to Fielack Electric


text:
Analysis Advertising Digital
Facebook's Creative Shop wants to move people, not jobs
Fergus O'Hare talks to Campaign Asia-Pacific about the role and goal of Facebook Creative Shop in Asia, industry outreach efforts and the pursuit of 'thumb stopping' creative work.
Fergus O'Hare
SINGAPORE - As head of APAC for Facebook Creative Shop, Fergus O'Hare is pretty vocal about the team's mission to reinvent advertising and one day, hopes to put himself out of a job.
"I'm genuinely surprised I haven't put myself out of a job yet," he quips doing an interview with Campaign Asia-Pacific at Facebook's office in Singapore.
Though given that he intends to manoeuvre himself into irrelevance by ensuring the advertising industry wields the mobile platform (and Facebook) with finesse and reverence to craft, it might just be a while more.
O'Hare believes that the state of mobile advertising currently mirrors TV when it first began, when radio still dominated.
"We're at that point with radio commercials just before TV happened, where they just took a radio presenter and put him in front of a camera," he says. "That's how far away we are with mobile at the moment, we're taking TVCs and putting it on mobile the way we used to put radio ads on TV."
"We saw how far TV has come from someone delivering a monologue to the wonderful beautiful commercials that capture people's attention when they're in front of the TV," he adds. "But they're not in front of the TV anymore, they're scrolling on their mobile, so how do we build for that? That's what we're trying to do now."
Since taking on the role in September last year inheriting a team of seven, O'Hare has expanded it to 18, poaching some of the best known chief creative officers in region along the way.
Valerie Cheng from JWT now leads the Singapore and SEA team while Juhi Kalia, JWT's former global ECD for Lux, heads up India and Indonesia. Ex-Clemenger BBDO creative director Rebecca Carrasco heads up Australia and New Zealand, while Kitty Lun, former boss of Lowe China, leads China, and Jun Fukawa, previously a creative director at JWT London, leads Japan.
O'Hare is adamant about Creative Shop not being another advertising agency, but given all the high-ranking ex-creative agency talent, the industry could be forgiven for initially thinking that there's now yet another competitor in the room.
"The agencies were scared of us at first but they're more receptive now," he says. "I don't blame them for being intimidated, I look at our talent list and I get intimidated. But that's not why we're here, we're here to pass on knowledge and work with them, to scale what we can do on the mobile platform."
The rationale behind having ex-agency talent as the points of contact with the industry is to bridge the gap between creative pursuit and what is a data-driven, people-populated technology platform—with a suite of ad products.
"I hired great ad agency people because they understand the pain points," he added. "We have a great leadership team in place now to bring vision alive of changing the advertising industry. They're trained in the ways of Facebook, and hugely connected with the industry."
The social network already rakes in a hefty amount of ad revenue thanks to brands putting their money on the platform.
The company generated US$5.64 billion in ad revenue in the fourth quarter of 2015, up 57 percent year-over-year. Its mobile ad business grew 82 percent year-over-year to account for 80 percent of its total ad revenue. Overall revenue grew 52% year-over-year to hit US$5.84 billion.
There's certainly consensus that money must be spent on the platform, where millions of consumers spend a good chunk of their time. And the role of Creative Shop role is simply, to help make the ads better.
"I think we have the best creative canvas in the world, but without creativity, it's nothing," says O'Hare. "Even with all the tools, if the work is not great it's not going to work."
Cultivating mobile-first creativity
During the most recent Facebook Awards, the company's annual competition to showcase the best work being executed on its platform, 21 winners hailed from Asia Pacific – a strong sign that the region is adapting to a mobile-centric approach to creative campaigns.
Some trends to emerge from the submissions, according to O'Hare, include the fact that 80 percent of winning submissions had a video element while humour was a key factor in driving attention to a campaign. In addition, more then 50 percent of the winners came from Australia and New Zealand [see the winners gallery here].
"What was most important is that all the winning submissions contained the big brand idea," he adds. "Just because it's mobile and tech doesn't mean you don't still need that big idea to pin it all under."
Facebook has been busy launching new ad formats and tools to enable the creatives to execute those big ideas on its platform, falling under an umbrella term that O'Hare has dubbed "ADD-vertising".
In addition to products such as Messenger, Facebook 360, Facebook Live, which is also available to users, the suite of brand-side products includes Canvas, dynamic ads for Instagram, Carousel, Slideshow and a new offering called PockeTVC.
"What we've done is take TVCs and re-cut them for mobile," says O'Hare. "We always say build for mobile-first but if you haven't we can take those existing assets and make it ready for the mobile feed."
Industry outreach
Creative Shop is in the process of establishing a creative council in the region, where agency representatives can participate in pushing creative boundaries on the platform.
"We'll showcase the latest technology and let them build on that," says O'Hare. "Use their brain power to innovate, collaborate and then scale what we do."
The team is already working closely with TBWA in the APAC region, with people embedded with the creative agency to conduct training programmes to teach mobile-first creativity.
"The goal is to get them building and is the first time we've worked with an entire network," he adds.
Outreach efforts with the creative agency community in Asia recently went up another notch, with the launch of the Creative Ambassador programme, in partnership with WPP.
The first phase of the programme was a two-day education session hosted at Facebook Singapore, and saw attendance from representatives from multiple WPP agencies across five markets: Japan, Hong Kong, Vietnam, Malaysia and Thailand.
Agency brands involved included Geometry, Grey, J.Walter Thompson, Mirum, Ogilvy & Mather, Possible, VML, Wunderman and Y&R [see photos from the programme here].
The next phase will see the "ambassadors" sharing their training with their teams in their home countries. WPP will also have access to the Creative Shop team to help them strategise creative ideas and activate them on Instagram and Facebook.
O'Hare says the training initiatives are intended to address the knowledge gap in the industry.
"Most don't know all the products we have and the potential is has. Agencies are at that point now where they need to understand the technology better," he adds. "A lot of agencies felt guarded because they felt that they couldn't do it and what I do is go in and say 'you already have the skills' and we have a better canvas than traditional media for your ideas."
The team also takes in feedback from the industry; to further refine it's offerings.
"We ask them what would make it better for them, what do they find restrictive and then we go and start changing products," he added.
A road show under the Mobile Moves People banner is already underway, with Creative Shop team travelling across the region to teach and bring together best industry practices on how to build 'mobile ready' content that captures hearts and minds.
A Video Lab is also in the works, which will eventually see the company offering research and insights into video viewing habits, what makes content engaging and what needs to be done to secure attention after the first two seconds.
O'Hare is firm in his belief that as long as agencies and brands "don't skimp on the craft" and to start seeing the work that can be done on mobile as "pieces of art" the way they would a TVC, there's real impact to be had.
"But what you need now is 'thumb-stopping' art," he says. "People will always be bombarded by information, whatever the technology. It will always be about having that great idea or story that connects."
"That's really our mission and APAC is a good region to change the world of marketing from as there's talent and momentum," he adds. "And we have the will to do it. I tell my team, it's about going beyond winning awards, I want to be making headlines about how we're changing marketing."
creative shop
fergus ohare
Former R/GA exec Nicky Bell to lead Facebook ...
Michael Heusner
Facebook's Creative Shop leader on global ambitions,...
Facebook promotes APAC Creative Shop head to global ...
Facebook remains top social-media platform for APAC ...


text:
Rum Doings Episode 232: The Symbol Of Disposable Mortality
by John Walker on Jan.09, 2017, under Rum Doings
In our 232th ever Rum Doings, our topic is, have you ever eaten a ghost?
Discussions of our Christmas break, Lappish holidays, and festive feasts breaks way into an accidental conversion to Catholicism. We laugh at the colossally stupid Canary, forecast 2017, and then talk about the Mandela Effect, and specifically this article about it. And then mailing lists, and a surprise celebration of George Michael.
Or you can listen to it right here:
:podcast, rum doings, rumdoings
January 9th, 2017 on 13:06
I share Nicks aversion to the fake MIDI orchestra theme music. Especially obnoxious in the mid to late 1990s, with shows like Xena – Warrior Princess, Relic Hunter , Hercules. I should have been smack dab in the middle of their target demographic – but I just couldn't bring myself to watch them because of the tinny fake theme music – that and the horrendously fake looking fight scenes.
Nick Mailer
I'll paste a response I made to someone who mailed me on the topic:
"Let me not put it so absolutely: if the choice of synth strings is a stylistic one, chosen consciously for its specific aesthetic, then this is fine. Perhaps I could include the Twin Peaks theme in this category; however, if you choose programmatic and synthetic music as a way of cutting corners, because it's "good enough" and "the punter won't notice", then you deserve to be sent to purgatory. Or actual hell if we're talking about a synth sax.
John doesn't really get this because he has a tin ear (and palate)"
John had cross-replied:
"What about Jean Mich… oh wait."
To which I responded:
"As in the mail that crossed this one, I am fine with synth music. I love it, in fact, from the early experimenters through Wendy Carlos and even old Jarry boy. But if it's there as an ersatz exception rather than a celebration of its specificities, that is contemptible."
I don't know if Elon Musk really believes in what he's doing for the future, or just really believes in his own image as a futurologist, but there's something distinctly…un-progressive? In the way he runs SpaceX.
It's gotten a reputation in engineering circles as a terrible employer; extremely long hours (50+ hours per week) are expected as standard, with no overtime pay. Look at any position on their website; "Must be willing to work extended hours and weekends as needed" is a common phrase.
Idealistic graduate engineers line up to work there, and end up doing so for a salary they can sometimes struggle to live on. They throw their entire lives into it for a few years before burning out, yet there's still a constant line of naive replacements waiting to do the same.
I've heard that some companies with a good public image deliberately under-pay to ensure they get the people who want to work for them (rather then the people who just want the prestige of working for them). But I don't know of any other engineering company exploit the idealism of its employees to such a degree.
January 11th, 2017 on 08:58
See also The Bearanstein or stain for other good crazy parrallal universe "evidence" http://www.avclub.com/article/how-you-spell-berenstain-bears-could-be-proof-para-223615


Eastwood Towne Center is located at the corner of Town Center Blvd & Lake Lansing Rd., Lansing. It is a Lifestyle/Specialty Center which opened in 2002. It is an Open shopping mall with 2,000 parking spaces. It covers an area of 393,000 sqft. and has about 66 stores.


Garage Door Repair in 60656 is regarded in and around the Greater Chicago Metropolitan Area and encompassing areas as a leader in the garage door repair industry. It is for we present exceptional repair services that are cost-effective and are effective. For many years, we have featured remarkable garage door repair services that customers appreciate and usually highly recommend us to their friends and family members. Customer full satisfaction has been and will continually be our main priority!
Is there a concern with your garage door now? Our team of expert garage door technicians able to repair all types of garage door repairs. Often, we repair broken cables, spring replacements, door openers, panel replacement, a bent track, roller replacement, weather seal replacement, panel replacement and more! Customers in 60656 definitely value the economically-priced and speedy garage door repair work we do. Garage Door Repair in 60656 will guarantee your garage door is repaired as it is supposed to be the first time, so your garage door will again work as it should.
We know precisely how to effectively repair all types of residential and commercial garage doors. Any time a garage door is damaged, it can be aggravating, especially if your vehicle is stuck within the garage. Our professionally-trained repair technicians are industry specialists at repairing all types of garage door problems. To discover more, get in touch with the Garage Door Repair in 60656 professionals right now! You will be so glad you did!