<commit_before>
/**
 * TO DO
 * x. TRY X11 HEADLESS SETUP
 * x. BLIT THE MULTI SAMPLE BUFFER TO A REFULAR ONE AND READ FROM THERE
 * x. Anti aliasing for RGB images
 *  . Depth image -> more precise from 255
 * x. Compress the mask images
 *  . save the results to a new folder under ./build  --> experiments/build/results
 *  . skip the folders already existed
 */
#include <string>
#include <iostream>
#include <fstream>

#include <opencv2/opencv.hpp>

#include "GL_include.h"
#include <EGL/egl.h>
#include "WindowManager.h"

#include "Shaper.h"
#include "Program.h"
#include "WindowManager.h"
#include "WindowManager_headless.h"
#include "PhysicalWorld.h"
#include "Instance.h"
#include "Config.h"
#include "Utility.h"
#include "InputParser.h"
Config progConfig;
Patronus::Shaper * shaper = nullptr;
Lumos::Program * gProgram = nullptr;
WindowManager_base * winMan = nullptr;
Patronus::PhysicalWorld * world = nullptr;
Lumos::Instance * selectedInstance = nullptr;
std::string SCENE_FILE_DIR = "./scene_file/";
std::string TEXTURE_DIR = "./scene_file/texture/ut/";
std::string CAMERA_DIR = "./cameras/";
std::string OUTPUT_DIR = "./output/";
std::string RENDER_LIST = "./obj_list.txt";

size_t WINDOW_HEIGHT = 600, WINDOW_WIDTH = 800;

void displayHelp(){
  std::ifstream ifs("./help.txt");
  if (ifs.is_open())
  {
    std::string line;
    while ( std::getline (ifs,line) )
    {
      std::cout << line << std::endl;
    }
    ifs.close();
  }
}

template <typename T>
void set(T & arg, T setTo, const std::string & var_name){
  std::cout << "Setting " << var_name << " to " << setTo << std::endl;
  arg = setTo;
}

int main(int argc, char *argv[])
{
  InputParser parser(argc, argv);
  std::vector<std::string> vargs;

  if (parser.has(Flag::HELP)){
      displayHelp();
      return EXIT_SUCCESS;
  }

  if (parser.has(Flag::WINDOW_DIMENTSION)){
     vargs = parser.get(Flag::WINDOW_DIMENTSION).getArgs();
     if (vargs.size() != 2){
      displayHelp();
      return EXIT_FAILURE;
     }
     set(WINDOW_WIDTH, (size_t)std::stoi(vargs[0].c_str()), "WINDOW_WIDTH");
     set(WINDOW_HEIGHT, (size_t)std::stoi(vargs[1].c_str()), "WINDOW_HEIGHT");
  }
  else
    std::cout << "Default WINDOW_HEIGHT is " << WINDOW_HEIGHT << std::endl
              << "Default WINDOW_HEIGHT is " << WINDOW_WIDTH << std::endl;

  if (parser.has(Flag::SCENE_DIRECTORY)){
     vargs = parser.get(Flag::SCENE_DIRECTORY).getArgs();
     if (vargs.size() != 1){
      displayHelp();
      return EXIT_FAILURE;
     }
     set(SCENE_FILE_DIR, vargs[0], "SCENE_DIRECTORY");
  }
  else {
    std::cout << "Default SCENE_DIRECTORY is " << SCENE_FILE_DIR << std::endl;
  }

  if (parser.has(Flag::TEXTURE_DIRECTORY)){
     vargs = parser.get(Flag::TEXTURE_DIRECTORY).getArgs();
     if (vargs.size() != 1){
      displayHelp();
      return EXIT_FAILURE;
     }
     set(TEXTURE_DIR, vargs[0], "TEXTURE_DIRECTORY");
  }
  else {
    std::cout << "Default TEXTURE_DIRECTORY is " << TEXTURE_DIR << std::endl;
  }

  if (parser.has(Flag::CAMERA_DIRECTORY)){
     vargs = parser.get(Flag::CAMERA_DIRECTORY).getArgs();
     if (vargs.size() != 1){
      displayHelp();
      return EXIT_FAILURE;
     }
     set(CAMERA_DIR, vargs[0], "CAMERA_DIRECTORY");
  }
  else {
    std::cout << "Default CAMERA_DIRECTORY is " << CAMERA_DIR << std::endl;
  }

  if (parser.has(Flag::OUTPUT_DIRECTORY)){
     vargs = parser.get(Flag::OUTPUT_DIRECTORY).getArgs();
     if (vargs.size() != 1){
      displayHelp();
      return EXIT_FAILURE;
     }
     set(OUTPUT_DIR, vargs[0], "OUTPUT_DIRECTORY");
  }
  else {
    std::cout << "Default OUTPUT_DIRECTORY is " << OUTPUT_DIR << std::endl;
  }

  if (parser.has(Flag::RENDER_LIST)){
     vargs = parser.get(Flag::RENDER_LIST).getArgs();
     if (vargs.size() != 1){
      displayHelp();
      return EXIT_FAILURE;
     }
     set(RENDER_LIST, vargs[0], "RENDER_LIST");
  }
  else {
    std::cout << "Default RENDER_LIST is " << RENDER_LIST << std::endl;
  }

  if (parser.has(Flag::HEADLEASS))
    winMan = new WindowManager_headless{WINDOW_WIDTH, WINDOW_HEIGHT};
  else
    winMan = new WindowManager{WINDOW_WIDTH, WINDOW_HEIGHT};

  GLError( __PRETTY_FUNCTION__ , __LINE__ );

  world = new Patronus::PhysicalWorld();
  gProgram = new Lumos::Program( );
  shaper = new Patronus::Shaper( );
  GLError( __PRETTY_FUNCTION__ , __LINE__ );

  gProgram->loadShaders( "./GLSL" );
  GLError( __PRETTY_FUNCTION__ , __LINE__ );

  gProgram->preDrawSetUp();

  winMan->show();

  return winMan->loop();
}<commit_msg>isolate main()<commit_after>
/**
 * TO DO
 * x. TRY X11 HEADLESS SETUP
 * x. BLIT THE MULTI SAMPLE BUFFER TO A REFULAR ONE AND READ FROM THERE
 * x. Anti aliasing for RGB images
 *  . Depth image -> more precise from 255
 * x. Compress the mask images
 *  . save the results to a new folder under ./build  --> experiments/build/results
 *  . skip the folders already existed
 */
#include <string>
#include <iostream>
#include <fstream>

#include <opencv2/opencv.hpp>

#include "GL_include.h"
#include <EGL/egl.h>
#include "WindowManager.h"

#include "Shaper.h"
#include "Program.h"
#include "WindowManager.h"
#include "WindowManager_headless.h"
#include "PhysicalWorld.h"
#include "Instance.h"
#include "Config.h"
#include "Utility.h"
#include "InputParser.h"
Config progConfig;
Patronus::Shaper * shaper = nullptr;
Lumos::Program * gProgram = nullptr;
WindowManager_base * winMan = nullptr;
Patronus::PhysicalWorld * world = nullptr;
Lumos::Instance * selectedInstance = nullptr;
std::string SCENE_FILE_DIR = "./scene_file/";
std::string TEXTURE_DIR = "./scene_file/texture/";
std::string CAMERA_DIR = "./cameras/";
std::string OUTPUT_DIR = "./output/";
std::string RENDER_LIST = "./obj_list.txt";

size_t WINDOW_HEIGHT = 600, WINDOW_WIDTH = 800;

void displayHelp(){
  std::ifstream ifs("./help.txt");
  if (ifs.is_open())
  {
    std::string line;
    while ( std::getline (ifs,line) )
    {
      std::cout << line << std::endl;
    }
    ifs.close();
  }
}

template <typename T>
void set(T & arg, T setTo, const std::string & var_name){
  std::cout << "Setting " << var_name << " to " << setTo << std::endl;
  arg = setTo;
}

void parseCmdLn(int argc, char *argv[]){
  InputParser parser(argc, argv);
  std::vector<std::string> vargs;

  if (parser.has(Flag::HELP)){
      displayHelp();
      exit( EXIT_SUCCESS );
  }

  if (parser.has(Flag::WINDOW_DIMENTSION)){
     vargs = parser.get(Flag::WINDOW_DIMENTSION).getArgs();
     if (vargs.size() != 2){
      displayHelp();
      exit( EXIT_FAILURE );
     }
     set(WINDOW_WIDTH, (size_t)std::stoi(vargs[0].c_str()), "WINDOW_WIDTH");
     set(WINDOW_HEIGHT, (size_t)std::stoi(vargs[1].c_str()), "WINDOW_HEIGHT");
  }
  else
    std::cout << "Default WINDOW_HEIGHT is " << WINDOW_HEIGHT << std::endl
              << "Default WINDOW_HEIGHT is " << WINDOW_WIDTH << std::endl;

  if (parser.has(Flag::SCENE_DIRECTORY)){
     vargs = parser.get(Flag::SCENE_DIRECTORY).getArgs();
     if (vargs.size() != 1){
      displayHelp();
      exit( EXIT_FAILURE );
     }
     set(SCENE_FILE_DIR, vargs[0], "SCENE_DIRECTORY");
  }
  else {
    std::cout << "Default SCENE_DIRECTORY is " << SCENE_FILE_DIR << std::endl;
  }

  if (parser.has(Flag::TEXTURE_DIRECTORY)){
     vargs = parser.get(Flag::TEXTURE_DIRECTORY).getArgs();
     if (vargs.size() != 1){
      displayHelp();
      exit( EXIT_FAILURE );
     }
     set(TEXTURE_DIR, vargs[0], "TEXTURE_DIRECTORY");
  }
  else {
    std::cout << "Default TEXTURE_DIRECTORY is " << TEXTURE_DIR << std::endl;
  }

  if (parser.has(Flag::CAMERA_DIRECTORY)){
     vargs = parser.get(Flag::CAMERA_DIRECTORY).getArgs();
     if (vargs.size() != 1){
      displayHelp();
      exit( EXIT_FAILURE );
     }
     set(CAMERA_DIR, vargs[0], "CAMERA_DIRECTORY");
  }
  else {
    std::cout << "Default CAMERA_DIRECTORY is " << CAMERA_DIR << std::endl;
  }

  if (parser.has(Flag::OUTPUT_DIRECTORY)){
     vargs = parser.get(Flag::OUTPUT_DIRECTORY).getArgs();
     if (vargs.size() != 1){
      displayHelp();
      exit( EXIT_FAILURE );
     }
     set(OUTPUT_DIR, vargs[0], "OUTPUT_DIRECTORY");
  }
  else {
    std::cout << "Default OUTPUT_DIRECTORY is " << OUTPUT_DIR << std::endl;
  }

  if (parser.has(Flag::RENDER_LIST)){
     vargs = parser.get(Flag::RENDER_LIST).getArgs();
     if (vargs.size() != 1){
      displayHelp();
      exit( EXIT_FAILURE );
     }
     set(RENDER_LIST, vargs[0], "RENDER_LIST");
  }
  else {
    std::cout << "Default RENDER_LIST is " << RENDER_LIST << std::endl;
  }

  if (parser.has(Flag::HEADLEASS))
    winMan = new WindowManager_headless{WINDOW_WIDTH, WINDOW_HEIGHT};
  else
    winMan = new WindowManager{WINDOW_WIDTH, WINDOW_HEIGHT};
}

int main(int argc, char *argv[])
{
  parseCmdLn(argc, argv);
  GLError( __PRETTY_FUNCTION__ , __LINE__ );

  world = new Patronus::PhysicalWorld();
  gProgram = new Lumos::Program( );
  shaper = new Patronus::Shaper( );
  GLError( __PRETTY_FUNCTION__ , __LINE__ );

  gProgram->loadShaders( "./GLSL" );
  GLError( __PRETTY_FUNCTION__ , __LINE__ );

  gProgram->preDrawSetUp();

  winMan->show();

  return winMan->loop();
}<|endoftext|>


<commit_before>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2011-2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include "fnord/http/cookies.h"
#include "fnord/inspect.h"

