<commit_before>#include "linuxapi.h"

#if defined(__linux__) && !defined(__ANDROID__)
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xos.h>
#include <GL/glx.h>

#undef Always // in X11/X.h
#undef PSize

#include <Tempest/Window>
#include <Tempest/Event>
#include <Tempest/DisplaySettings>

#include <unordered_map>
#include <fstream>
#include <Tempest/Assert>

#include <iostream>
#include "core/wrappers/atomic.h"
#include "thirdparty/utf8cpp/utf8.h"

typedef Window HWND;

using namespace Tempest;

static std::unordered_map<HWND, Tempest::Window*> wndWx;

static Display*  dpy  = 0;
static HWND      root = 0;

static const long event_mask = 0xFFFFFF;

static HWND pin( LinuxAPI::Window* w ){
  return *((HWND*)w);
  }

static void xProc(XEvent& xev, HWND &hWnd, bool &quit);

static Atom& wmDeleteMessage(){
  static Atom w  = XInternAtom( dpy, "WM_DELETE_WINDOW", 0);
  return w;
  }

static Atom& _NET_WM_STATE(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE", 0);
  return w;
  }

static Atom& _NET_WM_STATE_MAXIMIZED_HORZ(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE_MAXIMIZED_HORZ", 0);
  return w;
  }

static Atom& _NET_WM_STATE_MAXIMIZED_VERT(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE_MAXIMIZED_VERT", 0);
  return w;
  }

static Atom& _NET_WM_STATE_FULLSCREEN(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE_FULLSCREEN", 0);
  return w;
  }

static void maximizeWindow( HWND& w ) {
  Atom a[2];
  a[0] = _NET_WM_STATE_MAXIMIZED_HORZ();
  a[1] = _NET_WM_STATE_MAXIMIZED_VERT();

  XChangeProperty ( dpy, w, _NET_WM_STATE(),
    XA_ATOM, 32, PropModeReplace, (unsigned char*)a, 2);
  }

static void fullScreen( HWND& w ) {
  Atom a[1];
  a[0] = _NET_WM_STATE_FULLSCREEN();

  XChangeProperty ( dpy, w, _NET_WM_STATE(),
    XA_ATOM, 32, PropModeReplace, (unsigned char*)a, 1);
  }

static void minimaizeWindow( HWND& w ) {
  XIconifyWindow(dpy, w, DefaultScreen(dpy) );
  XFlush(dpy);
  }

static LinuxAPI::Window* X11_CreateWindow( int w, int h,
                                           Tempest::Window::ShowMode m ){
  HWND * win = new HWND;
  GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
  XVisualInfo * vi = glXChooseVisual(dpy, 0, att);
  XSetWindowAttributes    swa;

  Colormap cmap;
  cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);

  swa.override_redirect = true;
  swa.colormap   = cmap;
  swa.event_mask = PointerMotionMask | ExposureMask |
                   ButtonPressMask |ButtonReleaseMask|
                   KeyPressMask | KeyReleaseMask;

  *win = XCreateWindow( dpy, root, 0, 0, w, h,
                        0, vi->depth, InputOutput, vi->visual,
                        CWColormap | CWEventMask, &swa );
  XSetWMProtocols(dpy, *win, &wmDeleteMessage(), 1);

  //XSelectInput(dpy, *win, );
  XStoreName(dpy, *win, "Tempest Application");

  XFreeColormap( dpy, cmap );
  XFree(vi);

  if( m==Tempest::Window::FullScreen )
    fullScreen(*win);

  if( m==Tempest::Window::Maximized )
    maximizeWindow(*win);

  minimaizeWindow(*win);

  return (LinuxAPI::Window*)win;
  }

LinuxAPI::LinuxAPI() {
  TranslateKeyPair k[] = {
    { XK_KP_Left,   Event::K_Left   },
    { XK_KP_Right,  Event::K_Right  },
    { XK_KP_Up,     Event::K_Up     },
    { XK_KP_Down,   Event::K_Down   },

    { XK_Escape, Event::K_ESCAPE },
    { XK_BackSpace,   Event::K_Back   },
    { XK_Delete, Event::K_Delete },
    { XK_Insert, Event::K_Insert },
    { XK_Home,   Event::K_Home   },
    { XK_End,    Event::K_End    },
    { XK_Pause,  Event::K_Pause  },
    { XK_Return, Event::K_Return },

    { XK_F1,     Event::K_F1 },
    {   48,      Event::K_0  },
    {   97,      Event::K_A  },

    { 0,         Event::K_NoKey }
    };

  setupKeyTranslate(k);
  setFuncKeysCount(24);
  }

LinuxAPI::~LinuxAPI() {
  }

void *LinuxAPI::display() {
  return dpy;
  }

bool LinuxAPI::testDisplaySettings( SystemAPI::Window* w, const DisplaySettings & s ) {
  return 1;
  }

bool LinuxAPI::setDisplaySettings( SystemAPI::Window* w, const DisplaySettings &s ) {
  return 0;
  }

Size LinuxAPI::implScreenSize() {
  Screen * scr = XDefaultScreenOfDisplay(dpy);
  int w = XWidthOfScreen (scr);
  int h = XHeightOfScreen(scr);

  return Size(w,h);
  }

void LinuxAPI::startApplication(ApplicationInitArgs *) {
  dpy = XOpenDisplay(NULL);

  if(dpy == NULL) {
    T_ASSERT_X( dpy, "cannot connect to X server!");
    exit(0);
    }

  root = DefaultRootWindow(dpy);
  }

void LinuxAPI::endApplication() {
  XCloseDisplay(dpy);
  }

static void render( Tempest::Window* w ){
  if( w->showMode()!=Tempest::Window::Minimized && w->isActive() )
    w->render();
  }

int LinuxAPI::nextEvent(bool &quit) {
  XEvent xev;
  memset(&xev,0,sizeof(xev));

  if( !XPending(dpy) ){
    XNextEvent(dpy, &xev);
    for( auto i=wndWx.begin(); i!=wndWx.end(); ++i )
      render( i->second );
    return 0;
    }

  xProc( xev, xev.xclient.window, quit);
  //Sleep(0);
  return 0;
  }

int LinuxAPI::nextEvents(bool &quit) {
  XEvent xev;
  memset(&xev,0,sizeof(xev));

  while( !quit ){
    if( XPending( dpy ) ){
      XNextEvent(dpy, &xev);
      xProc( xev, xev.xclient.window, quit );
      } else {
      for( auto i=wndWx.begin(); i!=wndWx.end(); ++i )
        render( i->second );
      return 0;
      }
    }

  return 0;
  }

LinuxAPI::Window *LinuxAPI::createWindow(int w, int h) {
  return X11_CreateWindow(w, h, Tempest::Window::Normal );
  }

SystemAPI::Window *LinuxAPI::createWindowMaximized() {
  return X11_CreateWindow( 800, 600, Tempest::Window::Maximized );
  }

SystemAPI::Window *LinuxAPI::createWindowMinimized() {
  return X11_CreateWindow( 800, 600, Tempest::Window::Minimized );
  }

SystemAPI::Window *LinuxAPI::createWindowFullScr() {
  return X11_CreateWindow( 800, 600, Tempest::Window::FullScreen );
  }

Widget* LinuxAPI::addOverlay(WindowOverlay *ov) {
  if( wndWx.empty() ){
    delete ov;
    return 0;
    }

  Tempest::Window* w = wndWx.begin()->second;
  SystemAPI::addOverlay(w, ov);
  return ov;
  }

Point LinuxAPI::windowClientPos( SystemAPI::Window * hWnd ) {
  XWindowAttributes xwa;
  XGetWindowAttributes(dpy, pin(hWnd), &xwa);

  return Point( xwa.x, xwa.y );
  }

Size LinuxAPI::windowClientRect( SystemAPI::Window * hWnd ) {
  XWindowAttributes xwa;
  XGetWindowAttributes(dpy, pin(hWnd), &xwa);

  return Size( xwa.width, xwa.height );
  }

void LinuxAPI::deleteWindow( Window *w ) {
  XDestroyWindow(dpy, pin(w));
  wndWx.erase( pin(w) );
  delete (HWND*)w;
  }

void LinuxAPI::show(Window *hWnd) {
  XMapWindow(dpy, pin(hWnd) );
  }

void LinuxAPI::setGeometry( Window *hw, int x, int y, int w, int h ) {
  XMoveResizeWindow( dpy, *((::Window*)hw), x, y, w, h );
  }

void LinuxAPI::bind( Window *w, Tempest::Window *wx ) {
  wndWx[ pin(w) ] = wx;
  }

LinuxAPI::CpuInfo LinuxAPI::cpuInfoImpl(){
  CpuInfo info;
  memset(&info, 0, sizeof(info));

  info.cpuCount = 1;
  return info;
  }

LinuxAPI::File *LinuxAPI::fopenImpl( const char *fname, const char *mode ) {
  return SystemAPI::fopenImpl( fname, mode );
  }

LinuxAPI::File *LinuxAPI::fopenImpl( const char16_t *fname, const char *mode ) {
  return SystemAPI::fopenImpl( toUtf8(fname).data(), mode );
  }

static Event::MouseButton toButton( XButtonEvent& msg ){
  if( msg.button==Button1 )
    return Event::ButtonLeft;

  if( msg.button==Button3 )
    return Event::ButtonRight;

  if( msg.button==Button2 )
    return Event::ButtonMid;

  return Event::ButtonNone;
  }

static Tempest::KeyEvent makeKeyEvent( XKeyEvent& k,
                                       bool scut = false ){
  int keysyms_per_keycode_return = 0;
  KeySym *ksym = XGetKeyboardMapping( dpy, k.keycode,
                                      1,
                                      &keysyms_per_keycode_return );

  char txt[10];
  XLookupString(&k, txt, sizeof(txt), ksym, 0 );

  char16_t txt16[10] = {};
  utf8::unchecked::utf8to16(txt, txt+strlen(txt), txt16 );

  Tempest::KeyEvent::KeyType e = SystemAPI::translateKey(*ksym);

  if( !scut ){
    if( Event::K_0<=e && e<= Event::K_9 )
      e = Tempest::KeyEvent::K_NoKey;

    if( Event::K_A<=e && e<= Event::K_Z )
      e = Tempest::KeyEvent::K_NoKey;
    }

  XFree(ksym);
  return Tempest::KeyEvent( e );
  }

void xProc( XEvent& xev, HWND &hWnd, bool &quit ) {
    Tempest::Window* w = 0;
    std::unordered_map<HWND, Tempest::Window*>::iterator i
        = wndWx.find( hWnd );

    if( i!= wndWx.end() )
      w = i->second;

    if( !w )
      return;

    {
      HWND root;
      int x, y;
      unsigned ww, hh, border, depth;

      if( XGetGeometry(dpy, hWnd, &root, &x, &y, &ww, &hh, &border, &depth) ){
        SystemAPI::moveEvent( w, x, y );
        SystemAPI::sizeEvent( w, ww, hh );
        }
    }

    switch( xev.type ) {
      case Expose:
        if( xev.xexpose.count == 0 ){
          render( w );
          }
        break;

    /*
      case WM_CHAR:
      {
         Tempest::KeyEvent e = Tempest::KeyEvent( uint32_t(wParam) );

         DWORD wrd[3] = {
           VK_RETURN,
           VK_BACK,
           0
           };

         if( 0 == *std::find( wrd, wrd+2, wParam) ){
           Tempest::KeyEvent ed( e.key, e.u16, Event::KeyDown );
           SystemAPI::emitEvent(w, ed);

           Tempest::KeyEvent eu( e.key, e.u16, Event::KeyUp );
           SystemAPI::emitEvent(w, eu);
           }
      }
      break;*/

      case KeyPress:
      {
         SystemAPI::emitEvent( w,
                               makeKeyEvent( xev.xkey ),
                               makeKeyEvent( xev.xkey, true),
                               Event::KeyDown );
      }
      break;

      case KeyRelease:
      {
         SystemAPI::emitEvent( w,
                               makeKeyEvent( xev.xkey ),
                               makeKeyEvent( xev.xkey, true),
                               Event::KeyUp );
      }
      break;

      case ButtonPress:
      case ButtonRelease: {
        bool isWheel = false;
        if( xev.type==ButtonPress && XPending(dpy) &&
            (xev.xbutton.button == Button4 || xev.xbutton.button == Button5) ){
          XEvent ev;
          XNextEvent(dpy, &ev);
          isWheel = (ev.type==ButtonRelease);
          }

        if( isWheel ){
          int ticks = 0;
          if( xev.xbutton.button == Button4 ) {
            ticks = 100;
            }
          else if ( xev.xbutton.button == Button5 ) {
            ticks = -100;
            }
          Tempest::MouseEvent e( xev.xbutton.x,
                                 xev.xbutton.y,
                                 Tempest::Event::ButtonNone,
                                 ticks,
                                 0,
                                 Event::MouseWheel );
          SystemAPI::emitEvent(w, e);
          } else {
          MouseEvent e( xev.xbutton.x,
                        xev.xbutton.y,
                        toButton( xev.xbutton ),
                        0,
                        0,
                        xev.type==ButtonPress ? Event::MouseDown : Event::MouseUp );
          SystemAPI::emitEvent(w, e);
          }
        }
        break;

      case MotionNotify: {
        MouseEvent e( xev.xmotion.x,
                      xev.xmotion.y,
                      Event::ButtonNone,
                      0,
                      0,
                      Event::MouseMove  );
        SystemAPI::emitEvent(w, e);
        }
        break;
/*
      case WM_ACTIVATEAPP:
      {
          bool a = (wParam==TRUE);
          SystemAPI::activateEvent(w,a);

          if( !a && w->isFullScreenMode() ){
            ShowWindow( hWnd, SW_MINIMIZE );
            }
      }
      break;*/

      case ClientMessage:{
        if( xev.xclient.data.l[0] == long(wmDeleteMessage()) ){
          Tempest::CloseEvent e;
          SystemAPI::emitEvent(w, e);
          if( !e.isAccepted() )
            quit = true;
          }
        }
        break;

      case DestroyNotify:{
        quit = true;
        }
        break;

      default: break;
      }

    return;
    }