namespace fnord {
namespace http {

bool Cookies::getCookie(
    const CookieList& cookies,
    const std::string& key,
    std::string* dst) {
  for (const auto& cookie : cookies) {
    if (cookie.first == key) {
      *dst = cookie.second;
      return true;
    }
  }

  return false;
}

Cookies::CookieList Cookies::parseCookieHeader(const std::string& header_str) {
  std::vector<std::pair<std::string, std::string>> cookies;

  auto begin = header_str.c_str();
  auto end = begin + header_str.length();
  auto cur = begin;
  while (begin < end) {
    for (; begin < end && *begin == ' '; ++begin);
    for (; cur < end && *cur != '='; ++cur);
    auto split = ++cur;
    for (; cur < end && *cur != ';'; ++cur);
    cookies.emplace_back(
        std::make_pair(
            URI::urlDecode(std::string(begin, split - 1)),
            URI::urlEncode(std::string(split, cur))));
    begin = ++cur;
  }

  return cookies;
}

std::string Cookies::mkCookie(
    const std::string& key,
    const std::string& value,
    const UnixTime& expire /* = UnixTime::epoch() */,
    const std::string& path /* = "" */,
    const std::string& domain /* = "" */,
    bool secure /* = false */,
    bool httponly /* = false */) {
  auto cookie_str = StringUtil::format(
      "$0=$1",
      URI::urlEncode(key),
      URI::urlEncode(value));

  if (path.length() > 0) {
    cookie_str.append(StringUtil::format("; Path=$0", path));
  }

  if (domain.length() > 0) {
    cookie_str.append(StringUtil::format("; Domain=$0", domain));
  }

  if (static_cast<uint64_t>(expire) > 0) {
    cookie_str.append(StringUtil::format("; Expires=$0",
        expire.toString("%a, %d-%b-%Y %H:%M:%S UTC")));
  }

  if (httponly) {
    cookie_str.append("; HttpOnly");
  }

  if (secure) {
    cookie_str.append("; Secure");
  }

  return cookie_str;
}

} // namespace http
} // namespace fnord
<commit_msg>fix stupid bug<commit_after>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2011-2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include "fnord/http/cookies.h"
#include "fnord/inspect.h"

namespace fnord {
namespace http {

bool Cookies::getCookie(
    const CookieList& cookies,
    const std::string& key,
    std::string* dst) {
  for (const auto& cookie : cookies) {
    if (cookie.first == key) {
      *dst = cookie.second;
      return true;
    }
  }

  return false;
}

Cookies::CookieList Cookies::parseCookieHeader(const std::string& header_str) {
  std::vector<std::pair<std::string, std::string>> cookies;

  auto begin = header_str.c_str();
  auto end = begin + header_str.length();
  auto cur = begin;
  while (begin < end) {
    for (; begin < end && *begin == ' '; ++begin);
    for (; cur < end && *cur != '='; ++cur);
    auto split = ++cur;
    for (; cur < end && *cur != ';'; ++cur);
    cookies.emplace_back(
        std::make_pair(
            URI::urlDecode(std::string(begin, split - 1)),
            URI::urlDecode(std::string(split, cur))));
    begin = ++cur;
  }

  return cookies;
}

std::string Cookies::mkCookie(
    const std::string& key,
    const std::string& value,
    const UnixTime& expire /* = UnixTime::epoch() */,
    const std::string& path /* = "" */,
    const std::string& domain /* = "" */,
    bool secure /* = false */,
    bool httponly /* = false */) {
  auto cookie_str = StringUtil::format(
      "$0=$1",
      URI::urlEncode(key),
      URI::urlEncode(value));

  if (path.length() > 0) {
    cookie_str.append(StringUtil::format("; Path=$0", path));
  }

  if (domain.length() > 0) {
    cookie_str.append(StringUtil::format("; Domain=$0", domain));
  }

  if (static_cast<uint64_t>(expire) > 0) {
    cookie_str.append(StringUtil::format("; Expires=$0",
        expire.toString("%a, %d-%b-%Y %H:%M:%S UTC")));
  }

  if (httponly) {
    cookie_str.append("; HttpOnly");
  }

  if (secure) {
    cookie_str.append("; Secure");
  }

  return cookie_str;
}

} // namespace http
} // namespace fnord
<|endoftext|>


<commit_before>/// \file    main.cpp

#include "HelloTriangleApplication.hpp"
#include "VDeleter.hpp"

// waf-generated header
#include "config.hpp"

#define DOCTEST_CONFIG_IMPLEMENT
#include "doctest.h"

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

#include <iostream>
#include <string>

int main(int argc, char* argv[])
{
  int res{0};
#ifndef DOCTEST_CONFIG_DISABLE
  doctest::Context context;

  context.setOption("no-run", true);

  context.applyCommandLine(argc, argv);

  using namespace std::literals::string_literals;
  auto begin_argv = argv + 1;
  auto end_argv = argv + argc;
  if (end_argv != std::find(begin_argv, end_argv, "--test"s)) {
    context.setOption("no-run", false);
    context.setOption("exit", true);
  }

  res = context.run();
  if (context.shouldExit()) return res;
#endif
  HelloTriangleApplication app;

  try {
    app.run();
  }
  catch (const std::runtime_error& e) {
    std::cerr << e.what() << std::endl;
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS + res;
}

// vim:set et ts=2 sw=2 sts=2:

<commit_msg>Rename 'res' variable to 'test_result'<commit_after>/// \file    main.cpp

#include "HelloTriangleApplication.hpp"
#include "VDeleter.hpp"

// waf-generated header
#include "config.hpp"

#define DOCTEST_CONFIG_IMPLEMENT
#include "doctest.h"

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

#include <iostream>
#include <string>

int main(int argc, char* argv[])
{
  int test_result{0};
#ifndef DOCTEST_CONFIG_DISABLE
  doctest::Context context;

  context.setOption("no-run", true);

  context.applyCommandLine(argc, argv);

  using namespace std::literals::string_literals;
  auto begin_argv = argv + 1;
  auto end_argv = argv + argc;
  if (end_argv != std::find(begin_argv, end_argv, "--test"s)) {
    context.setOption("no-run", false);
    context.setOption("exit", true);
  }

  test_result = context.run();
  if (context.shouldExit()) return test_result;
#endif
  HelloTriangleApplication app;

  try {
    app.run();
  }
  catch (const std::runtime_error& e) {
    std::cerr << e.what() << std::endl;
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS + test_result;
}

// vim:set et ts=2 sw=2 sts=2:

<|endoftext|>


<commit_before>
#include "main.hpp"
#include <algorithm>
#include <string>
#include <iostream>
#include <limits>

const std::size_t SEQUENCE_COUNT = 8;
const std::size_t SEQUENCE_LENGTH = 16;

int main(int argc, char** argv)
{
    std::vector<Node*> nodes;
    for (std::size_t j = 0; j < SEQUENCE_COUNT; j++)
        nodes.push_back(new Node(getSequence(), NULL, NULL));

    while (nodes.size() > 1)
    {
        std::vector<Node*> newList;

        while (!nodes.empty())
        {
            if (nodes.size() == 1)
            {
                newList.push_back(new Node(nodes[0]->sequence_, nodes[0], NULL));
                nodes.erase(nodes.begin());
            }
            else
            {
                uint8_t* blank;
                std::pair<uint8_t*, int> best = std::make_pair(blank,
                                            std::numeric_limits<int>::max());
                std::size_t bestIndex = 0;
                for (std::size_t j = 1; j < nodes.size(); j++)
                {
                    auto result = score(nodes[0], nodes[j]);
                    if (result.second < best.second)
                    {
                        best = result;
                        bestIndex = j;
                    }
                }

                newList.push_back(new Node(best.first, nodes[0], nodes[bestIndex]));
                nodes.erase(nodes.begin() + (const long)bestIndex);
                nodes.erase(nodes.begin());
            }
        }

        nodes = newList;
    }

    std::cout << "Comparison of first two children: " <<
        score(nodes[0]->left_, nodes[0]->right_).second <<
        std::endl;

    std::cout << "Comparison of first two children: " <<
        scoreSSE(nodes[0]->left_, nodes[0]->right_).second <<
        std::endl;

    std::cout << "In-order traversal of tree:" << std::endl;
    //printTree(nodes[0], 0);
    std::cout << "End of in-order traversal of tree." << std::endl;

    return EXIT_SUCCESS;
}

std::pair<uint8_t*, int> score(const Node* nodeA, const Node* nodeB)
{
    uint8_t* result = new uint8_t[SEQUENCE_LENGTH];
    int score = 0;

    for (std::size_t j = 0; j < SEQUENCE_LENGTH; j++)
    {
        auto a = nodeA->sequence_[j], b = nodeB->sequence_[j];
        auto aAndb = a & b;
        if (aAndb == 0)
        {
            result[j] = a | b;
            score++;
        }
        else
            result[j] = aAndb;
    }

    return std::make_pair(result, score);
}

std::pair<__m128i*, int> scoreSSE(const Node* nodeA, const Node* nodeB)
{
    static __m128i zero = _mm_set1_ps(0.f), comp, tempOr, a, b, r;
    static uint8_t* aUnit = reinterpret_cast<uint8_t*>(&a);
    static uint8_t* bUnit = reinterpret_cast<uint8_t*>(&b);
    static uint8_t* rUnit = reinterpret_cast<uint8_t*>(&r);

    int score = 0;
    __m128i* result = new __m128i[SEQUENCE_LENGTH / 16];
    for (int j = 0; j < SEQUENCE_LENGTH - 15; j += 16)
    {
        for (int k = 0; k < 16; k++)
        {
            aUnit[k] = nodeA->sequence_[j + k];
            bUnit[k] = nodeB->sequence_[j + k];
        }

        r = _mm_and_si128(a, b);
        for (int k = 0; k < 16; k++)
            score += !(int)rUnit[k];

        tempOr = _mm_or_si128(a, b);
        comp = _mm_cmpeq_epi8(zero, r);
        comp = _mm_and_si128(comp, tempOr);
        result[j / 16] = _mm_or_si128(comp, r);
    }

    return std::make_pair(result, score);
}

uint8_t* getSequence()
{
    auto mersenneTwister = getMersenneTwister();
    std::uniform_int_distribution<int> randomInt(1, 4);

    uint8_t* sequence = new uint8_t[SEQUENCE_LENGTH];
    for (std::size_t j = 0; j < SEQUENCE_LENGTH; j++)
    {
        switch (randomInt(mersenneTwister))
        {
            case 1:
                sequence[j] = 0x1;
                break;
            case 2:
                sequence[j] = 0x2;
                break;
            case 3:
                sequence[j] = 0x4;
                break;
            case 4:
                sequence[j] = 0x8;
                break;
        }
    }

    return sequence;
}

void printTree(const Node* node, int depth)
{
    if (node == NULL)
        return;

    printTree(node->left_, depth + 1);

    for (int j = 0; j < depth - 1; j++)
        std::cout << "    ";
    std::cout << "|--";

    if (node->right_ != NULL && node->right_ != NULL)
        std::cout << score(node->left_, node->right_).second;
    else
    {
        for (std::size_t j = 0; j < std::min(100, (int)SEQUENCE_LENGTH); j++)
        {
            switch(node->sequence_[j])
            {
                case 1:
                    std::cout << "A";
                    break;
                case 2:
                    std::cout << "T";
                    break;
                case 4:
                    std::cout << "C";
                    break;
                case 8:
                    std::cout << "G";
                    break;
            }
        }
    }

    std::cout << std::endl;

    printTree(node->right_, depth + 1);
}

std::mt19937 getMersenneTwister()
{
    std::array<int, std::mt19937::state_size> seed_data;
    std::random_device r;
    std::generate_n(seed_data.data(), seed_data.size(), std::ref(r));
    std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
    std::mt19937 mersenneTwister(seq);
    return mersenneTwister;
}
<commit_msg>slight optimizations<commit_after>
#include "main.hpp"
#include <algorithm>
#include <string>
#include <iostream>
#include <limits>
#include <memory.h>

const std::size_t SEQUENCE_COUNT = 8;
const std::size_t SEQUENCE_LENGTH = 16;
const int UNITS_PER_SSE = 16;

int main(int argc, char** argv)
{
    std::vector<Node*> nodes;
    for (std::size_t j = 0; j < SEQUENCE_COUNT; j++)
        nodes.push_back(new Node(getSequence(), NULL, NULL));

    while (nodes.size() > 1)
    {
        std::vector<Node*> newList;

        while (!nodes.empty())
        {
            if (nodes.size() == 1)
            {
                newList.push_back(new Node(nodes[0]->sequence_, nodes[0], NULL));
                nodes.erase(nodes.begin());
            }
            else
            {
                uint8_t* blank;
                std::pair<uint8_t*, int> best = std::make_pair(blank,
                                            std::numeric_limits<int>::max());
                std::size_t bestIndex = 0;
                for (std::size_t j = 1; j < nodes.size(); j++)
                {
                    auto result = score(nodes[0], nodes[j]);
                    if (result.second < best.second)
                    {
                        best = result;
                        bestIndex = j;
                    }
                }

                newList.push_back(new Node(best.first, nodes[0], nodes[bestIndex]));
                nodes.erase(nodes.begin() + (const long)bestIndex);
                nodes.erase(nodes.begin());
            }
        }

        nodes = newList;
    }

    std::cout << "Comparison of first two children: " <<
        score(nodes[0]->left_, nodes[0]->right_).second <<
        std::endl;

    std::cout << "Comparison of first two children: " <<
        scoreSSE(nodes[0]->left_, nodes[0]->right_).second <<
        std::endl;

    std::cout << "In-order traversal of tree:" << std::endl;
    //printTree(nodes[0], 0);
    std::cout << "End of in-order traversal of tree." << std::endl;

    return EXIT_SUCCESS;
}

std::pair<uint8_t*, int> score(const Node* nodeA, const Node* nodeB)
{
    uint8_t* result = new uint8_t[SEQUENCE_LENGTH];
    int score = 0;

    for (std::size_t j = 0; j < SEQUENCE_LENGTH; j++)
    {
        auto a = nodeA->sequence_[j], b = nodeB->sequence_[j];
        auto aAndb = a & b;
        if (aAndb == 0)
        {
            result[j] = a | b;
            score++;
        }
        else
            result[j] = aAndb;
    }

    return std::make_pair(result, score);
}

std::pair<__m128i*, int> scoreSSE(const Node* nodeA, const Node* nodeB)
{
    static __m128i zero = _mm_set1_ps(0.f), comp, aOrB, a, b, r;
    static uint8_t* rUnit = reinterpret_cast<uint8_t*>(&r);

    int score = 0;
    __m128i* result = new __m128i[SEQUENCE_LENGTH / UNITS_PER_SSE];
    for (int j = 0; j <= SEQUENCE_LENGTH - UNITS_PER_SSE; j += UNITS_PER_SSE)
    {
        memcpy(&a, nodeA->sequence_, sizeof(__m128i));
        memcpy(&b, nodeB->sequence_, sizeof(__m128i));

        r = _mm_and_si128(a, b);
        for (int k = 0; k < UNITS_PER_SSE; k++)
            score += !(int)rUnit[k];

        aOrB = _mm_or_si128(a, b);
        comp = _mm_cmpeq_epi8(zero, r);
        comp = _mm_and_si128(comp, aOrB);
        result[j / UNITS_PER_SSE] = _mm_or_si128(comp, r);
    }

    return std::make_pair(result, score);
}

uint8_t* getSequence()
{
    auto mersenneTwister = getMersenneTwister();
    std::uniform_int_distribution<int> randomInt(1, 4);

    uint8_t* sequence = new uint8_t[SEQUENCE_LENGTH];
    for (std::size_t j = 0; j < SEQUENCE_LENGTH; j++)
    {
        switch (randomInt(mersenneTwister))
        {
            case 1:
                sequence[j] = 0x1;
                break;
            case 2:
                sequence[j] = 0x2;
                break;
            case 3:
                sequence[j] = 0x4;
                break;
            case 4:
                sequence[j] = 0x8;
                break;
        }
    }

    return sequence;
}

void printTree(const Node* node, int depth)
{
    if (node == NULL)
        return;

    printTree(node->left_, depth + 1);

    for (int j = 0; j < depth - 1; j++)
        std::cout << "    ";
    std::cout << "|--";

    if (node->right_ != NULL && node->right_ != NULL)
        std::cout << score(node->left_, node->right_).second;
    else
    {
        for (std::size_t j = 0; j < std::min(100, (int)SEQUENCE_LENGTH); j++)
        {
            switch(node->sequence_[j])
            {
                case 1:
                    std::cout << "A";
                    break;
                case 2:
                    std::cout << "T";
                    break;
                case 4:
                    std::cout << "C";
                    break;
                case 8:
                    std::cout << "G";
                    break;
            }
        }
    }

    std::cout << std::endl;

    printTree(node->right_, depth + 1);
}

std::mt19937 getMersenneTwister()
{
    std::array<int, std::mt19937::state_size> seed_data;
    std::random_device r;
    std::generate_n(seed_data.data(), seed_data.size(), std::ref(r));
    std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
    std::mt19937 mersenneTwister(seq);
    return mersenneTwister;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <time.h>
#include <unistd.h>
#include <sys/shm.h>

#include "bcm_host.h"

#include "GLES2/gl2.h"
#include "EGL/egl.h"
#include "EGL/eglext.h"

#include "shader.h"
#include "inotify-cxx.h"

typedef struct {
    uint32_t screen_width;
    uint32_t screen_height;
    // OpenGL|ES objects
    EGLDisplay display;
    EGLSurface surface;
    EGLContext context;

    GLuint buf;

    Shader shader;

} CUBE_STATE_T;

bool* fragHasChanged;
std::string fragFile;
std::string vertSource =
"attribute vec4 a_position;"
"varying vec2 v_texcoord;"
"void main(void) {"
"    gl_Position = a_position;"
"    v_texcoord = a_position.xy*0.5+0.5;"
"}";

static CUBE_STATE_T _state, *state=&_state;

static void init_ogl(CUBE_STATE_T *state){
    int32_t success = 0;
    EGLBoolean result;
    EGLint num_config;

    static EGL_DISPMANX_WINDOW_T nativewindow;

    DISPMANX_ELEMENT_HANDLE_T dispman_element;
    DISPMANX_DISPLAY_HANDLE_T dispman_display;
    DISPMANX_UPDATE_HANDLE_T dispman_update;
    VC_RECT_T dst_rect;
    VC_RECT_T src_rect;

    static const EGLint attribute_list[] = {
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_NONE
    };

    static const EGLint context_attributes[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
    };
    EGLConfig config;

    // get an EGL display connection
    state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    assert(state->display!=EGL_NO_DISPLAY);

    // initialize the EGL display connection
    result = eglInitialize(state->display, NULL, NULL);
    assert(EGL_FALSE != result);

    // get an appropriate EGL frame buffer configuration
    result = eglChooseConfig(state->display, attribute_list, &config, 1, &num_config);
    assert(EGL_FALSE != result);

    // get an appropriate EGL frame buffer configuration
    result = eglBindAPI(EGL_OPENGL_ES_API);
    assert(EGL_FALSE != result);

    // create an EGL rendering context
    state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, context_attributes);
    assert(state->context!=EGL_NO_CONTEXT);

    // create an EGL window surface
    success = graphics_get_display_size(0 /* LCD */, &state->screen_width, &state->screen_height);
    assert( success >= 0 );

    dst_rect.x = 0;
    dst_rect.y = 0;
    dst_rect.width = state->screen_width;
    dst_rect.height = state->screen_height;

    src_rect.x = 0;
    src_rect.y = 0;
    src_rect.width = state->screen_width << 16;
    src_rect.height = state->screen_height << 16;

    dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
    dispman_update = vc_dispmanx_update_start( 0 );
    dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display,
                                               0/*layer*/, &dst_rect, 0/*src*/,
                                               &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, 0/*transform*/);

    nativewindow.element = dispman_element;
    nativewindow.width = state->screen_width;
    nativewindow.height = state->screen_height;
    vc_dispmanx_update_submit_sync( dispman_update );

    state->surface = eglCreateWindowSurface( state->display, config, &nativewindow, NULL );
    assert(state->surface != EGL_NO_SURFACE);

    // connect the context to the surface
    result = eglMakeCurrent(state->display, state->surface, state->surface, state->context);
    assert(EGL_FALSE != result);

    // Set background color and clear buffers
    glClearColor(0.15f, 0.25f, 0.35f, 1.0f);
    glClear( GL_COLOR_BUFFER_BIT );

}

static bool loadFromPath(const std::string& path, std::string* into) {
    std::ifstream file;
    std::string buffer;

    file.open(path.c_str());
    if(!file.is_open()) return false;
    while(!file.eof()) {
        getline(file, buffer);
        (*into) += buffer + "\n";
    }

    file.close();
    return true;
}

static void draw(CUBE_STATE_T *state, GLfloat cx, GLfloat cy){

    if(*fragHasChanged) {
        std::string fragSource;
        if(loadFromPath(fragFile, &fragSource)){
            state->shader.detach(GL_FRAGMENT_SHADER | GL_VERTEX_SHADER);
            state->shader.build(fragSource,vertSource);
            *fragHasChanged = false;
            std::cout << "Parent: reloading shader" << std::endl;
        }
    }

    // Now render to the main frame buffer
    glBindFramebuffer(GL_FRAMEBUFFER,0);
    // Clear the background (not really necessary I suppose)
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glBindBuffer(GL_ARRAY_BUFFER, state->buf);
    state->shader.use();

    state->shader.sendUniform("u_time",((float)clock())/CLOCKS_PER_SEC);
    state->shader.sendUniform("u_mouse",cx, cy);
    state->shader.sendUniform("u_resolution",state->screen_width, state->screen_height);

    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glFlush();
    glFinish();

    eglSwapBuffers(state->display, state->surface);
}

static int get_mouse(CUBE_STATE_T *state, int *outx, int *outy){
    static int fd = -1;
    const int width=state->screen_width, height=state->screen_height;
    static int x=800, y=400;
    const int XSIGN = 1<<4, YSIGN = 1<<5;
    if (fd<0) {
       fd = open("/dev/input/mouse0",O_RDONLY|O_NONBLOCK);
    }
    if (fd>=0) {
        struct {char buttons, dx, dy; } m;
        while (1) {
           int bytes = read(fd, &m, sizeof m);
           if (bytes < (int)sizeof m) goto _exit;
           if (m.buttons&8) {
              break; // This bit should always be set
           }
           read(fd, &m, 1); // Try to sync up again
        }
        if (m.buttons&3)
           return m.buttons&3;
        x+=m.dx;
        y+=m.dy;
        if (m.buttons&XSIGN)
           x-=256;
        if (m.buttons&YSIGN)
           y-=256;
        if (x<0) x=0;
        if (y<0) y=0;
        if (x>width) x=width;
        if (y>height) y=height;
   }
_exit:
   if (outx) *outx = x;
   if (outy) *outy = y;
   return 0;
}

void drawThread() {
    while (1) {
        int x, y, b;
        b = get_mouse(state, &x, &y);
        if (b) break;
        draw(state, x, y);
    }
}

void watchThread(const std::string& file) {
    Inotify notify;

    InotifyWatch watch(file, IN_ALL_EVENTS);
    notify.Add(watch);

    for (;;) {
        std::cout << "Child: Watching again" << std::endl;
        notify.WaitForEvents();

        size_t count = notify.GetEventCount();
        while(count-- > 0) {
            InotifyEvent event;
            bool got_event = notify.GetEvent(&event);

            if(got_event && !(*fragHasChanged)){
                std::string mask_str;
                event.DumpTypes(mask_str);
                *fragHasChanged = true;
                std::cout << "Child: Something have change " << mask_str << std::endl;
            }
        }
    }
}

void init(const std::string& fragFile) {
    GLfloat cx, cy;
    bcm_host_init();

    // Clear application state
    memset( state, 0, sizeof( *state ) );

    // Start OGLES
    init_ogl(state);

    //  Build shader;
    //
    std::string fragSource;
    if(!loadFromPath(fragFile, &fragSource)) {
        return;
    }
    state->shader.build(fragSource,vertSource);

    //  Make Quad
    //
    static const GLfloat vertex_data[] = {
        -1.0,-1.0,1.0,1.0,
        1.0,-1.0,1.0,1.0,
        1.0,1.0,1.0,1.0,
        -1.0,1.0,1.0,1.0
    };
    GLint posAttribut = state->shader.getAttribLocation("a_position");

    glClearColor ( 0.0, 1.0, 1.0, 1.0 );

    glGenBuffers(1, &state->buf);

    // Prepare viewport
    glViewport ( 0, 0, state->screen_width, state->screen_height );

    // Upload vertex data to a buffer
    glBindBuffer(GL_ARRAY_BUFFER, state->buf);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data),
                 vertex_data, GL_STATIC_DRAW);
    glVertexAttribPointer(posAttribut, 4, GL_FLOAT, 0, 16, 0);
    glEnableVertexAttribArray(posAttribut);

}

//==============================================================================