#endif
<commit_msg>minimaize window support for X11<commit_after>#include "linuxapi.h"

#if defined(__linux__) && !defined(__ANDROID__)
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xos.h>
#include <GL/glx.h>

#undef Always // in X11/X.h
#undef PSize

#include <Tempest/Window>
#include <Tempest/Event>
#include <Tempest/DisplaySettings>

#include <unordered_map>
#include <fstream>
#include <Tempest/Assert>

#include <iostream>
#include "core/wrappers/atomic.h"
#include "thirdparty/utf8cpp/utf8.h"

typedef Window HWND;

using namespace Tempest;

static std::unordered_map<HWND, Tempest::Window*> wndWx;

static Display*  dpy  = 0;
static HWND      root = 0;

static const long event_mask = 0xFFFFFF;

static HWND pin( LinuxAPI::Window* w ){
  return *((HWND*)w);
  }

static void xProc(XEvent& xev, HWND &hWnd, bool &quit);

static Atom& wmDeleteMessage(){
  static Atom w  = XInternAtom( dpy, "WM_DELETE_WINDOW", 0);
  return w;
  }

static Atom& _NET_WM_STATE(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE", 0);
  return w;
  }

static Atom& _NET_WM_STATE_MAXIMIZED_HORZ(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE_MAXIMIZED_HORZ", 0);
  return w;
  }

static Atom& _NET_WM_STATE_MAXIMIZED_VERT(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE_MAXIMIZED_VERT", 0);
  return w;
  }

static Atom& _NET_WM_STATE_FULLSCREEN(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE_FULLSCREEN", 0);
  return w;
  }

static void maximizeWindow( HWND& w ) {
  Atom a[2];
  a[0] = _NET_WM_STATE_MAXIMIZED_HORZ();
  a[1] = _NET_WM_STATE_MAXIMIZED_VERT();

  XChangeProperty ( dpy, w, _NET_WM_STATE(),
    XA_ATOM, 32, PropModeReplace, (unsigned char*)a, 2);
  }

static void fullScreen( HWND& w ) {
  Atom a[1];
  a[0] = _NET_WM_STATE_FULLSCREEN();

  XChangeProperty ( dpy, w, _NET_WM_STATE(),
    XA_ATOM, 32, PropModeReplace, (unsigned char*)a, 1);
  }

static void minimaizeWindow( const HWND& w ) {
  XWMHints *wmHints;

  wmHints = XAllocWMHints();
  wmHints->initial_state = IconicState;
  wmHints->flags         = StateHint;

  XSetWMProperties( dpy, w, 0,0,
                    0,0, 0,
                    wmHints, 0);
  XFree(wmHints);
  }

static LinuxAPI::Window* X11_CreateWindow( int w, int h,
                                           Tempest::Window::ShowMode m ){
  HWND * win = new HWND;
  GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
  XVisualInfo * vi = glXChooseVisual(dpy, 0, att);
  XSetWindowAttributes    swa;

  Colormap cmap;
  cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);

  swa.override_redirect = true;
  swa.colormap   = cmap;
  swa.event_mask = PointerMotionMask | ExposureMask |
                   ButtonPressMask |ButtonReleaseMask|
                   KeyPressMask | KeyReleaseMask;

  *win = XCreateWindow( dpy, root, 0, 0, w, h,
                        0, vi->depth, InputOutput, vi->visual,
                        CWColormap | CWEventMask, &swa );
  XSetWMProtocols(dpy, *win, &wmDeleteMessage(), 1);
  XStoreName(dpy, *win, "Tempest Application");

  XFreeColormap( dpy, cmap );
  XFree(vi);

  if( m==Tempest::Window::FullScreen )
    fullScreen(*win);

  if( m==Tempest::Window::Maximized )
    maximizeWindow(*win);

  if( m==Tempest::Window::Minimized )
    minimaizeWindow(*win);

  return (LinuxAPI::Window*)win;
  }

LinuxAPI::LinuxAPI() {
  TranslateKeyPair k[] = {
    { XK_KP_Left,   Event::K_Left   },
    { XK_KP_Right,  Event::K_Right  },
    { XK_KP_Up,     Event::K_Up     },
    { XK_KP_Down,   Event::K_Down   },

    { XK_Escape, Event::K_ESCAPE },
    { XK_BackSpace,   Event::K_Back   },
    { XK_Delete, Event::K_Delete },
    { XK_Insert, Event::K_Insert },
    { XK_Home,   Event::K_Home   },
    { XK_End,    Event::K_End    },
    { XK_Pause,  Event::K_Pause  },
    { XK_Return, Event::K_Return },

    { XK_F1,     Event::K_F1 },
    {   48,      Event::K_0  },
    {   97,      Event::K_A  },

    { 0,         Event::K_NoKey }
    };

  setupKeyTranslate(k);
  setFuncKeysCount(24);
  }

LinuxAPI::~LinuxAPI() {
  }

void *LinuxAPI::display() {
  return dpy;
  }

bool LinuxAPI::testDisplaySettings( SystemAPI::Window* w, const DisplaySettings & s ) {
  return 1;
  }

bool LinuxAPI::setDisplaySettings( SystemAPI::Window* w, const DisplaySettings &s ) {
  return 0;
  }

Size LinuxAPI::implScreenSize() {
  Screen * scr = XDefaultScreenOfDisplay(dpy);
  int w = XWidthOfScreen (scr);
  int h = XHeightOfScreen(scr);

  return Size(w,h);
  }

void LinuxAPI::startApplication(ApplicationInitArgs *) {
  dpy = XOpenDisplay(NULL);

  if(dpy == NULL) {
    T_ASSERT_X( dpy, "cannot connect to X server!");
    exit(0);
    }

  root = DefaultRootWindow(dpy);
  }

void LinuxAPI::endApplication() {
  XCloseDisplay(dpy);
  }

static void render( Tempest::Window* w ){
  if( w->showMode()!=Tempest::Window::Minimized && w->isActive() )
    w->render();
  }

int LinuxAPI::nextEvent(bool &quit) {
  XEvent xev;
  memset(&xev,0,sizeof(xev));

  if( !XPending(dpy) ){
    XNextEvent(dpy, &xev);
    for( auto i=wndWx.begin(); i!=wndWx.end(); ++i )
      render( i->second );
    return 0;
    }

  xProc( xev, xev.xclient.window, quit);
  //Sleep(0);
  return 0;
  }

int LinuxAPI::nextEvents(bool &quit) {
  XEvent xev;
  memset(&xev,0,sizeof(xev));

  while( !quit ){
    if( XPending( dpy ) ){
      XNextEvent(dpy, &xev);
      xProc( xev, xev.xclient.window, quit );
      } else {
      for( auto i=wndWx.begin(); i!=wndWx.end(); ++i )
        render( i->second );
      return 0;
      }
    }

  return 0;
  }

LinuxAPI::Window *LinuxAPI::createWindow(int w, int h) {
  return X11_CreateWindow(w, h, Tempest::Window::Normal );
  }

SystemAPI::Window *LinuxAPI::createWindowMaximized() {
  return X11_CreateWindow( 800, 600, Tempest::Window::Maximized );
  }

SystemAPI::Window *LinuxAPI::createWindowMinimized() {
  return X11_CreateWindow( 800, 600, Tempest::Window::Minimized );
  }

SystemAPI::Window *LinuxAPI::createWindowFullScr() {
  return X11_CreateWindow( 800, 600, Tempest::Window::FullScreen );
  }

Widget* LinuxAPI::addOverlay(WindowOverlay *ov) {
  if( wndWx.empty() ){
    delete ov;
    return 0;
    }

  Tempest::Window* w = wndWx.begin()->second;
  SystemAPI::addOverlay(w, ov);
  return ov;
  }

Point LinuxAPI::windowClientPos( SystemAPI::Window * hWnd ) {
  XWindowAttributes xwa;
  XGetWindowAttributes(dpy, pin(hWnd), &xwa);

  return Point( xwa.x, xwa.y );
  }

Size LinuxAPI::windowClientRect( SystemAPI::Window * hWnd ) {
  XWindowAttributes xwa;
  XGetWindowAttributes(dpy, pin(hWnd), &xwa);

  return Size( xwa.width, xwa.height );
  }

void LinuxAPI::deleteWindow( Window *w ) {
  XDestroyWindow(dpy, pin(w));
  wndWx.erase( pin(w) );
  delete (HWND*)w;
  }

void LinuxAPI::show(Window *hWnd) {
  XMapWindow(dpy, pin(hWnd) );
  }

void LinuxAPI::setGeometry( Window *hw, int x, int y, int w, int h ) {
  XMoveResizeWindow( dpy, *((::Window*)hw), x, y, w, h );
  }

void LinuxAPI::bind( Window *w, Tempest::Window *wx ) {
  wndWx[ pin(w) ] = wx;
  }

LinuxAPI::CpuInfo LinuxAPI::cpuInfoImpl(){
  CpuInfo info;
  memset(&info, 0, sizeof(info));

  info.cpuCount = 1;
  return info;
  }

LinuxAPI::File *LinuxAPI::fopenImpl( const char *fname, const char *mode ) {
  return SystemAPI::fopenImpl( fname, mode );
  }

LinuxAPI::File *LinuxAPI::fopenImpl( const char16_t *fname, const char *mode ) {
  return SystemAPI::fopenImpl( toUtf8(fname).data(), mode );
  }

static Event::MouseButton toButton( XButtonEvent& msg ){
  if( msg.button==Button1 )
    return Event::ButtonLeft;

  if( msg.button==Button3 )
    return Event::ButtonRight;

  if( msg.button==Button2 )
    return Event::ButtonMid;

  return Event::ButtonNone;
  }

static Tempest::KeyEvent makeKeyEvent( XKeyEvent& k,
                                       bool scut = false ){
  int keysyms_per_keycode_return = 0;
  KeySym *ksym = XGetKeyboardMapping( dpy, k.keycode,
                                      1,
                                      &keysyms_per_keycode_return );

  char txt[10];
  XLookupString(&k, txt, sizeof(txt), ksym, 0 );

  char16_t txt16[10] = {};
  utf8::unchecked::utf8to16(txt, txt+strlen(txt), txt16 );

  Tempest::KeyEvent::KeyType e = SystemAPI::translateKey(*ksym);

  if( !scut ){
    if( Event::K_0<=e && e<= Event::K_9 )
      e = Tempest::KeyEvent::K_NoKey;

    if( Event::K_A<=e && e<= Event::K_Z )
      e = Tempest::KeyEvent::K_NoKey;
    }

  XFree(ksym);
  return Tempest::KeyEvent( e );
  }

void xProc( XEvent& xev, HWND &hWnd, bool &quit ) {
    Tempest::Window* w = 0;
    std::unordered_map<HWND, Tempest::Window*>::iterator i
        = wndWx.find( hWnd );

    if( i!= wndWx.end() )
      w = i->second;

    if( !w )
      return;

    {
      HWND root;
      int x, y;
      unsigned ww, hh, border, depth;

      if( XGetGeometry(dpy, hWnd, &root, &x, &y, &ww, &hh, &border, &depth) ){
        SystemAPI::moveEvent( w, x, y );
        SystemAPI::sizeEvent( w, ww, hh );
        }
    }

    switch( xev.type ) {
      case Expose:
        if( xev.xexpose.count == 0 ){
          render( w );
          }
        break;

    /*
      case WM_CHAR:
      {
         Tempest::KeyEvent e = Tempest::KeyEvent( uint32_t(wParam) );

         DWORD wrd[3] = {
           VK_RETURN,
           VK_BACK,
           0
           };

         if( 0 == *std::find( wrd, wrd+2, wParam) ){
           Tempest::KeyEvent ed( e.key, e.u16, Event::KeyDown );
           SystemAPI::emitEvent(w, ed);

           Tempest::KeyEvent eu( e.key, e.u16, Event::KeyUp );
           SystemAPI::emitEvent(w, eu);
           }
      }
      break;*/

      case KeyPress:
      {
         SystemAPI::emitEvent( w,
                               makeKeyEvent( xev.xkey ),
                               makeKeyEvent( xev.xkey, true),
                               Event::KeyDown );
      }
      break;

      case KeyRelease:
      {
         SystemAPI::emitEvent( w,
                               makeKeyEvent( xev.xkey ),
                               makeKeyEvent( xev.xkey, true),
                               Event::KeyUp );
      }
      break;

      case ButtonPress:
      case ButtonRelease: {
        bool isWheel = false;
        if( xev.type==ButtonPress && XPending(dpy) &&
            (xev.xbutton.button == Button4 || xev.xbutton.button == Button5) ){
          XEvent ev;
          XNextEvent(dpy, &ev);
          isWheel = (ev.type==ButtonRelease);
          }

        if( isWheel ){
          int ticks = 0;
          if( xev.xbutton.button == Button4 ) {
            ticks = 100;
            }
          else if ( xev.xbutton.button == Button5 ) {
            ticks = -100;
            }
          Tempest::MouseEvent e( xev.xbutton.x,
                                 xev.xbutton.y,
                                 Tempest::Event::ButtonNone,
                                 ticks,
                                 0,
                                 Event::MouseWheel );
          SystemAPI::emitEvent(w, e);
          } else {
          MouseEvent e( xev.xbutton.x,
                        xev.xbutton.y,
                        toButton( xev.xbutton ),
                        0,
                        0,
                        xev.type==ButtonPress ? Event::MouseDown : Event::MouseUp );
          SystemAPI::emitEvent(w, e);
          }
        }
        break;

      case MotionNotify: {
        MouseEvent e( xev.xmotion.x,
                      xev.xmotion.y,
                      Event::ButtonNone,
                      0,
                      0,
                      Event::MouseMove  );
        SystemAPI::emitEvent(w, e);
        }
        break;
/*
      case WM_ACTIVATEAPP:
      {
          bool a = (wParam==TRUE);
          SystemAPI::activateEvent(w,a);

          if( !a && w->isFullScreenMode() ){
            ShowWindow( hWnd, SW_MINIMIZE );
            }
      }
      break;*/

      case ClientMessage:{
        if( xev.xclient.data.l[0] == long(wmDeleteMessage()) ){
          Tempest::CloseEvent e;
          SystemAPI::emitEvent(w, e);
          if( !e.isAccepted() )
            quit = true;
          }
        }
        break;

      case DestroyNotify:{
        quit = true;
        }
        break;

      default: break;
      }

    return;
    }

#endif
<|endoftext|>


<commit_before><commit_msg>P1 - still very bad<commit_after><|endoftext|>


<commit_before>#include <SFML/Network.hpp>
#include <iostream>
#include <vector>

#include "common/terrain.h"
#include "common/vector3.h"
#include "common/octree.h"
#include "common/player.h"
#include "common/packets.h"
#include "server/heartbeat.h"

// Choose a random port for opening sockets (ports < 1024 are reserved)
const unsigned short Port = 28997;

Terrain *terrain;
Heartbeat beater;

void listBlocks(std::vector<PositionedBlock> *Blocks, Octree<Block*> octree, float x, float y, float z, float size) {
    if (octree.hasChildren) {
        float subsize = size / 2;
        listBlocks(Blocks, octree.children[0], x,         y,         z,         subsize);
        listBlocks(Blocks, octree.children[1], x+subsize, y,         z,         subsize);
        listBlocks(Blocks, octree.children[2], x,         y+subsize, z,         subsize);
        listBlocks(Blocks, octree.children[3], x+subsize, y+subsize, z,         subsize);
        listBlocks(Blocks, octree.children[4], x,         y,         z+subsize, subsize);
        listBlocks(Blocks, octree.children[5], x+subsize, y,         z+subsize, subsize);
        listBlocks(Blocks, octree.children[6], x,         y+subsize, z+subsize, subsize);
        listBlocks(Blocks, octree.children[7], x+subsize, y+subsize, z+subsize, subsize);
    } else if (octree.value->Type > 0) {
        Blocks->push_back(PositionedBlock(octree.value, Vector3(x, y, z), size));
    }
}

void sendTerrain(sf::SocketTCP Client, Vector3 ChunkIndex) {
    printf("(%f,%f,%f)\n", ChunkIndex.X, ChunkIndex.Y, ChunkIndex.Z);

    Octree<Block*> Chunk = terrain->GeneratedTerrain[ChunkIndex];
    std::vector<PositionedBlock> Blocks;
    listBlocks(&Blocks, Chunk,
               ChunkIndex.X * terrain->chunkSize,
               ChunkIndex.Y * terrain->chunkSize,
               ChunkIndex.Z * terrain->chunkSize,
                              terrain->chunkSize);

    sf::Packet Packet;
    Packet << "Take this chunk. It will be useful in times of need.";
    Packet << (int) Blocks.size();

    for (int i = 0; i < Blocks.size(); i++) // << (char)Blocks[i].block->Type
        Packet << Blocks[i].pos << Blocks[i].sideLength;

    Client.Send(Packet);
}

std::map<sf::SocketTCP, Player> players();

// Launch a server and receive incoming messages
int main() {
    if (beater.Beat())
        std::cout << "Heartbeat successful." << std::endl;
    else
        std::cout << "Error while sending heartbeat!" << std::endl;

    std::cout << "Setting up terrain..." << std::endl;
    terrain = new Terrain(3, 0, 10,10,10, 25);
    terrain->Regenerate();
    terrain->SaveToFile("server.mcube");

    // Create a socket for listening to incoming connections
    sf::SocketTCP Listener;
    if (!Listener.Listen(Port))
        return EXIT_FAILURE;
    std::cout << "Listening to port " << Port << ", waiting for connections..." << std::endl;

    // Create a selector for handling several sockets (the listener + the socket associated to each client)
    sf::SelectorTCP Selector;

    // Add the listener
    Selector.Add(Listener);

    // Loop while... we close the program :)
    while (true)
    {
        // Get the sockets ready for reading
        unsigned int NbSockets = Selector.Wait();

        // We can read from each returned socket
        for (unsigned int i = 0; i < NbSockets; ++i)
        {
            // Get the current socket
            sf::SocketTCP Socket = Selector.GetSocketReady(i);

            if (Socket == Listener)
            {
                // If the listening socket is ready, it means that we can accept a new connection
                sf::IPAddress Address;
                sf::SocketTCP Client;
                Listener.Accept(Client, &Address);
                std::cout << "Client connected: " << Address << std::endl;

                sf::Packet Packet;
                Packet << "First, I have to let you in on this secret.";
                Packet << terrain->chunkSize;
                Client.Send(Packet);

                // Add it to the selector
                Selector.Add(Client);
            }
            else
            {
                // Else, it is a client socket so we can read the data he sent
                sf::Packet Packet;
                if (Socket.Receive(Packet) == sf::Socket::Done)
                {
                    // Extract the message and display it
                    std::string Message;
                    Packet >> Message;

                    if (Message == "Terrain pl0z") {
                        Vector3 ChunkIndex;
                        Packet >> ChunkIndex;
                        sendTerrain(Socket, ChunkIndex);
                    } else
                        std::cout << "A client says: \"" << Message << "\"" << std::endl;
                }
                else
                {
                    // Error: we'd better remove the socket from the selector
                    std::cout << "Client disconnected" << std::endl;
                    Selector.Remove(Socket);
                }
            }
        }
    }

    return EXIT_SUCCESS;
}

<commit_msg>Lazy loading of chunks--preliminary<commit_after>#include <SFML/Network.hpp>
#include <iostream>
#include <vector>

#include "common/terrain.h"
#include "common/vector3.h"
#include "common/octree.h"
#include "common/player.h"
#include "common/packets.h"
#include "server/heartbeat.h"

// Choose a random port for opening sockets (ports < 1024 are reserved)
const unsigned short Port = 28997;

Terrain *terrain;
Heartbeat beater;

void listBlocks(std::vector<PositionedBlock> *Blocks, Octree<Block*> octree, float x, float y, float z, float size) {
    if (octree.hasChildren) {
        float subsize = size / 2;
        listBlocks(Blocks, octree.children[0], x,         y,         z,         subsize);
        listBlocks(Blocks, octree.children[1], x+subsize, y,         z,         subsize);
        listBlocks(Blocks, octree.children[2], x,         y+subsize, z,         subsize);
        listBlocks(Blocks, octree.children[3], x+subsize, y+subsize, z,         subsize);
        listBlocks(Blocks, octree.children[4], x,         y,         z+subsize, subsize);
        listBlocks(Blocks, octree.children[5], x+subsize, y,         z+subsize, subsize);
        listBlocks(Blocks, octree.children[6], x,         y+subsize, z+subsize, subsize);
        listBlocks(Blocks, octree.children[7], x+subsize, y+subsize, z+subsize, subsize);
    } else if (octree.value->Type > 0) {
        Blocks->push_back(PositionedBlock(octree.value, Vector3(x, y, z), size));
    }
}

void sendTerrain(sf::SocketTCP Client, Vector3 ChunkIndex) {
    printf("(%f,%f,%f)\n", ChunkIndex.X, ChunkIndex.Y, ChunkIndex.Z);

    Octree<Block*> Chunk = terrain->GeneratedTerrain[ChunkIndex];

    if (!Chunk) {
        sf::Packet Packet;
        Packet << "Take this chunk. It will be useful in times of need.";
        Packet << (int) 0;
        Client.Send(Packet);

        return;
    }

    std::vector<PositionedBlock> Blocks;
    listBlocks(&Blocks, Chunk,
               ChunkIndex.X * terrain->chunkSize,
               ChunkIndex.Y * terrain->chunkSize,
               ChunkIndex.Z * terrain->chunkSize,
                              terrain->chunkSize);

    sf::Packet Packet;
    Packet << "Take this chunk. It will be useful in times of need.";
    Packet << (int) Blocks.size();

    for (int i = 0; i < Blocks.size(); i++) // << (char)Blocks[i].block->Type
        Packet << Blocks[i].pos << Blocks[i].sideLength;

    Client.Send(Packet);
}

std::map<sf::SocketTCP, Player> players();