int main(int argc, char **argv){

    fragFile = std::string(argv[1]);

    int shmId = shmget(IPC_PRIVATE, sizeof(bool), 0666);

    pid_t pid = fork();

    fragHasChanged = (bool *) shmat(shmId, NULL, 0);

    switch(pid) {
        case -1: //error
        break;

        case 0: // child
        {
            *fragHasChanged = false;
            watchThread(fragFile);
        }
        break;

        default:
        {
            init(fragFile);
            drawThread();

            kill(pid, SIGKILL);
        }
        break;
    }

    shmctl(shmId, IPC_RMID, NULL);

    return 0;
}

<commit_msg>debug<commit_after>#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <time.h>
#include <unistd.h>
#include <sys/shm.h>

#include "bcm_host.h"

#include "GLES2/gl2.h"
#include "EGL/egl.h"
#include "EGL/eglext.h"

#include "shader.h"
#include "inotify-cxx.h"

typedef struct {
    uint32_t screen_width;
    uint32_t screen_height;
    // OpenGL|ES objects
    EGLDisplay display;
    EGLSurface surface;
    EGLContext context;

    GLuint buf;

    Shader shader;

} CUBE_STATE_T;

bool* fragHasChanged;
std::string fragFile;
std::string vertSource =
"attribute vec4 a_position;"
"varying vec2 v_texcoord;"
"void main(void) {"
"    gl_Position = a_position;"
"    v_texcoord = a_position.xy*0.5+0.5;"
"}";

static CUBE_STATE_T _state, *state=&_state;

static void init_ogl(CUBE_STATE_T *state){
    int32_t success = 0;
    EGLBoolean result;
    EGLint num_config;

    static EGL_DISPMANX_WINDOW_T nativewindow;

    DISPMANX_ELEMENT_HANDLE_T dispman_element;
    DISPMANX_DISPLAY_HANDLE_T dispman_display;
    DISPMANX_UPDATE_HANDLE_T dispman_update;
    VC_RECT_T dst_rect;
    VC_RECT_T src_rect;

    static const EGLint attribute_list[] = {
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_NONE
    };

    static const EGLint context_attributes[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
    };
    EGLConfig config;

    // get an EGL display connection
    state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    assert(state->display!=EGL_NO_DISPLAY);

    // initialize the EGL display connection
    result = eglInitialize(state->display, NULL, NULL);
    assert(EGL_FALSE != result);

    // get an appropriate EGL frame buffer configuration
    result = eglChooseConfig(state->display, attribute_list, &config, 1, &num_config);
    assert(EGL_FALSE != result);

    // get an appropriate EGL frame buffer configuration
    result = eglBindAPI(EGL_OPENGL_ES_API);
    assert(EGL_FALSE != result);

    // create an EGL rendering context
    state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, context_attributes);
    assert(state->context!=EGL_NO_CONTEXT);

    // create an EGL window surface
    success = graphics_get_display_size(0 /* LCD */, &state->screen_width, &state->screen_height);
    assert( success >= 0 );

    dst_rect.x = 0;
    dst_rect.y = 0;
    dst_rect.width = state->screen_width;
    dst_rect.height = state->screen_height;

    src_rect.x = 0;
    src_rect.y = 0;
    src_rect.width = state->screen_width << 16;
    src_rect.height = state->screen_height << 16;

    dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
    dispman_update = vc_dispmanx_update_start( 0 );
    dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display,
                                               0/*layer*/, &dst_rect, 0/*src*/,
                                               &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, 0/*transform*/);

    nativewindow.element = dispman_element;
    nativewindow.width = state->screen_width;
    nativewindow.height = state->screen_height;
    vc_dispmanx_update_submit_sync( dispman_update );

    state->surface = eglCreateWindowSurface( state->display, config, &nativewindow, NULL );
    assert(state->surface != EGL_NO_SURFACE);

    // connect the context to the surface
    result = eglMakeCurrent(state->display, state->surface, state->surface, state->context);
    assert(EGL_FALSE != result);

    // Set background color and clear buffers
    glClearColor(0.15f, 0.25f, 0.35f, 1.0f);
    glClear( GL_COLOR_BUFFER_BIT );

}

static bool loadFromPath(const std::string& path, std::string* into) {
    std::ifstream file;
    std::string buffer;

    file.open(path.c_str());
    if(!file.is_open()) return false;
    while(!file.eof()) {
        getline(file, buffer);
        (*into) += buffer + "\n";
    }

    file.close();
    return true;
}

static void draw(CUBE_STATE_T *state, GLfloat cx, GLfloat cy){

    if(*fragHasChanged) {
        std::string fragSource;
        if(loadFromPath(fragFile, &fragSource)){
            state->shader.detach(GL_FRAGMENT_SHADER | GL_VERTEX_SHADER);
            state->shader.build(fragSource,vertSource);
            *fragHasChanged = false;
            std::cout << "Parent: reloading shader" << std::endl;
        }
    }

    // Now render to the main frame buffer
    glBindFramebuffer(GL_FRAMEBUFFER,0);
    // Clear the background (not really necessary I suppose)
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glBindBuffer(GL_ARRAY_BUFFER, state->buf);
    state->shader.use();

    state->shader.sendUniform("u_time",((float)clock())/CLOCKS_PER_SEC);
    state->shader.sendUniform("u_mouse",cx, cy);
    state->shader.sendUniform("u_resolution",state->screen_width, state->screen_height);

    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glFlush();
    glFinish();

    eglSwapBuffers(state->display, state->surface);
}

static int get_mouse(CUBE_STATE_T *state, int *outx, int *outy){
    static int fd = -1;
    const int width=state->screen_width, height=state->screen_height;
    static int x=800, y=400;
    const int XSIGN = 1<<4, YSIGN = 1<<5;
    if (fd<0) {
       fd = open("/dev/input/mouse0",O_RDONLY|O_NONBLOCK);
    }
    if (fd>=0) {
        struct {char buttons, dx, dy; } m;
        while (1) {
           int bytes = read(fd, &m, sizeof m);
           if (bytes < (int)sizeof m) goto _exit;
           if (m.buttons&8) {
              break; // This bit should always be set
           }
           read(fd, &m, 1); // Try to sync up again
        }
        if (m.buttons&3)
           return m.buttons&3;
        x+=m.dx;
        y+=m.dy;
        if (m.buttons&XSIGN)
           x-=256;
        if (m.buttons&YSIGN)
           y-=256;
        if (x<0) x=0;
        if (y<0) y=0;
        if (x>width) x=width;
        if (y>height) y=height;
   }
_exit:
   if (outx) *outx = x;
   if (outy) *outy = y;
   return 0;
}

void drawThread() {
    while (1) {
        int x, y, b;
        b = get_mouse(state, &x, &y);
        if (b) break;
        draw(state, x, y);
    }
}

void watchThread(const std::string& file) {
    Inotify notify;

    InotifyWatch watch(file, IN_ALL_EVENTS);
    notify.Add(watch);

    try {
        for (;;) {
            std::cout << "Child: Watching again" << std::endl;
            notify.WaitForEvents();

            size_t count = notify.GetEventCount();
            while(count-- > 0) {
                InotifyEvent event;
                bool got_event = notify.GetEvent(&event);

                if(got_event && !(*fragHasChanged)){
                    std::string mask_str;
                    event.DumpTypes(mask_str);
                    *fragHasChanged = true;
                    std::cout << "Child: Something have change " << mask_str << std::endl;
                }
            }
        }
    } catch (InotifyException &e) {
        cerr << "Inotify exception occured: " << e.GetMessage() << endl;
    } catch (exception &e) {
        cerr << "STL exception occured: " << e.what() << endl;
    } catch (...) {
        cerr << "unknown exception occured" << endl;
    }
}

void init(const std::string& fragFile) {
    GLfloat cx, cy;
    bcm_host_init();

    // Clear application state
    memset( state, 0, sizeof( *state ) );

    // Start OGLES
    init_ogl(state);

    //  Build shader;
    //
    std::string fragSource;
    if(!loadFromPath(fragFile, &fragSource)) {
        return;
    }
    state->shader.build(fragSource,vertSource);

    //  Make Quad
    //
    static const GLfloat vertex_data[] = {
        -1.0,-1.0,1.0,1.0,
        1.0,-1.0,1.0,1.0,
        1.0,1.0,1.0,1.0,
        -1.0,1.0,1.0,1.0
    };
    GLint posAttribut = state->shader.getAttribLocation("a_position");

    glClearColor ( 0.0, 1.0, 1.0, 1.0 );

    glGenBuffers(1, &state->buf);

    // Prepare viewport
    glViewport ( 0, 0, state->screen_width, state->screen_height );

    // Upload vertex data to a buffer
    glBindBuffer(GL_ARRAY_BUFFER, state->buf);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data),
                 vertex_data, GL_STATIC_DRAW);
    glVertexAttribPointer(posAttribut, 4, GL_FLOAT, 0, 16, 0);
    glEnableVertexAttribArray(posAttribut);

}

//==============================================================================

int main(int argc, char **argv){

    fragFile = std::string(argv[1]);

    int shmId = shmget(IPC_PRIVATE, sizeof(bool), 0666);

    pid_t pid = fork();

    fragHasChanged = (bool *) shmat(shmId, NULL, 0);

    switch(pid) {
        case -1: //error
        break;

        case 0: // child
        {
            *fragHasChanged = false;
            watchThread(fragFile);
        }
        break;

        default:
        {
            init(fragFile);
            drawThread();

            kill(pid, SIGKILL);
        }
        break;
    }

    shmctl(shmId, IPC_RMID, NULL);

    return 0;
}

<|endoftext|>


<commit_before>#include <algorithm>
#include <array>
#include <iomanip>
#include <curl/curl.h>
#include <memory>
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <vector>
#include <sys/stat.h>
#include <cerrno>
#include <cstring>
#include <system_error>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

const std::string listing("http://nwn.efupw.com/rootdir/index.dat");
const std::string patch_dir("http://nwn.efupw.com/rootdir/patch/");
const std::string update_check("");

const std::string file_checksum(const std::string &path);

size_t writefunction(const char *ptr, size_t size, size_t nmemb, void *userdata)
{
    std::string *s = static_cast<std::string *>(userdata);
    s->append(ptr, size * nmemb);
    return size * nmemb;
}

std::vector<std::string> &split(const std::string &s, char delim,
        std::vector<std::string> &elems)
{
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim))
    {
        elems.push_back(item);
    }
    return elems;
}

std::vector<std::string> split(const std::string &s, char delim)
{
    std::vector<std::string> elems;
    return split(s, delim, elems);
}

class Target
{
    public:
        enum class Status {
            Nonexistent,
            Outdated,
            Current
        };
        explicit Target(const std::string &name, const std::string &checksum):
            m_name(name.find_first_of('/') == std::string::npos ? name :
                    name, name.find_first_of('/') + 1, name.size() - 1),
            m_checksum(checksum)
            {}
        std::string name() const { return m_name; }
        const std::string checksum() const { return m_checksum; }

        void fetch()
        {
            std::cout << "Statting target " << name() << "...";
            std::string path;
            std::fstream fs(name(), std::ios_base::in);
            if (!fs.good())
            {
                fs.close();
                std::cout << " doesn't exist, creating new." << std::endl;
                auto elems = split(name(), '/');
                for (size_t i = 0, k = elems.size(); i < k; ++i)
                    //for (auto s : elems)
                {
                    const std::string &s(elems[i]);
                    if (s.size() && s != ".")
                    {
                        path.append((i > 0 ? "/" : "") + s);
                        // i indicates a directory.
                        if (i < k - 1)
                        {
                            auto status = mkdir(path.c_str(), S_IRWXU);
                            if (status == -1)
                            {
                                std::error_code err(errno, std::generic_category());
                                if (err != std::errc::file_exists)
                                {
                                    std::cout << "error making dir: "
                                        << path << ": "
                                        << err.message() << std::endl;
                                }
                            }
                        }
                        //std::cout << "the path: " << path << std::endl;
                    }
                }
                fs.open(path, std::ios_base::out);
                if (!fs.good())
                {
                    fs.close();
                    std::cout << "Failed to create file: " << path << std::endl;
                }
                else
                {
                    fs.close();
                    do_fetch();
                    return;
                    //std::cout << "opened path " << path << std::endl;
                }
            }
            if (fs.good())
            {
                fs.close();
                //const std::string calcsum(file_checksum(name()));
                /*
                std::cout << "calced sum for " << name()
                    << " : " << calcsum << ", expected " << checksum() << std::endl;
                    */
                //if (calcsum == checksum())
                if (status() == Status::Current)
                {
                    std::cout << " already up to date." << std::endl;
                }
                else
                {
                    std::cout << " outdated, downloading new." << std::endl;
                    do_fetch();
                }
            }
        }
        Status status()
        {
            std::ifstream is(name());
            if (!is.good())
            {
                return Status::Nonexistent;
            }
            is.close();
            const std::string calcsum(file_checksum(name()));
            if (calcsum == checksum())
            {
                return Status::Current;
            }
            else
            {
                return Status::Outdated;
            }
        }

    private:
        void do_fetch()
        {
            std::string s;
            std::shared_ptr<CURL *> phandle =
                std::make_shared<CURL *>(curl_easy_init());
            std::string url(patch_dir + name());
            curl_easy_setopt(*phandle, CURLOPT_URL, url.c_str());
            curl_easy_setopt(*phandle, CURLOPT_WRITEFUNCTION, &writefunction);
            curl_easy_setopt(*phandle, CURLOPT_WRITEDATA, &s);
            //curl_easy_setopt(*phandle, CURLOPT_NOPROGRESS, 0);
            curl_easy_perform(*phandle);
            curl_easy_cleanup(*phandle);
            phandle.reset();
            std::ofstream ofs(name());
            if (ofs.good())
            {
                ofs << s;
                ofs.close();
            }
            else
            {
                std::cout << "Couldn't write to " << name() << std::endl;
            }
        }

        std::string m_name;
        std::string m_checksum;
};

std::ostream& operator<<(std::ostream &os, const Target &t)
{
    return os << "name: " << t.name() << ", checksum: " << t.checksum();
}

class CurlGlobalInit
{
    public:
        CurlGlobalInit()
        {
            curl_global_init(CURL_GLOBAL_ALL);
        }

        ~CurlGlobalInit()
        {
            curl_global_cleanup();
        }
};

const std::string file_checksum(const std::string &path)
{
#define md_md5
#ifdef md_md5
    auto md = EVP_md5();
    const int md_len = MD5_DIGEST_LENGTH;
#else
    auto md = EVP_sha1();
    const int md_len = SHA_DIGEST_LENGTH;
#endif
    std::array<unsigned char, md_len> result;
    EVP_MD_CTX *mdctx = nullptr;
    std::ifstream is(path, std::ifstream::binary);
    if (!is.good())
    {
        std::cout << "Couldn't open file " << path
           << " for checksumming." << std::endl;
        return std::string();
    }
    else
    {
        //std::cout << "opened file " << path << std::endl;
    }

    const int length = 8192;
    std::array<unsigned char, length> buffer;
    auto buf = reinterpret_cast<char *>(buffer.data());
    mdctx = EVP_MD_CTX_create();
    int status = EVP_DigestInit_ex(mdctx, md, nullptr);
    while (status && is)
    {
        is.read(buf, length);
        status = EVP_DigestUpdate(mdctx, buffer.data(), is.gcount());
    }
    status = EVP_DigestFinal_ex(mdctx, result.data(), nullptr);
    EVP_MD_CTX_destroy(mdctx);
    std::stringstream calcsum;
    calcsum << std::setfill('0');

    for (unsigned char c : result)
    {
        calcsum << std::hex << std::setw(2)
            << static_cast<unsigned int>(c);
    }
    /*
    std::for_each(std::begin(result), std::end(result),
            [&calcsum](unsigned char c)
            {
            calcsum << std::hex << std::setw(2)
            << static_cast<unsigned int>(c);
            });
            */
    //std::cout << calcsum.str() << std::endl;
    return calcsum.str();
}

int main(int argc, char *argv[])
{
    CurlGlobalInit curl_global;
    std::string fetch;
    std::shared_ptr<CURL *> phandle = std::make_shared<CURL *>(curl_easy_init());
    curl_easy_setopt(*phandle, CURLOPT_URL, listing.c_str());
    curl_easy_setopt(*phandle, CURLOPT_WRITEFUNCTION, &writefunction);
    curl_easy_setopt(*phandle, CURLOPT_WRITEDATA, &fetch);
    //curl_easy_setopt(*phandle, CURLOPT_NOPROGRESS, 0);
    curl_easy_perform(*phandle);
    curl_easy_cleanup(*phandle);
    phandle.reset();
    //std::cout << fetch << std::endl;
    std::vector<std::string> lines(split(fetch, '\n'));
    //split(fetch, '\n', lines);
    //std::cout << lines[1] << std::endl;
    std::vector<Target> new_targets, old_targets;
    for (auto beg = std::begin(lines), end = std::end(lines);
            beg != end; ++beg)
    {
        auto data(split(*beg, '@'));
        Target t(data[0], data[data.size() - 1]);
        auto status = t.status();
        if (status == Target::Status::Nonexistent)
        {
            new_targets.push_back(std::move(t));
        }
        else if (status == Target::Status::Outdated)
        {
            old_targets.push_back(std::move(t));
        }
    }
    if (new_targets.size())
    {
        std::cout << "New targets: " << new_targets.size() << std::endl;
        for (auto &t : new_targets)
        {
            std::cout << "- " << t << std::endl;
            //t.fetch();
        }
        //std::cout << new_targets[4] << std::endl;
        new_targets[0].fetch();
        //new_targets[4].fetch();
    }
    else
    {
        std::cout << "No new targets." << std::endl;
    }

    if (old_targets.size())
    {
        std::cout << "Outdated targets: " << old_targets.size() << std::endl;
        for (auto &t : old_targets)
        {
            std::cout << "- " << t << std::endl;
        }
    }
    else
    {
        std::cout << "No targets out of date." << std::endl;
    }

    /*
    const std::string path = "bin/override/spells.2da";
    const std::string checksum("38eaad974c15e5f3119469f17e8e97a9");
    std::cout << "file checksum test: "
        << path << " = " << checksum
        << " : " << (file_checksum(path) == checksum)
        << std::endl;
    */
    std::cout << std::endl;
    return 0;
}
<commit_msg>Use auto for declaration.<commit_after>#include <algorithm>
#include <array>
#include <iomanip>
#include <curl/curl.h>
#include <memory>
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <vector>
#include <sys/stat.h>
#include <cerrno>
#include <cstring>
#include <system_error>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

const std::string listing("http://nwn.efupw.com/rootdir/index.dat");
const std::string patch_dir("http://nwn.efupw.com/rootdir/patch/");
const std::string update_check("");

const std::string file_checksum(const std::string &path);

size_t writefunction(const char *ptr, size_t size, size_t nmemb, void *userdata)
{
    std::string *s = static_cast<std::string *>(userdata);
    s->append(ptr, size * nmemb);
    return size * nmemb;
}

std::vector<std::string> &split(const std::string &s, char delim,
        std::vector<std::string> &elems)
{
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim))
    {
        elems.push_back(item);
    }
    return elems;
}

std::vector<std::string> split(const std::string &s, char delim)
{
    std::vector<std::string> elems;
    return split(s, delim, elems);
}

class Target
{
    public:
        enum class Status {
            Nonexistent,
            Outdated,
            Current
        };
        explicit Target(const std::string &name, const std::string &checksum):
            m_name(name.find_first_of('/') == std::string::npos ? name :
                    name, name.find_first_of('/') + 1, name.size() - 1),
            m_checksum(checksum)
            {}
        std::string name() const { return m_name; }
        const std::string checksum() const { return m_checksum; }

        void fetch()
        {
            std::cout << "Statting target " << name() << "...";
            std::string path;
            std::fstream fs(name(), std::ios_base::in);
            if (!fs.good())
            {
                fs.close();
                std::cout << " doesn't exist, creating new." << std::endl;
                auto elems = split(name(), '/');
                for (size_t i = 0, k = elems.size(); i < k; ++i)
                    //for (auto s : elems)
                {
                    const std::string &s(elems[i]);
                    if (s.size() && s != ".")
                    {
                        path.append((i > 0 ? "/" : "") + s);
                        // i indicates a directory.
                        if (i < k - 1)
                        {
                            auto status = mkdir(path.c_str(), S_IRWXU);
                            if (status == -1)
                            {
                                std::error_code err(errno, std::generic_category());
                                if (err != std::errc::file_exists)
                                {
                                    std::cout << "error making dir: "
                                        << path << ": "
                                        << err.message() << std::endl;
                                }
                            }
                        }
                        //std::cout << "the path: " << path << std::endl;
                    }
                }
                fs.open(path, std::ios_base::out);
                if (!fs.good())
                {
                    fs.close();
                    std::cout << "Failed to create file: " << path << std::endl;
                }
                else
                {
                    fs.close();
                    do_fetch();
                    return;
                    //std::cout << "opened path " << path << std::endl;
                }
            }
            if (fs.good())
            {
                fs.close();
                //const std::string calcsum(file_checksum(name()));
                /*
                std::cout << "calced sum for " << name()
                    << " : " << calcsum << ", expected " << checksum() << std::endl;
                    */
                //if (calcsum == checksum())
                if (status() == Status::Current)
                {
                    std::cout << " already up to date." << std::endl;
                }
                else
                {
                    std::cout << " outdated, downloading new." << std::endl;
                    do_fetch();
                }
            }
        }
        Status status()
        {
            std::ifstream is(name());
            if (!is.good())
            {
                return Status::Nonexistent;
            }
            is.close();
            auto calcsum(file_checksum(name()));
            if (calcsum == checksum())
            {
                return Status::Current;
            }
            else
            {
                return Status::Outdated;
            }
        }

    private:
        void do_fetch()
        {
            std::string s;
            std::shared_ptr<CURL *> phandle =
                std::make_shared<CURL *>(curl_easy_init());
            std::string url(patch_dir + name());
            curl_easy_setopt(*phandle, CURLOPT_URL, url.c_str());
            curl_easy_setopt(*phandle, CURLOPT_WRITEFUNCTION, &writefunction);
            curl_easy_setopt(*phandle, CURLOPT_WRITEDATA, &s);
            //curl_easy_setopt(*phandle, CURLOPT_NOPROGRESS, 0);
            curl_easy_perform(*phandle);
            curl_easy_cleanup(*phandle);
            phandle.reset();
            std::ofstream ofs(name());
            if (ofs.good())
            {
                ofs << s;
                ofs.close();
            }
            else
            {
                std::cout << "Couldn't write to " << name() << std::endl;
            }
        }

        std::string m_name;
        std::string m_checksum;
};

std::ostream& operator<<(std::ostream &os, const Target &t)
{
    return os << "name: " << t.name() << ", checksum: " << t.checksum();
}

class CurlGlobalInit
{
    public:
        CurlGlobalInit()
        {
            curl_global_init(CURL_GLOBAL_ALL);
        }

        ~CurlGlobalInit()
        {
            curl_global_cleanup();
        }
};

const std::string file_checksum(const std::string &path)
{
#define md_md5
#ifdef md_md5
    auto md = EVP_md5();
    const int md_len = MD5_DIGEST_LENGTH;
#else
    auto md = EVP_sha1();
    const int md_len = SHA_DIGEST_LENGTH;
#endif
    std::array<unsigned char, md_len> result;
    EVP_MD_CTX *mdctx = nullptr;
    std::ifstream is(path, std::ifstream::binary);
    if (!is.good())
    {
        std::cout << "Couldn't open file " << path
           << " for checksumming." << std::endl;
        return std::string();
    }
    else
    {
        //std::cout << "opened file " << path << std::endl;
    }

    const int length = 8192;
    std::array<unsigned char, length> buffer;
    auto buf = reinterpret_cast<char *>(buffer.data());
    mdctx = EVP_MD_CTX_create();
    int status = EVP_DigestInit_ex(mdctx, md, nullptr);
    while (status && is)
    {
        is.read(buf, length);
        status = EVP_DigestUpdate(mdctx, buffer.data(), is.gcount());
    }
    status = EVP_DigestFinal_ex(mdctx, result.data(), nullptr);
    EVP_MD_CTX_destroy(mdctx);
    std::stringstream calcsum;
    calcsum << std::setfill('0');

    for (unsigned char c : result)
    {
        calcsum << std::hex << std::setw(2)
            << static_cast<unsigned int>(c);
    }
    /*
    std::for_each(std::begin(result), std::end(result),
            [&calcsum](unsigned char c)
            {
            calcsum << std::hex << std::setw(2)
            << static_cast<unsigned int>(c);
            });
            */
    //std::cout << calcsum.str() << std::endl;
    return calcsum.str();
}