// Launch a server and receive incoming messages
int main() {
    if (beater.Beat())
        std::cout << "Heartbeat successful." << std::endl;
    else
        std::cout << "Error while sending heartbeat!" << std::endl;

    std::cout << "Setting up terrain..." << std::endl;
    terrain = new Terrain(3, 0, 10,10,10, 25);
    terrain->Regenerate();
    terrain->SaveToFile("server.mcube");

    // Create a socket for listening to incoming connections
    sf::SocketTCP Listener;
    if (!Listener.Listen(Port))
        return EXIT_FAILURE;
    std::cout << "Listening to port " << Port << ", waiting for connections..." << std::endl;

    // Create a selector for handling several sockets (the listener + the socket associated to each client)
    sf::SelectorTCP Selector;

    // Add the listener
    Selector.Add(Listener);

    // Loop while... we close the program :)
    while (true)
    {
        // Get the sockets ready for reading
        unsigned int NbSockets = Selector.Wait();

        // We can read from each returned socket
        for (unsigned int i = 0; i < NbSockets; ++i)
        {
            // Get the current socket
            sf::SocketTCP Socket = Selector.GetSocketReady(i);

            if (Socket == Listener)
            {
                // If the listening socket is ready, it means that we can accept a new connection
                sf::IPAddress Address;
                sf::SocketTCP Client;
                Listener.Accept(Client, &Address);
                std::cout << "Client connected: " << Address << std::endl;

                sf::Packet Packet;
                Packet << "First, I have to let you in on this secret.";
                Packet << terrain->chunkSize;
                Client.Send(Packet);

                // Add it to the selector
                Selector.Add(Client);
            }
            else
            {
                // Else, it is a client socket so we can read the data he sent
                sf::Packet Packet;
                if (Socket.Receive(Packet) == sf::Socket::Done)
                {
                    // Extract the message and display it
                    std::string Message;
                    Packet >> Message;

                    if (Message == "Terrain pl0z") {
                        Vector3 ChunkIndex;
                        Packet >> ChunkIndex;
                        sendTerrain(Socket, ChunkIndex);
                    } else
                        std::cout << "A client says: \"" << Message << "\"" << std::endl;
                }
                else
                {
                    // Error: we'd better remove the socket from the selector
                    std::cout << "Client disconnected" << std::endl;
                    Selector.Remove(Socket);
                }
            }
        }
    }

    return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>#ifndef SERVER_HTTP_HPP
#define	SERVER_HTTP_HPP

#include <boost/asio.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/functional/hash.hpp>

#include <unordered_map>
#include <thread>
#include <functional>
#include <iostream>
#include <sstream>

// Late 2017 TODO: remove the following checks and always use std::regex
#ifdef USE_BOOST_REGEX
#include <boost/regex.hpp>
#define REGEX_NS boost
#else
#include <regex>
#define REGEX_NS std
#endif

namespace HTTPExServer {
    template <class socket_type>
    class ServerBase {
    public:
        virtual ~ServerBase() {}

        class Response : public std::ostream {
            friend class ServerBase<socket_type>;

            boost::asio::streambuf streambuf;

            std::shared_ptr<socket_type> socket;

            Response(const std::shared_ptr<socket_type> &socket): std::ostream(&streambuf), socket(socket) {}

        public:
            size_t size() {
                return streambuf.size();
            }
        };

        class Content : public std::istream {
            friend class ServerBase<socket_type>;
        public:
            size_t size() {
                return streambuf.size();
            }
            std::string string() {
                std::stringstream ss;
                ss << rdbuf();
                return ss.str();
            }
        private:
            boost::asio::streambuf &streambuf;
            Content(boost::asio::streambuf &streambuf): std::istream(&streambuf), streambuf(streambuf) {}
        };

        class Request {
            friend class ServerBase<socket_type>;

            //Based on http://www.boost.org/doc/libs/1_60_0/doc/html/unordered/hash_equality.html
            class iequal_to {
            public:
              bool operator()(const std::string &key1, const std::string &key2) const {
                return boost::algorithm::iequals(key1, key2);
              }
            };
            class ihash {
            public:
              size_t operator()(const std::string &key) const {
                std::size_t seed=0;
                for(auto &c: key)
                  boost::hash_combine(seed, std::tolower(c));
                return seed;
              }
            };
        public:
            std::string method, path, http_version;

            Content content;

            std::unordered_multimap<std::string, std::string, ihash, iequal_to> header;

            REGEX_NS::smatch path_match;

            std::string remote_endpoint_address;
            unsigned short remote_endpoint_port;

        private:
            Request(): content(streambuf) {}

            boost::asio::streambuf streambuf;
        };

        class Config {
            friend class ServerBase<socket_type>;

            Config(unsigned short port, size_t num_threads): num_threads(num_threads), port(port), reuse_address(true) {}
            size_t num_threads;
        public:
            unsigned short port;
            ///IPv4 address in dotted decimal form or IPv6 address in hexadecimal notation.
            ///If empty, the address will be any address.
            std::string address;
            ///Set to false to avoid binding the socket to an address that is already in use.
            bool reuse_address;
        };
        ///Set before calling start().
        Config config;

        std::unordered_map<std::string, std::unordered_map<std::string,
            std::function<void(std::shared_ptr<typename ServerBase<socket_type>::Response>, std::shared_ptr<typename ServerBase<socket_type>::Request>)> > >  resource;

        std::unordered_map<std::string,
            std::function<void(std::shared_ptr<typename ServerBase<socket_type>::Response>, std::shared_ptr<typename ServerBase<socket_type>::Request>)> > default_resource;

        std::function<void(const std::exception&)> exception_handler;

    private:
        std::vector<std::pair<std::string, std::vector<std::pair<REGEX_NS::regex,
            std::function<void(std::shared_ptr<typename ServerBase<socket_type>::Response>, std::shared_ptr<typename ServerBase<socket_type>::Request>)> > > > > opt_resource;

    public:
        void start() {
            //Copy the resources to opt_resource for more efficient request processing
            opt_resource.clear();
            for(auto& res: resource) {
                for(auto& res_method: res.second) {
                    auto it=opt_resource.end();
                    for(auto opt_it=opt_resource.begin();opt_it!=opt_resource.end();opt_it++) {
                        if(res_method.first==opt_it->first) {
                            it=opt_it;
                            break;
                        }
                    }
                    if(it==opt_resource.end()) {
                        opt_resource.emplace_back();
                        it=opt_resource.begin()+(opt_resource.size()-1);
                        it->first=res_method.first;
                    }
                    it->second.emplace_back(REGEX_NS::regex(res.first), res_method.second);
                }
            }

            if(!io_service)
                io_service=std::make_shared<boost::asio::io_service>();

            if(io_service->stopped())
                io_service->reset();

            boost::asio::ip::tcp::endpoint endpoint;
            if(config.address.size()>0)
                endpoint=boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(config.address), config.port);
            else
                endpoint=boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), config.port);

            if(!acceptor)
                acceptor=std::unique_ptr<boost::asio::ip::tcp::acceptor>(new boost::asio::ip::tcp::acceptor(*io_service));
            acceptor->open(endpoint.protocol());
            acceptor->set_option(boost::asio::socket_base::reuse_address(config.reuse_address));
            acceptor->bind(endpoint);
            acceptor->listen();

            accept();

            //If num_threads>1, start m_io_service.run() in (num_threads-1) threads for thread-pooling
            threads.clear();
            for(size_t c=1;c<config.num_threads;c++) {
                threads.emplace_back([this](){
                    io_service->run();
                });
            }

            //Main thread
            if(config.num_threads>0)
                io_service->run();

            //Wait for the rest of the threads, if any, to finish as well
            for(auto& t: threads) {
                t.join();
            }
        }

        void stop() {
            acceptor->close();
            if(config.num_threads>0)
                io_service->stop();
        }

        ///Use this function if you need to recursively send parts of a longer message
        void send(const std::shared_ptr<Response> &response, const std::function<void(const boost::system::error_code&)>& callback=nullptr) const {
            boost::asio::async_write(*response->socket, response->streambuf, [this, response, callback](const boost::system::error_code& ec, size_t /*bytes_transferred*/) {
                if(callback)
                    callback(ec);
            });
        }

        /// If you have your own boost::asio::io_service, store its pointer here before running start().
        /// You might also want to set config.num_threads to 0.
        std::shared_ptr<boost::asio::io_service> io_service;
    protected:
        std::unique_ptr<boost::asio::ip::tcp::acceptor> acceptor;
        std::vector<std::thread> threads;

        long timeout_request;
        long timeout_content;

        ServerBase(unsigned short port, size_t num_threads, long timeout_request, long timeout_send_or_receive) :
                config(port, num_threads), timeout_request(timeout_request), timeout_content(timeout_send_or_receive) {}

        virtual void accept()=0;

        std::shared_ptr<boost::asio::deadline_timer> get_timeout_timer(const std::shared_ptr<socket_type> &socket, long seconds) {
            if(seconds==0)
                return nullptr;

            auto timer=std::make_shared<boost::asio::deadline_timer>(*io_service);
            timer->expires_from_now(boost::posix_time::seconds(seconds));
            timer->async_wait([socket](const boost::system::error_code& ec){
                if(!ec) {
                    boost::system::error_code ec;
                    socket->lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
                    socket->lowest_layer().close();
                }
            });
            return timer;
        }

        void read_request_and_content(const std::shared_ptr<socket_type> &socket) {
            //Create new streambuf (Request::streambuf) for async_read_until()
            //shared_ptr is used to pass temporary objects to the asynchronous functions
            std::shared_ptr<Request> request(new Request());
            try {
                request->remote_endpoint_address=socket->lowest_layer().remote_endpoint().address().to_string();
                request->remote_endpoint_port=socket->lowest_layer().remote_endpoint().port();
            }
            catch(const std::exception &e) {
                if(exception_handler)
                   exception_handler(e);
            }

            //Set timeout on the following boost::asio::async-read or write function
            auto timer=get_timeout_timer(socket, timeout_request);

            boost::asio::async_read_until(*socket, request->streambuf, "\r\n\r\n",
                    [this, socket, request, timer](const boost::system::error_code& ec, size_t bytes_transferred) {
                if(timer)
                    timer->cancel();
                if(!ec) {
                    //request->streambuf.size() is not necessarily the same as bytes_transferred, from Boost-docs:
                    //"After a successful async_read_until operation, the streambuf may contain additional data beyond the delimiter"
                    //The chosen solution is to extract lines from the stream directly when parsing the header. What is left of the
                    //streambuf (maybe some bytes of the content) is appended to in the async_read-function below (for retrieving content).
                    size_t num_additional_bytes=request->streambuf.size()-bytes_transferred;

                    if(!parse_request(request))
                        return;

                    //If content, read that as well
                    auto it=request->header.find("Content-Length");
                    if(it!=request->header.end()) {
                        unsigned long long content_length;
                        try {
                            content_length=stoull(it->second);
                        }
                        catch(const std::exception &e) {
                            if(exception_handler)
                                exception_handler(e);
                            return;
                        }
                        if(content_length>num_additional_bytes) {
                            //Set timeout on the following boost::asio::async-read or write function
                            auto timer=get_timeout_timer(socket, timeout_content);
                            boost::asio::async_read(*socket, request->streambuf,
                                    boost::asio::transfer_exactly(content_length-num_additional_bytes),
                                    [this, socket, request, timer]
                                    (const boost::system::error_code& ec, size_t /*bytes_transferred*/) {
                                if(timer)
                                    timer->cancel();
                                if(!ec)
                                    find_resource(socket, request);
                            });
                        }
                        else
                            find_resource(socket, request);
                    }
                    else
                        find_resource(socket, request);
                }
            });
        }

        bool parse_request(const std::shared_ptr<Request> &request) const {
            std::string line;
            getline(request->content, line);
            size_t method_end;
            if((method_end=line.find(' '))!=std::string::npos) {
                size_t path_end;
                if((path_end=line.find(' ', method_end+1))!=std::string::npos) {
                    request->method=line.substr(0, method_end);
                    request->path=line.substr(method_end+1, path_end-method_end-1);

                    size_t protocol_end;
                    if((protocol_end=line.find('/', path_end+1))!=std::string::npos) {
                        if(line.compare(path_end+1, protocol_end-path_end-1, "HTTP")!=0)
                            return false;
                        request->http_version=line.substr(protocol_end+1, line.size()-protocol_end-2);
                    }
                    else
                        return false;

                    getline(request->content, line);
                    size_t param_end;
                    while((param_end=line.find(':'))!=std::string::npos) {
                        size_t value_start=param_end+1;
                        if((value_start)<line.size()) {
                            if(line[value_start]==' ')
                                value_start++;
                            if(value_start<line.size())
                                request->header.insert(std::make_pair(line.substr(0, param_end), line.substr(value_start, line.size()-value_start-1)));
                        }

                        getline(request->content, line);
                    }
                }
                else
                    return false;
            }
            else
                return false;
            return true;
        }

        void find_resource(const std::shared_ptr<socket_type> &socket, const std::shared_ptr<Request> &request) {
            //Find path- and method-match, and call write_response
            for(auto& res: opt_resource) {
                if(request->method==res.first) {
                    for(auto& res_path: res.second) {
                        REGEX_NS::smatch sm_res;
                        if(REGEX_NS::regex_match(request->path, sm_res, res_path.first)) {
                            request->path_match=std::move(sm_res);
                            write_response(socket, request, res_path.second);
                            return;
                        }
                    }
                }
            }
            auto it_method=default_resource.find(request->method);
            if(it_method!=default_resource.end()) {
                write_response(socket, request, it_method->second);
            }
        }

        void write_response(const std::shared_ptr<socket_type> &socket, const std::shared_ptr<Request> &request,
                std::function<void(std::shared_ptr<typename ServerBase<socket_type>::Response>,
                                   std::shared_ptr<typename ServerBase<socket_type>::Request>)>& resource_function) {
            //Set timeout on the following boost::asio::async-read or write function
            auto timer=get_timeout_timer(socket, timeout_content);

            auto response=std::shared_ptr<Response>(new Response(socket), [this, request, timer](Response *response_ptr) {
                auto response=std::shared_ptr<Response>(response_ptr);
                send(response, [this, response, request, timer](const boost::system::error_code& ec) {
                    if(timer)
                        timer->cancel();
                    if(!ec) {
                        float http_version;
                        try {
                            http_version=stof(request->http_version);
                        }
                        catch(const std::exception &e){
                            if(exception_handler)
                                exception_handler(e);
                            return;
                        }

                        auto range=request->header.equal_range("Connection");
                        for(auto it=range.first;it!=range.second;it++) {
                            if(boost::iequals(it->second, "close"))
                                return;
                        }
                        if(http_version>1.05)
                            read_request_and_content(response->socket);
                    }
                });
            });

            try {
                resource_function(response, request);
            }
            catch(const std::exception &e) {
                if(exception_handler)
                    exception_handler(e);
                return;
            }
        }
    };

    template<class socket_type>
    class Server : public ServerBase<socket_type> {};

    typedef boost::asio::ip::tcp::socket HTTP;

	// Your function

    template<>
    class Server<HTTP> : public ServerBase<HTTP> {
    public:
        Server(unsigned short port, size_t num_threads=1, long timeout_request=5, long timeout_content=300) :
                ServerBase<HTTP>::ServerBase(port, num_threads, timeout_request, timeout_content) {}

    protected:
        void accept() {
            //Create new socket for this connection
            //Shared_ptr is used to pass temporary objects to the asynchronous functions
            auto socket=std::make_shared<HTTP>(*io_service);

            acceptor->async_accept(*socket, [this, socket](const boost::system::error_code& ec){
                //Immediately start accepting a new connection (if io_service hasn't been stopped)
                if (ec != boost::asio::error::operation_aborted)
                    accept();

                if(!ec) {
                    boost::asio::ip::tcp::no_delay option(true);
                    socket->set_option(option);

                    read_request_and_content(socket);
                }
            });
        }
    };
}
#endif	/* SERVER_HTTP_HPP */
 <commit_msg>Delete server_http.hpp<commit_after><|endoftext|>