int main(int argc, char *argv[])
{
    CurlGlobalInit curl_global;
    std::string fetch;
    std::shared_ptr<CURL *> phandle = std::make_shared<CURL *>(curl_easy_init());
    curl_easy_setopt(*phandle, CURLOPT_URL, listing.c_str());
    curl_easy_setopt(*phandle, CURLOPT_WRITEFUNCTION, &writefunction);
    curl_easy_setopt(*phandle, CURLOPT_WRITEDATA, &fetch);
    //curl_easy_setopt(*phandle, CURLOPT_NOPROGRESS, 0);
    curl_easy_perform(*phandle);
    curl_easy_cleanup(*phandle);
    phandle.reset();
    //std::cout << fetch << std::endl;
    std::vector<std::string> lines(split(fetch, '\n'));
    //split(fetch, '\n', lines);
    //std::cout << lines[1] << std::endl;
    std::vector<Target> new_targets, old_targets;
    for (auto beg = std::begin(lines), end = std::end(lines);
            beg != end; ++beg)
    {
        auto data(split(*beg, '@'));
        Target t(data[0], data[data.size() - 1]);
        auto status = t.status();
        if (status == Target::Status::Nonexistent)
        {
            new_targets.push_back(std::move(t));
        }
        else if (status == Target::Status::Outdated)
        {
            old_targets.push_back(std::move(t));
        }
    }
    if (new_targets.size())
    {
        std::cout << "New targets: " << new_targets.size() << std::endl;
        for (auto &t : new_targets)
        {
            std::cout << "- " << t << std::endl;
            //t.fetch();
        }
        //std::cout << new_targets[4] << std::endl;
        new_targets[0].fetch();
        //new_targets[4].fetch();
    }
    else
    {
        std::cout << "No new targets." << std::endl;
    }

    if (old_targets.size())
    {
        std::cout << "Outdated targets: " << old_targets.size() << std::endl;
        for (auto &t : old_targets)
        {
            std::cout << "- " << t << std::endl;
        }
    }
    else
    {
        std::cout << "No targets out of date." << std::endl;
    }

    /*
    const std::string path = "bin/override/spells.2da";
    const std::string checksum("38eaad974c15e5f3119469f17e8e97a9");
    std::cout << "file checksum test: "
        << path << " = " << checksum
        << " : " << (file_checksum(path) == checksum)
        << std::endl;
    */
    std::cout << std::endl;
    return 0;
}
<|endoftext|>


<commit_before>#include <Bounce2.h>
#include <FastLED.h>
// #include <EEPROM.h>

#define DEBUG

#ifdef DEBUG
  #define DEBUG_PRINT(msg) (Serial.println(msg))
#else
  #define DEBUG_PRINT(msg) ()
#endif

// Digital PINs
#define LED_PIN_CH1 4
#define LED_PIN_CH2 2
#define MODE_BUTTON_PIN 6
#define DROP_BUTTON_PIN 7
#define BRIGHTNESS_BUTTON_PIN 8
#define BEAT_BUTTON_PIN 10

// Analog PINs
#define ACCELX_PIN A0
#define ACCELY_PIN A2
#define ACCELZ_PIN A4

// Other constants
#define BAUD_RATE 9600
#define NUM_LEDS_CH0 120
#define NUM_LEDS_CH1 29
#define FRAME_LENGTH 33 // 30 fps
#define NUM_STATES 2
#define MAX_MILLIAMPS 500 // should run for ~8h on 2x2000maH 18650

#include <Pattern.h>
#include <PatternList.h>
#include <PatternState.h>
#include <PaletteList.h>

#include <Plasma.h>
#include <Juggle.h>
#include <Sinelon.h>
#include <Confetti.h>
#include <Heartbeat.h>
#include <Bpm.h>

#include <BrightnessControl.h>
#include <ModeControl.h>
#include <BeatControl.h>
#include <DropControl.h>
#include <AccellerationControl.h>

CRGB ledsCh0[NUM_LEDS_CH0];
PatternState stateCh0(NUM_LEDS_CH0, ledsCh0);

CRGB ledsCh1[NUM_LEDS_CH1];
PatternState stateCh1(NUM_LEDS_CH1, ledsCh1);

Heartbeat *heartbeat = new Heartbeat();
Pattern *patternItems[] = {
  new Bpm(),
  heartbeat,
  new Plasma(),
  new Juggle(),
  new Sinelon(),
  new Confetti()
};
PatternList patternList(6, patternItems);

CRGBPalette16 *paletteItems[] = {
  new CRGBPalette16(
    CRGB::Blue,
    CRGB::DarkBlue,
    CRGB::DarkBlue,
    CRGB::DarkBlue,
    CRGB::DarkBlue,
    CRGB::DarkBlue,
    CRGB::DarkBlue,
    CRGB::DarkBlue,
    CRGB::Blue,
    CRGB::DarkBlue,
    CRGB::SkyBlue,
    CRGB::SkyBlue,
    CRGB::LightBlue,
    CRGB::White,
    CRGB::LightBlue,
    CRGB::SkyBlue
  ),
  // Lava
  new CRGBPalette16(
    CRGB::Black,
    CRGB::Maroon,
    CRGB::Black,
    CRGB::Maroon,
    CRGB::DarkRed,
    CRGB::Maroon,
    CRGB::DarkRed,
    CRGB::DarkRed,
    CRGB::DarkRed,
    CRGB::Red,
    CRGB::Orange,
    CRGB::White,
    CRGB::Orange,
    CRGB::Red,
    CRGB::DarkRed,
    CRGB::Black
  ),
  // Rainbow
  new CRGBPalette16(
    0xFF0000, 0xD52A00, 0xAB5500, 0xAB7F00,
    0xABAB00, 0x56D500, 0x00FF00, 0x00D52A,
    0x00AB55, 0x0056AA, 0x0000FF, 0x2A00D5,
    0x5500AB, 0x7F0081, 0xAB0055, 0xD5002B
  )
};
PaletteList paletteList(3, paletteItems);

BrightnessControl brightnessControl(BRIGHTNESS_BUTTON_PIN);
ModeControl modeControl(MODE_BUTTON_PIN);
BeatControl beatControl(BEAT_BUTTON_PIN);
DropControl dropControl(DROP_BUTTON_PIN);
AccellerationControl accellerationControl(ACCELX_PIN, ACCELY_PIN, ACCELZ_PIN);

// See https://learn.adafruit.com/multi-tasking-the-arduino-part-1/using-millis-for-timing
long previousMillis = 0;

// // Cycle mode in persistent memory on every on switch.
// // More resilient against hardware failures than a button.
// void updateModeFromEEPROM() {
//   mode = EEPROM.read(0);
//   if(!mode) {
//     mode = 1;
//   }
//   mode = (mode % modeCount) + 1;
//
//   EEPROM.write(0, mode);
// }

void setup() {
  FastLED.addLeds<NEOPIXEL, LED_PIN_CH1>(ledsCh0, NUM_LEDS_CH0);
  FastLED.addLeds<NEOPIXEL, LED_PIN_CH2>(ledsCh1, NUM_LEDS_CH1);

  Serial.begin(BAUD_RATE);

  // https://github.com/FastLED/FastLED/wiki/Power-notes#managing-power-in-fastled
  FastLED.setMaxPowerInVoltsAndMilliamps(5,MAX_MILLIAMPS);

  brightnessControl.setup();
  FastLED.setBrightness(brightnessControl.getBrightness());

  modeControl.setup();

  beatControl.setup();

  dropControl.setup();

  stateCh0.palette = paletteList.curr();
  patternList.setState(0, &stateCh0);

  stateCh1.palette = paletteList.curr();
  patternList.setState(1, &stateCh1);

  // updateModeFromEEPROM();
}

void loop() {
  // Timing
  unsigned long currentMillis = millis();

  // Mode and Palette
  modeControl.update();
  if(modeControl.rose()) {
    if(modeControl.wasLongPress()) {
      CRGBPalette16 *palette = paletteList.next();
      stateCh0.palette = palette;
      stateCh1.palette = palette;
    } else {
      patternList.next();
    }
  }
  Pattern *currPattern = patternList.curr();

  // Beat
  beatControl.update();
  currPattern->setBpm(beatControl.getBpm());
  currPattern->setOnBeat(beatControl.onBeat());
  currPattern->setBeatProgress(beatControl.beatProgress());

  // Drop
  dropControl.update();
  currPattern->setIsDropping((dropControl.read() == LOW));

  // Accelleration
  int magnitude;
  EVERY_N_MILLISECONDS(100) {
    // Expensive calc, perform sparingly
    accellerationControl.update();
    magnitude = accellerationControl.getAdjustedMagnitude();
    heartbeat->setMagnitude(magnitude);
  }

  // Patterns
  int frameLength = currPattern->getFrameLength();
  // Should use EVERY_N_MILLISECONDS, but the C++ macro
  // can't seem to change values dynamically
  if(currentMillis - previousMillis > frameLength) {
    previousMillis = currentMillis;
    patternList.loop(0);

    // Brightness
    brightnessControl.update();
    FastLED.setBrightness(brightnessControl.getBrightness());

    FastLED.show();
  }

}
<commit_msg>Sanity delay on boot<commit_after>#include <Bounce2.h>
#include <FastLED.h>
// #include <EEPROM.h>

#define DEBUG

#ifdef DEBUG
  #define DEBUG_PRINT(msg) (Serial.println(msg))
#else
  #define DEBUG_PRINT(msg) ()
#endif

// Digital PINs
#define LED_PIN_CH1 4
#define LED_PIN_CH2 2
#define MODE_BUTTON_PIN 6
#define DROP_BUTTON_PIN 7
#define BRIGHTNESS_BUTTON_PIN 8
#define BEAT_BUTTON_PIN 10

// Analog PINs
#define ACCELX_PIN A0
#define ACCELY_PIN A2
#define ACCELZ_PIN A4

// Other constants
#define BAUD_RATE 9600
#define NUM_LEDS_CH0 120
#define NUM_LEDS_CH1 29
#define FRAME_LENGTH 33 // 30 fps
#define NUM_STATES 2
#define MAX_MILLIAMPS 500 // should run for ~8h on 2x2000maH 18650

#include <Pattern.h>
#include <PatternList.h>
#include <PatternState.h>
#include <PaletteList.h>

#include <Plasma.h>
#include <Juggle.h>
#include <Sinelon.h>
#include <Confetti.h>
#include <Heartbeat.h>
#include <Bpm.h>

#include <BrightnessControl.h>
#include <ModeControl.h>
#include <BeatControl.h>
#include <DropControl.h>
#include <AccellerationControl.h>

CRGB ledsCh0[NUM_LEDS_CH0];
PatternState stateCh0(NUM_LEDS_CH0, ledsCh0);

CRGB ledsCh1[NUM_LEDS_CH1];
PatternState stateCh1(NUM_LEDS_CH1, ledsCh1);

Heartbeat *heartbeat = new Heartbeat();
Pattern *patternItems[] = {
  new Bpm(),
  heartbeat,
  new Plasma(),
  new Juggle(),
  new Sinelon(),
  new Confetti()
};
PatternList patternList(6, patternItems);

CRGBPalette16 *paletteItems[] = {
  new CRGBPalette16(
    CRGB::Blue,
    CRGB::DarkBlue,
    CRGB::DarkBlue,
    CRGB::DarkBlue,
    CRGB::DarkBlue,
    CRGB::DarkBlue,
    CRGB::DarkBlue,
    CRGB::DarkBlue,
    CRGB::Blue,
    CRGB::DarkBlue,
    CRGB::SkyBlue,
    CRGB::SkyBlue,
    CRGB::LightBlue,
    CRGB::White,
    CRGB::LightBlue,
    CRGB::SkyBlue
  ),
  // Lava
  new CRGBPalette16(
    CRGB::Black,
    CRGB::Maroon,
    CRGB::Black,
    CRGB::Maroon,
    CRGB::DarkRed,
    CRGB::Maroon,
    CRGB::DarkRed,
    CRGB::DarkRed,
    CRGB::DarkRed,
    CRGB::Red,
    CRGB::Orange,
    CRGB::White,
    CRGB::Orange,
    CRGB::Red,
    CRGB::DarkRed,
    CRGB::Black
  ),
  // Rainbow
  new CRGBPalette16(
    0xFF0000, 0xD52A00, 0xAB5500, 0xAB7F00,
    0xABAB00, 0x56D500, 0x00FF00, 0x00D52A,
    0x00AB55, 0x0056AA, 0x0000FF, 0x2A00D5,
    0x5500AB, 0x7F0081, 0xAB0055, 0xD5002B
  )
};
PaletteList paletteList(3, paletteItems);