<commit_before>/*
 * This badge clock was coded by none other than Simon Smith and Cameron Kachur.
 * It does clock things such as tell time and.........................
 * You wish you could make a clock badgerooni like this.
 * Happy clocking and turn down for only dead batteries.
 * Boilermake 2014 - All clock no sleep
 */

#define MAX_TERMINAL_LINE_LEN 40
#define MAX_TERMINAL_WORDS     7

// 14 is strlen("send FFFF -m ")
// the max message length able to be sent from the terminal is
// total terminal line length MINUS the rest of the message
#define MAX_TERMINAL_MESSAGE_LEN  MAX_TERMINAL_LINE_LEN - 14

#include <RF24.h>
#include <SPI.h>
#include <EEPROM.h>

// Maps commands to integers
const byte PINGTIME = 0;
const byte REQUESTTIME    = 1;

// Global Variables
int SROEPin = 3; // using digital pin 3 for SR !OE
int SRLatchPin = 8; // using digital pin 4 for SR latch
boolean terminalConnect = false; // indicates if the terminal has connected to the board yet

// nRF24L01 radio static initializations
RF24 radio(9,10); // Setup nRF24L01 on SPI bus using pins 9 & 10 as CE & CSN, respectively

uint16_t this_node_address = (EEPROM.read(0) << 8) | EEPROM.read(1); // Radio address for this node
unsigned long startTime = 0;
unsigned long synced_time = 0;

struct message{
  byte command;
  uint16_t from;
  unsigned long time;
};

// This runs once on boot
void setup() {
  Serial.begin(9600);

  // SPI initializations
  SPI.begin();
  SPI.setBitOrder(MSBFIRST); // nRF requires MSB first
  SPI.setClockDivider(16); // Set SPI clock to 16 MHz / 16 = 1 MHz

  // nRF radio initializations
  radio.begin();
  radio.setDataRate(RF24_1MBPS); // 1Mbps transfer rate
  radio.setCRCLength(RF24_CRC_16); // 16-bit CRC
  radio.setChannel(80); // Channel center frequency = 2.4005 GHz + (Channel# * 1 MHz)
  radio.setRetries(200, 1); // set the delay and number of retries upon failed transmit
  radio.openReadingPipe(0, this_node_address); // Open this address
  radio.startListening(); // Start listening on opened address

  // Shift register pin initializations
  pinMode(SROEPin, OUTPUT);
  pinMode(SRLatchPin, OUTPUT);
  digitalWrite(SROEPin, HIGH);
  digitalWrite(SRLatchPin, LOW);

  // make the pretty LEDs happenT727262578
  displayDemo();

  startTime = millis();
  //
  digitalWrite(SROEPin, LOW);
}

// This loops forever
void loop() {
  if (Serial && !terminalConnect) {
    terminalConnect = true;
    if (synced_time == 0) {
      sync_time_serial();
    }
  } else if (!Serial && terminalConnect) {
    terminalConnect = false;
  }

  //if (synced_time == 0) {
  //  radio_time_request(0x00a9);
 //   delay(5000);
 // }

  //radio_listen();
  displayTime();
}

void displayTime() {
  unsigned long time = millis() - startTime + synced_time;
  int hour = (time / 3600000) % 12;
  int minute = (time / 60000) % 60;
  int second = (time / 1000) % 60;

  if (second % 2) {
    setLEDS(ledNum(toLED16(hour)) | ledNum(toLED16(minute / 5)));
  } else {
    setLEDS(ledNum(toLED16(hour)));
  }
  delay(1000);
  if (minute % 5 == 0 && second == 0) {
    for (int i = 0; i < 16; i++) {
      setLEDS(ledNum((i + toLED16(9 + minute)) % 16 + 1));
      delay((int) 1000/16);
    }
  }

  Serial.print(millis());
  Serial.print(" : ");
  Serial.print(time);
  Serial.print(" : ");
  Serial.print(hour);
  Serial.print(" : ");
  Serial.print(minute);
  Serial.print(" : ");
  Serial.println(second);
}

//12 hour clock, but 16 LEDs
int toLED16(int i) {
  int ret = i;

  //We have to not use 4 of the 16 for a 12 clock
  if (ret >= 3) ret += 1;
  if (ret >= 5) ret += 1;
  if (ret >= 11) ret += 1;
  if (ret >= 13) ret += 1;
  ret += 9;
  return ret % 16;
}

//Wait a bit and see if we get serial time sync
void sync_time_serial() {
  #define MAX_SERIAL_SYNC_WAIT 10000
  #define TIME_HEADER 'T'
  #define TIME_LEN 9
  unsigned long sync_start = millis();
  Serial.println("Start Time Sync");

  String strTime = "";
  unsigned long newtime = 0;
  while ( true){ //11 is length of
    char c = Serial.read();
    delay(100);
    if (c == TIME_HEADER) {
      for (int i = 0; i < TIME_LEN; i++) {
        strTime += (char) Serial.read();
      }
      synced_time = strtoul(strTime.c_str(), NULL, 10);
      Serial.print("Successfully synced time. :");
      Serial.println(strTime);
      startTime = 0;
      return;
    }

    if ((millis() - sync_start) > MAX_SERIAL_SYNC_WAIT) {
      Serial.println("Abandoning Serial Time Sync");
      return;
    }
  }
}

void radio_time_request(uint16_t to) {
  struct message * new_message = (struct message *) malloc(sizeof(struct message));

  new_message->command = 0;
  new_message->from = to;
  new_message->time = 0;

  radio.stopListening();
  radio.openWritingPipe(to);
  radio.write(new_message, sizeof(new_message));
  radio.startListening();
  Serial.print("WE Time Pinged : ");
  Serial.println(to);
}

void radio_time_send(uint16_t to) {
  unsigned long time = millis() - startTime + synced_time;
  struct message * new_message = (struct message *) malloc(sizeof(struct message));

  new_message->command = 1;
  new_message->from = this_node_address;
  new_message->time = time;

  Serial.print("WE FULFILLED TIMEREQUEST : ");
  Serial.println(time);

  radio.stopListening();
  radio.openWritingPipe(to);
  radio.write(new_message, 7);
  radio.startListening();
}

void radio_listen() {
  while (radio.available()) {
    struct message * current_message = (struct message *) malloc(sizeof(struct message));

    radio.read( current_message,  4 + 2 + 1);
    if (current_message->command == 0) {
        Serial.print("Received Time PING : ");
        Serial.println(current_message->from);
        //Recieved time Ping, send back time! :D
        radio_time_send(current_message->from);
    }
    if (current_message->command == 1) {
        Serial.print("Received Time UPDATE : ");
        Serial.print(current_message->from);
        Serial.print(" : ");
        Serial.println(current_message->time);
        //Uh Logic for accepting new time.
        synced_time = current_message->time;
        startTime = 0;
    }
  }
}

/*
// Display LED pattern

// LED numbering:

           9
       8       10
     7           11
   6               12
  5                 13
   4               14
     3           15
       2       16
           1

shift register 1-8: AA
shift register 9-16: BB

setLEDS data in hex: 0xAABB
where AA in binary = 0b[8][7][6][5][4][3][2][1]
      BB in binary = 0b[16][15][14][13][12][11][10][9]

*/
word ledNum(int i) {
  word shit[17];
  shit[0] = 0x0000;

  shit[1] = 0x0100;
  shit[2] = 0x0200;
  shit[3] = 0x0400;
  shit[4] = 0x0800;
  shit[5] = 0x1000;
  shit[6] = 0x2000;
  shit[7] = 0x4000;
  shit[8] = 0x8000;

  shit[9] =  0x0001;
  shit[10] = 0x0002;
  shit[11] = 0x0004;
  shit[12] = 0x0008;
  shit[13] = 0x0010;
  shit[14] = 0x0020;
  shit[15] = 0x0040;
  shit[16] = 0x0080;

  return shit[i];
}

// LED display demo
void displayDemo() {
  digitalWrite(SROEPin, LOW);
  for (int i = 0; i < 4; i++) {
    setLEDS(0xAAAA);
    delay(125);
    setLEDS(0x5555);
    delay(125);
  }
  digitalWrite(SROEPin, HIGH);
}

// Sends word sized value to both SRs & latches output pins
void setLEDS(word value) {
  byte Hvalue = value >> 8;
  byte Lvalue = value & 0x00FF;
  SPI.transfer(Lvalue);
  SPI.transfer(Hvalue);
  digitalWrite(SRLatchPin, HIGH);
  digitalWrite(SRLatchPin, LOW);
}
<commit_msg>Fixed some un-nice variable names<commit_after>/*
 * This badge clock was coded by none other than Simon Smith and Cameron Kachur.
 * It does clock things such as tell time and.........................
 * You wish you could make a clock badgerooni like this.
 * Happy clocking and turn down for only dead batteries.
 * Boilermake 2014 - All clock no sleep
 */

#define MAX_TERMINAL_LINE_LEN 40
#define MAX_TERMINAL_WORDS     7

// 14 is strlen("send FFFF -m ")
// the max message length able to be sent from the terminal is
// total terminal line length MINUS the rest of the message
#define MAX_TERMINAL_MESSAGE_LEN  MAX_TERMINAL_LINE_LEN - 14

#include <RF24.h>
#include <SPI.h>
#include <EEPROM.h>

// Maps commands to integers
const byte PINGTIME = 0;
const byte REQUESTTIME    = 1;

// Global Variables
int SROEPin = 3; // using digital pin 3 for SR !OE
int SRLatchPin = 8; // using digital pin 4 for SR latch
boolean terminalConnect = false; // indicates if the terminal has connected to the board yet

// nRF24L01 radio static initializations
RF24 radio(9,10); // Setup nRF24L01 on SPI bus using pins 9 & 10 as CE & CSN, respectively

uint16_t this_node_address = (EEPROM.read(0) << 8) | EEPROM.read(1); // Radio address for this node
unsigned long startTime = 0;
unsigned long synced_time = 0;

struct message{
  byte command;
  uint16_t from;
  unsigned long time;
};

// This runs once on boot
void setup() {
  Serial.begin(9600);

  // SPI initializations
  SPI.begin();
  SPI.setBitOrder(MSBFIRST); // nRF requires MSB first
  SPI.setClockDivider(16); // Set SPI clock to 16 MHz / 16 = 1 MHz

  // nRF radio initializations
  radio.begin();
  radio.setDataRate(RF24_1MBPS); // 1Mbps transfer rate
  radio.setCRCLength(RF24_CRC_16); // 16-bit CRC
  radio.setChannel(80); // Channel center frequency = 2.4005 GHz + (Channel# * 1 MHz)
  radio.setRetries(200, 1); // set the delay and number of retries upon failed transmit
  radio.openReadingPipe(0, this_node_address); // Open this address
  radio.startListening(); // Start listening on opened address

  // Shift register pin initializations
  pinMode(SROEPin, OUTPUT);
  pinMode(SRLatchPin, OUTPUT);
  digitalWrite(SROEPin, HIGH);
  digitalWrite(SRLatchPin, LOW);

  // make the pretty LEDs happenT727262578
  displayDemo();

  startTime = millis();
  //
  digitalWrite(SROEPin, LOW);
}

// This loops forever
void loop() {
  if (Serial && !terminalConnect) {
    terminalConnect = true;
    if (synced_time == 0) {
      sync_time_serial();
    }
  } else if (!Serial && terminalConnect) {
    terminalConnect = false;
  }

  //if (synced_time == 0) {
  //  radio_time_request(0x00a9);
 //   delay(5000);
 // }

  //radio_listen();
  displayTime();
}

void displayTime() {
  unsigned long time = millis() - startTime + synced_time;
  int hour = (time / 3600000) % 12;
  int minute = (time / 60000) % 60;
  int second = (time / 1000) % 60;

  if (second % 2) {
    setLEDS(ledNum(toLED16(hour)) | ledNum(toLED16(minute / 5)));
  } else {
    setLEDS(ledNum(toLED16(hour)));
  }
  delay(1000);
  if (minute % 5 == 0 && second == 0) {
    for (int i = 0; i < 16; i++) {
      setLEDS(ledNum((i + toLED16(9 + minute)) % 16 + 1));
      delay((int) 1000/16);
    }
  }

  Serial.print(millis());
  Serial.print(" : ");
  Serial.print(time);
  Serial.print(" : ");
  Serial.print(hour);
  Serial.print(" : ");
  Serial.print(minute);
  Serial.print(" : ");
  Serial.println(second);
}

//12 hour clock, but 16 LEDs
int toLED16(int i) {
  int ret = i;

  //We have to not use 4 of the 16 for a 12 clock
  if (ret >= 3) ret += 1;
  if (ret >= 5) ret += 1;
  if (ret >= 11) ret += 1;
  if (ret >= 13) ret += 1;
  ret += 9;
  return ret % 16;
}

//Wait a bit and see if we get serial time sync
void sync_time_serial() {
  #define MAX_SERIAL_SYNC_WAIT 10000
  #define TIME_HEADER 'T'
  #define TIME_LEN 9
  unsigned long sync_start = millis();
  Serial.println("Start Time Sync");

  String strTime = "";
  unsigned long newtime = 0;
  while ( true){ //11 is length of
    char c = Serial.read();
    delay(100);
    if (c == TIME_HEADER) {
      for (int i = 0; i < TIME_LEN; i++) {
        strTime += (char) Serial.read();
      }
      synced_time = strtoul(strTime.c_str(), NULL, 10);
      Serial.print("Successfully synced time. :");
      Serial.println(strTime);
      startTime = 0;
      return;
    }

    if ((millis() - sync_start) > MAX_SERIAL_SYNC_WAIT) {
      Serial.println("Abandoning Serial Time Sync");
      return;
    }
  }
}

void radio_time_request(uint16_t to) {
  struct message * new_message = (struct message *) malloc(sizeof(struct message));

  new_message->command = 0;
  new_message->from = to;
  new_message->time = 0;

  radio.stopListening();
  radio.openWritingPipe(to);
  radio.write(new_message, sizeof(new_message));
  radio.startListening();
  Serial.print("WE Time Pinged : ");
  Serial.println(to);
}

void radio_time_send(uint16_t to) {
  unsigned long time = millis() - startTime + synced_time;
  struct message * new_message = (struct message *) malloc(sizeof(struct message));

  new_message->command = 1;
  new_message->from = this_node_address;
  new_message->time = time;

  Serial.print("WE FULFILLED TIMEREQUEST : ");
  Serial.println(time);

  radio.stopListening();
  radio.openWritingPipe(to);
  radio.write(new_message, 7);
  radio.startListening();
}

void radio_listen() {
  while (radio.available()) {
    struct message * current_message = (struct message *) malloc(sizeof(struct message));

    radio.read( current_message,  4 + 2 + 1);
    if (current_message->command == 0) {
        Serial.print("Received Time PING : ");
        Serial.println(current_message->from);
        //Recieved time Ping, send back time! :D
        radio_time_send(current_message->from);
    }
    if (current_message->command == 1) {
        Serial.print("Received Time UPDATE : ");
        Serial.print(current_message->from);
        Serial.print(" : ");
        Serial.println(current_message->time);
        //Uh Logic for accepting new time.
        synced_time = current_message->time;
        startTime = 0;
    }
  }
}

/*
// Display LED pattern

// LED numbering:

           9
       8       10
     7           11
   6               12
  5                 13
   4               14
     3           15
       2       16
           1

shift register 1-8: AA
shift register 9-16: BB

setLEDS data in hex: 0xAABB
where AA in binary = 0b[8][7][6][5][4][3][2][1]
      BB in binary = 0b[16][15][14][13][12][11][10][9]

*/
word ledNum(int i) {
  word led[17];
  led[0] = 0x0000;

  led[1] = 0x0100;
  led[2] = 0x0200;
  led[3] = 0x0400;
  led[4] = 0x0800;
  led[5] = 0x1000;
  led[6] = 0x2000;
  led[7] = 0x4000;
  led[8] = 0x8000;

  led[9] =  0x0001;
  led[10] = 0x0002;
  led[11] = 0x0004;
  led[12] = 0x0008;
  led[13] = 0x0010;
  led[14] = 0x0020;
  led[15] = 0x0040;
  led[16] = 0x0080;

  return led[i];
}

// LED display demo
void displayDemo() {
  digitalWrite(SROEPin, LOW);
  for (int i = 0; i < 4; i++) {
    setLEDS(0xAAAA);
    delay(125);
    setLEDS(0x5555);
    delay(125);
  }
  digitalWrite(SROEPin, HIGH);
}

// Sends word sized value to both SRs & latches output pins
void setLEDS(word value) {
  byte Hvalue = value >> 8;
  byte Lvalue = value & 0x00FF;
  SPI.transfer(Lvalue);
  SPI.transfer(Hvalue);
  digitalWrite(SRLatchPin, HIGH);
  digitalWrite(SRLatchPin, LOW);
}
<|endoftext|>


<commit_before>/* Rapicorn Tests
 * Copyright (C) 2008 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * A copy of the GNU Lesser General Public License should ship along
 * with this library; if not, see http://www.gnu.org/copyleft/.
 */
#include <rapicorn/rapicorn.hh>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>

namespace {
using namespace Rapicorn;

static void
fill_store (Store1 &s1)
{
  String dirname = ".";
  DIR *d = opendir (dirname.c_str());
  s1.clear();
  if (!d)
    {
      warning ("failed to access directory: %s: %s", dirname.c_str(), strerror (errno));
      return;
    }
  struct dirent *e = readdir (d);
  while (e)
    {
      Array row;
      uint n = 0;
      row[n++] = e->d_ino;
      row[n++] = " | ";
      row[n++] = e->d_type;
      row[n++] = " | ";
      row[n++] = e->d_name;
      s1.insert (-1, row);
      e = readdir (d);
    }
  closedir (d);
}

static Store1*
create_store ()
{
  Store1 *s1 = Store1::create_memory_store (Type::lookup ("String"));
  fill_store (*s1);
  return s1;
}

extern "C" int
main (int   argc,
      char *argv[])
{
  /* initialize Rapicorn for X11 */
  Application::init_with_x11 (&argc, &argv, "FileView");
  /* initialization acquired global Rapicorn mutex */

  /* load GUI definition file, relative to argv[0] */
  Application::auto_load ("RapicornTest", "fileview.xml", argv[0]);

  /* create root item */
  Store1 *s1 = create_store();
  Window window = Application::create_window ("main-dialog",
                                              Args (""),
                                              Args ("ListModel=" + s1->model().object_url()));
  window.show();

  Application::execute_loops();

  return 0;
}

} // anon
<commit_msg>FileView: allow file store filling for any directory.<commit_after>/* Rapicorn Tests
 * Copyright (C) 2008 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * A copy of the GNU Lesser General Public License should ship along
 * with this library; if not, see http://www.gnu.org/copyleft/.
 */
#include <rapicorn/rapicorn.hh>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>

namespace {
using namespace Rapicorn;

static void
fill_store (Store1       &s1,
            const String &dirname)
{
  DIR *d = opendir (dirname.c_str());
  s1.clear();
  if (!d)
    {
      warning ("failed to access directory: %s: %s", dirname.c_str(), strerror (errno));
      return;
    }
  struct dirent *e = readdir (d);
  while (e)
    {
      Array row;
      uint n = 0;
      row[n++] = e->d_ino;
      row[n++] = " | ";
      row[n++] = e->d_type;
      row[n++] = " | ";
      row[n++] = e->d_name;
      s1.insert (-1, row);
      e = readdir (d);
    }
  closedir (d);
}

static Store1*
create_store ()
{
  Store1 *s1 = Store1::create_memory_store (Type::lookup ("String"));
  fill_store (*s1, ".");
  return s1;
}

extern "C" int
main (int   argc,
      char *argv[])
{
  /* initialize Rapicorn for X11 */
  Application::init_with_x11 (&argc, &argv, "FileView");
  /* initialization acquired global Rapicorn mutex */

  /* load GUI definition file, relative to argv[0] */
  Application::auto_load ("RapicornTest", "fileview.xml", argv[0]);

  /* create root item */
  Store1 *s1 = create_store();
  Window window = Application::create_window ("main-dialog",
                                              Args (""),
                                              Args ("ListModel=" + s1->model().object_url()));
  window.show();

  Application::execute_loops();

  return 0;
}

} // anon
<|endoftext|>


<commit_before>/*======================================================================

  This file is part of the elastix software.

  Copyright (c) University Medical Center Utrecht. All rights reserved.
  See src/CopyrightElastix.txt or http://elastix.isi.uu.nl/legal.php for
  details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE. See the above copyright notices for more information.

======================================================================*/

#ifndef __elxOptimizerBase_hxx
#define __elxOptimizerBase_hxx

#include "elxOptimizerBase.h"

#include "itkSingleValuedNonLinearOptimizer.h"
#include "itk_zlib.h"

namespace elastix
{
using namespace itk;

/**
 * ****************** Constructor ***********************************
 */

template <class TElastix>
OptimizerBase<TElastix>
::OptimizerBase()
{
  this->m_NewSamplesEveryIteration = false;

} // end Constructor

/**
 * ****************** SetCurrentPositionPublic ************************
 *
 * Add empty SetCurrentPositionPublic, so it is known everywhere.
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::SetCurrentPositionPublic( const ParametersType & /** param */ )
{
  xl::xout["error"] << "ERROR: This function should be overridden or just "
    << "not used.\n";
  xl::xout["error"] << "  Are you using BSplineTransformWithDiffusion in "
    << "combination with another optimizer than the "
    << "StandardGradientDescentOptimizer? Don't!" << std::endl;

  /** Throw an exception if this function is not overridden. */
  itkExceptionMacro( << "ERROR: The SetCurrentPositionPublic method is not "
    << "implemented in your optimizer" );

} // end SetCurrentPositionPublic()

/**
 * ****************** BeforeEachResolutionBase **********************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::BeforeEachResolutionBase( void )
{
  /** Get the current resolution level. */
  unsigned int level
    = this->GetRegistration()->GetAsITKBaseType()->GetCurrentLevel();

  /** Check if after every iteration a new sample set should be created. */
  this->m_NewSamplesEveryIteration = false;
  this->GetConfiguration()->ReadParameter( this->m_NewSamplesEveryIteration,
    "NewSamplesEveryIteration", this->GetComponentLabel(), level, 0 );

} // end BeforeEachResolutionBase()