BrightnessControl brightnessControl(BRIGHTNESS_BUTTON_PIN);
ModeControl modeControl(MODE_BUTTON_PIN);
BeatControl beatControl(BEAT_BUTTON_PIN);
DropControl dropControl(DROP_BUTTON_PIN);
AccellerationControl accellerationControl(ACCELX_PIN, ACCELY_PIN, ACCELZ_PIN);

// See https://learn.adafruit.com/multi-tasking-the-arduino-part-1/using-millis-for-timing
long previousMillis = 0;

// // Cycle mode in persistent memory on every on switch.
// // More resilient against hardware failures than a button.
// void updateModeFromEEPROM() {
//   mode = EEPROM.read(0);
//   if(!mode) {
//     mode = 1;
//   }
//   mode = (mode % modeCount) + 1;
//
//   EEPROM.write(0, mode);
// }

void setup() {
  // Sanity delay
  delay(500);

  FastLED.addLeds<NEOPIXEL, LED_PIN_CH1>(ledsCh0, NUM_LEDS_CH0);
  FastLED.addLeds<NEOPIXEL, LED_PIN_CH2>(ledsCh1, NUM_LEDS_CH1);

  Serial.begin(BAUD_RATE);

  // https://github.com/FastLED/FastLED/wiki/Power-notes#managing-power-in-fastled
  FastLED.setMaxPowerInVoltsAndMilliamps(5,MAX_MILLIAMPS);

  brightnessControl.setup();
  FastLED.setBrightness(brightnessControl.getBrightness());

  modeControl.setup();

  beatControl.setup();

  dropControl.setup();

  stateCh0.palette = paletteList.curr();
  patternList.setState(0, &stateCh0);

  stateCh1.palette = paletteList.curr();
  patternList.setState(1, &stateCh1);

  // updateModeFromEEPROM();
}

void loop() {
  // Timing
  unsigned long currentMillis = millis();

  // Mode and Palette
  modeControl.update();
  if(modeControl.rose()) {
    if(modeControl.wasLongPress()) {
      CRGBPalette16 *palette = paletteList.next();
      stateCh0.palette = palette;
      stateCh1.palette = palette;
    } else {
      patternList.next();
    }
  }
  Pattern *currPattern = patternList.curr();

  // Beat
  beatControl.update();
  currPattern->setBpm(beatControl.getBpm());
  currPattern->setOnBeat(beatControl.onBeat());
  currPattern->setBeatProgress(beatControl.beatProgress());

  // Drop
  dropControl.update();
  currPattern->setIsDropping((dropControl.read() == LOW));

  // Accelleration
  int magnitude;
  EVERY_N_MILLISECONDS(100) {
    // Expensive calc, perform sparingly
    accellerationControl.update();
    magnitude = accellerationControl.getAdjustedMagnitude();
    heartbeat->setMagnitude(magnitude);
  }

  // Patterns
  int frameLength = currPattern->getFrameLength();
  // Should use EVERY_N_MILLISECONDS, but the C++ macro
  // can't seem to change values dynamically
  if(currentMillis - previousMillis > frameLength) {
    previousMillis = currentMillis;
    patternList.loop(0);

    // Brightness
    brightnessControl.update();
    FastLED.setBrightness(brightnessControl.getBrightness());

    FastLED.show();
  }

}
<|endoftext|>


<commit_before>#include <SFML/Graphics.hpp>

#include <Windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    sf::RenderWindow window(sf::VideoMode(1280, 960), "WarZone!");

    // map params
    int width = 40;
    int height = 27;
    int scale = 2;
    int tileSize = 16;
    int menuRows = 3;
    int yOffset = tileSize * menuRows;
    int tileScaled = tileSize * scale;
    int yOffsetScaled = yOffset * scale;

    // grass tile
    sf::Texture grassTex;
    grassTex.loadFromFile("assets/textures/grass.png");
    sf::Image grassImg = grassTex.copyToImage();

    // selection graphic
    sf::Texture selectionTex;
    selectionTex.loadFromFile("assets/textures/selection.png");
    sf::Sprite selection(selectionTex);
    selection.scale(scale, scale);

    // map graphic
    sf::Texture mapTex;
    mapTex.create(width * tileSize, height * tileSize + yOffset);

    for (int y = 0; y < height; ++y)
        for (int x = 0; x < width; ++x)
            mapTex.update(grassImg, x * tileSize, y * tileSize + yOffset);

    sf::Sprite map(mapTex);
    map.scale(scale, scale);

    // mouse details
    sf::Vector2i mouse(sf::Mouse::getPosition());
    int gridX = 0; // mouse coords on map tile grid
    int gridY = 0;

    // main loop
    while (window.isOpen())
    {
        // event handling
        {
            sf::Event event;
            window.pollEvent(event); // may drop events, need proper handling

            if (event.type == sf::Event::Closed)
                window.close();

            if (event.type == sf::Event::KeyPressed)
            {
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
                    window.close();
            }

            if (event.type == sf::Event::MouseMoved)
                mouse = sf::Mouse::getPosition(window);
        }

        // update func
        {
            mouse = sf::Mouse::getPosition(window);
            gridX = (mouse.x / tileScaled) * tileScaled;
            gridY = (mouse.y / tileScaled) * tileScaled;

            selection.setPosition(gridX, gridY);
        }

        // render func
        {
            window.clear();
            window.draw(map);

            if (gridY >= yOffsetScaled)
                window.draw(selection);

            window.display();
        }
    }

    return 0;
}<commit_msg>(Seemingly) fixed event handling<commit_after>#include <SFML/Graphics.hpp>

#include <Windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    sf::RenderWindow window(sf::VideoMode(1280, 960), "WarZone!");

    // map params
    int width = 40;
    int height = 27;
    int scale = 2;
    int tileSize = 16;
    int menuRows = 3;
    int yOffset = tileSize * menuRows;
    int tileScaled = tileSize * scale;
    int yOffsetScaled = yOffset * scale;

    // grass tile
    sf::Texture grassTex;
    grassTex.loadFromFile("assets/textures/grass.png");
    sf::Image grassImg = grassTex.copyToImage();

    // selection graphic
    sf::Texture selectionTex;
    selectionTex.loadFromFile("assets/textures/selection.png");
    sf::Sprite selection(selectionTex);
    selection.scale(scale, scale);

    // map graphic
    sf::Texture mapTex;
    mapTex.create(width * tileSize, height * tileSize + yOffset);

    for (int y = 0; y < height; ++y)
        for (int x = 0; x < width; ++x)
            mapTex.update(grassImg, x * tileSize, y * tileSize + yOffset);

    sf::Sprite map(mapTex);
    map.scale(scale, scale);

    // mouse details
    sf::Vector2i mouse(sf::Mouse::getPosition());
    int gridX = 0; // mouse coords on map tile grid
    int gridY = 0;

    // main loop
    while (window.isOpen())
    {
        // event handling
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();

            if (event.type == sf::Event::KeyPressed)
            {
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
                    window.close();
            }
        }

        // update func
        {
            mouse = sf::Mouse::getPosition(window);
            gridX = (mouse.x / tileScaled) * tileScaled;
            gridY = (mouse.y / tileScaled) * tileScaled;

            selection.setPosition(gridX, gridY);
        }

        // render func
        {
            window.clear();
            window.draw(map);

            if (gridY >= yOffsetScaled)
                window.draw(selection);

            window.display();
        }
    }

    return 0;
}<|endoftext|>


<commit_before>/* The MIT License (MIT)
 *
 * Copyright (c) 2013-2016 Hironori Ishibashi
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

/**
 * @file main.cpp
 * @author Hironori Ishibashi
 * @brief メイン関数。
 */

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <memory>
#include <fstream>

#include "init.h"
#include "chess_engine.h"
#include "uci_shell.h"
#include "params.h"
#include "sayulisp.h"

// デバッグスイッチ。
// #define SAYURI_DEBUG_dd1bb50e_83bf_4b24_af8b_7c7bf60bc063

/**
 * UCI出力を標準出力に出力するコールバック関数。
 * @param message UCIShellからのメッセージ。
 */
void Print(const std::string& message) {
  std::cout << message << std::endl;
}

/**
 * 実行ループ。
 * @param shell 実行するUCIShell。
 */
void Run(Sayuri::UCIShell& shell) {
  while (true) {
    std::string input;
    std::getline(std::cin, input);

    if (input == "quit") {
      break;
    } else {
      shell.InputCommand(input);
    }
  }
}

/**
 * メイン関数。
 * @param argc コマンドの引数の数。
 * @param argv コマンドの引数。
 * @return 終了コード。
 */
int main(int argc, char* argv[]) {
#if defined(SAYURI_DEBUG_dd1bb50e_83bf_4b24_af8b_7c7bf60bc063)
  // デバッグ用。
  return Sayuri::DebugMain(argc, argv);

#else
  if ((argc >= 2)
  && (std::strcmp(argv[1], "--help") == 0)) {
    // ヘルプの表示。
    std::string usage_str =
R"...(Usage:
    $ sayuri [option]

[option]:
    --version
        Shows version.

    --license
        Shows license terms.

    --help
        Shows help.

    --sayulisp <file name>
        Runs Sayuri as Sayulisp Interpreter.
        <file name> is Sayulisp script.
        If <file name> is '-', Sayuri reads script from standard input.)...";
    std::cout << usage_str << std::endl;
  } else if ((argc >= 2)
  && (std::strcmp(argv[1], "--version") == 0)) {
    // バージョン番号の表示。
    std::cout << Sayuri::ID_NAME << std::endl;
  } else if ((argc >= 2)
  && (std::strcmp(argv[1], "--license") == 0)) {
    // ライセンス分の表示。
    std::cout << Sayuri::LICENSE << std::endl;
  } else if ((argc >= 2)
  && (std::strcmp(argv[1], "--sayulisp") == 0)) {
    // Sayulispモード。
    // 引数がもう一つ必要。
    if (argc < 3) {
      std::cerr << "Insufficient arguments. '--sayulisp' needs <file name>."
      << std::endl;
      return 1;
    }

    // エンジン初期化。
    Sayuri::Init();

    // Sayurlispを作成。
    std::unique_ptr<Sayuri::Sayulisp>
    sayulisp_ptr(new Sayuri::Sayulisp());

    // 入力ストリームを得る。
    std::istream* stream_ptr = nullptr;
    std::ifstream file;
    if (std::strcmp(argv[2], "-") == 0) {
      stream_ptr = &(std::cin);
    } else {
      file.open(argv[2]);
      if (!file) {
        std::cerr << "Couldn't open '" << argv[2] << "'." << std::endl;
        return 1;
      }
      stream_ptr = &file;
    }

    // 実行。
    int status = 0;
    try {
      status = sayulisp_ptr->Run(stream_ptr);
    } catch (Sayuri::LispObjectPtr error) {
      return 1;
    }

    // 終了。
    if (file) file.close();
    return status;
  } else {
    // プログラムの起動。
    // 初期化。
    Sayuri::Init();

    // エンジン準備。
    std::unique_ptr<Sayuri::SearchParams>
    search_params_ptr(new Sayuri::SearchParams());

    std::unique_ptr<Sayuri::EvalParams>
    eval_params_ptr(new Sayuri::EvalParams());

    std::unique_ptr<Sayuri::TranspositionTable>
    table_ptr(new Sayuri::TranspositionTable(Sayuri::UCI_DEFAULT_TABLE_SIZE));

    std::unique_ptr<Sayuri::ChessEngine>
    engine_ptr(new Sayuri::ChessEngine(*search_params_ptr, *eval_params_ptr,
    *table_ptr));

    std::unique_ptr<Sayuri::UCIShell>
    shell_ptr(new Sayuri::UCIShell(*engine_ptr));

    shell_ptr->AddOutputListener(Print);

    // エンジン起動。
    Run(*shell_ptr);

    // 後処理。
    Sayuri::Postprocess();
  }

  return EXIT_SUCCESS;
#endif
}
<commit_msg>Sayulispでコマンドライン引数が使えるようにした<commit_after>/* The MIT License (MIT)
 *
 * Copyright (c) 2013-2016 Hironori Ishibashi
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

/**
 * @file main.cpp
 * @author Hironori Ishibashi
 * @brief メイン関数。
 */

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <memory>
#include <fstream>

#include "init.h"
#include "chess_engine.h"
#include "uci_shell.h"
#include "params.h"
#include "sayulisp.h"

// デバッグスイッチ。
// #define SAYURI_DEBUG_dd1bb50e_83bf_4b24_af8b_7c7bf60bc063

/**
 * UCI出力を標準出力に出力するコールバック関数。
 * @param message UCIShellからのメッセージ。
 */
void Print(const std::string& message) {
  std::cout << message << std::endl;
}

/**
 * 実行ループ。
 * @param shell 実行するUCIShell。
 */
void Run(Sayuri::UCIShell& shell) {
  while (true) {
    std::string input;
    std::getline(std::cin, input);

    if (input == "quit") {
      break;
    } else {
      shell.InputCommand(input);
    }
  }
}

/**
 * メイン関数。
 * @param argc コマンドの引数の数。
 * @param argv コマンドの引数。
 * @return 終了コード。
 */
int main(int argc, char* argv[]) {
#if defined(SAYURI_DEBUG_dd1bb50e_83bf_4b24_af8b_7c7bf60bc063)
  // デバッグ用。
  return Sayuri::DebugMain(argc, argv);

#else
  if ((argc >= 2)
  && (std::strcmp(argv[1], "--help") == 0)) {
    // ヘルプの表示。
    std::string usage_str =
R"...(Usage:
    $ sayuri [option]

[option]:
    --version
        Shows version.

    --license
        Shows license terms.

    --help
        Shows help.

    --sayulisp <file name> [<argv>...]
        Runs Sayuri as Sayulisp Interpreter.
        <file name> is Sayulisp script.
        If <file name> is '-', Sayuri reads script from standard input.
        <argv> is bound to Symbol 'argv'.)...";
    std::cout << usage_str << std::endl;
  } else if ((argc >= 2)
  && (std::strcmp(argv[1], "--version") == 0)) {
    // バージョン番号の表示。
    std::cout << Sayuri::ID_NAME << std::endl;
  } else if ((argc >= 2)
  && (std::strcmp(argv[1], "--license") == 0)) {
    // ライセンス分の表示。
    std::cout << Sayuri::LICENSE << std::endl;
  } else if ((argc >= 2)
  && (std::strcmp(argv[1], "--sayulisp") == 0)) {
    // Sayulispモード。
    // 引数がもう一つ必要。
    if (argc < 3) {
      std::cerr << "Insufficient arguments. '--sayulisp' needs <file name>."
      << std::endl;
      return 1;
    }

    // エンジン初期化。
    Sayuri::Init();

    // Sayurlispを作成。
    std::unique_ptr<Sayuri::Sayulisp>
    sayulisp_ptr(new Sayuri::Sayulisp());

    // 入力ストリームを得る。
    std::istream* stream_ptr = nullptr;
    std::ifstream file;
    if (std::strcmp(argv[2], "-") == 0) {
      stream_ptr = &(std::cin);
    } else {
      file.open(argv[2]);
      if (!file) {
        std::cerr << "Couldn't open '" << argv[2] << "'." << std::endl;
        return 1;
      }
      stream_ptr = &file;
    }

    // 引数の作成。
    Sayuri::LispObjectPtr argv_list = Sayuri::Lisp::NewList(argc - 2);
    Sayuri::LispIterator<true> itr {argv_list.get()};
    for (int i = 2; i < argc; ++i, ++itr) {
      itr.current_->car(Sayuri::Lisp::NewString(argv[i]));
    }
    sayulisp_ptr->BindSymbol("argv", argv_list);  // 登録。

    // 実行。
    int status = 0;
    try {
      status = sayulisp_ptr->Run(stream_ptr);
    } catch (Sayuri::LispObjectPtr error) {
      return 1;
    }

    // 終了。
    if (file) file.close();
    return status;
  } else {
    // プログラムの起動。
    // 初期化。
    Sayuri::Init();

    // エンジン準備。
    std::unique_ptr<Sayuri::SearchParams>
    search_params_ptr(new Sayuri::SearchParams());

    std::unique_ptr<Sayuri::EvalParams>
    eval_params_ptr(new Sayuri::EvalParams());

    std::unique_ptr<Sayuri::TranspositionTable>
    table_ptr(new Sayuri::TranspositionTable(Sayuri::UCI_DEFAULT_TABLE_SIZE));

    std::unique_ptr<Sayuri::ChessEngine>
    engine_ptr(new Sayuri::ChessEngine(*search_params_ptr, *eval_params_ptr,
    *table_ptr));

    std::unique_ptr<Sayuri::UCIShell>
    shell_ptr(new Sayuri::UCIShell(*engine_ptr));

    shell_ptr->AddOutputListener(Print);

    // エンジン起動。
    Run(*shell_ptr);

    // 後処理。
    Sayuri::Postprocess();
  }

  return EXIT_SUCCESS;
#endif
}
<|endoftext|>


<commit_before>#include <QUrl>
#include <QDebug>
#include <QTimer>
#include <QCoreApplication>
#include <QCommandLineParser>

#include "Util.h"
#include "Version.h"
#include "Downloader.h"

int main(int argc, char **argv) {
  QCoreApplication app(argc, argv);
  QCoreApplication::setApplicationName("efdl");
  QCoreApplication::setApplicationVersion(versionString(false));

  QCommandLineParser parser;
  parser.setApplicationDescription(QObject::tr("Efficient downloading application."));
  parser.addHelpOption();
  parser.addVersionOption();
  parser.addPositionalArgument("URL", QObject::tr("URL to download."));

  QCommandLineOption connsOpt(QStringList{"c", "conns"},
                              QObject::tr("Number of simultaneous connections to"
                                          " use. (defaults to 1)"),
                              QObject::tr("num"));
  parser.addOption(connsOpt);

  QCommandLineOption confirmOpt(QStringList{"confirm"},
                                QObject::tr("Confirm to download on redirections."));
  parser.addOption(confirmOpt);

  QCommandLineOption verboseOpt(QStringList{"verbose"},
                                QObject::tr("Verbose mode."));
  parser.addOption(verboseOpt);

  QCommandLineOption chunksOpt(QStringList{"chunks"},
                               QObject::tr("Number of chunks to split the download"
                                           "up into. Cannot be used with --chunk-size."),
                               QObject::tr("num"));
  parser.addOption(chunksOpt);

  QCommandLineOption chunkSizeOpt(QStringList{"chunk-size"},
                               QObject::tr("Size of each chunk which dictates "
                                           "how many to use. Cannot be used with --chunks."),
                               QObject::tr("bytes"));
  parser.addOption(chunkSizeOpt);

  // Process CLI arguments.
  parser.process(app);
  const QStringList args = parser.positionalArguments();
  if (args.size() != 1) {
    parser.showHelp(-1);
  }

  int conns = 1, chunks = -1, chunkSize = -1;
  bool confirm = parser.isSet(confirmOpt),
    verbose = parser.isSet(verboseOpt);

  bool ok;
  if (parser.isSet(connsOpt)) {
    conns = parser.value(connsOpt).toInt(&ok);
    if (!ok || conns <= 0) {
      qCritical() << "ERROR Number of connections must be a positive number!";
      return -1;
    }
  }

  if (parser.isSet(chunksOpt)) {
    chunks = parser.value(chunksOpt).toInt(&ok);
    if (!ok || chunks <= 0) {
      qCritical() << "ERROR Number of chunks must be a positive number!";
      return -1;
    }
  }

  if (parser.isSet(chunkSizeOpt)) {
    chunkSize = parser.value(chunkSizeOpt).toInt(&ok);
    if (!ok || chunkSize <= 0) {
      qCritical() << "ERROR Chunk size must be a positive number!";
      return -1;
    }
  }

  if (chunks != -1 && chunkSize != -1) {
    qCritical() << "ERROR --chunks and --chunk-size cannot be used at the same time!";
    return -1;
  }

  QUrl url{args[0], QUrl::StrictMode};
  if (!url.isValid()) {
    qCritical() << "ERROR Invalid URL!";
    return -1;
  }

  const QStringList schemes{"http", "https"};
  if (!schemes.contains(url.scheme().toLower())) {
    qCritical() << "ERROR Invalid scheme! Valid ones are:" <<
      qPrintable(schemes.join(" "));
    return -1;
  }

  Util::registerCustomTypes();

  // Begin transfer in event loop.
  Downloader dl{url, conns, chunks, chunkSize, confirm, verbose};
  QObject::connect(&dl, &Downloader::finished, &app, &QCoreApplication::quit);
  QTimer::singleShot(0, &dl, SLOT(start()));

  return app.exec();
}
<commit_msg>Reordering of command line arguments in usage print.<commit_after>#include <QUrl>
#include <QDebug>
#include <QTimer>
#include <QCoreApplication>
#include <QCommandLineParser>

#include "Util.h"
#include "Version.h"
#include "Downloader.h"

int main(int argc, char **argv) {
  QCoreApplication app(argc, argv);
  QCoreApplication::setApplicationName("efdl");
  QCoreApplication::setApplicationVersion(versionString(false));

  QCommandLineParser parser;
  parser.setApplicationDescription(QObject::tr("Efficient downloading application."));
  parser.addHelpOption();
  parser.addVersionOption();
  parser.addPositionalArgument("URL", QObject::tr("URL to download."));

  QCommandLineOption verboseOpt(QStringList{"verbose"},
                                QObject::tr("Verbose mode."));
  parser.addOption(verboseOpt);

  QCommandLineOption confirmOpt(QStringList{"confirm"},
                                QObject::tr("Confirm to download on redirections."));
  parser.addOption(confirmOpt);

  QCommandLineOption connsOpt(QStringList{"c", "conns"},
                              QObject::tr("Number of simultaneous connections to"
                                          " use. (defaults to 1)"),
                              QObject::tr("num"));
  parser.addOption(connsOpt);

  QCommandLineOption chunksOpt(QStringList{"chunks"},
                               QObject::tr("Number of chunks to split the download"
                                           "up into. Cannot be used with --chunk-size."),
                               QObject::tr("num"));
  parser.addOption(chunksOpt);

  QCommandLineOption chunkSizeOpt(QStringList{"chunk-size"},
                               QObject::tr("Size of each chunk which dictates "
                                           "how many to use. Cannot be used with --chunks."),
                               QObject::tr("bytes"));
  parser.addOption(chunkSizeOpt);

  // Process CLI arguments.
  parser.process(app);
  const QStringList args = parser.positionalArguments();
  if (args.size() != 1) {
    parser.showHelp(-1);
  }

  int conns = 1, chunks = -1, chunkSize = -1;
  bool confirm = parser.isSet(confirmOpt),
    verbose = parser.isSet(verboseOpt);

  bool ok;
  if (parser.isSet(connsOpt)) {
    conns = parser.value(connsOpt).toInt(&ok);
    if (!ok || conns <= 0) {
      qCritical() << "ERROR Number of connections must be a positive number!";
      return -1;
    }
  }

  if (parser.isSet(chunksOpt)) {
    chunks = parser.value(chunksOpt).toInt(&ok);
    if (!ok || chunks <= 0) {
      qCritical() << "ERROR Number of chunks must be a positive number!";
      return -1;
    }
  }

  if (parser.isSet(chunkSizeOpt)) {
    chunkSize = parser.value(chunkSizeOpt).toInt(&ok);
    if (!ok || chunkSize <= 0) {
      qCritical() << "ERROR Chunk size must be a positive number!";
      return -1;
    }
  }

  if (chunks != -1 && chunkSize != -1) {
    qCritical() << "ERROR --chunks and --chunk-size cannot be used at the same time!";
    return -1;
  }

  QUrl url{args[0], QUrl::StrictMode};
  if (!url.isValid()) {
    qCritical() << "ERROR Invalid URL!";
    return -1;
  }

  const QStringList schemes{"http", "https"};
  if (!schemes.contains(url.scheme().toLower())) {
    qCritical() << "ERROR Invalid scheme! Valid ones are:" <<
      qPrintable(schemes.join(" "));
    return -1;
  }

  Util::registerCustomTypes();

  // Begin transfer in event loop.
  Downloader dl{url, conns, chunks, chunkSize, confirm, verbose};
  QObject::connect(&dl, &Downloader::finished, &app, &QCoreApplication::quit);
  QTimer::singleShot(0, &dl, SLOT(start()));

  return app.exec();
}
<|endoftext|>