/**
 * ****************** AfterRegistrationBase **********************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::AfterRegistrationBase( void )
{
  typedef typename ParametersType::ValueType ParametersValueType;

  /** Get the final parameters. */
  ParametersType finalTP = this->GetAsITKBaseType()->GetCurrentPosition();

  /** Compute the crc checksum using zlib crc32 function. */
  const unsigned char * crcInputData = reinterpret_cast<const unsigned char *>( finalTP.data_block() );
  uLong crc = crc32(0L, Z_NULL, 0);
  crc = crc32(crc, crcInputData, finalTP.Size()* sizeof(ParametersValueType) );

  elxout << "\nRegistration result checksum: "
    << crc
    << std::endl;

} // end AfterRegistrationBase()

/**
 * ****************** SelectNewSamples ****************************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::SelectNewSamples( void )
{
  /** Force the metric to base its computation on a new subset of image samples.
   * Not every metric may have implemented this.
   */
  for ( unsigned int i = 0; i < this->GetElastix()->GetNumberOfMetrics(); ++i )
  {
    this->GetElastix()->GetElxMetricBase(i)->SelectNewSamples();
  }

} // end SelectNewSamples()

/**
 * ****************** GetNewSamplesEveryIteration ********************
 */

template <class TElastix>
bool
OptimizerBase<TElastix>
::GetNewSamplesEveryIteration( void ) const
{
  /** itkGetConstMacro Without the itkDebugMacro. */
  return this->m_NewSamplesEveryIteration;

} // end GetNewSamplesEveryIteration()

/**
 * ****************** SetSinusScales ********************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::SetSinusScales( double amplitude, double frequency,
  unsigned long numberOfParameters )
{
  typedef typename ITKBaseType::ScalesType ScalesType;

  const double nrofpar = static_cast<double>( numberOfParameters );
  ScalesType scales( numberOfParameters );

  for ( unsigned long i = 0; i < numberOfParameters; ++i )
  {
    const double x = static_cast<double>( i ) / nrofpar * 2.0
      * vnl_math::pi * frequency;
    scales[ i ] = vcl_pow( amplitude, vcl_sin( x ) );
  }
  this->GetAsITKBaseType()->SetScales( scales );

} // end SetSinusScales()

} // end namespace elastix

#endif // end #ifndef __elxOptimizerBase_hxx
<commit_msg>SK: <commit_after>/*======================================================================

  This file is part of the elastix software.

  Copyright (c) University Medical Center Utrecht. All rights reserved.
  See src/CopyrightElastix.txt or http://elastix.isi.uu.nl/legal.php for
  details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE. See the above copyright notices for more information.

======================================================================*/

#ifndef __elxOptimizerBase_hxx
#define __elxOptimizerBase_hxx

#include "elxOptimizerBase.h"

#include "itkSingleValuedNonLinearOptimizer.h"
#include "itk_zlib.h"

namespace elastix
{
using namespace itk;

/**
 * ****************** Constructor ***********************************
 */

template <class TElastix>
OptimizerBase<TElastix>
::OptimizerBase()
{
  this->m_NewSamplesEveryIteration = false;

} // end Constructor

/**
 * ****************** SetCurrentPositionPublic ************************
 *
 * Add empty SetCurrentPositionPublic, so it is known everywhere.
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::SetCurrentPositionPublic( const ParametersType & /** param */ )
{
  xl::xout["error"] << "ERROR: This function should be overridden or just "
    << "not used.\n";
  xl::xout["error"] << "  Are you using BSplineTransformWithDiffusion in "
    << "combination with another optimizer than the "
    << "StandardGradientDescentOptimizer? Don't!" << std::endl;

  /** Throw an exception if this function is not overridden. */
  itkExceptionMacro( << "ERROR: The SetCurrentPositionPublic method is not "
    << "implemented in your optimizer" );

} // end SetCurrentPositionPublic()

/**
 * ****************** BeforeEachResolutionBase **********************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::BeforeEachResolutionBase( void )
{
  /** Get the current resolution level. */
  unsigned int level
    = this->GetRegistration()->GetAsITKBaseType()->GetCurrentLevel();

  /** Check if after every iteration a new sample set should be created. */
  this->m_NewSamplesEveryIteration = false;
  this->GetConfiguration()->ReadParameter( this->m_NewSamplesEveryIteration,
    "NewSamplesEveryIteration", this->GetComponentLabel(), level, 0 );

} // end BeforeEachResolutionBase()

/**
 * ****************** AfterRegistrationBase **********************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::AfterRegistrationBase( void )
{
  typedef long IntParametersValueType;
  typedef Array<IntParametersValueType> IntParametersType;

  /** Get the final parameters, round to six decimals and store as int. */
  ParametersType finalTP = this->GetAsITKBaseType()->GetCurrentPosition();
  const unsigned long N = finalTP.GetSize();
  IntParametersType intTP( N );
  for (unsigned int i = 0; i < N; ++i )
  {
    intTP[i] = static_cast<IntParametersValueType>( itk::Math::Round( finalTP[i] * 1e6 ) );
  }

  /** Compute the crc checksum using zlib crc32 function. */
  const unsigned char * crcInputData = reinterpret_cast<const unsigned char *>( intTP.data_block() );
  uLong crc = crc32(0L, Z_NULL, 0);
  crc = crc32(crc, crcInputData, intTP.Size()* sizeof(IntParametersValueType) );

  elxout << "\nRegistration result checksum: "
    << crc
    << std::endl;

} // end AfterRegistrationBase()

/**
 * ****************** SelectNewSamples ****************************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::SelectNewSamples( void )
{
  /** Force the metric to base its computation on a new subset of image samples.
   * Not every metric may have implemented this.
   */
  for ( unsigned int i = 0; i < this->GetElastix()->GetNumberOfMetrics(); ++i )
  {
    this->GetElastix()->GetElxMetricBase(i)->SelectNewSamples();
  }

} // end SelectNewSamples()

/**
 * ****************** GetNewSamplesEveryIteration ********************
 */

template <class TElastix>
bool
OptimizerBase<TElastix>
::GetNewSamplesEveryIteration( void ) const
{
  /** itkGetConstMacro Without the itkDebugMacro. */
  return this->m_NewSamplesEveryIteration;

} // end GetNewSamplesEveryIteration()

/**
 * ****************** SetSinusScales ********************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::SetSinusScales( double amplitude, double frequency,
  unsigned long numberOfParameters )
{
  typedef typename ITKBaseType::ScalesType ScalesType;

  const double nrofpar = static_cast<double>( numberOfParameters );
  ScalesType scales( numberOfParameters );

  for ( unsigned long i = 0; i < numberOfParameters; ++i )
  {
    const double x = static_cast<double>( i ) / nrofpar * 2.0
      * vnl_math::pi * frequency;
    scales[ i ] = vcl_pow( amplitude, vcl_sin( x ) );
  }
  this->GetAsITKBaseType()->SetScales( scales );

} // end SetSinusScales()

} // end namespace elastix

#endif // end #ifndef __elxOptimizerBase_hxx
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

//_________________________________________________________________________
// An analysis task to check the PHOS/EMCAL simulated trigger
//
//*-- Yves Schutz & Gustavo Conesa Balbastre
//////////////////////////////////////////////////////////////////////////////

#include <TChain.h>
#include <TFile.h>
#include <TNtuple.h>
#include <TVector3.h>

#include "AliAnaCaloTrigger.h"
#include "AliESD.h"
#include "AliLog.h"

//______________________________________________________________________________
AliAnaCaloTrigger::AliAnaCaloTrigger(const char *name) :
  AliAnalysisTask(name,""),
  fChain(0),
  fESD(0),
  fOutputContainer(0),
  fCalorimeter("PHOS"),
  fNtTrigger22(0),
  fNtTriggerNN(0)

{
  // Constructor.
  // Input slot #0 works with an Ntuple
  DefineInput(0, TChain::Class());
  // Output slot #0 writes into a TH1 container
  DefineOutput(0,  TObjArray::Class()) ;
}
//____________________________________________________________________________
AliAnaCaloTrigger::AliAnaCaloTrigger(const AliAnaCaloTrigger & ct) :
  AliAnalysisTask(ct), fChain(ct.fChain), fESD(ct.fESD),
  fOutputContainer(ct.fOutputContainer), fCalorimeter(ct. fCalorimeter),
  fNtTrigger22(ct.fNtTrigger22), fNtTriggerNN(ct.fNtTriggerNN)
{

  // cpy ctor
  SetName (ct.GetName()) ;
  SetTitle(ct.GetTitle()) ;

}

//_________________________________________________________________________
AliAnaCaloTrigger & AliAnaCaloTrigger::operator = (const AliAnaCaloTrigger & source)
{
  // assignment operator

  if(&source == this) return *this;

  fChain = source.fChain ;
  fESD = source.fESD ;
  fOutputContainer = source.fOutputContainer ;
  fCalorimeter = source. fCalorimeter ;
  fNtTrigger22 = source.fNtTrigger22 ;
  fNtTriggerNN = source.fNtTriggerNN ;

  return *this;

}

//______________________________________________________________________________
AliAnaCaloTrigger::~AliAnaCaloTrigger()
{
  // dtor
  fOutputContainer->Clear() ;
  delete fOutputContainer ;
  delete fNtTrigger22 ;
  delete fNtTriggerNN ;
}

//______________________________________________________________________________
void AliAnaCaloTrigger::ConnectInputData(const Option_t*)
{
  // Initialisation of branch container and histograms

  AliInfo(Form("*** Initialization of %s", GetName())) ;

  // Get input data
  fChain = dynamic_cast<TChain *>(GetInputData(0)) ;
  if (!fChain) {
    AliError(Form("Input 0 for %s not found\n", GetName()));
    return ;
  }

  // One should first check if the branch address was taken by some other task
  char ** address = (char **)GetBranchAddress(0, "ESD");
  if (address) {
    fESD = (AliESD*)(*address);
  } else {
    fESD = new AliESD();
    SetBranchAddress(0, "ESD", &fESD);
  }
}

//________________________________________________________________________

void AliAnaCaloTrigger::CreateOutputObjects()
{

  // create histograms
  fNtTrigger22 = new TNtuple(fCalorimeter+"trigger22", "Trigger data 2x2 patch", "a22:a220:enMax:phEnMax:eta22:phi22:etaMax:phiMax:phEtaMax:phPhiMax");
  fNtTriggerNN = new TNtuple(fCalorimeter+"triggerNN", "Trigger data NxN patch", "aNN:aNN0:enMax:phEnMax:etaNN:phiNN:etaMax:phiMax:phEtaMax:phPhiMax");

  // create output container

  fOutputContainer = new TObjArray(2) ;
  fOutputContainer->SetName(GetName()) ;

  fOutputContainer->AddAt(fNtTrigger22,             0) ;
  fOutputContainer->AddAt(fNtTriggerNN,             1) ;

}

//______________________________________________________________________________
void AliAnaCaloTrigger::Exec(Option_t *)
{
  // Processing of one event

  Long64_t entry = fChain->GetReadEntry() ;

  if (!fESD) {
    AliError("fESD is not connected to the input!") ;
    return ;
  }

  if ( !((entry-1)%100) )
    AliInfo(Form("%s ----> Processing event # %lld",  (dynamic_cast<TChain *>(fChain))->GetFile()->GetName(), entry)) ;

  // Get trigger information of fCalorimeter
  TArrayF * triggerAmplitudes = 0x0 ;
  TArrayF * triggerPosition   = 0x0 ;
  Int_t firstCaloCluster      = 0 ;
  Int_t numberOfCaloClusters  = 0 ;

  if(fCalorimeter == "PHOS"){
    triggerAmplitudes      = fESD->GetPHOSTriggerAmplitudes();
    triggerPosition        = fESD->GetPHOSTriggerPosition();
    firstCaloCluster       = fESD->GetFirstPHOSCluster() ;
    numberOfCaloClusters   = fESD->GetNumberOfPHOSClusters() ;
  }
  else if(fCalorimeter == "EMCAL"){
    triggerAmplitudes    = fESD->GetEMCALTriggerAmplitudes();
    triggerPosition      = fESD->GetEMCALTriggerPosition();
    firstCaloCluster     = fESD->GetFirstEMCALCluster() ;
    numberOfCaloClusters = fESD->GetNumberOfEMCALClusters() ;
  }

  // trigger amplitudes
  const Float_t a22    = static_cast<Float_t>(triggerAmplitudes->At(0)) ;
  const Float_t a22O   = static_cast<Float_t>(triggerAmplitudes->At(1)) ;
  const Float_t aNN    = static_cast<Float_t>(triggerAmplitudes->At(2)) ;
  const Float_t aNNO   = static_cast<Float_t>(triggerAmplitudes->At(3)) ;

  // trigger position
  const Float_t x22  =  static_cast<Float_t>(triggerPosition->At(0)) ;
  const Float_t y22  =  static_cast<Float_t>(triggerPosition->At(1)) ;
  const Float_t z22  =  static_cast<Float_t>(triggerPosition->At(2)) ;
  const Float_t xNN  =  static_cast<Float_t>(triggerPosition->At(3)) ;
  const Float_t yNN  =  static_cast<Float_t>(triggerPosition->At(4)) ;
  const Float_t zNN  =  static_cast<Float_t>(triggerPosition->At(5)) ;

  Float_t enMax       = 0. ;
  Float_t phEnMax     = 0. ;
  Float_t etaMax      = 0.5 ;
  Float_t phiMax      = 0. ;
  Float_t phEtaMax    = 0.5 ;
  Float_t phPhiMax    = 0. ;

  TVector3 vpos22(x22, y22, z22) ;
  TVector3 vposNN(xNN, yNN, zNN) ;
  Float_t eta22 = vpos22.Eta() ;
  Float_t phi22 = vpos22.Phi() * TMath::RadToDeg() + 360. ;
  Float_t etaNN = vposNN.Eta() ;
  Float_t phiNN = vposNN.Phi() * TMath::RadToDeg() + 360. ;

  Int_t      icaloCluster ;

  // loop over the Calorimeters Clusters

  for(icaloCluster = firstCaloCluster ; icaloCluster < firstCaloCluster + numberOfCaloClusters ; icaloCluster++) {
    AliESDCaloCluster * cluster = fESD->GetCaloCluster(icaloCluster) ;
    if (cluster) {

      Float_t cluEnergy = cluster->GetClusterEnergy() ;
      Float_t pos[3] ;
      TVector3 vpos ;

      cluster->GetGlobalPosition( pos ) ;

      if ( cluEnergy > enMax) {
	enMax = cluEnergy ;
	vpos.SetXYZ(pos[0], pos[1], pos[2]) ;
	etaMax = vpos.Eta() ;
	phiMax = vpos.Phi() ;
      }

      Float_t * pid = cluster->GetPid() ;

      if(pid[AliPID::kPhoton] > 0.9) {
	if ( cluEnergy > phEnMax) {
	  phEnMax = cluEnergy ;
	  vpos.SetXYZ(pos[0], pos[1], pos[2]) ;
	  phEtaMax = vpos.Eta() ;
	  phPhiMax = vpos.Phi() ;
	}
      }
    }

    fNtTrigger22->Fill(a22, a22O, enMax, phEnMax, eta22, phi22, etaMax, phiMax * TMath::RadToDeg() + 360., phEtaMax, phPhiMax * TMath::RadToDeg() + 360.);
    fNtTriggerNN->Fill(aNN, aNNO, enMax, phEnMax, etaNN, phiNN, etaMax, phiMax * TMath::RadToDeg() + 360., phEtaMax, phPhiMax * TMath::RadToDeg() + 360.);
 }

  PostData(0, fOutputContainer);

}

//______________________________________________________________________________
void AliAnaCaloTrigger::Terminate(Option_t *)
{
  // Processing when the event loop is ended

}
<commit_msg>Let the taskmanager open the outfile before the task creates the output objects (Yves)<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

//_________________________________________________________________________
// An analysis task to check the PHOS/EMCAL simulated trigger
//
//*-- Yves Schutz & Gustavo Conesa Balbastre
//////////////////////////////////////////////////////////////////////////////

#include <TChain.h>
#include <TFile.h>
#include <TNtuple.h>
#include <TVector3.h>

#include "AliAnaCaloTrigger.h"
#include "AliESD.h"
#include "AliLog.h"

//______________________________________________________________________________
AliAnaCaloTrigger::AliAnaCaloTrigger(const char *name) :
  AliAnalysisTask(name,""),
  fChain(0),
  fESD(0),
  fOutputContainer(0),
  fCalorimeter("PHOS"),
  fNtTrigger22(0),
  fNtTriggerNN(0)

{
  // Constructor.
  // Input slot #0 works with an Ntuple
  DefineInput(0, TChain::Class());
  // Output slot #0 writes into a TH1 container
  DefineOutput(0,  TObjArray::Class()) ;
}
//____________________________________________________________________________
AliAnaCaloTrigger::AliAnaCaloTrigger(const AliAnaCaloTrigger & ct) :
  AliAnalysisTask(ct), fChain(ct.fChain), fESD(ct.fESD),
  fOutputContainer(ct.fOutputContainer), fCalorimeter(ct. fCalorimeter),
  fNtTrigger22(ct.fNtTrigger22), fNtTriggerNN(ct.fNtTriggerNN)
{

  // cpy ctor
  SetName (ct.GetName()) ;
  SetTitle(ct.GetTitle()) ;

}

//_________________________________________________________________________
AliAnaCaloTrigger & AliAnaCaloTrigger::operator = (const AliAnaCaloTrigger & source)
{
  // assignment operator

  if(&source == this) return *this;

  fChain = source.fChain ;
  fESD = source.fESD ;
  fOutputContainer = source.fOutputContainer ;
  fCalorimeter = source. fCalorimeter ;
  fNtTrigger22 = source.fNtTrigger22 ;
  fNtTriggerNN = source.fNtTriggerNN ;

  return *this;

}

//______________________________________________________________________________
AliAnaCaloTrigger::~AliAnaCaloTrigger()
{
  // dtor
  fOutputContainer->Clear() ;
  delete fOutputContainer ;
  delete fNtTrigger22 ;
  delete fNtTriggerNN ;
}

//______________________________________________________________________________
void AliAnaCaloTrigger::ConnectInputData(const Option_t*)
{
  // Initialisation of branch container and histograms

  AliInfo(Form("*** Initialization of %s", GetName())) ;

  // Get input data
  fChain = dynamic_cast<TChain *>(GetInputData(0)) ;
  if (!fChain) {
    AliError(Form("Input 0 for %s not found\n", GetName()));
    return ;
  }

  // One should first check if the branch address was taken by some other task
  char ** address = (char **)GetBranchAddress(0, "ESD");
  if (address) {
    fESD = (AliESD*)(*address);
  } else {
    fESD = new AliESD();
    SetBranchAddress(0, "ESD", &fESD);
  }
}

//________________________________________________________________________

void AliAnaCaloTrigger::CreateOutputObjects()
{

  // create histograms
  fNtTrigger22 = new TNtuple(fCalorimeter+"trigger22", "Trigger data 2x2 patch", "a22:a220:enMax:phEnMax:eta22:phi22:etaMax:phiMax:phEtaMax:phPhiMax");
  fNtTriggerNN = new TNtuple(fCalorimeter+"triggerNN", "Trigger data NxN patch", "aNN:aNN0:enMax:phEnMax:etaNN:phiNN:etaMax:phiMax:phEtaMax:phPhiMax");

  // create output container

  fOutputContainer = new TObjArray(2) ;
  fOutputContainer->SetName(GetName()) ;

  fOutputContainer->AddAt(fNtTrigger22,             0) ;
  fOutputContainer->AddAt(fNtTriggerNN,             1) ;

}

//______________________________________________________________________________
void AliAnaCaloTrigger::Exec(Option_t *)
{
  // Processing of one event

  Long64_t entry = fChain->GetReadEntry() ;

  if (!fESD) {
    AliError("fESD is not connected to the input!") ;
    return ;
  }

  if ( !((entry-1)%100) )
    AliInfo(Form("%s ----> Processing event # %lld",  (dynamic_cast<TChain *>(fChain))->GetFile()->GetName(), entry)) ;

  // Get trigger information of fCalorimeter
  TArrayF * triggerAmplitudes = 0x0 ;
  TArrayF * triggerPosition   = 0x0 ;
  Int_t firstCaloCluster      = 0 ;
  Int_t numberOfCaloClusters  = 0 ;

  if(fCalorimeter == "PHOS"){
    triggerAmplitudes      = fESD->GetPHOSTriggerAmplitudes();
    triggerPosition        = fESD->GetPHOSTriggerPosition();
    firstCaloCluster       = fESD->GetFirstPHOSCluster() ;
    numberOfCaloClusters   = fESD->GetNumberOfPHOSClusters() ;
  }
  else if(fCalorimeter == "EMCAL"){
    triggerAmplitudes    = fESD->GetEMCALTriggerAmplitudes();
    triggerPosition      = fESD->GetEMCALTriggerPosition();
    firstCaloCluster     = fESD->GetFirstEMCALCluster() ;
    numberOfCaloClusters = fESD->GetNumberOfEMCALClusters() ;
  }

  if( triggerAmplitudes && triggerPosition ){
  // trigger amplitudes
  const Float_t a22    = static_cast<Float_t>(triggerAmplitudes->At(0)) ;
  const Float_t a22O   = static_cast<Float_t>(triggerAmplitudes->At(1)) ;
  const Float_t aNN    = static_cast<Float_t>(triggerAmplitudes->At(2)) ;
  const Float_t aNNO   = static_cast<Float_t>(triggerAmplitudes->At(3)) ;

  // trigger position
  const Float_t x22  =  static_cast<Float_t>(triggerPosition->At(0)) ;
  const Float_t y22  =  static_cast<Float_t>(triggerPosition->At(1)) ;
  const Float_t z22  =  static_cast<Float_t>(triggerPosition->At(2)) ;
  const Float_t xNN  =  static_cast<Float_t>(triggerPosition->At(3)) ;
  const Float_t yNN  =  static_cast<Float_t>(triggerPosition->At(4)) ;
  const Float_t zNN  =  static_cast<Float_t>(triggerPosition->At(5)) ;

  Float_t enMax       = 0. ;
  Float_t phEnMax     = 0. ;
  Float_t etaMax      = 0.5 ;
  Float_t phiMax      = 0. ;
  Float_t phEtaMax    = 0.5 ;
  Float_t phPhiMax    = 0. ;

  TVector3 vpos22(x22, y22, z22) ;
  TVector3 vposNN(xNN, yNN, zNN) ;
  Float_t eta22 = vpos22.Eta() ;
  Float_t phi22 = vpos22.Phi() * TMath::RadToDeg() + 360. ;
  Float_t etaNN = vposNN.Eta() ;
  Float_t phiNN = vposNN.Phi() * TMath::RadToDeg() + 360. ;

  Int_t      icaloCluster ;

  // loop over the Calorimeters Clusters

  for(icaloCluster = firstCaloCluster ; icaloCluster < firstCaloCluster + numberOfCaloClusters ; icaloCluster++) {
    AliESDCaloCluster * cluster = fESD->GetCaloCluster(icaloCluster) ;
    if (cluster) {

      Float_t cluEnergy = cluster->GetClusterEnergy() ;
      Float_t pos[3] ;
      TVector3 vpos ;

      cluster->GetGlobalPosition( pos ) ;

      if ( cluEnergy > enMax) {
	enMax = cluEnergy ;
	vpos.SetXYZ(pos[0], pos[1], pos[2]) ;
	etaMax = vpos.Eta() ;
	phiMax = vpos.Phi() ;
      }

      Float_t * pid = cluster->GetPid() ;

      if(pid[AliPID::kPhoton] > 0.9) {
	if ( cluEnergy > phEnMax) {
	  phEnMax = cluEnergy ;
	  vpos.SetXYZ(pos[0], pos[1], pos[2]) ;
	  phEtaMax = vpos.Eta() ;
	  phPhiMax = vpos.Phi() ;
	}
      }
    }//if cluster

    fNtTrigger22->Fill(a22, a22O, enMax, phEnMax, eta22, phi22, etaMax, phiMax * TMath::RadToDeg() + 360., phEtaMax, phPhiMax * TMath::RadToDeg() + 360.);
    fNtTriggerNN->Fill(aNN, aNNO, enMax, phEnMax, etaNN, phiNN, etaMax, phiMax * TMath::RadToDeg() + 360., phEtaMax, phPhiMax * TMath::RadToDeg() + 360.);
  }//CaloCluster loop

  }//If trigger arrays filled

  PostData(0, fOutputContainer);

}

//______________________________________________________________________________
void AliAnaCaloTrigger::Terminate(Option_t *)
{
  // Processing when the event loop is ended

}
<|endoftext|>